/* Copyright 1997 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (c) 1989 Acorn Computers Ltd., Cambridge, England
 *
 * :RCS Log discontinued:
 * Revision 1.1  95/01/11  10:21:43  kwelton
 * Initial revision
 * 
 * Revision 1.1  89/04/28  14:57:01  mark
 * Initial revision
 * 
 */
/* xcb.h
 *
 * Definitions for expansion card bus (XCB, formerly known
 * as "podule") device access.
 */
#ifndef  _XCB_
#define  _XCB_

typedef struct
{
    unsigned char id0,          _pad0[3];
    unsigned char flags,        _pad1[3];
    unsigned char unused,       _pad2[3];
    unsigned char product_lo,   _pad3[3];
    unsigned char product_hi,   _pad4[3];
    unsigned char company_lo,   _pad5[3];
    unsigned char company_hi,   _pad6[3];
    unsigned char country,      _pad7[3];
    union
    {
        char            d_char[4];
        unsigned char   d_uchar[4];
        short           d_short[2];
        unsigned short  d_ushort[2];
        int             d_int;
        unsigned int    d_uint;
    } data[1024-8];
} XCBID, *XCBIDRef;
/* bits in c_id0 field: */
#define XCB_ID0_IRQ             (1 << 0)        /* set if IRQ outstanding */
#define XCB_ID0_NOT_PRESENT     (1 << 1)        /* pull-up gives 1 if slot empty */
#define XCB_ID0_FIQ             (1 << 2)        /* set if FIQ outstanding */
#define XCB_ID0_EXTRA           (0xF8)          /* remaining 5 bits should be 0 */


/* expansion card source country codes */

#define XCB_COUNTRY_UK  0
#define XCB_COUNTRY_ITALY       4
#define XCB_COUNTRY_SPAIN       5
#define XCB_COUNTRY_FRANCE      6
#define XCB_COUNTRY_GERMANY     7
#define XCB_COUNTRY_PORTUGAL    8
#define XCB_COUNTRY_GREECE      10
#define XCB_COUNTRY_SWEDEN      11
#define XCB_COUNTRY_FINLAND     12
#define XCB_COUNTRY_DENMARK     14
#define XCB_COUNTRY_NORWAY      15
#define XCB_COUNTRY_ICELAND     16
#define XCB_COUNTRY_CANADA      17
#define XCB_COUNTRY_TURKEY      20

/* expansion card manufacturing company codes */

#define XCB_COMPANY_ACORNUK                     0
#define XCB_COMPANY_ACORNUSA                    1
#define XCB_COMPANY_OLIVETTI                    2
#define XCB_COMPANY_WATFORD                     3
#define XCB_COMPANY_COMPUTERCONCEPTS            4
#define XCB_COMPANY_INTELIGENTINTERFACES        5
#define XCB_COMPANY_CAMAN                       6
#define XCB_COMPANY_ARMADILLO                   7
#define XCB_COMPANY_SOFTOPTION                  8
#define XCB_COMPANY_WILDVISION                  9
#define XCB_COMPANY_ANGLOCOMPUTERS              10
#define XCB_COMPANY_RESOURCE                    11

/* expansion card product type codes */
#define XCB_PRODUCT_HOSTTUBE                    0 /* To a BBC */
#define XCB_PRODUCT_PARASITETUBE                1 /* To a second processor */
#define XCB_PRODUCT_SCSI                        2
#define XCB_PRODUCT_ETHERNET                    3
#define XCB_PRODUCT_IBMDISC                     4
#define XCB_PRODUCT_RAMROM                      5
#define XCB_PRODUCT_BBCIO                       6
#define XCB_PRODUCT_MODEM                       7
#define XCB_PRODUCT_TELETEXT                    8
#define XCB_PRODUCT_CDROM                       9
#define XCB_PRODUCT_IEEE488                     10
#define XCB_PRODUCT_WINCHESTER                  11
#define XCB_PRODUCT_ESDI                        12
#define XCB_PRODUCT_SMD                         13
#define XCB_PRODUCT_LASERPRINTER                14
#define XCB_PRODUCT_SCANNER                     15
#define XCB_PRODUCT_FASTRING                    16
#define XCB_PRODUCT_VMEBUS                      17
#define XCB_PRODUCT_PROMPROGRAMMER              18
#define XCB_PRODUCT_MIDI                        19
#define XCB_PRODUCT_MONOVPU                     20
#define XCB_PRODUCT_FRAMEGRABBER                21
#define XCB_PRODUCT_SOUNDSAMPLER                22
#define XCB_PRODUCT_VIDEODIGITISER              23
#define XCB_PRODUCT_GENLOCK                     24
#define XCB_PRODUCT_CODECSAMPLER                25
#define XCB_PRODUCT_IMAGEANALYSER               26
#define XCB_PRODUCT_ANALOGUEINPUT               27
#define XCB_PRODUCT_CDSOUNDSAMPLER              28
#define XCB_PRODUCT_6MIPSSIGPROC                29
#define XCB_PRODUCT_12MIPSSIGPROC               30
#define XCB_PRODUCT_33MIPSSIGPROC               31
#define XCB_PRODUCT_TOUCHSCREEN                 32
#define XCB_PRODUCT_TRANSPUTERLINK              33

