Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

pci.c File Reference

PCI bus driver. More...

#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.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
uint8_ts  The size of the read operation:
  • 1 = 8-bit;
  • 2 = 16-bit;
  • 4 = 32-bit.
Returns:
The byte/word/dword read from the controller.
Note:
Thanks to "The Mobius" operating system.


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.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
v  The value to write.
uint8_ts  The size of the write operation:
  • 1 = 8-bit;
  • 2 = 16-bit;
  • 4 = 32-bit.
Note:
Thanks to "The Mobius" operating system.


uint8_t pci_read_config_byte (int bus, int dev, int func, int reg)
 Read a configuration byte from the PCI controller.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
Returns:
The byte read from the controller.


uint16_t pci_read_config_word (int bus, int dev, int func, int reg)
 Read a configuration word from the PCI controller.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
Returns:
The word read from the controller.


uint32_t pci_read_config_dword (int bus, int dev, int func, int reg)
 Read a configuration double word from the PCI controller.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
Returns:
The dword read from the 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.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
val  The byte to write.


void pci_write_config_word (int bus, int dev, int func, int reg, uint16_t val)
 Write a configuration word to the PCI controller.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
val  The word to write.


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.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
val  The dword to write.


void pci_read_irq (pci_cfg_t *cfg)
 Read the IRQ line of the device if it is present.
Parameters:
cfg  The PCI device structure.
Note:
This routine sets up the pci_cfg_t::irq field.


uint32_t pci_size (uint32_t base, unsigned long mask)
 Calculate the size of an I/O space.
Parameters:
base  The size read from the controller.
mask  The address mask of the I/O space.
Returns:
The size of the given I/O space aligned by the mask.
Note:
For memory-based devices the size of an I/O space is the size of the memory-mapped buffer; for I/O based devices it is the maximum offset of the ports.


void pci_read_bases (pci_cfg_t *cfg, int tot_bases, int rom)
 Read the base addresses of the selected deivice.
Parameters:
cfg  The PCI device structure.
tot_bases  The amount of bases to read. Every PCI device has up to 6 base addresses (6 for normal devices, 2 for PCI to PCI bridges and only 1 for cardbuses).
rom  The ROM address register (from this register we can read the ROM base address and the ROM space size).
Note:
This routine sets up the pci_cfg_t::base field and the pci_cfg_t::rom_base field.


bool pci_probe (int bus, int dev, int func, pci_cfg_t *cfg)
 Probe for a PCI device.
Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
cfg  The PCI device structure.
Note:
This routine sets up the pci_cfg_t structure.
Returns:
  • TRUE if a device is present at the configuration (bus, dev, func);
  • FALSE the device is not present.


void pci_set_master (pci_cfg_t *cfg)
 Enable bus-mastering (aka 32-bit DMA) for a PCI device.
Parameters:
cfg  The PCI device structure.


int pci_find_capability (pci_cfg_t *cfg, int cap)
 Tell if a device supports a given PCI capability.
Parameters:
cfg  The PCI device structure.
cap  The given capability (see pci.h PCI_CAP_* for a complete list of supported capabilities).
Returns:
  • 0 if the capability is not supported;
  • otherwise it returns the position of the supported capability in the capability list of this device.


int pci_set_power_state (pci_cfg_t *cfg, int state)
 Set a new power state for the device using the Power Management Capabilities.
Parameters:
cfg  The PCI device structure.
state  The power state (from D0 to D3).
Returns:
  • 0 if we can successfully change the power state;
  • -EIO if the device doesn't support PCI Power Management;
  • -EINVAL if trying to enter to a state we're already in.


int pcibios_enable_device_io (pci_cfg_t *cfg)
 Low level function to initialize a PCI device before it's used by a driver.
Parameters:
cfg  The PCI device structure.
Note:
This is a low-level routine, so it is strongly recommended to do not use it externally. In this case you can use pci_enable_device() instead.


int pci_enable_device (pci_cfg_t *cfg)
 Initialize a PCI device before it's used by a driver.
Parameters:
cfg  The PCI device structure.


bool pci_find_cfg (pci_cfg_t *cfg, bool enable)
 Look for a device in the PCI bus and eventually enable it.
Parameters:
cfg  The PCI device configuration structure.
enable 
  • TRUE enable the device if present;
  • FALSE simply look for a device without enabling it.
Returns:
  • TRUE a device has been found;
  • FALSE device not found.


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.


Detailed Description

PCI bus driver.

Author:
Andrea Righi <drizzt@inwind.it>
Date:
Last update: 2003-11-09
Note:
Copyright (©) 2003 Andrea Righi

To make this driver I have gotten some information from "Linux" and "The Mobius" drivers. Thanks!
-Andrea Righi.

Definition in file pci.c.


Define Documentation

#define PCI_CLASS_ENTRIES   ( sizeof(classes)/sizeof(classes_t) )
 

The amount of supported PCI classes.

Definition at line 27 of file pci.c.


Function Documentation

int pci_enable_device pci_cfg_t   cfg
 

Initialize a PCI device before it's used by a driver.

Parameters:
cfg  The PCI device structure.

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 }

int pci_find_capability pci_cfg_t   cfg,
int    cap
 

Tell if a device supports a given PCI capability.

Parameters:
cfg  The PCI device structure.
cap  The given capability (see pci.h PCI_CAP_* for a complete list of supported capabilities).
Returns:
  • 0 if the capability is not supported;
  • otherwise it returns the position of the supported capability in the capability list of this device.

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 }

bool pci_find_cfg pci_cfg_t   cfg,
bool    enable
 

