/*
 * Copyright (c) 1997-2004 MIPS Technologies, Inc.
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above
 *      copyright
 *        notice, this list of conditions and the following disclaimer
 *        in the documentation and/or other materials provided with
 *        the distribution.
 *      * Neither the name of MIPS Technologies Inc. nor the names of its
 *        contributors may be used to endorse or promote products derived
 *        from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * sys/init.h: add an entry to the .sdeinit/.sdefini section.
 */


#ifndef __SYS_INIT_H__
#define __SYS_INIT_H__

/*
 * A bit like constructors/destructors, but you have some control
 * over the order in which they are called.
 */

/* Each section contains a list of these data structures */
#ifndef __ASSEMBLER__
struct ifent {
    int		if_type;
    void	(*if_func)(void);
};

extern struct ifent __SDEINIT_LIST__[];
extern struct ifent __SDEFINI_LIST__[];
#endif

/* 
 * These type codes specify the order in which .init functions 
 * will be called.
 *
 * On termination the entries in the .fini table are called in 
 * the reverse order to this.
 */
#define IF_END		0	/* end of table */
#define IF_SYSCTRL	1	/* System controller initialisation */
#define IF_SYSCTRLDEP	2	/* System controller dependent stuff */
#define IF_DEVICE	3	/* low-level device initialisation */
#define IF_RTOS		4	/* RTOS initialisation */
#define IF_DRIVER	5	/* higher-level device driver initialisation */
#define IF_FILESYS	6	/* file system installation/initialisation */
#define IF_MOUNT	7	/* mountable file systems */
#define IF_PREMAIN	8	/* called just before main() */
#define IF_MAX		8

#ifndef __ASSEMBLER__

#if __GNUC__ >= 3

#define DECL_INIT_FUNC(type, func) \
  __attribute__ (( used, section (".sdeinit"))) \
  static const struct ifent __sdeinit__ ## func = {type, func};

#define DECL_FINI_FUNC(type, func) \
  __attribute__ (( used, section (".sdefini"))) \
  static const struct ifent __sdefini__ ## func = {type, func};

#else /* __GNUC__ < 3 */

#define DECL_INIT_FUNC(type, func) \
  __attribute__ (( section (".sdeinit"))) \
  static const struct ifent __sdeinit__ ## func = {type, func};

#define DECL_FINI_FUNC(type, func) \
  __attribute__ (( section (".sdefini"))) \
  static const struct ifent __sdefini__ ## func = {type, func};

#endif /* __GNUC__ */

#else /* __ASSEMBLER__ */

#define DECL_INIT_FUNC(type, func) \
  .section	.sdeinit,"a",@progbits; \
__sdeinit___/**/func: ; \
  .size	__sdeinit___/**/func,8; \
  .word		type, func; \
  .previous

#define DECL_FINI_FUNC(type, func) \
  .section	.sdefini,"a",@progbits; \
__sdefini___/**/func: ; \
  .size	__sdefini___/**/func,8; \
  .previous

#endif /* __ASSEMBLER__ */

#endif /* __SYS_INIT_H__ */
