/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

#ident		"$Header: autoconf.h 1.19 89/09/01 $"

#ifndef	_SYS_AUTOCONF_H_

/*
 * autoconf.h
 *	New autoconfiguration process definitions.
 */

/* $Log:	autoconf.h,v $
 */

/* 
 * The structure definition for the system global definition:
 *      "struct driver_module drivers[];".
 *
 * The functions in the record below are documented with their
 * definition.  "Name" is the driver prefix string stripped of trailing
 * "_"'s, suitable for printf'ing.
 *
 * "On_busses" is a pointer to an array of dev_on_bus structures.  There
 * is one element in this array for each type of bus this type of device
 * can appear on according to this driver module.  This table is
 * terminated by a NULL element.  See the description of "struct
 * dev_on_bus".
 *
 * "Devices" is a pointer to a table of a device specific structure which has
 * as many elements as there are devices of this type config'ed into the
 * system. This structure always begins the same, and the definition of the
 * structure gen_device is that common preamble.  The number of records in this
 * table is "numdev".  The actual size of each record is "size_dev".  The
 * number of devices in this table that probed alive is "nalive". You can tell
 * which ones probed alive by checking the driver field of the device record.
 * Only the ones which probed alive will be non-zero.
 */

struct  driver_module {
    char        *name;			  /* Printing name of devices. */
    int         numdev;                   /* limit for "devices", below */
    int         nalive;                   /* # that probe alive */
    int         (*probe)();               /* returns 1 if device found */
    void        (*init)();
    void        (*intr)();
    int         (*poll)();                /* returns 1 if device interrupted */
    struct      dev_on_bus      *on_busses; /* the beginning of an array */
    struct      gen_device      *devices; /* the beginning of an array */
    unsigned    size_dev;		  /* the true size of a dev record */
};

/*
 * This structure is a map between a bus type (VME, Multibus, etc.) and a table
 * of possible configurations for a particular device.  Usually, there is an
 * array of these per device.  Each element of the array is for a different
 * bus.  The value of "nspaces" determines how many adjacent records
 * of an array of "struct device_config" constitutes a single unit. The array
 * is terminated by an element with a bus type of 0, or NOBUS.  This array
 * would be in space.c
 */

struct dev_on_bus {
    int         bustype;
    int         nspaces;                  /* # of rec./unit in config_array */
    struct      device_config   *config_array;
};

/*
 * Bus types.  Note that at this time, command busses are directly
 * tied to the owner device, unlike address busses.  It was decided
 * that the overhead of converting back and forth between a
 * generalized command block format and the bus-owner specific command
 * block format was not worth it.
 */

#define NOBUS           0

/*
 * The rest of these are just examples, as the true numbers come from
 *  config.h, generated by the config utility.
 * #define SB8000       1
 * #define MULTIBUS     2
 * #define SCEDSCSI     3
 * #define DCCBUS       4
 * #define VMEBUS       5
 * #define SSMSCSI      6
 */

struct device_config {
    /*
     * This structure describes a possible configuration for a device on
     * a general bus. There is normally an array of these for each device/bus
     * combination that describes all possible (or at least all SEQUENT
     * allowable) configurations.  This is usually found in the space.c file
     * for the driver.  The name of the table must be "<dev>_<bus>_config",
     * where <dev> is the device prefix (appears on all driver routines, etc.),
     * and <bus> is the bus name, eg "multibus" or "vmebus".  For
     * command busses, "space" is the target adaptor number and
     * "dev_addr" is the logic unit number, with "dev_len" = 1 and
     * "busint" the same as for address busses.  We could have (and
     * still can) use "dev_addr" for both target adaptor number and
     * logical unit number.  This array is terminated by a record which has
     * dev_len = -1.
     */
    int         dev_len;                  /* # of bytes in this CSR block */
    int         space;                    /* bus specific */
    long        dev_addr;                 /* first CSR address */
    int         busint;                   /* the interrput level on the bus. */
};