Look for a device in the PCI bus and eventually enable it.

Parameters:
cfg  The PCI device configuration structure.
enable 
  • TRUE enable the device if present;
  • FALSE simply look for a device without enabling it.
Returns:
  • TRUE a device has been found;
  • FALSE device not found.

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 }

bool pci_probe int    bus,
int    dev,
int    func,
pci_cfg_t   cfg
 

Probe for a PCI device.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
cfg  The PCI device structure.
Note:
This routine sets up the pci_cfg_t structure.
Returns:
  • TRUE if a device is present at the configuration (bus, dev, func);
  • FALSE the device is not present.

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 }

void pci_read_bases pci_cfg_t   cfg,
int    tot_bases,
int    rom
 

Read the base addresses of the selected deivice.

Parameters:
cfg  The PCI device structure.
tot_bases  The amount of bases to read. Every PCI device has up to 6 base addresses (6 for normal devices, 2 for PCI to PCI bridges and only 1 for cardbuses).
rom  The ROM address register (from this register we can read the ROM base address and the ROM space size).
Note:
This routine sets up the pci_cfg_t::base field and the pci_cfg_t::rom_base field.

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 }

uint8_t pci_read_config_byte int    bus,
int    dev,
int    func,
int    reg
 

Read a configuration byte from the PCI controller.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
Returns:
The byte read from the controller.

Definition at line 279 of file pci.c.

00280 {
00281         return ( pciRead(bus, dev, func, reg, sizeof(byte)) );
00282 }

uint32_t pci_read_config_dword int    bus,
int    dev,
int    func,
int    reg
 

Read a configuration double word from the PCI controller.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
Returns:
The dword read from the controller.

Definition at line 303 of file pci.c.

00304 {
00305         return ( pciRead(bus, dev, func, reg, sizeof(dword)) );
00306 }

uint16_t pci_read_config_word int    bus,
int    dev,
int    func,
int    reg
 

Read a configuration word from the PCI controller.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
Returns:
The word read from the controller.

Definition at line 291 of file pci.c.

00292 {
00293         return ( pciRead(bus, dev, func, reg, sizeof(word)) );
00294 }

void pci_read_irq pci_cfg_t   cfg
 

Read the IRQ line of the device if it is present.

Parameters:
cfg  The PCI device structure.
Note:
This routine sets up the pci_cfg_t::irq field.

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 }

void pci_scan  
 

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 }

void pci_set_master pci_cfg_t   cfg
 

Enable bus-mastering (aka 32-bit DMA) for a PCI device.

Parameters:
cfg  The PCI device structure.

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 }

int pci_set_power_state pci_cfg_t   cfg,
int    state
 

Set a new power state for the device using the Power Management Capabilities.

Parameters:
cfg  The PCI device structure.
state  The power state (from D0 to D3).
Returns:
  • 0 if we can successfully change the power state;
  • -EIO if the device doesn't support PCI Power Management;
  • -EINVAL if trying to enter to a state we're already in.

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 }

uint32_t pci_size uint32_t    base,
unsigned long    mask
 

Calculate the size of an I/O space.

Parameters:
base  The size read from the controller.
mask  The address mask of the I/O space.
Returns:
The size of the given I/O space aligned by the mask.
Note:
For memory-based devices the size of an I/O space is the size of the memory-mapped buffer; for I/O based devices it is the maximum offset of the ports.

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 }

void pci_write_config_byte int    bus,
int    dev,
int    func,
int    reg,
uint8_t    val
 

Write a configuration byte to the PCI controller.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
val  The byte to write.

Definition at line 317 of file pci.c.

00318 {
00319         pciWrite(bus, dev, func, reg, val, sizeof(byte));
00320 }

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.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
val  The dword to write.

Definition at line 341 of file pci.c.

00342 {
00343         pciWrite(bus, dev, func, reg, val, sizeof(dword));
00344 }

void pci_write_config_word int    bus,
int    dev,
int    func,
int    reg,
uint16_t    val
 

Write a configuration word to the PCI controller.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
val  The word to write.

Definition at line 329 of file pci.c.

00330 {
00331         pciWrite(bus, dev, func, reg, val, sizeof(word));
00332 }

int pcibios_enable_device_io pci_cfg_t   cfg
 

Low level function to initialize a PCI device before it's used by a driver.

Parameters:
cfg  The PCI device structure.
Note:
This is a low-level routine, so it is strongly recommended to do not use it externally. In this case you can use pci_enable_device() instead.

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 }

uint32_t pciRead int    bus,
int    dev,
int    func,
int    reg,
int    uint8_ts
 

Read a configuration byte/word/dword from the PCI controller.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
uint8_ts  The size of the read operation:
  • 1 = 8-bit;
  • 2 = 16-bit;
  • 4 = 32-bit.
Returns:
The byte/word/dword read from the controller.
Note:
Thanks to "The Mobius" operating system.

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 }

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.

Parameters:
bus  The bus number.
dev  The device number.
func  The function number.
reg  The PCI register.
v  The value to write.
uint8_ts  The size of the write operation:
  • 1 = 8-bit;
  • 2 = 16-bit;
  • 4 = 32-bit.
Note:
Thanks to "The Mobius" operating system.

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 }


Variable Documentation

classes_t classes[]
 

PCI supported classes. It is used to recognize to what class a device belongs.

Definition at line 31 of file pci.c.

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 at line 525 of file pci.c.


Generated on Fri Feb 20 15:32:19 2004 for Minirighi by doxygen1.2.18