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

pci.c

Go to the documentation of this file.
00001 /*!     \file drivers/pci/pci.c
00002  *      \brief PCI bus driver.
00003  *      \author Andrea Righi <drizzt@inwind.it>
00004  *      \date Last update: 2003-11-09
00005  *      \note Copyright (&copy;) 2003 Andrea Righi
00006  *
00007  *      \n
00008  *      To make this driver I have gotten some information from
00009  *      "Linux" and "The Mobius" drivers. Thanks!\n
00010  *      -Andrea Righi.
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 //! The amount of supported PCI classes.
00027 #define PCI_CLASS_ENTRIES       ( sizeof(classes)/sizeof(classes_t) )
00028 
00029 //! PCI supported classes. It is used to recognize to what
00030 //! class a device belongs.
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 //! \brief
00184 //!     Read a configuration byte/word/dword from the PCI
00185 //!     controller.
00186 //! \param bus The bus number.
00187 //! \param dev The device number.
00188 //! \param func The function number.
00189 //! \param reg The PCI register.
00190 //! \param uint8_ts
00191 //!     The size of the read operation:
00192 //!     \li 1 = 8-bit;
00193 //!     \li 2 = 16-bit;
00194 //!     \li 4 = 32-bit.
00195 //! \return The byte/word/dword read from the controller.
00196 //! \note
00197 //!     Thanks to "The Mobius" operating system.
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 //! \brief
00228 //!     Write a configuration byte/word/dword to the PCI
00229 //!     controller.
00230 //! \param bus The bus number.
00231 //! \param dev The device number.
00232 //! \param func The function number.
00233 //! \param reg The PCI register.
00234 //! \param v The value to write.
00235 //! \param uint8_ts
00236 //!     The size of the write operation:
00237 //!     \li 1 = 8-bit;
00238 //!     \li 2 = 16-bit;
00239 //!     \li 4 = 32-bit.
00240 //! \note
00241 //!     Thanks to "The Mobius" operating system.
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 // --- PCI read functions --------------------------------------------- //
00271 
00272 //! \brief
00273 //!     Read a configuration byte from the PCI controller.
00274 //! \param bus The bus number.
00275 //! \param dev The device number.
00276 //! \param func The function number.
00277 //! \param reg The PCI register.
00278 //! \return The byte read from the controller.
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 //! \brief
00285 //!     Read a configuration word from the PCI controller.
00286 //! \param bus The bus number.
00287 //! \param dev The device number.
00288 //! \param func The function number.
00289 //! \param reg The PCI register.
00290 //! \return The word read from the controller.
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 //! \brief
00297 //!     Read a configuration double word from the PCI controller.
00298 //! \param bus The bus number.
00299 //! \param dev The device number.
00300 //! \param func The function number.
00301 //! \param reg The PCI register.
00302 //! \return The dword read from the controller.
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 // --- PCI write functions -------------------------------------------- //
00309 
00310 //! \brief
00311 //!     Write a configuration byte to the PCI controller.
00312 //! \param bus The bus number.
00313 //! \param dev The device number.
00314 //! \param func The function number.
00315 //! \param reg The PCI register.
00316 //! \param val The byte to write.
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 //! \brief
00323 //!     Write a configuration word to the PCI controller.
00324 //! \param bus The bus number.
00325 //! \param dev The device number.
00326 //! \param func The function number.
00327 //! \param reg The PCI register.
00328 //! \param val The word to write.
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 //! \brief
00335 //!     Write a configuration double word to the PCI controller.
00336 //! \param bus The bus number.
00337 //! \param dev The device number.
00338 //! \param func The function number.
00339 //! \param reg The PCI register.
00340 //! \param val The dword to write.
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 // --- PCI utility functions ------------------------------------------ //
00347 
00348 //! \brief Read the IRQ line of the device if it is present.
00349 //! \param cfg The PCI device structure.
00350 //! \note This routine sets up the pci_cfg_t::irq field.
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 //! \brief Calculate the size of an I/O space.
00363 //! \param base The size read from the controller.
00364 //! \param mask The address mask of the I/O space.
00365 //! \return
00366 //!     The size of the given I/O space aligned by the mask.
00367 //! \note
00368 //!     For memory-based devices the size of an I/O space is the
00369 //!     size of the memory-mapped buffer; for I/O based devices it
00370 //!     is the maximum offset of the ports.
00371 uint32_t pci_size(uint32_t base, unsigned long mask)
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 }
00380 
00381 //! \brief Read the base addresses of the selected deivice.
00382 //! \param cfg The PCI device structure.
00383 //! \param tot_bases
00384 //!     The amount of bases to read.
00385 //!     Every PCI device has up to 6 base addresses (6 for
00386 //!     normal devices, 2 for PCI to PCI bridges and only 1 for
00387 //!     cardbuses).
00388 //! \param rom
00389 //!     The ROM address register (from this register we can read the
00390 //!     ROM base address and the ROM space size).
00391 //! \note
00392 //!     This routine sets up the pci_cfg_t::base field and the
00393 //!     pci_cfg_t::rom_base field.
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         // 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 }
00456 
00457 //! \brief Probe for a PCI device.
00458 //! \param bus The bus number.
00459 //! \param dev The device number.
00460 //! \param func The function number.
00461 //! \param cfg The PCI device structure.
00462 //! \note This routine sets up the pci_cfg_t structure.
00463 //! \return
00464 //!     \li #TRUE if a device is present at the configuration
00465 //!     (\p bus, \p dev, \p func);
00466 //!     \li #FALSE the device is not present.
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         // 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 }
00522 
00523 //! SiS 5597 and 5598 require latency timer set to at most 32 to avoid
00524 //! lockups; otherwise default value is 255.
00525 unsigned int pcibios_max_latency=255;
00526 
00527 //! \brief Enable bus-mastering (aka 32-bit DMA) for a PCI device.
00528 //! \param cfg The PCI device structure.
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         // 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 }
00553 
00554 //! \brief Tell if a device supports a given PCI capability.
00555 //! \param cfg The PCI device structure.
00556 //! \param cap
00557 //!     The given capability (see pci.h PCI_CAP_* for a
00558 //!     complete list of supported capabilities).
00559 //! \return
00560 //!     \li 0 if the capability is not supported;
00561 //!     \li otherwise it returns the position of the supported
00562 //!     capability in the capability list of this device.
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 //! \brief
00603 //!     Set a new power state for the device using the Power
00604 //!     Management Capabilities.
00605 //! \param cfg
00606 //!     The PCI device structure.
00607 //! \param state The power state (from D0 to D3).
00608 //! \return
00609 //!     \li 0 if we can successfully change the power state;
00610 //!     \li -#EIO if the device doesn't support PCI Power Management;
00611 //!     \li -#EINVAL if trying to enter to a state we're already in.
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         // 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 }
00678 
00679 //! \brief
00680 //!     Low level function to initialize a PCI device before it's
00681 //!     used by a driver.
00682 //! \param cfg The PCI device structure.
00683 //! \note
00684 //!     This is a low-level routine, so it is strongly recommended
00685 //!     to do not use it externally.
00686 //!     In this case you can use pci_enable_device() instead.
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                         // 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 }
00731 
00732 //! \brief Initialize a PCI device before it's used by a driver.
00733 //! \param cfg The PCI device structure.
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 //! \brief
00761 //!     Look for a device in the PCI bus and eventually enable it.
00762 //! \param cfg The PCI device configuration structure.
00763 //! \param enable
00764 //!     \li #TRUE enable the device if present;
00765 //!     \li #FALSE simply look for a device without enabling it.
00766 //! \return
00767 //!     \li #TRUE a device has been found;
00768 //!     \li #FALSE device not found.
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                                 // 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 }
00802 
00803 //! \brief
00804 //!     Scan all the PCI buses, looking for devices.
00805 //!     If a device is found it will be enabled.
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                         // 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 }

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