/*
*  programmable interrupt vectors (for the 8259's)
*/
enum
{
       Bptvec=         3,              /* breakpoints */
       Mathemuvec=     7,              /* math coprocessor emulation interrupt */
       Mathovervec=    9,              /* math coprocessor overrun interrupt */
       Matherr1vec=    16,             /* math coprocessor error interrupt */
       Faultvec=       14,             /* page fault */

       Int0vec=        24,             /* first 8259 */
        Clockvec=      Int0vec+0,      /*  clock interrupts */
        Kbdvec=        Int0vec+1,      /*  keyboard interrupts */
        Uart1vec=      Int0vec+3,      /*  modem line */
        Uart0vec=      Int0vec+4,      /*  serial line */
        PCMCIAvec=     Int0vec+5,      /*  PCMCIA card change */
        Floppyvec=     Int0vec+6,      /*  floppy interrupts */
        Parallelvec=   Int0vec+7,      /*  parallel port interrupts */
       Int1vec=        Int0vec+8,
        Ethervec=      Int0vec+10,     /*  ethernet interrupt */
        Mousevec=      Int0vec+12,     /*  mouse interrupt */
        Matherr2vec=   Int0vec+13,     /*  math coprocessor */
        ATA0vec=       Int0vec+14,     /*  hard disk */

       Syscallvec=     64,
};

/*
*  8259 interrupt controllers
*/
enum
{
       Int0ctl=        0x20,           /* control port (ICW1, OCW2, OCW3) */
       Int0aux=        0x21,           /* everything else (ICW2, ICW3, ICW4, OCW1) */
       Int1ctl=        0xA0,           /* control port */
       Int1aux=        0xA1,           /* everything else (ICW2, ICW3, ICW4, OCW1) */

       Icw1=           0x10,           /* select bit in ctl register */
       Ocw2=           0x00,
       Ocw3=           0x08,

       EOI=            0x20,           /* non-specific end of interrupt */

       Elcr1=          0x4D0,          /* Edge/Level Triggered Register */
       Elcr2=          0x4D1,
};

extern int      int0mask;               /* interrupts enabled for first 8259 */
extern int      int1mask;               /* interrupts enabled for second 8259 */

#define NVRAUTHADDR     0
#define LINESIZE        0

enum {
       MaxEISA         = 16,
       EISAconfig      = 0xC80,

       MaxScsi         = 4,
       NTarget         = 16,

       MaxEther        = 4,
};

#define DMAOK(x, l)     ((ulong)(((ulong)(x))+(l)) < (ulong)(KZERO|16*1024*1024))

enum {
       BusCBUS         = 0,            /* Corollary CBUS */
       BusCBUSII,                      /* Corollary CBUS II */
       BusEISA,                        /* Extended ISA */
       BusFUTURE,                      /* IEEE Futurebus */
       BusINTERN,                      /* Internal bus */
       BusISA,                         /* Industry Standard Architecture */
       BusMBI,                         /* Multibus I */
       BusMBII,                        /* Multibus II */
       BusMCA,                         /* Micro Channel Architecture */
       BusMPI,                         /* MPI */
       BusMPSA,                        /* MPSA */
       BusNUBUS,                       /* Apple Macintosh NuBus */
       BusPCI,                         /* Peripheral Component Interconnect */
       BusPCMCIA,                      /* PC Memory Card International Association */
       BusTC,                          /* DEC TurboChannel */
       BusVL,                          /* VESA Local bus */
       BusVME,                         /* VMEbus */
       BusXPRESS,                      /* Express System Bus */
};

#define MKBUS(t,b,d,f)  (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
#define BUSFNO(tbdf)    (((tbdf)>>8)&0x07)
#define BUSDNO(tbdf)    (((tbdf)>>11)&0x1F)
#define BUSBNO(tbdf)    (((tbdf)>>16)&0xFF)
#define BUSTYPE(tbdf)   ((tbdf)>>24)
#define BUSBDF(tbdf)    ((tbdf)&0x00FFFF00)
#define BUSUNKNOWN      (-1)

/*
* PCI support code.
*/
enum {                                  /* type 0 and type 1 pre-defined header */
       PciVID          = 0x00,         /* vendor ID */
       PciDID          = 0x02,         /* device ID */
       PciPCR          = 0x04,         /* command */
       PciPSR          = 0x06,         /* status */
       PciRID          = 0x08,         /* revision ID */
       PciCCRp         = 0x09,         /* programming interface class code */
       PciCCRu         = 0x0A,         /* sub-class code */
       PciCCRb         = 0x0B,         /* base class code */
       PciCLS          = 0x0C,         /* cache line size */
       PciLTR          = 0x0D,         /* latency timer */
       PciHDT          = 0x0E,         /* header type */
       PciBST          = 0x0F,         /* BIST */

