#include <const.h>
#include <errno.h>
#include <arch/i386.h>
#include <arch/mem.h>
#include <kernel/clock.h>
#include <kernel/console.h>
#include <kernel/keyboard.h>
#include <kernel/kmalloc.h>
#include <kernel/pci.h>
Go to the source code of this file.
Defines | |||||||||||||
| #define | PCI_CLASS_ENTRIES ( sizeof(classes)/sizeof(classes_t) ) | ||||||||||||
| The amount of supported PCI classes. | |||||||||||||
Functions | |||||||||||||
| uint32_t | pciRead (int bus, int dev, int func, int reg, int uint8_ts) | ||||||||||||
Read a configuration byte/word/dword from the PCI controller.
| |||||||||||||
| void | pciWrite (int bus, int dev, int func, int reg, uint32_t v, int uint8_ts) | ||||||||||||
Write a configuration byte/word/dword to the PCI controller.
| |||||||||||||
| uint8_t | pci_read_config_byte (int bus, int dev, int func, int reg) | ||||||||||||
Read a configuration byte from the PCI controller.
| |||||||||||||
| uint16_t | pci_read_config_word (int bus, int dev, int func, int reg) | ||||||||||||
Read a configuration word from the PCI controller.
| |||||||||||||
| uint32_t | pci_read_config_dword (int bus, int dev, int func, int reg) | ||||||||||||
Read a configuration double word from the PCI controller.
| |||||||||||||
| void | pci_write_config_byte (int bus, int dev, int func, int reg, uint8_t val) | ||||||||||||
Write a configuration byte to the PCI controller.
| |||||||||||||
| void | pci_write_config_word (int bus, int dev, int func, int reg, uint16_t val) | ||||||||||||
Write a configuration word to the PCI controller.
| |||||||||||||
| void | pci_write_config_dword (int bus, int dev, int func, int reg, uint32_t val) | ||||||||||||
Write a configuration double word to the PCI controller.
| |||||||||||||
| void | pci_read_irq (pci_cfg_t *cfg) | ||||||||||||
Read the IRQ line of the device if it is present.
| |||||||||||||
| uint32_t | pci_size (uint32_t base, unsigned long mask) | ||||||||||||
Calculate the size of an I/O space.
| |||||||||||||
| void | pci_read_bases (pci_cfg_t *cfg, int tot_bases, int rom) | ||||||||||||
Read the base addresses of the selected deivice.
| |||||||||||||
| bool | pci_probe (int bus, int dev, int func, pci_cfg_t *cfg) | ||||||||||||
Probe for a PCI device.
| |||||||||||||
| void | pci_set_master (pci_cfg_t *cfg) | ||||||||||||
Enable bus-mastering (aka 32-bit DMA) for a PCI device.
| |||||||||||||
| int | pci_find_capability (pci_cfg_t *cfg, int cap) | ||||||||||||
Tell if a device supports a given PCI capability.
| |||||||||||||
| int | pci_set_power_state (pci_cfg_t *cfg, int state) | ||||||||||||
Set a new power state for the device using the Power Management Capabilities.
| |||||||||||||
| int | pcibios_enable_device_io (pci_cfg_t *cfg) | ||||||||||||
Low level function to initialize a PCI device before it's used by a driver.
| |||||||||||||
| int | pci_enable_device (pci_cfg_t *cfg) | ||||||||||||
Initialize a PCI device before it's used by a driver.
| |||||||||||||
| bool | pci_find_cfg (pci_cfg_t *cfg, bool enable) | ||||||||||||
Look for a device in the PCI bus and eventually enable it.
| |||||||||||||
| void | pci_scan () | ||||||||||||
| Scan all the PCI buses, looking for devices. If a device is found it will be enabled. | |||||||||||||
Variables | |||||||||||||
| classes_t | classes [] | ||||||||||||
| PCI supported classes. It is used to recognize to what class a device belongs. | |||||||||||||
| unsigned int | pcibios_max_latency = 255 | ||||||||||||
| SiS 5597 and 5598 require latency timer set to at most 32 to avoid lockups; otherwise default value is 255. | |||||||||||||
Definition in file pci.c.
|
|
The amount of supported PCI classes.
|
|
|
Initialize a PCI device before it's used by a driver.
Definition at line 734 of file pci.c.
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 }
|
|
||||||||||||
|
Tell if a device supports a given PCI capability.
Definition at line 563 of file pci.c.
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 }
|
|
||||||||||||
|
Look for a device in the PCI bus and eventually enable it.
Definition at line 769 of file pci.c.
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 // Device found //
00789 memcpy(cfg, pcfg, sizeof(pci_cfg_t));
00790 // Enable the device if required //
00791 if (enable) pci_enable_device(pcfg);
00792 // Free the temporary structure //
00793 kfree(pcfg);
00794 return(TRUE);
00795 }
00796 }
00797 }
00798 // Device not found //
00799 kfree(pcfg);
00800 return(FALSE);
00801 }
|
|
||||||||||||||||||||
|
Probe for a PCI device.
Definition at line 467 of file pci.c.
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 // Setup the bus, device and function number //
00478 cfg->bus = bus;
00479 cfg->dev = dev;
00480 cfg->func = func;
00481
00482 // Set the power state to unknown //
00483 cfg->current_state = 4;
00484
00485 // Identify the type of the device //
00486 switch(cfg->header_type & 0x7F)
00487 {
00488 case PCI_HEADER_TYPE_NORMAL:
00489 // --- NORMAL DEVICE --- //
00490 // Read the IRQ line //
00491 pci_read_irq(cfg);
00492 // Read the base memory and I/O addresses //
00493 pci_read_bases(cfg, 6, PCI_ROM_ADDRESS);
00494 // Read subsysem vendor and subsystem device id //
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 // --- PCI <-> PCI BRIDGE --- //
00501 pci_read_bases(cfg, 2, PCI_ROM_ADDRESS_1);
00502 break;
00503
00504 case PCI_HEADER_TYPE_CARDBUS:
00505 // --- PCI CARDBUS --- //
00506 // Read the IRQ line //
00507 pci_read_irq(cfg);
00508 // Read the base memory and I/O addresses //
00509 pci_read_bases(cfg, 1, 0);
00510 // Read subsysem vendor and subsystem device id //
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 // --- UNKNOW HEADER TYPE --- //
00517 break;
00518 }
00519
00520 return(TRUE);
00521 }
|
|
||||||||||||||||
|
Read the base addresses of the selected deivice.
Definition at line 394 of file pci.c.
00395 {
00396 uint32_t l, sz, reg;
00397 int i;
00398
00399 // Clear all previous bases and sizes informations //
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 // Read informations about bases and sizes //
00405 for(i=0; i<tot_bases; i++)
00406 {
00407 // Read bases and size //
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 // Check if informations are valid //
00415 if (!sz || sz == 0xFFFFFFFF)
00416 continue;
00417 if (l == 0xFFFFFFFF)
00418 l = 0;
00419
00420 // Store informations //
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 // --- ROM --- //
00436 if (rom)
00437 {
00438 // Initialize values //
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 }
|
|
||||||||||||||||||||
|
Read a configuration byte from the PCI controller.
Definition at line 279 of file pci.c.
|
|
||||||||||||||||||||
|
Read a configuration double word from the PCI controller.
Definition at line 303 of file pci.c.
|
|
||||||||||||||||||||
|
Read a configuration word from the PCI controller.
Definition at line 291 of file pci.c.
|
|
|
Read the IRQ line of the device if it is present.
Definition at line 351 of file pci.c.
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 }
|
|
|
Scan all the PCI buses, looking for devices. If a device is found it will be enabled.
Definition at line 806 of file pci.c.
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 // kprintf("\n\rDo you want to enable this device (Y/N)? ");
00881 pci_enable_device(&pcfg);
00882 key = kgetchar();
00883 if ( key==CTRL_C ) return;
00884 /*
00885 key &= 0xFF;
00886 if ( key=='Y' || key=='y' )
00887 {
00888 putchar(key);
00889 pci_enable_device(&pcfg);
00890 }
00891 else
00892 putchar('N');
00893 */
00894 kprintf("\n\r");
00895 }
00896 }
00897 kprintf("\n\rPCI: finished\n\r");
00898 }
|
|
|
Enable bus-mastering (aka 32-bit DMA) for a PCI device.
Definition at line 529 of file pci.c.
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 // Check the latency time, because certain BIOSes forget to set //
00542 // it properly... //
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 }
|
|
||||||||||||
|
Set a new power state for the device using the Power Management Capabilities.
Definition at line 612 of file pci.c.
00613 {
00614 int pm;
00615 uint16_t pmcsr;
00616 uint16_t pmc;
00617
00618 // Bound the state to a valid range //
00619 if (state > 3) state = 3;
00620
00621 // Validate current state. //
00622 // Can enter D0 from any state, but we can't go deeper if we're //
00623 // in a low power state. //
00624 if (state > 0 && cfg->current_state > state)
00625 return(-EINVAL);
00626 else if (cfg->current_state == state)
00627 // we're already there //
00628 return(0);
00629
00630 // find PCI PM capability in list //
00631 pm = pci_find_capability(cfg, PCI_CAP_ID_PM);
00632
00633 // Abort if the device doesn't support PM capabilities //
00634 if (!pm) return(-EIO);
00635
00636 // Check if this device supports the desired state //
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 // If we're in D3, force entire word to 0. //
00647 // This doesn't affect PME_Status, disables PME_En, and //
00648 // sets PowerState to 0. //
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 // Enter specified state //
00659 pci_write_config_word(cfg->bus, cfg->dev, cfg->func, pm+PCI_PM_CTRL, pmcsr);
00660
00661 // Mandatory power management transition delays //
00662 // see PCI PM 1.1 5.6.1 table 18 //
00663 if( (state == 3) || (cfg->current_state == 3) )
00664 {
00665 // Set task state to interruptible //
00666 // LINUX do it so: //
00667 // set_current_state(TASK_UNINTERRUPTIBLE); //
00668 // schedule_timeout(HZ/100); //
00669 delay(HZ/100);
00670 }
00671 else if( (state == 2) || (cfg->current_state == 2) )
00672 // udelay(200);
00673 delay(200);
00674 cfg->current_state = state;
00675
00676 return(0);
00677 }
|
|
||||||||||||
|
Calculate the size of an I/O space.
Definition at line 371 of file pci.c.
00372 {
00373 // Find the significant bits //
00374 uint32_t size = mask & base;
00375 // Get the lowest of them to find the decode size //
00376 size = size & ~(size-1);
00377 // extent = size - 1 //
00378 return(size-1);
00379 }
|
|
||||||||||||||||||||||||
|
Write a configuration byte to the PCI controller.
Definition at line 317 of file pci.c.
|
|
||||||||||||||||||||||||
|
Write a configuration double word to the PCI controller.
Definition at line 341 of file pci.c.
|
|
||||||||||||||||||||||||
|
Write a configuration word to the PCI controller.
Definition at line 329 of file pci.c.
|
|
|
Low level function to initialize a PCI device before it's used by a driver.
Definition at line 687 of file pci.c.
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 // Command IO based //
00698 cmd |= PCI_COMMAND_IO;
00699
00700 if ( !(cmd & PCI_COMMAND_IO) )
00701 {
00702 // Device is not IO-based //
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 // Any PCI-to-PCI bridge must be enabled by setting //
00710 // both I/O space and memory space access bits in the //
00711 // command register. //
00712 cmd |= PCI_COMMAND_MEMORY;
00713 }
00714
00715 // Always enable bus master!!! //
00716 cmd |= PCI_COMMAND_MASTER;
00717
00718 if ( cmd!=old_cmd )
00719 {
00720 // Set the cache line and default latency (32) //
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 // Enable the appropriate bits in the PCI command register //
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 }
|
|
||||||||||||||||||||||||
|
Read a configuration byte/word/dword from the PCI controller.
Definition at line 198 of file pci.c.
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 }
|
|
||||||||||||||||||||||||||||
|
Write a configuration byte/word/dword to the PCI controller.
Definition at line 242 of file pci.c.
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 }
|
|
|
PCI supported classes. It is used to recognize to what class a device belongs.
|
|
|
SiS 5597 and 5598 require latency timer set to at most 32 to avoid lockups; otherwise default value is 255.
|
1.2.18