1*5c47fe09SDavid du Colombier /* 2*5c47fe09SDavid du Colombier * PCI 3*5c47fe09SDavid du Colombier */ 4*5c47fe09SDavid du Colombier typedef unsigned long long uintpci; 5*5c47fe09SDavid du Colombier 6*5c47fe09SDavid du Colombier #define BUSUNKNOWN (-1) 7*5c47fe09SDavid du Colombier 8*5c47fe09SDavid du Colombier enum { 9*5c47fe09SDavid du Colombier BusCBUS = 0, /* Corollary CBUS */ 10*5c47fe09SDavid du Colombier BusCBUSII, /* Corollary CBUS II */ 11*5c47fe09SDavid du Colombier BusEISA, /* Extended ISA */ 12*5c47fe09SDavid du Colombier BusFUTURE, /* IEEE Futurebus */ 13*5c47fe09SDavid du Colombier BusINTERN, /* Internal bus */ 14*5c47fe09SDavid du Colombier BusISA, /* Industry Standard Architecture */ 15*5c47fe09SDavid du Colombier BusMBI, /* Multibus I */ 16*5c47fe09SDavid du Colombier BusMBII, /* Multibus II */ 17*5c47fe09SDavid du Colombier BusMCA, /* Micro Channel Architecture */ 18*5c47fe09SDavid du Colombier BusMPI, /* MPI */ 19*5c47fe09SDavid du Colombier BusMPSA, /* MPSA */ 20*5c47fe09SDavid du Colombier BusNUBUS, /* Apple Macintosh NuBus */ 21*5c47fe09SDavid du Colombier BusPCI, /* Peripheral Component Interconnect */ 22*5c47fe09SDavid du Colombier BusPCMCIA, /* PC Memory Card International Association */ 23*5c47fe09SDavid du Colombier BusTC, /* DEC TurboChannel */ 24*5c47fe09SDavid du Colombier BusVL, /* VESA Local bus */ 25*5c47fe09SDavid du Colombier BusVME, /* VMEbus */ 26*5c47fe09SDavid du Colombier BusXPRESS, /* Express System Bus */ 27*5c47fe09SDavid du Colombier }; 28*5c47fe09SDavid du Colombier 29*5c47fe09SDavid du Colombier #define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8)) 30*5c47fe09SDavid du Colombier #define BUSFNO(tbdf) (((tbdf)>>8)&0x07) 31*5c47fe09SDavid du Colombier #define BUSDNO(tbdf) (((tbdf)>>11)&0x1F) 32*5c47fe09SDavid du Colombier #define BUSBNO(tbdf) (((tbdf)>>16)&0xFF) 33*5c47fe09SDavid du Colombier #define BUSTYPE(tbdf) ((tbdf)>>24) 34*5c47fe09SDavid du Colombier #define BUSBDF(tbdf) ((tbdf)&0x00FFFF00) 35*5c47fe09SDavid du Colombier 36*5c47fe09SDavid du Colombier enum { /* type 0 & type 1 pre-defined header */ 37*5c47fe09SDavid du Colombier PciVID = 0x00, /* vendor ID */ 38*5c47fe09SDavid du Colombier PciDID = 0x02, /* device ID */ 39*5c47fe09SDavid du Colombier PciPCR = 0x04, /* command */ 40*5c47fe09SDavid du Colombier PciPSR = 0x06, /* status */ 41*5c47fe09SDavid du Colombier PciRID = 0x08, /* revision ID */ 42*5c47fe09SDavid du Colombier PciCCRp = 0x09, /* programming interface class code */ 43*5c47fe09SDavid du Colombier PciCCRu = 0x0A, /* sub-class code */ 44*5c47fe09SDavid du Colombier PciCCRb = 0x0B, /* base class code */ 45*5c47fe09SDavid du Colombier PciCLS = 0x0C, /* cache line size */ 46*5c47fe09SDavid du Colombier PciLTR = 0x0D, /* latency timer */ 47*5c47fe09SDavid du Colombier PciHDT = 0x0E, /* header type */ 48*5c47fe09SDavid du Colombier PciBST = 0x0F, /* BIST */ 49*5c47fe09SDavid du Colombier 50*5c47fe09SDavid du Colombier PciBAR0 = 0x10, /* base address */ 51*5c47fe09SDavid du Colombier PciBAR1 = 0x14, 52*5c47fe09SDavid du Colombier 53*5c47fe09SDavid du Colombier PciCAP = 0x34, /* capabilities pointer */ 54*5c47fe09SDavid du Colombier PciINTL = 0x3C, /* interrupt line */ 55*5c47fe09SDavid du Colombier PciINTP = 0x3D, /* interrupt pin */ 56*5c47fe09SDavid du Colombier }; 57*5c47fe09SDavid du Colombier 58*5c47fe09SDavid du Colombier /* ccrb (base class code) values; controller types */ 59*5c47fe09SDavid du Colombier enum { 60*5c47fe09SDavid du Colombier Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ 61*5c47fe09SDavid du Colombier Pcibcstore = 1, /* mass storage */ 62*5c47fe09SDavid du Colombier Pcibcnet = 2, /* network */ 63*5c47fe09SDavid du Colombier Pcibcdisp = 3, /* display */ 64*5c47fe09SDavid du Colombier Pcibcmmedia = 4, /* multimedia */ 65*5c47fe09SDavid du Colombier Pcibcmem = 5, /* memory */ 66*5c47fe09SDavid du Colombier Pcibcbridge = 6, /* bridge */ 67*5c47fe09SDavid du Colombier Pcibccomm = 7, /* simple comms (e.g., serial) */ 68*5c47fe09SDavid du Colombier Pcibcbasesys = 8, /* base system */ 69*5c47fe09SDavid du Colombier Pcibcinput = 9, /* input */ 70*5c47fe09SDavid du Colombier Pcibcdock = 0xa, /* docking stations */ 71*5c47fe09SDavid du Colombier Pcibcproc = 0xb, /* processors */ 72*5c47fe09SDavid du Colombier Pcibcserial = 0xc, /* serial bus (e.g., USB) */ 73*5c47fe09SDavid du Colombier Pcibcwireless = 0xd, /* wireless */ 74*5c47fe09SDavid du Colombier Pcibcintell = 0xe, /* intelligent i/o */ 75*5c47fe09SDavid du Colombier Pcibcsatcom = 0xf, /* satellite comms */ 76*5c47fe09SDavid du Colombier Pcibccrypto = 0x10, /* encryption/decryption */ 77*5c47fe09SDavid du Colombier Pcibcdacq = 0x11, /* data acquisition & signal proc. */ 78*5c47fe09SDavid du Colombier }; 79*5c47fe09SDavid du Colombier 80*5c47fe09SDavid du Colombier /* ccru (sub-class code) values; common cases only */ 81*5c47fe09SDavid du Colombier enum { 82*5c47fe09SDavid du Colombier /* mass storage */ 83*5c47fe09SDavid du Colombier Pciscscsi = 0, /* SCSI */ 84*5c47fe09SDavid du Colombier Pciscide = 1, /* IDE (ATA) */ 85*5c47fe09SDavid du Colombier Pciscsata = 6, /* SATA */ 86*5c47fe09SDavid du Colombier 87*5c47fe09SDavid du Colombier /* network */ 88*5c47fe09SDavid du Colombier Pciscether = 0, /* Ethernet */ 89*5c47fe09SDavid du Colombier 90*5c47fe09SDavid du Colombier /* display */ 91*5c47fe09SDavid du Colombier Pciscvga = 0, /* VGA */ 92*5c47fe09SDavid du Colombier Pciscxga = 1, /* XGA */ 93*5c47fe09SDavid du Colombier Pcisc3d = 2, /* 3D */ 94*5c47fe09SDavid du Colombier 95*5c47fe09SDavid du Colombier /* bridges */ 96*5c47fe09SDavid du Colombier Pcischostpci = 0, /* host/pci */ 97*5c47fe09SDavid du Colombier Pciscpcicpci = 1, /* pci/pci */ 98*5c47fe09SDavid du Colombier 99*5c47fe09SDavid du Colombier /* simple comms */ 100*5c47fe09SDavid du Colombier Pciscserial = 0, /* 16450, etc. */ 101*5c47fe09SDavid du Colombier Pciscmultiser = 1, /* multiport serial */ 102*5c47fe09SDavid du Colombier 103*5c47fe09SDavid du Colombier /* serial bus */ 104*5c47fe09SDavid du Colombier Pciscusb = 3, /* USB */ 105*5c47fe09SDavid du Colombier }; 106*5c47fe09SDavid du Colombier 107*5c47fe09SDavid du Colombier enum { /* type 0 pre-defined header */ 108*5c47fe09SDavid du Colombier PciCIS = 0x28, /* cardbus CIS pointer */ 109*5c47fe09SDavid du Colombier PciSVID = 0x2C, /* subsystem vendor ID */ 110*5c47fe09SDavid du Colombier PciSID = 0x2E, /* subsystem ID */ 111*5c47fe09SDavid du Colombier PciEBAR0 = 0x30, /* expansion ROM base address */ 112*5c47fe09SDavid du Colombier PciMGNT = 0x3E, /* burst period length */ 113*5c47fe09SDavid du Colombier PciMLT = 0x3F, /* maximum latency between bursts */ 114*5c47fe09SDavid du Colombier }; 115*5c47fe09SDavid du Colombier 116*5c47fe09SDavid du Colombier enum { /* type 1 pre-defined header */ 117*5c47fe09SDavid du Colombier PciPBN = 0x18, /* primary bus number */ 118*5c47fe09SDavid du Colombier PciSBN = 0x19, /* secondary bus number */ 119*5c47fe09SDavid du Colombier PciUBN = 0x1A, /* subordinate bus number */ 120*5c47fe09SDavid du Colombier PciSLTR = 0x1B, /* secondary latency timer */ 121*5c47fe09SDavid du Colombier PciIBR = 0x1C, /* I/O base */ 122*5c47fe09SDavid du Colombier PciILR = 0x1D, /* I/O limit */ 123*5c47fe09SDavid du Colombier PciSPSR = 0x1E, /* secondary status */ 124*5c47fe09SDavid du Colombier PciMBR = 0x20, /* memory base */ 125*5c47fe09SDavid du Colombier PciMLR = 0x22, /* memory limit */ 126*5c47fe09SDavid du Colombier PciPMBR = 0x24, /* prefetchable memory base */ 127*5c47fe09SDavid du Colombier PciPMLR = 0x26, /* prefetchable memory limit */ 128*5c47fe09SDavid du Colombier PciPUBR = 0x28, /* prefetchable base upper 32 bits */ 129*5c47fe09SDavid du Colombier PciPULR = 0x2C, /* prefetchable limit upper 32 bits */ 130*5c47fe09SDavid du Colombier PciIUBR = 0x30, /* I/O base upper 16 bits */ 131*5c47fe09SDavid du Colombier PciIULR = 0x32, /* I/O limit upper 16 bits */ 132*5c47fe09SDavid du Colombier PciEBAR1 = 0x28, /* expansion ROM base address */ 133*5c47fe09SDavid du Colombier PciBCR = 0x3E, /* bridge control register */ 134*5c47fe09SDavid du Colombier }; 135*5c47fe09SDavid du Colombier 136*5c47fe09SDavid du Colombier enum { /* type 2 pre-defined header */ 137*5c47fe09SDavid du Colombier PciCBExCA = 0x10, 138*5c47fe09SDavid du Colombier PciCBSPSR = 0x16, 139*5c47fe09SDavid du Colombier PciCBPBN = 0x18, /* primary bus number */ 140*5c47fe09SDavid du Colombier PciCBSBN = 0x19, /* secondary bus number */ 141*5c47fe09SDavid du Colombier PciCBUBN = 0x1A, /* subordinate bus number */ 142*5c47fe09SDavid du Colombier PciCBSLTR = 0x1B, /* secondary latency timer */ 143*5c47fe09SDavid du Colombier PciCBMBR0 = 0x1C, 144*5c47fe09SDavid du Colombier PciCBMLR0 = 0x20, 145*5c47fe09SDavid du Colombier PciCBMBR1 = 0x24, 146*5c47fe09SDavid du Colombier PciCBMLR1 = 0x28, 147*5c47fe09SDavid du Colombier PciCBIBR0 = 0x2C, /* I/O base */ 148*5c47fe09SDavid du Colombier PciCBILR0 = 0x30, /* I/O limit */ 149*5c47fe09SDavid du Colombier PciCBIBR1 = 0x34, /* I/O base */ 150*5c47fe09SDavid du Colombier PciCBILR1 = 0x38, /* I/O limit */ 151*5c47fe09SDavid du Colombier PciCBSVID = 0x40, /* subsystem vendor ID */ 152*5c47fe09SDavid du Colombier PciCBSID = 0x42, /* subsystem ID */ 153*5c47fe09SDavid du Colombier PciCBLMBAR = 0x44, /* legacy mode base address */ 154*5c47fe09SDavid du Colombier }; 155*5c47fe09SDavid du Colombier 156*5c47fe09SDavid du Colombier enum { 157*5c47fe09SDavid du Colombier /* bar bits */ 158*5c47fe09SDavid du Colombier Barioaddr = 1<<0, /* vs. memory addr */ 159*5c47fe09SDavid du Colombier Barwidthshift = 1, 160*5c47fe09SDavid du Colombier Barwidthmask = 3, 161*5c47fe09SDavid du Colombier Barwidth32 = 0, 162*5c47fe09SDavid du Colombier Barwidth64 = 2, 163*5c47fe09SDavid du Colombier Barprefetch = 1<<3, 164*5c47fe09SDavid du Colombier }; 165*5c47fe09SDavid du Colombier 166*5c47fe09SDavid du Colombier enum 167*5c47fe09SDavid du Colombier { /* command register */ 168*5c47fe09SDavid du Colombier IOen = (1<<0), 169*5c47fe09SDavid du Colombier MEMen = (1<<1), 170*5c47fe09SDavid du Colombier MASen = (1<<2), 171*5c47fe09SDavid du Colombier MemWrInv = (1<<4), 172*5c47fe09SDavid du Colombier PErrEn = (1<<6), 173*5c47fe09SDavid du Colombier SErrEn = (1<<8), 174*5c47fe09SDavid du Colombier }; 175*5c47fe09SDavid du Colombier 176*5c47fe09SDavid du Colombier /* capabilities */ 177*5c47fe09SDavid du Colombier enum { 178*5c47fe09SDavid du Colombier PciCapPMG = 0x01, /* power management */ 179*5c47fe09SDavid du Colombier PciCapAGP = 0x02, 180*5c47fe09SDavid du Colombier PciCapVPD = 0x03, /* vital product data */ 181*5c47fe09SDavid du Colombier PciCapSID = 0x04, /* slot id */ 182*5c47fe09SDavid du Colombier PciCapMSI = 0x05, 183*5c47fe09SDavid du Colombier PciCapCHS = 0x06, /* compact pci hot swap */ 184*5c47fe09SDavid du Colombier PciCapPCIX = 0x07, 185*5c47fe09SDavid du Colombier PciCapHTC = 0x08, /* hypertransport irq conf */ 186*5c47fe09SDavid du Colombier PciCapVND = 0x09, /* vendor specific information */ 187*5c47fe09SDavid du Colombier PciCapPCIe = 0x10, 188*5c47fe09SDavid du Colombier PciCapMSIX = 0x11, 189*5c47fe09SDavid du Colombier PciCapSATA = 0x12, 190*5c47fe09SDavid du Colombier PciCapHSW = 0x0c, /* hot swap */ 191*5c47fe09SDavid du Colombier }; 192*5c47fe09SDavid du Colombier 193*5c47fe09SDavid du Colombier typedef struct Pcidev Pcidev; 194*5c47fe09SDavid du Colombier struct Pcidev 195*5c47fe09SDavid du Colombier { 196*5c47fe09SDavid du Colombier int tbdf; /* type+bus+device+function */ 197*5c47fe09SDavid du Colombier ushort vid; /* vendor ID */ 198*5c47fe09SDavid du Colombier ushort did; /* device ID */ 199*5c47fe09SDavid du Colombier 200*5c47fe09SDavid du Colombier ushort pcr; 201*5c47fe09SDavid du Colombier 202*5c47fe09SDavid du Colombier uchar rid; 203*5c47fe09SDavid du Colombier uchar ccrp; 204*5c47fe09SDavid du Colombier uchar ccru; 205*5c47fe09SDavid du Colombier uchar ccrb; 206*5c47fe09SDavid du Colombier uchar cls; 207*5c47fe09SDavid du Colombier uchar ltr; 208*5c47fe09SDavid du Colombier 209*5c47fe09SDavid du Colombier struct { 210*5c47fe09SDavid du Colombier uintpci bar; /* base address */ 211*5c47fe09SDavid du Colombier int size; 212*5c47fe09SDavid du Colombier } mem[6]; 213*5c47fe09SDavid du Colombier 214*5c47fe09SDavid du Colombier uchar intl; /* interrupt line */ 215*5c47fe09SDavid du Colombier 216*5c47fe09SDavid du Colombier Pcidev* list; 217*5c47fe09SDavid du Colombier Pcidev* link; /* next device on this bno */ 218*5c47fe09SDavid du Colombier 219*5c47fe09SDavid du Colombier Pcidev* parent; /* up a bus */ 220*5c47fe09SDavid du Colombier Pcidev* bridge; /* down a bus */ 221*5c47fe09SDavid du Colombier 222*5c47fe09SDavid du Colombier int pmrb; /* power management register block */ 223*5c47fe09SDavid du Colombier 224*5c47fe09SDavid du Colombier struct { 225*5c47fe09SDavid du Colombier uintpci bar; 226*5c47fe09SDavid du Colombier int size; 227*5c47fe09SDavid du Colombier } ioa, mema; 228*5c47fe09SDavid du Colombier }; 229*5c47fe09SDavid du Colombier 230*5c47fe09SDavid du Colombier #define PCIWINDOW 0 231*5c47fe09SDavid du Colombier #define PCIWADDR(va) (PADDR(va)+PCIWINDOW) 232*5c47fe09SDavid du Colombier 233*5c47fe09SDavid du Colombier #pragma varargck type "T" int 234*5c47fe09SDavid du Colombier #pragma varargck type "T" uint 235*5c47fe09SDavid du Colombier 236*5c47fe09SDavid du Colombier void pcienable(Pcidev *); 237*5c47fe09SDavid du Colombier void pcidisable(Pcidev *); 238*5c47fe09SDavid du Colombier void pcisetbme(Pcidev* ); 239*5c47fe09SDavid du Colombier Pcidev* pcimatch(Pcidev* prev, int vid, int did); 240*5c47fe09SDavid du Colombier void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a); 241*5c47fe09SDavid du Colombier void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a); 242