/*
 * The next structure is actually defined per bus device. (For example,
 * ex_device, st_device, mbad_device, the last an SB8000 device.) The structure
 * gen_device is the common beginning of each DEV_device structure
 * type, necessary so the config utility can fill in the records and
 * so that the bus drivers can fill out the map info.  The real definition
 * of this structure is in the driver source, probably in DEV.h  Here, we
 * need the definition of gen_device anyway, to give the config utility and
 * the bus drivers a definition.
 *
 * "Busnum" is an indicator of the bus or bus type that this device is on.
 * If the number is negative, it is the negative of the bus type (eg -SB8000)
 * and indicates a wild card for that bus type.  Devices on the sequent bus are
 * effectively always wild carded because the configuration information comes
 * from the firmware Table Of Contents.  If "busnum" is non-negative, it is an
 * index into the system global array "busses", and indicates on which bus this
 * device has been config'ured.  This slot is always filled in by config.
 *
 * "Unit" is a indicator of the configuration of the device on the given bus.
 * If negative (-1 will do), the unit is wild carded.  If non-negative, "unit"
 * is an index into the device and bus specific configuration table (for
 * example, into eg_multibus_config).  This slot is also always set by config.
 *
 * If the device probes alive, "bus" and "config" will be set (at autoconfig
 * time) to point to the bus and configuration records (respectively) found
 * by wild carding or specified by "busnum" and "unit" (respectively).
 *
 * During probing, "on_bus" will be set to point to the dev_on_bus record that
 * is selected by the driver/bus combination of this device record.
 *
 * Also at probe time, if the device probes alive, "driver" will be
 * set to point at the driver that owns this device, and this device
 * will be inserted into the chain of devices on the bus.  The last
 * device in the chain has "next" 0, the rest point to the next device
 * in the chain.  The order of devices in the chain is unimportant, so
 * devices will most likely be added at the head of the chain.
 *
 * If the device doesn't probe alive, "driver" is guaranteed to be (an
 * appropriate cast of) zero.
 *
 * "Nspaces" is a copy of "nspaces"  from the "dev_on_bus" table entry
 * that pointed to the configuration table by which this unit is
 * defined. This not only tells how many records of the
 * "device_configuration" pointed to by "config" are relevant, but
 * also how many "devreg"s there are.  Initialized by configure at autoconfig
 * time. 
 *
 * "Map_origin", "bus_map_addr", "map_extent" and "n_maps" are "owned"
 * by the driver of this device's bus.  "Map_origin" is a pointer to a private
 * structure that allows the bus driver to determine which of its maps belong
 * to the current device.  This structure allows the bus to record which of
 * this devices maps are in use (typically keyed to a specific DMA request).
 * "Map_extent" is the total number of bytes of mapping available to the
 * device.  "Bus_map_addr" is the address from the bus side of the beginning of
 * the area covered by the maps, and "n_maps" is the number of maps assigned
 * and is therefore the number of regions into which this set of map registers
 * can be segmented. 
 *
 * "Devreg" is the Sequent bus address of the device registers for address
 * bus devices, and a pointer to a command block descriptor for command bus
 * devices.  At probe time, this field is set by the bus "probe_setup" routine,
 * which is called by "configure".  When the bus "alloc_maps" function is
 * called, this field is given a permanent value.  This happens BEFORE init
 * time. In all cases, the bus routine in question is one gotten
 * from the bus record of the bus on which this device sits (pointed to by
 * "bus"). Note that "devreg" can be more than one pointer.  "Nspaces" is the
 * number of pointers in this field.
 */

struct gen_device {
    int         busnum;                    /* index into system bus table. */
    int         unit;                     /* Unit #, index into config table */
    int 	segsize;		  /* Size of a DMA segment */
    int		segalign;		  /* driver promises this alignment */
    int		nsegs;			  /* this device need this many segs */
    struct      driver_module   *driver;  /* pointer into "drivers[]" */
    struct      dev_on_bus      *on_bus;  /* points into drivers[].on_busses */
    struct      bus             *bus;
    struct      device_config   *config;
    struct      gen_device      *next;    /* Chain of devices on same bus */
    char       *map_origin;               /* sequent addr of map regs. */
    char       *bus_map_addr;             /* start of dma map, bus side. */
    long        map_extent;               /* # of bytes covered by map. */
    int         n_maps;                   /* Number of maps */
    int         nspaces;                  /* length of devreg, below */
    /* Devreg is really variable length, but the compiler wants a size... */
    char       *devreg[1];                 /* could point to CSR or CB */
    /*
     * here would start the device specific per device fields if this were,
     * for example, struct ex_dev instead of struct gen_dev
     */
};