       PciBAR0         = 0x10,         /* base address */
       PciBAR1         = 0x14,

       PciINTL         = 0x3C,         /* interrupt line */
       PciINTP         = 0x3D,         /* interrupt pin */
};

enum {                                  /* type 0 pre-defined header */
       PciBAR2         = 0x18,
       PciBAR3         = 0x1C,
       PciBAR4         = 0x20,
       PciBAR5         = 0x24,
       PciCIS          = 0x28,         /* cardbus CIS pointer */
       PciSVID         = 0x2C,         /* subsystem vendor ID */
       PciSID          = 0x2E,         /* cardbus CIS pointer */
       PciEBAR0        = 0x30,         /* expansion ROM base address */
       PciMGNT         = 0x3E,         /* burst period length */
       PciMLT          = 0x3F,         /* maximum latency between bursts */
};

enum {                                  /* type 1 pre-defined header */
       PciPBN          = 0x18,         /* primary bus number */
       PciSBN          = 0x19,         /* secondary bus number */
       PciUBN          = 0x1A,         /* subordinate bus number */
       PciSLTR         = 0x1B,         /* secondary latency timer */
       PciIBR          = 0x1C,         /* I/O base */
       PciILR          = 0x1D,         /* I/O limit */
       PciSPSR         = 0x1E,         /* secondary status */
       PciMBR          = 0x20,         /* memory base */
       PciMLR          = 0x22,         /* memory limit */
       PciPMBR         = 0x24,         /* prefetchable memory base */
       PciPMLR         = 0x26,         /* prefetchable memory limit */
       PciPUBR         = 0x28,         /* prefetchable base upper 32 bits */
       PciPULR         = 0x2C,         /* prefetchable limit upper 32 bits */
       PciIUBR         = 0x30,         /* I/O base upper 16 bits */
       PciIULR         = 0x32,         /* I/O limit upper 16 bits */
       PciEBAR1        = 0x28,         /* expansion ROM base address */
       PciBCR          = 0x3E,         /* bridge control register */
};

typedef struct Pcidev Pcidev;
typedef struct Pcidev {
       int     tbdf;                   /* type+bus+device+function */
       ushort  vid;                    /* vendor ID */
       ushort  did;                    /* device ID */

       struct {
               ulong   bar;            /* base address */
               int     size;
       } mem[6];

       uchar   intl;                   /* interrupt line */
       ushort  ccru;


       Pcidev* list;
       Pcidev* bridge;                 /* down a bus */
       Pcidev* link;                   /* next device on this bno */
} Pcidev;

extern int pcicfgr8(Pcidev*, int);
extern int pcicfgr16(Pcidev*, int);
extern int pcicfgr32(Pcidev*, int);
extern void pcicfgw8(Pcidev*, int, int);
extern void pcicfgw16(Pcidev*, int, int);
extern void pcicfgw32(Pcidev*, int, int);
extern void pcihinv(Pcidev*);
extern Pcidev* pcimatch(Pcidev*, int, int);
extern Pcidev* pcimatchtbdf(int);
extern void pcireset(void);
extern void pcisetbme(Pcidev*);

/*
*  a parsed plan9.ini line
*/
#define ISAOPTLEN       16
#define NISAOPT         8

typedef struct ISAConf {
       char    type[NAMELEN];
       ulong   port;
       ulong   irq;
       ulong   dma;
       ulong   mem;
       ulong   size;
       ulong   freq;

       int     nopt;
       char    opt[NISAOPT][ISAOPTLEN];
} ISAConf;

extern int isaconfig(char*, int, ISAConf*);

/*
* SCSI support code.
*/
enum {
       STblank         =-6,            /* blank block */
       STnomem         =-5,            /* buffer allocation failed */
       STtimeout       =-4,            /* bus timeout */
       STownid         =-3,            /* playing with myself */
       STharderr       =-2,            /* controller error of some kind */
       STinit          =-1,            /* */
       STok            = 0,            /* good */
       STcheck         = 0x02,         /* check condition */
       STcondmet       = 0x04,         /* condition met/good */
       STbusy          = 0x08,         /* busy */
       STintok         = 0x10,         /* intermediate/good */
       STintcondmet    = 0x14,         /* intermediate/condition met/good */
       STresconf       = 0x18,         /* reservation conflict */
       STterminated    = 0x22,         /* command terminated */
       STqfull         = 0x28,         /* queue full */
};

typedef struct Target {
       int     ctlrno;
       int     targetno;
       uchar*  inquiry;
       uchar*  sense;

       QLock;
       char    id[NAMELEN];
       int     ok;

       char    fflag;
       Filter  work[3];
       Filter  rate[3];
} Target;

typedef int (*Scsiio)(Target*, int, uchar*, int, void*, int*);