/* Hardware addressing (via IOC) */

#define XCB_SPEED_SLOW          0
#define XCB_SPEED_MEDIUM        1
#define XCB_SPEED_FAST          2
#define XCB_SPEED_SYNC          3               /* slowest of all...(!) */              
#define SLOW   0
#define MEDIUM 1
#define FAST   2
#define SYNC   3
#define XCB_SPEED(speed) (speed)

#define XCB_SLOT_OFF(slot)      ((slot) << 14)
#define XCB_ADDRESS(speed, slot) \
        (0x03240000 + (XCB_SPEED(speed) << 19) + \
         XCB_SLOT_OFF(slot))

#define XCB_IDx(speed, slot) ((XCBIDRef)(XCB_ADDRESS (speed, slot)))
#define XCB_ID(slot)         XCB_IDx (SYNC, slot)       /* recommended speed */


/* XCB manager interface details */

#define XCB_SLOTS       4
#define XCB_MAX_ETHERNET_CARDS 2


/*
 * The XCBInfo structure contains card-identification information, as 
 * stored in ARM memory.  Each expansion card must also contain these
 * codes, in a standard format and location, so that the XCB manager 
 * can read the card ID and hence match cards to drivers.
 */
typedef struct xcb_info
{
    unsigned short product, company;
    unsigned char  country;
} XCBInfo, *XCBInfoRef;

#ifdef NOT_YET
typedef struct xcb_io_mem
{
    struct xcb_io_mem  *next;                   /* in access-def list */
    int flags;                                  /* b/w, r/w, speed, multi etc */
    unsigned short offset, len;                 /* area loc/len in words  */
} XCIOMem, *XCIOMemRef;
/*
 * Flags bits: 
 *      0..1:   I/O cycle speed use XCB_SPEED_xxx 
 *      2:      memc-space address (speed ignored)
 *      3:      readable
 *      4       writable
 *      5:      byte-wide (0 => halfword-wide) access
 *      6:      can use ldm/stm access as appropriate in this area
 *      7:      is multi-mapped fifo register (requires bit 6 also)
 */
#define XCIO_SPEED__MASK        (3 << 0)        /*  */
#endif 

    
/*
 * Expansion Card type record.  This is the means whereby an XCB
 * device driver is linked with the XCB manager, in a fashion
 * analogous to the normal cdevsw and bdevsw tables (note that most
 * expansion card drivers will also have entries in one or both of
 * those tables).  The file "xcbconf.c" in the kernel build directory
 * contains a table, xcb_type[], of expansion card type structures,
 * one for each supported card type; the count of entries is set in
 * the external int nxcb_type.  Adding an XCB device driver requires
 * the inclusion in xcb_type of an entry for the card type.  At boot
 * time, the expansion card bus is scanned for expansion cards; the ID
 * of each installed card is determined by reading the first few bytes
 * of XCB ID space for the slot the card resides in.  Only those cards
 * with IDs matching entries in xcb_type will be considered valid as
 * far as RISC iX is concerned.  For all valid cards, a sequence of
 * initialisation is then performed, as follows:
 * 
 *    {cpu priority level still at MAX_SPL}
 *    for each valid card               {round 1}
 *       if (card_type->init_high != NULL)
 *           (*card_type->init_high) (card_slot);
 *
 *    {cpu priority reduced to 0, but xcb interrupts disabled}
 *    for each valid card               {round 2}
 *       if (card_type->init_low != NULL)
 *           (*card_type->init_low) (card_slot, 0);
 *    enable interrupts from expansion card bus
 *    for each valid card               {round 3}
 *       if (card_type->init_low != NULL)
 *           (*card_type->init_low) (card_slot, 1);
 * 
 * The first round of calls is designed to allow a driver to bring its
 * hardware to a stable, non-interrupting, initialised state, before the
 * processor interrupt priority is dropped from its initial maximum
 * and interrupts are allowed in.  The "init_high" function must not
 * reduce the processor priority.
 *
 * The second round of calls, via the "init_low" field, permits
 * further initialisation if required, with general interrupts
 * enabled, but no interrupts from expansion cards (marked by the
 * second parameter being 0).  The standard Ethernet card uses this
 * call to perform a test routine during which each configured card is
 * checked for correct functionality: if the card is OK then it is
 * added to the driver's tables and an interrupt handler is declared
 * for it using the function decl_xcb_interrupt().
 *
 * During either of the first two initialisation calls to a driver,
 * the driver may call the function decl_xcb_interrupt(), to declare
 * to the interrupt manager the existence of an interrupt handler for
 * IRQs from a specific card.  At most one call may be made, for each
 * slot in which a valid card has been found.  In the case that the
 * hardware configuration does not include a full-spec backplane, as
 * indicated by (xcb_regs == (XCBRegsRef)0), any call to this function
 * (and to the function decl_xcb_irq_sense, for non-standard card
 * interrupt indication) MUST happen at this time: an attempt to call
 * it later will cause a panic.
 *
 * The third and last round of initialisation calls uses the same
 * entry point as the second round, but with a second parameter of 1,
 * marking the fact that by this point interrupts from expansion cards
 * have been enabled, and all declared xcb interrupt handlers can
 * potentially be called.  Again the processor priority level is 0.
 * The Ethernet driver uses this call to perform final setup for each
 * configured working Ethernet card, during which time the Ethernet
 * interrupt handler is functioning normally.
 *
 * During the second and third calls, the driver may raise and lower
 * priority as required, using the normal splnnn calls, but should
 * return with the SPL restored to 0.
 *
 * The finally xcb driver entry point is used when the system reboot
 * or halt mechanism is invoked (e.g. via the "reboot" or "halt"
 * programs); the function specified in the shutdown field will be
 * called, as follows:
 *
 *    {cpu priority at maximum}
 *    foreach valid card:
 *       if (card_type->shutdown != NULL)
 *           (*card_type->shutdown) (card_slot);
 *
 * This function should arrange to close off any activity on the
 * device and bring the card to a stable quiescent state such that
 * when the kernel passes control to RISC OS, the card (a) will not
 * generate any interrupts, and (b) is in a condition equivalent to
 * the hardware reset state, such that the ID bytes used to identify
 * the card are readable at the standard address.
 *
 * In all cases, the called function is passed the physical slot
 * number of the expansion card as its first only parameter; from this
 * the device address may be derived.  Multiple instances of the same
 * card type on the bus will cause multiple calls on the function, one
 * for each slot in which a card of the given type is found.
 */