/* The structure definition for the system global definition:
 *      "struct bus busses[];".
 *
 * "Bustype" define the type of bus this record describes.  See the #define's
 * above. It is filled in by the config utility.
 *
 * "Owner" is a pointer to the device descriptor  that this bus is on, for
 * example the mbad or ssm that owns this multibus.  It is filled in by the
 * config utility.
 *
 * "Devices" is a chain of devices that are on this bus.  It is pieced
 * together during device probing.
 *
 * "Devcount" is the number of devices on this bus that probed alive.
 * Although not strictly necessary, (the bus driver could scoot down
 * the chain of devices counting) it is easy to get this number and
 * useful to the bus driver.
 * 
 * All of the remaining slots will always be filled in by the config utility.
 * If a driver need to have one of them be null, it will have to do a #define
 * to do it.  Note that this means that the header file for the device driver
 * (where such a define would be) needs to be included into the file
 * that the config utility creates.
 *
 * The functions are defined in the function interfaces.
 */

struct bus {
    int         bustype;
    struct      gen_device      *owner;
    int         (*probe_setup)();         /* Returns 1 if successful */
    void        (*alloc_maps)();
    int         (*dma_setup)();           /* Returns 1 if successful */
    char         *(*dma_remap)();           /* Returns 1 if successful */
    void        (*dma_done)();
    void        (*dma_flush)();
    int		(*intr_setup)();
    void        (*ack_int)();
    struct      gen_device      *devices; /* chain of devices on this bus */
    int         devcount;                 /* # of devices in the chain. */
};

/*
 * Pseudo-device configuration structure(s).
 */

struct	pseudo_dev {
	char		*pd_name;		/* name (eg, "pty") */
	ulong		pd_flags;		/* flags (arbitrary) */
	void		(*pd_boot)();		/* boot procedure */
};

/*
 * DEVICEN(x)
 * Given a device structure of any type compatible with the gen_device, return
 * the number of this device, as in "sd2"
 */

#define DEVICEN(x) \
	(((char *)(x) - (char *)((struct gen_device *)x)->driver->devices) /  \
	((struct gen_device *)x)->driver->size_dev)

#define BUS_INT_OK	0
#define BUS_INTLVL_BAD	1
#define BUS_INTVEC_BAD	2
#define BUS_INTMAP_BAD	4

#ifdef INKERNEL
/* 
 * The following is created and filled in by the config utility.
 * There is one entry in this array for each software module that is
 * a driver.  There should be one per type of card that plugs into the system,
 * directly or indirectly. Examples include mbad driver, systech drivers,
 * ssm drivers, etc. The array is terminated by a record with numdev == 0.
 * Note that the order of drivers is important.  All drivers that control,
 * for example, a multibus, must come before any multibus device drivers.
 * The user must specify these boards in the correct order, and the config
 * utility must check the order! 
 */   
extern struct driver_module drivers[]; 

/*
 * The following is created and filled in by the config utility.
 * There is one entry in this array for each bus in the system including
 * the SB8000 (Sequent) bus.  This table is terminated by a record
 * with a zero "bustype" (NOBUS).
 */

extern struct bus busses[];

/*
 * The following is created and filled in by the config utility.  There is one
 * entry in this array for each type of bus in the system.  The entries are the
 * names of the bus types, translated to lowercase from the defined macros
 */

extern char *bus_type[];

extern	struct	pseudo_dev	pseudo_dev[];	/* pseudo-devices */

#endif /* INKERNEL */

#define	_SYS_AUTOCONF_H_
#endif	/* _SYS_AUTOCONF_H_ */
