00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <const.h>
00014 #include <errno.h>
00015
00016 #include <arch/i386.h>
00017 #include <arch/mem.h>
00018
00019 #include <kernel/clock.h>
00020 #include <kernel/console.h>
00021 #include <kernel/keyboard.h>
00022 #include <kernel/kmalloc.h>
00023
00024 #include <kernel/pci.h>
00025
00026
00027 #define PCI_CLASS_ENTRIES ( sizeof(classes)/sizeof(classes_t) )
00028
00029
00030
00031 classes_t classes[] =
00032 {
00033 { 0x00, 0x00, 0x00, "Undefined" },
00034 { 0x00, 0x01, 0x00, "VGA" },
00035
00036 { 0x01, 0x00, 0x00, "SCSI" },
00037 { 0x01, 0x01, 0x00, "IDE" },
00038 { 0x01, 0x01, 0x8A, "Controller IDE via Bus Master" },
00039 { 0x01, 0x02, 0x00, "Floppy" },
00040 { 0x01, 0x03, 0x00, "IPI" },
00041 { 0x01, 0x04, 0x00, "RAID" },
00042 { 0x01, 0x05, 0x20, "ATA (Single DMA)" },
00043 { 0x01, 0x05, 0x30, "ATA (Chained DMA)" },
00044 { 0x01, 0x80, 0x00, "Other" },
00045
00046 { 0x02, 0x00, 0x00, "Ethernet" },
00047 { 0x02, 0x01, 0x00, "Token Ring" },
00048 { 0x02, 0x02, 0x00, "FDDI" },
00049 { 0x02, 0x03, 0x00, "ATM" },
00050 { 0x02, 0x04, 0x00, "ISDN" },
00051 { 0x02, 0x05, 0x00, "WordFip" },
00052 { 0x02, 0x06, 0x00, "PICMG 2.14" },
00053 { 0x02, 0x80, 0x00, "Other" },
00054
00055 { 0x03, 0x00, 0x00, "VGA" },
00056 { 0x03, 0x00, 0x01, "VGA+8514" },
00057 { 0x03, 0x01, 0x00, "XGA" },
00058 { 0x03, 0x02, 0x00, "3D" },
00059 { 0x03, 0x80, 0x00, "Other" },
00060
00061 { 0x04, 0x00, 0x00, "Video" },
00062 { 0x04, 0x01, 0x00, "Audio" },
00063 { 0x04, 0x02, 0x00, "Telephony" },
00064 { 0x04, 0x80, 0x00, "Other" },
00065
00066 { 0x05, 0x00, 0x00, "RAM" },
00067 { 0x05, 0x01, 0x00, "Flash" },
00068 { 0x05, 0x80, 0x00, "Other" },
00069
00070 { 0x06, 0x00, 0x00, "PCI to HOST" },
00071 { 0x06, 0x01, 0x00, "PCI to ISA" },
00072 { 0x06, 0x02, 0x00, "PCI to EISA" },
00073 { 0x06, 0x03, 0x00, "PCI to MCA" },
00074 { 0x06, 0x04, 0x00, "PCI to PCI" },
00075 { 0x06, 0x04, 0x01, "PCI to PCI (Subtractive Decode)" },
00076 { 0x06, 0x05, 0x00, "PCI to PCMCIA" },
00077 { 0x06, 0x06, 0x00, "PCI to NuBUS" },
00078 { 0x06, 0x07, 0x00, "PCI to Cardbus" },
00079 { 0x06, 0x08, 0x00, "PCI to RACEway (Transparent)" },
00080 { 0x06, 0x08, 0x01, "PCI to RACEway (End-point)" },
00081 { 0x06, 0x09, 0x00, "PCI to PCI" },
00082 { 0x06, 0x09, 0x40, "PCI to PCI (Primary bus to host)" },
00083 { 0x06, 0x09, 0x80, "PCI to PCI (Secondary bus to host)" },
00084 { 0x06, 0x0A, 0x00, "PCI to InfiBand" },
00085 { 0x06, 0x80, 0x00, "PCI to Other" },
00086
00087 { 0x07, 0x00, 0x00, "Serial" },
00088 { 0x07, 0x00, 0x01, "Serial - 16450" },
00089 { 0x07, 0x00, 0x02, "Serial - 16550" },
00090 { 0x07, 0x00, 0x03, "Serial - 16650" },
00091 { 0x07, 0x00, 0x04, "Serial - 16750" },
00092 { 0x07, 0x00, 0x05, "Serial - 16850" },
00093 { 0x07, 0x00, 0x06, "Serial - 16950" },
00094 { 0x07, 0x01, 0x00, "Parallel" },
00095 { 0x07, 0x01, 0x01, "Parallel - BiDir" },
00096 { 0x07, 0x01, 0x02, "Parallel - ECP" },
00097 { 0x07, 0x01, 0x03, "Parallel - IEEE1284" },
00098 { 0x07, 0x01, 0xFE, "Parallel - IEEE1284 Target" },
00099 { 0x07, 0x02, 0x00, "Multiport Serial" },
00100 { 0x07, 0x03, 0x00, "Hayes Compatible Modem" },
00101 { 0x07, 0x03, 0x01, "Hayes Compatible Modem, 16450" },
00102 { 0x07, 0x03, 0x02, "Hayes Compatible Modem, 16550" },
00103 { 0x07, 0x03, 0x03, "Hayes Compatible Modem, 16650" },
00104 { 0x07, 0x03, 0x04, "Hayes Compatible Modem, 16750" },
00105 { 0x07, 0x80, 0x00, "Other" },
00106
00107 { 0x08, 0x00, 0x00, "PIC" },
00108 { 0x08, 0x00, 0x01, "ISA PIC" },
00109 { 0x08, 0x00, 0x02, "EISA PIC" },
00110 { 0x08, 0x00, 0x10, "I/O APIC" },
00111 { 0x08, 0x00, 0x20, "I/O(x) APIC" },
00112 { 0x08, 0x01, 0x00, "DMA" },
00113 { 0x08, 0x01, 0x01, "ISA DMA" },
00114 { 0x08, 0x01, 0x02, "EISA DMA" },
00115 { 0x08, 0x02, 0x00, "Timer" },
00116 { 0x08, 0x02, 0x01, "ISA Timer" },
00117 { 0x08, 0x02, 0x02, "EISA Timer" },
00118 { 0x08, 0x03, 0x00, "RTC" },
00119 { 0x08, 0x03, 0x01, "ISA RTC" },
00120 { 0x08, 0x04, 0x00, "Hot-Plug" },
00121 { 0x08, 0x80, 0x00, "Other" },
00122
00123 { 0x09, 0x00, 0x00, "Keyboard" },
00124 { 0x09, 0x01, 0x00, "Pen" },
00125 { 0x09, 0x02, 0x00, "Mouse" },
00126 { 0x09, 0x03, 0x00, "Scanner" },
00127 { 0x09, 0x04, 0x00, "Game Port" },
00128 { 0x09, 0x04, 0x10, "Game Port (Legacy)" },
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, 0x20, "USB (EHCI)" },
00151 { 0x0c, 0x03, 0x80, "USB" },
00152 { 0x0c, 0x03, 0xFE, "USB Device" },
00153 { 0x0c, 0x04, 0x00, "Fiber" },
00154 { 0x0c, 0x05, 0x00, "SMBus Controller" },
00155 { 0x0c, 0x06, 0x00, "InfiniBand" },
00156 { 0x0c, 0x80, 0x00, "Other" },
00157
00158 { 0x0d, 0x00, 0x00, "iRDA" },
00159 { 0x0d, 0x01, 0x00, "Consumer IR" },
00160 { 0x0d, 0x10, 0x00, "RF" },
00161 { 0x0d, 0x80, 0x00, "Other" },
00162
00163 { 0x0e, 0x00, 0x00, "I2O" },
00164 { 0x0e, 0x80, 0x00, "Other" },
00165
00166 { 0x0f, 0x01, 0x00, "TV" },
00167 { 0x0f, 0x02, 0x00, "Audio" },
00168 { 0x0f, 0x03, 0x00, "Voice" },
00169 { 0x0f, 0x04, 0x00, "Data" },
00170 { 0x0f, 0x80, 0x00, "Other" },
00171
00172 { 0x10, 0x00, 0x00, "Network" },
00173 { 0x10, 0x10, 0x00, "Entertainment" },
00174 { 0x10, 0x80, 0x00, "Other" },
00175
00176 { 0x11, 0x00, 0x00, "DPIO Modules" },
00177 { 0x11, 0x01, 0x00, "Performance Counters" },
00178 { 0x11, 0x10, 0x00, "Comm Sync, Time+Frequency Measurement" },
00179 { 0x11, 0x20, 0x00, "Management Card" },
00180 { 0x11, 0x80, 0x00, "Other" },
00181 };
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 uint32_t pciRead(int bus, int dev, int func, int reg, int uint8_ts)
00199 {
00200 uint16_t base;
00201
00202 union {
00203 confadd_t c;
00204 uint32_t n;
00205 } u;
00206
00207 u.n = 0;
00208 u.c.enable = 1;
00209 u.c.rsvd = 0;
00210 u.c.bus = bus;
00211 u.c.dev = dev;
00212 u.c.func = func;
00213 u.c.reg = reg & 0xFC;
00214
00215 out32(0xCF8, u.n);
00216 base = 0xCFC + (reg & 0x03);
00217
00218 switch(uint8_ts)
00219 {
00220 case 1: return in(base);
00221 case 2: return in16(base);
00222 case 4: return in32(base);
00223 default: return 0;
00224 }
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 void pciWrite(int bus, int dev, int func, int reg, uint32_t v, int uint8_ts)
00243 {
00244 uint16_t base;
00245
00246 union {
00247 confadd_t c;
00248 uint32_t n;
00249 } u;
00250
00251 u.n = 0;
00252 u.c.enable = 1;
00253 u.c.rsvd = 0;
00254 u.c.bus = bus;
00255 u.c.dev = dev;
00256 u.c.func = func;
00257 u.c.reg = reg & 0xFC;
00258
00259 base = 0xCFC + (reg & 0x03);
00260 out32(0xCF8, u.n);
00261
00262 switch(uint8_ts)
00263 {
00264 case 1: out(base, (uint8_t) v); break;
00265 case 2: out16(base, (uint16_t) v); break;
00266 case 4: out32(base, v); break;
00267 }
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 uint8_t pci_read_config_byte(int bus, int dev, int func, int reg)
00280 {
00281 return ( pciRead(bus, dev, func, reg, sizeof(byte)) );
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291 uint16_t pci_read_config_word(int bus, int dev, int func, int reg)
00292 {
00293 return ( pciRead(bus, dev, func, reg, sizeof(word)) );
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 uint32_t pci_read_config_dword(int bus, int dev, int func, int reg)
00304 {
00305 return ( pciRead(bus, dev, func, reg, sizeof(dword)) );
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 void pci_write_config_byte(int bus, int dev, int func, int reg, uint8_t val)
00318 {
00319 pciWrite(bus, dev, func, reg, val, sizeof(byte));
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329 void pci_write_config_word(int bus, int dev, int func, int reg, uint16_t val)
00330 {
00331 pciWrite(bus, dev, func, reg, val, sizeof(word));
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 void pci_write_config_dword(int bus, int dev, int func, int reg, uint32_t val)
00342 {
00343 pciWrite(bus, dev, func, reg, val, sizeof(dword));
00344 }
00345
00346
00347
00348
00349
00350
00351 void pci_read_irq(pci_cfg_t *cfg)
00352 {
00353 unsigned char irq;
00354
00355 irq = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, PCI_INTERRUPT_PIN);
00356 if (irq)
00357 irq = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, PCI_INTERRUPT_LINE);
00358
00359 cfg->irq = irq;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 uint32_t pci_size(uint32_t base, unsigned long mask)
00372 {
00373
00374 uint32_t size = mask & base;
00375
00376 size = size & ~(size-1);
00377
00378 return(size-1);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 void pci_read_bases(pci_cfg_t *cfg, int tot_bases, int rom)
00395 {
00396 uint32_t l, sz, reg;
00397 int i;
00398
00399
00400 memset(cfg->base, 0, sizeof(cfg->base));
00401 memset(cfg->size, 0, sizeof(cfg->size));
00402 memset(cfg->type, 0, sizeof(cfg->type));
00403
00404
00405 for(i=0; i<tot_bases; i++)
00406 {
00407
00408 reg = PCI_BASE_ADDRESS_0 + (i << 2);
00409 l = pci_read_config_dword(cfg->bus, cfg->dev, cfg->func, reg);
00410 pci_write_config_dword(cfg->bus, cfg->dev, cfg->func, reg, ~0);
00411 sz = pci_read_config_dword(cfg->bus, cfg->dev, cfg->func, reg);
00412 pci_write_config_dword(cfg->bus, cfg->dev, cfg->func, reg, l);
00413
00414
00415 if (!sz || sz == 0xFFFFFFFF)
00416 continue;
00417 if (l == 0xFFFFFFFF)
00418 l = 0;
00419
00420
00421 if ( (l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY )
00422 {
00423 cfg->base[i] = l & PCI_BASE_ADDRESS_MEM_MASK;
00424 cfg->size[i] = pci_size(sz, PCI_BASE_ADDRESS_MEM_MASK);
00425 cfg->type[i] = PCI_IO_RESOURCE_MEM;
00426 }
00427 else
00428 {
00429 cfg->base[i] = l & PCI_BASE_ADDRESS_IO_MASK;
00430 cfg->size[i] = pci_size(sz, PCI_BASE_ADDRESS_IO_MASK);
00431 cfg->type[i] = PCI_IO_RESOURCE_IO;
00432 }
00433 }
00434
00435
00436 if (rom)
00437 {
00438
00439 cfg->rom_base = 0;
00440 cfg->rom_size = 0;
00441
00442 l = pci_read_config_dword(cfg->bus, cfg->dev, cfg->func, rom);
00443 pci_write_config_dword(cfg->bus, cfg->dev, cfg->func, rom, ~PCI_ROM_ADDRESS_ENABLE);
00444 sz = pci_read_config_dword(cfg->bus, cfg->dev, cfg->func, rom);
00445 pci_write_config_dword(cfg->bus, cfg->dev, cfg->func, rom, l);
00446 if (l == 0xFFFFFFFF)
00447 l = 0;
00448 if (sz && sz != 0xFFFFFFFF)
00449 {
00450 cfg->rom_base = l & PCI_ROM_ADDRESS_MASK;
00451 sz = pci_size(sz, PCI_ROM_ADDRESS_MASK);
00452 cfg->rom_size = cfg->rom_size + (unsigned long)sz;
00453 }
00454 }
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 bool pci_probe(int bus, int dev, int func, pci_cfg_t *cfg)
00468 {
00469 uint32_t *temp = (uint32_t *) cfg;
00470 int i;
00471
00472 for(i=0; i<4; i++)
00473 temp[i] = pci_read_config_dword(bus, dev, func, (i << 2));
00474
00475 if(cfg->vendor_id == 0xFFFF) return FALSE;
00476
00477
00478 cfg->bus = bus;
00479 cfg->dev = dev;
00480 cfg->func = func;
00481
00482
00483 cfg->current_state = 4;
00484
00485
00486 switch(cfg->header_type & 0x7F)
00487 {
00488 case PCI_HEADER_TYPE_NORMAL:
00489
00490
00491 pci_read_irq(cfg);
00492
00493 pci_read_bases(cfg, 6, PCI_ROM_ADDRESS);
00494
00495 cfg->subsys_vendor = pci_read_config_word(bus, dev, func, PCI_SUBSYSTEM_VENDOR_ID);
00496 cfg->subsys_device = pci_read_config_word(bus, dev, func, PCI_SUBSYSTEM_ID);
00497 break;
00498
00499 case PCI_HEADER_TYPE_BRIDGE:
00500
00501 pci_read_bases(cfg, 2, PCI_ROM_ADDRESS_1);
00502 break;
00503
00504 case PCI_HEADER_TYPE_CARDBUS:
00505
00506
00507 pci_read_irq(cfg);
00508
00509 pci_read_bases(cfg, 1, 0);
00510
00511 cfg->subsys_vendor = pci_read_config_word(bus, dev, func, PCI_CB_SUBSYSTEM_VENDOR_ID);
00512 cfg->subsys_device = pci_read_config_word(bus, dev, func, PCI_CB_SUBSYSTEM_ID);
00513 break;
00514
00515 default:
00516
00517 break;
00518 }
00519
00520 return(TRUE);
00521 }
00522
00523
00524
00525 unsigned int pcibios_max_latency=255;
00526
00527
00528
00529 void pci_set_master(pci_cfg_t *cfg)
00530 {
00531 uint16_t cmd;
00532 uint8_t lat;
00533
00534 cmd = pci_read_config_word(cfg->bus, cfg->dev, cfg->func, PCI_COMMAND);
00535 if ( !(cmd & PCI_COMMAND_MASTER) )
00536 {
00537 kprintf("PCI: Enabling bus mastering for device in slot %d:%d:%d\n", cfg->bus, cfg->dev, cfg->func);
00538 cmd |= PCI_COMMAND_MASTER;
00539 pci_write_config_word(cfg->bus, cfg->dev, cfg->func, PCI_COMMAND, cmd);
00540 }
00541
00542
00543 lat = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, PCI_LATENCY_TIMER);
00544 if ( lat < 16 )
00545 lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
00546 else if ( lat > pcibios_max_latency )
00547 lat = pcibios_max_latency;
00548 else
00549 return;
00550 kprintf("PCI: Setting latency timer of device %d:%d:%d to %u\n", cfg->bus, cfg->dev, cfg->func, lat);
00551 pci_write_config_byte(cfg->bus, cfg->dev, cfg->func, PCI_LATENCY_TIMER, lat);
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 int pci_find_capability(pci_cfg_t *cfg, int cap)
00564 {
00565 uint16_t status;
00566 uint8_t pos, id;
00567 int ttl = 48;
00568
00569 status = pci_read_config_word(cfg->bus, cfg->dev, cfg->func, PCI_STATUS);
00570 if ( !(status & PCI_STATUS_CAP_LIST) )
00571 return(0);
00572
00573 switch (cfg->header_type & 0x7F)
00574 {
00575 case PCI_HEADER_TYPE_NORMAL:
00576 case PCI_HEADER_TYPE_BRIDGE:
00577 pos = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, PCI_CAPABILITY_LIST);
00578 break;
00579
00580 case PCI_HEADER_TYPE_CARDBUS:
00581 pos = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, PCI_CB_CAPABILITY_LIST);
00582 break;
00583
00584 default:
00585 return(0);
00586 break;
00587 }
00588
00589 while (ttl-- && pos>=0x40)
00590 {
00591 pos &= ~3;
00592 id = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, pos+PCI_CAP_LIST_ID);
00593 if (id == 0xff)
00594 break;
00595 if (id == cap)
00596 return(pos);
00597 pos = pci_read_config_byte(cfg->bus, cfg->dev, cfg->func, pos+PCI_CAP_LIST_NEXT);
00598 }
00599 return(0);
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 int pci_set_power_state(pci_cfg_t *cfg, int state)
00613 {
00614 int pm;
00615 uint16_t pmcsr;
00616 uint16_t pmc;
00617
00618
00619 if (state > 3) state = 3;
00620
00621
00622
00623
00624 if (state > 0 && cfg->current_state > state)
00625 return(-EINVAL);
00626 else if (cfg->current_state == state)
00627
00628 return(0);
00629
00630
00631 pm = pci_find_capability(cfg, PCI_CAP_ID_PM);
00632
00633
00634 if (!pm) return(-EIO);
00635
00636
00637 if (state == 1 || state == 2)
00638 {
00639 pmc = pci_read_config_word(cfg->bus, cfg->dev, cfg->func, pm+PCI_PM_PMC);
00640 if ( (state == 1 && !(pmc & PCI_PM_CAP_D1)) )
00641 return(-EIO);
00642 else if ( (state == 2 && !(pmc & PCI_PM_CAP_D2)) )
00643 return(-EIO);
00644 }
00645
00646
00647
00648
00649 if ( cfg->current_state>=3 )
00650 pmcsr = 0;
00651 else
00652 {
00653 pmcsr = pci_read_config_word(cfg->bus, cfg->dev, cfg->func, pm+PCI_PM_CTRL);
00654 pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
00655 pmcsr |= state;
00656 }
00657
00658
00659 pci_write_config_word(cfg->bus, cfg->dev, cfg->func, pm+PCI_PM_CTRL, pmcsr);
00660
00661
00662
00663 if( (state == 3) || (cfg->current_state == 3) )
00664 {
00665
00666
00667
00668
00669 delay(HZ/100);
00670 }
00671 else if( (state == 2) || (cfg->current_state == 2) )
00672
00673 delay(200);
00674 cfg->current_state = state;
00675
00676 return(0);
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 int pcibios_enable_device_io(pci_cfg_t *cfg)
00688 {
00689 uint16_t cmd, old_cmd;
00690 int i;
00691
00692 kprintf("\n\rLow level enabling PCI device %d:%d:%d... ", cfg->bus, cfg->dev, cfg->func);
00693
00694 old_cmd = cmd = pci_read_config_word(cfg->bus, cfg->dev, cfg->func, PCI_COMMAND);
00695 for (i=0; i<sizeof(cfg->type); i++)
00696 if (cfg->type[i] == PCI_IO_RESOURCE_IO)
00697
00698 cmd |= PCI_COMMAND_IO;
00699
00700 if ( !(cmd & PCI_COMMAND_IO) )
00701 {
00702
00703 kprintf("\n\rDevice is not IO-based!!!");
00704 return(-EINVAL);
00705 }
00706
00707 if ( (cfg->header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE )
00708 {
00709
00710
00711
00712 cmd |= PCI_COMMAND_MEMORY;
00713 }
00714
00715
00716 cmd |= PCI_COMMAND_MASTER;
00717
00718 if ( cmd!=old_cmd )
00719 {
00720
00721 pci_write_config_word(cfg->bus, cfg->dev, cfg->func,
00722 PCI_CACHE_LINE_SIZE, (32 << 8) | (L1_CACHE_BYTES / sizeof(uint32_t)));
00723
00724 pci_write_config_word(cfg->bus, cfg->dev, cfg->func, PCI_COMMAND, cmd);
00725 kprintf("OK!");
00726 }
00727 else
00728 kprintf("Already enabled.");
00729 return(0);
00730 }
00731
00732
00733
00734 int pci_enable_device(pci_cfg_t *cfg)
00735 {
00736 int err, pm;
00737
00738 kprintf("\n\rPowering on PCI device %d:%d:%d... ", cfg->bus, cfg->dev, cfg->func);
00739 pm = pci_set_power_state(cfg, 0);
00740 switch( pm )
00741 {
00742 case 0:
00743 kprintf("OK!");
00744 break;
00745
00746 case (-EIO):
00747 kprintf("\n\rDevice doesn't support Power Management Capabilities!!!");
00748 break;
00749
00750 case (-EINVAL):
00751 kprintf("\n\rDevice is already in this power state.");
00752 break;
00753 }
00754
00755 if ((err = pcibios_enable_device_io(cfg)) < 0)
00756 return(err);
00757 return(0);
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 bool pci_find_cfg(pci_cfg_t *cfg, bool enable)
00770 {
00771 uint16_t bus, dev, func;
00772 pci_cfg_t *pcfg;
00773
00774 pcfg = kmalloc( sizeof(pci_cfg_t) );
00775
00776 for (bus=0; bus<4; bus++)
00777 for (dev=0; dev<32; dev++)
00778 for (func=0; func<8; func++)
00779 {
00780 if ( pci_probe(bus, dev, func, pcfg) )
00781 {
00782 if (
00783 cfg->base_class == pcfg->base_class &&
00784 cfg->sub_class == pcfg->sub_class &&
00785 cfg->interface == pcfg->interface
00786 )
00787 {
00788
00789 memcpy(cfg, pcfg, sizeof(pci_cfg_t));
00790
00791 if (enable) pci_enable_device(pcfg);
00792
00793 kfree(pcfg);
00794 return(TRUE);
00795 }
00796 }
00797 }
00798
00799 kfree(pcfg);
00800 return(FALSE);
00801 }
00802
00803
00804
00805
00806 void pci_scan()
00807 {
00808 uint16_t bus, dev, func;
00809 pci_cfg_t pcfg;
00810 int i, key;
00811
00812 for (bus=0; bus<4; bus++)
00813 for (dev = 0; dev < 32; dev++)
00814 for (func = 0; func < 8; func++)
00815 {
00816 if ( pci_probe(bus, dev, func, &pcfg) )
00817 {
00818 set_color(WHITE);
00819 kprintf("\n\rPCI:%u:%u:%u", bus, dev, func);
00820 set_color(DEFAULT_COLOR);
00821
00822 kprintf( "\n\rVendor :%04X Device :%04X"
00823 "\n\rSubSys_Vendor:%04X SubSys_Device:%04X",
00824 pcfg.vendor_id, pcfg.device_id, pcfg.subsys_vendor, pcfg.subsys_device);
00825 kprintf( "\n\rBase_Class :%02X Sub_Class :%02X Interface :%02X",
00826 pcfg.base_class, pcfg.sub_class, pcfg.interface);
00827
00828 for (i=0;; i++)
00829 {
00830 if ( i>=PCI_CLASS_ENTRIES )
00831 {
00832 kprintf("\n\r* Description : Unknown device!");
00833 break;
00834 }
00835 if
00836 (
00837 (classes[i].base_class == pcfg.base_class) &&
00838 (classes[i].sub_class == pcfg.sub_class) &&
00839 (classes[i].interface == pcfg.interface)
00840 )
00841 {
00842 kprintf("\n\r* Description : %s", classes[i].name);
00843 break;
00844 }
00845 }
00846
00847 for (i=0; i<6; i++)
00848 if (pcfg.base[i])
00849 {
00850 if (pcfg.type[i] == PCI_IO_RESOURCE_IO)
00851 kprintf("\n\r* Base Register %d IO: %#06x (%#06x)",
00852 i, pcfg.base[i], pcfg.size[i]);
00853 else
00854 kprintf("\n\r* Base Register %d MM: %#010x (%#010x)",
00855 i, pcfg.base[i] & 0xfffffff0, pcfg.size[i]);
00856 }
00857 if (pcfg.rom_base)
00858 kprintf("\n\r* Base Register ROM : %#010x (%#010x)",
00859 pcfg.rom_base, pcfg.rom_size);
00860
00861 if (pcfg.irq)
00862 kprintf("\n\r* Interrupt line: %u", pcfg.irq);
00863
00864
00865 switch(pcfg.header_type & 0x7F)
00866 {
00867 case PCI_HEADER_TYPE_NORMAL:
00868 kprintf("\n\r* Normal device");
00869 break;
00870
00871 case PCI_HEADER_TYPE_BRIDGE:
00872 kprintf("\n\r* PCI <-> PCI bridge");
00873 break;
00874
00875 default:
00876 kprintf("\n\r* Unknown header type");
00877 break;
00878 }
00879
00880
00881 pci_enable_device(&pcfg);
00882 key = kgetchar();
00883 if ( key==CTRL_C ) return;
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 kprintf("\n\r");
00895 }
00896 }
00897 kprintf("\n\rPCI: finished\n\r");
00898 }