typedef struct xcb_type
{
    XCBInfo id;                                 /* ROM ID values */
    int flags;                                  /* for various purposes */
#ifdef NOTYET
    XCIOMemRef io_mem;                          /* for user access */
#endif 
    void (*init_high) (/*int slot*/);           /* init function 1, max prio */
    void (*init_low) (/*int slot*/);            /* init function 2, prio 0 */
    void (*shutdown) (/*int slot*/);            /* reboot shutdown function */
} XCBType, *XCBTypeRef;


#ifdef KERNEL
extern XCBType xcb_type[];
extern int nxcb_type;
#endif



#ifdef KERNEL
/*
 * decl_xcb_interrupt
 *
 * The parameters to decl_xcb_interrupt have the following meanings:
 *
 * slot:        0..(XCB_SLOTS-1) - the card's physical slot number.
 * handler:     the address of a statically allocated interrupt handler
 *              record.  The ih_fn field should be set to the address of
 *              the interrupt handling function, and the ih_farg field 
 *              should contain a value to be passed to this function on
 *              interrupt; the ih_mask and ih_next fields must be left 
 *              entirely alone by the driver.
 * priority:    the interrupt level at which IRQs from the expansion card
 *              should be serviced (i.e. a PRIO_xxxx value).  Normally,
 *              interrupts from the slot will actually arrive at this spl;
 *              however on those few systems configured without a proper
 *              backplane but with multiple expansion cards running at 
 *              different priorities, the lowest specified priority will
 *              be used for the single hardware interrupt level, but the
 *              handler function will be called with the spl level set to
 *              the requested level.
 *
 * This requests that whenever an expansion card in the specified slot
 * generates an IRQ, handler->ih_fn will be called, with argument
 * handler->ih_farg, with spl set to priority.
 */

extern void decl_xcb_interrupt (/* int slot, 
                                   struct int_hndlr *handler,
                                   int priority */);
#endif 

/*
 * Structure describing the way in which an interrupt from a non-
 * standard expansion card may be detected by the XCB manager.  On
 * systems with a proper backplane this mechanism is not used: the
 * backplane registers give indication of individual XCB interrupts.
 * On systems (regretably there still are a number) without a proper
 * backplane, we need to cope with XCB devices where the "standard"
 * IRQ flag is not used (ID byte 0, bit 0, positive logic).  Such
 * devices include the winchester expansion card (which has a separate
 * register) and early (pre-issue 1) ethernet cards, where the ID byte
 * must be read at FAST speed as opposed to SYNC.  This mechanism
 * assumes that an interrupting card may be identified by reading a
 * flag word from a (slot-adjusted) address and testing it against a
 * mask, the result indicating IRQ presence (!=0) or absence (==0).
 */
typedef struct xcb_irq_sense
{
    int *flag;          /* Note: slot address bits set by xcb manager */
    int mask;
} XCBIRQSense, *XCBIRQSenseRef;

#ifdef KERNEL
/*
 * decl_xcb_irq_sense need be called only for non-standard cards
 * in systems where the full-spec backplane hardware is not fitted.
 * This can be tested by checking the contents of the external
 * variable xcb_regs (see xcbregs.h).  See the comment above about
 * the meaning of the XCBIRQSense structure.  Note that the slot-
 * specific part of the device address (bits 14,15) is controlled
 * by the XCB manager, and should be left 0 in the flag field of
 * the structure passed in.
 */
extern void decl_xcb_irq_sense (/*int slot, XCBIRQSenseRef sense*/);
#endif 


#endif 

/* EOF xcb.h */
