00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <pci/pci.h>
00031 #include <sys/io.h>
00032 #include <ubixos/types.h>
00033 #include <lib/kprintf.h>
00034
00035 const struct {
00036 uInt8 baseClass;
00037 uInt8 subClass;
00038 uInt8 interface;
00039 const char* name;
00040 } pciClasses[] = {
00041 { 0x00, 0x00, 0x00, "Undefined" },
00042 { 0x00, 0x01, 0x00, "VGA" },
00043
00044 { 0x01, 0x00, 0x00, "SCSI" },
00045 { 0x01, 0x01, 0x00, "IDE" },
00046 { 0x01, 0x01, 0x8A, "IDE" },
00047 { 0x01, 0x02, 0x00, "Floppy" },
00048 { 0x01, 0x03, 0x00, "IPI" },
00049 { 0x01, 0x04, 0x00, "RAID" },
00050 { 0x01, 0x80, 0x00, "Other" },
00051
00052 { 0x02, 0x00, 0x00, "Ethernet" },
00053 { 0x02, 0x01, 0x00, "Token Ring" },
00054 { 0x02, 0x02, 0x00, "FDDI" },
00055 { 0x02, 0x03, 0x00, "ATM" },
00056 { 0x02, 0x04, 0x00, "ISDN" },
00057 { 0x02, 0x80, 0x00, "Other" },
00058
00059 { 0x03, 0x00, 0x00, "VGA" },
00060 { 0x03, 0x00, 0x01, "VGA+8514" },
00061 { 0x03, 0x01, 0x00, "XGA" },
00062 { 0x03, 0x02, 0x00, "3D" },
00063 { 0x03, 0x80, 0x00, "VGA Other" },
00064
00065 { 0x04, 0x00, 0x00, "Video" },
00066 { 0x04, 0x01, 0x00, "Audio" },
00067 { 0x04, 0x02, 0x00, "Telephony" },
00068 { 0x04, 0x80, 0x00, "Other" },
00069
00070 { 0x05, 0x00, 0x00, "RAM" },
00071 { 0x05, 0x01, 0x00, "Flash" },
00072 { 0x05, 0x80, 0x00, "Other" },
00073
00074 { 0x06, 0x00, 0x00, "PCI to HOST" },
00075 { 0x06, 0x01, 0x00, "PCI to ISA" },
00076 { 0x06, 0x02, 0x00, "PCI to EISA" },
00077 { 0x06, 0x03, 0x00, "PCI to MCA" },
00078 { 0x06, 0x04, 0x00, "PCI to PCI" },
00079 { 0x06, 0x04, 0x01, "PCI to PCI (Subtractive Decode)" },
00080 { 0x06, 0x05, 0x00, "PCI to PCMCIA" },
00081 { 0x06, 0x06, 0x00, "PCI to NuBUS" },
00082 { 0x06, 0x07, 0x00, "PCI to Cardbus" },
00083 { 0x06, 0x08, 0x00, "PCI to RACEway" },
00084 { 0x06, 0x09, 0x00, "PCI to PCI" },
00085 { 0x06, 0x0A, 0x00, "PCI to InfiBand" },
00086 { 0x06, 0x80, 0x00, "PCI to Other" },
00087
00088 { 0x07, 0x00, 0x00, "Serial" },
00089 { 0x07, 0x00, 0x01, "Serial - 16450" },
00090 { 0x07, 0x00, 0x02, "Serial - 16550" },
00091 { 0x07, 0x00, 0x03, "Serial - 16650" },
00092 { 0x07, 0x00, 0x04, "Serial - 16750" },
00093 { 0x07, 0x00, 0x05, "Serial - 16850" },
00094 { 0x07, 0x00, 0x06, "Serial - 16950" },
00095 { 0x07, 0x01, 0x00, "Parallel" },
00096 { 0x07, 0x01, 0x01, "Parallel - BiDir" },
00097 { 0x07, 0x01, 0x02, "Parallel - ECP" },
00098 { 0x07, 0x01, 0x03, "Parallel - IEEE1284" },
00099 { 0x07, 0x01, 0xFE, "Parallel - IEEE1284 Target" },
00100 { 0x07, 0x02, 0x00, "Multiport Serial" },
00101 { 0x07, 0x03, 0x00, "Hayes Compatible Modem" },
00102 { 0x07, 0x03, 0x01, "Hayes Compatible Modem, 16450" },
00103 { 0x07, 0x03, 0x02, "Hayes Compatible Modem, 16550" },
00104 { 0x07, 0x03, 0x03, "Hayes Compatible Modem, 16650" },
00105 { 0x07, 0x03, 0x04, "Hayes Compatible Modem, 16750" },
00106 { 0x07, 0x80, 0x00, "Other" },
00107
00108 { 0x08, 0x00, 0x00, "PIC" },
00109 { 0x08, 0x00, 0x01, "ISA PIC" },
00110 { 0x08, 0x00, 0x02, "EISA PIC" },
00111 { 0x08, 0x00, 0x10, "I/O APIC" },
00112 { 0x08, 0x00, 0x20, "I/O(x) APIC" },
00113 { 0x08, 0x01, 0x00, "DMA" },
00114 { 0x08, 0x01, 0x01, "ISA DMA" },
00115 { 0x08, 0x01, 0x02, "EISA DMA" },
00116 { 0x08, 0x02, 0x00, "Timer" },
00117 { 0x08, 0x02, 0x01, "ISA Timer" },
00118 { 0x08, 0x02, 0x02, "EISA Timer" },
00119 { 0x08, 0x03, 0x00, "RTC" },
00120 { 0x08, 0x03, 0x00, "ISA RTC" },
00121 { 0x08, 0x03, 0x00, "Hot-Plug" },
00122 { 0x08, 0x80, 0x00, "Other" },
00123
00124 { 0x09, 0x00, 0x00, "Keyboard" },
00125 { 0x09, 0x01, 0x00, "Pen" },
00126 { 0x09, 0x02, 0x00, "Mouse" },
00127 { 0x09, 0x03, 0x00, "Scanner" },
00128 { 0x09, 0x04, 0x00, "Game Port" },
00129 { 0x09, 0x80, 0x00, "Other" },
00130
00131 { 0x0a, 0x00, 0x00, "Generic" },
00132 { 0x0a, 0x80, 0x00, "Other" },
00133
00134 { 0x0b, 0x00, 0x00, "386" },
00135 { 0x0b, 0x01, 0x00, "486" },
00136 { 0x0b, 0x02, 0x00, "Pentium" },
00137 { 0x0b, 0x03, 0x00, "PentiumPro" },
00138 { 0x0b, 0x10, 0x00, "DEC Alpha" },
00139 { 0x0b, 0x20, 0x00, "PowerPC" },
00140 { 0x0b, 0x30, 0x00, "MIPS" },
00141 { 0x0b, 0x40, 0x00, "Coprocessor" },
00142 { 0x0b, 0x80, 0x00, "Other" },
00143
00144 { 0x0c, 0x00, 0x00, "FireWire" },
00145 { 0x0c, 0x00, 0x10, "OHCI FireWire" },
00146 { 0x0c, 0x01, 0x00, "Access.bus" },
00147 { 0x0c, 0x02, 0x00, "SSA" },
00148 { 0x0c, 0x03, 0x00, "USB (UHCI)" },
00149 { 0x0c, 0x03, 0x10, "USB (OHCI)" },
00150 { 0x0c, 0x03, 0x80, "USB" },
00151 { 0x0c, 0x03, 0xFE, "USB Device" },
00152 { 0x0c, 0x04, 0x00, "Fiber" },
00153 { 0x0c, 0x05, 0x00, "SMBus Controller" },
00154 { 0x0c, 0x06, 0x00, "InfiniBand" },
00155 { 0x0c, 0x80, 0x00, "Other" },
00156
00157 { 0x0d, 0x00, 0x00, "iRDA" },
00158 { 0x0d, 0x01, 0x00, "Consumer IR" },
00159 { 0x0d, 0x10, 0x00, "RF" },
00160 { 0x0d, 0x80, 0x00, "Other" },
00161
00162 { 0x0e, 0x00, 0x00, "I2O" },
00163 { 0x0e, 0x80, 0x00, "Other" },
00164
00165 { 0x0f, 0x01, 0x00, "TV" },
00166 { 0x0f, 0x02, 0x00, "Audio" },
00167 { 0x0f, 0x03, 0x00, "Voice" },
00168 { 0x0f, 0x04, 0x00, "Data" },
00169 { 0x0f, 0x80, 0x00, "Other" },
00170
00171 { 0x10, 0x00, 0x00, "Network" },
00172 { 0x10, 0x10, 0x00, "Entertainment" },
00173 { 0x10, 0x80, 0x00, "Other" },
00174
00175 { 0x11, 0x00, 0x00, "DPIO Modules" },
00176 { 0x11, 0x01, 0x00, "Performance Counters" },
00177 { 0x11, 0x10, 0x00, "Comm Sync, Time+Frequency Measurement" },
00178 { 0x11, 0x80, 0x00, "Other" },
00179
00180 };
00181
00182 uInt32 pciRead(int bus,int dev,int func,int reg,int bytes) {
00183 uInt16 base;
00184
00185 union {
00186 struct confadd c;
00187 uInt32 n;
00188 } u;
00189
00190 u.n = 0;
00191 u.c.enable = 1;
00192 u.c.rsvd = 0;
00193 u.c.bus = bus;
00194 u.c.dev = dev;
00195 u.c.func = func;
00196 u.c.reg = reg & 0xFC;
00197
00198 outportDWord(0xCF8, u.n);
00199
00200 base = 0xCFC + (reg & 0x03);
00201
00202 switch(bytes){
00203 case 1: return(inportByte(base));
00204 case 2: return(inportWord(base));
00205 case 4: return(inportDWord(base));
00206 default: return 0;
00207 }
00208 }
00209
00210 void pciWrite(int bus,int dev,int func,int reg,uInt32 v,int bytes) {
00211 uInt16 base;
00212
00213 union {
00214 struct confadd c;
00215 uInt32 n;
00216 } u;
00217
00218 u.n = 0;
00219 u.c.enable = 1;
00220 u.c.rsvd = 0;
00221 u.c.bus = bus;
00222 u.c.dev = dev;
00223 u.c.func = func;
00224 u.c.reg = reg & 0xFC;
00225
00226 base = 0xCFC + (reg & 0x03);
00227 outportDWord(0xCF8, u.n);
00228 switch(bytes){
00229 case 1: outportByte(base, (uInt8) v); break;
00230 case 2: outportWord(base, (uInt16) v); break;
00231 case 4: outportDWord(base, v); break;
00232 }
00233 }
00234
00235
00236 bool pciProbe(int bus, int dev, int func,struct pciConfig *cfg) {
00237 uInt32 *word = (uInt32 *) cfg;
00238 uInt32 v;
00239 int i;
00240 for(i=0;i<4;i++) {
00241 word[i] = pciRead(bus,dev,func,4*i,4);
00242 }
00243 if(cfg->vendorId == 0xffff) return FALSE;
00244 if(cfg->vendorId == 0x0) return FALSE;
00245
00246 cfg->bus = bus;
00247 cfg->dev = dev;
00248 cfg->func = func;
00249 cfg->subsysVendor = pciRead(bus, dev, func, 0x2c, 2);
00250 cfg->subsys = pciRead(bus, dev, func, 0x2e, 2);
00251 kprintf("Device Info: /bus/pci/%d/%d/%d\n",bus,dev,func);
00252 kprintf(" * Vendor: %X Device: %X Class/SubClass/Interface %X/%X/%X\n",cfg->vendorId,cfg->deviceId,cfg->baseClass,cfg->subClass,cfg->interface);
00253 kprintf(" * Status: %X Command: %X BIST/Type/Lat/CLS: %X/%X/%X/%X\n",cfg->status, cfg->command, cfg->bist, cfg->headerType,cfg->latencyTimer, cfg->cacheLineSize);
00254 switch(cfg->headerType & 0x7F){
00255 case 0:
00256 for(i=0;i<6;i++) {
00257 v = pciRead(bus,dev,func,i*4 + 0x10, 4);
00258 if(v) {
00259 int v2;
00260 pciWrite(bus,dev,func,i*4 + 0x10, 0xffffffff, 4);
00261 v2 = pciRead(bus,dev,func,i*4+0x10, 4) & 0xfffffff0;
00262 pciWrite(bus,dev,func,i*4 + 0x10, v, 4);
00263 v2 = 1 + ~v2;
00264 if(v & 1) {
00265 cfg->base[i] = v & 0xffff;
00266 cfg->size[i] = v2 & 0xffff;
00267 }
00268 else {
00269 cfg->base[i] = v;
00270 cfg->size[i] = v2;
00271 }
00272 }
00273 else {
00274 cfg->base[i] = 0;
00275 cfg->size[i] = 0;
00276 }
00277 }
00278 v = pciRead(bus,dev,func,0x3c,1);
00279 cfg->irq = (v == 0xff ? 0 : v);
00280 break;
00281 case 1:
00282 kprintf(" * PCI <-> PCI Bridge\n");
00283 break;
00284 default:
00285 kprintf(" * Unknown Header Type\n");
00286 break;
00287 }
00288
00289 return(TRUE);
00290 }
00291
00292 int pci_init() {
00293 uInt16 bus,dev,func;
00294 int i = 0x0;
00295 struct pciConfig pcfg;
00296 for (bus = 0x0; bus < 0x2; bus++) {
00297 for (dev = 0; dev < 32; dev++) {
00298 for (func = 0; func < 8; func++) {
00299 if (pciProbe(bus, dev, func, &pcfg) == TRUE) {
00300
00301 for (i=0x0;i<countof(pciClasses);i++) {
00302 if (pcfg.baseClass == pciClasses[i].baseClass && pcfg.subClass == pciClasses[i].subClass && pcfg.interface == pciClasses[i].interface) {
00303 kprintf("PCI Device: %s @ IRQ: 0x%X\n",pciClasses[i].name,pcfg.irq);
00304 break;
00305 }
00306 }
00307 }
00308 }
00309 }
00310 }
00311 return(0x0);
00312 }
00313
00314
00315