pci.c

Go to the documentation of this file.
00001 #define USER_SPACE 1
00002 /*
00003 pci.c
00004 
00005 Configure devices on the PCI bus
00006 
00007 Created:        Jan 2000 by Philip Homburg <philip@cs.vu.nl>
00008 */
00009 
00010 #include "../drivers.h"
00011 #define NDEBUG                  /* disable assertions */
00012 #include <assert.h>
00013 #include <ibm/pci.h>
00014 #include <sys/vm.h>
00015 #include <minix/com.h>
00016 #include <minix/syslib.h>
00017 
00018 #include "pci.h"
00019 #include "pci_amd.h"
00020 #include "pci_intel.h"
00021 #include "pci_sis.h"
00022 #include "pci_via.h"
00023 #if __minix_vmd
00024 #include "config.h"
00025 #endif
00026 
00027 #if !__minix_vmd
00028 #define irq_mode_pci(irq) ((void)0)
00029 #endif
00030 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <minix/sysutil.h>
00035 
00036 #define NR_PCIBUS       10
00037 #define NR_PCIDEV       40
00038 
00039 #define PBT_INTEL_HOST   1
00040 #define PBT_PCIBRIDGE    2
00041 #define PBT_CARDBUS      3
00042 
00043 #define BAM_NR          6       /* Number of base-address registers */
00044 
00045 PRIVATE int debug= 0;
00046 
00047 PRIVATE struct pcibus
00048 {
00049         int pb_type;
00050         int pb_needinit;
00051         int pb_isabridge_dev;
00052         int pb_isabridge_type;
00053 
00054         int pb_devind;
00055         int pb_busnr;
00056         u8_t (*pb_rreg8)(int busind, int devind, int port);
00057         u16_t (*pb_rreg16)(int busind, int devind, int port);
00058         u32_t (*pb_rreg32)(int busind, int devind, int port);
00059         void (*pb_wreg8)(int busind, int devind, int port, U8_t value);
00060         void (*pb_wreg16)(int busind, int devind, int port, U16_t value);
00061         void (*pb_wreg32)(int busind, int devind, int port, u32_t value);
00062         u16_t (*pb_rsts)(int busind);
00063         void (*pb_wsts)(int busind, U16_t value);
00064 } pcibus[NR_PCIBUS];
00065 PRIVATE int nr_pcibus= 0;
00066 
00067 PRIVATE struct pcidev
00068 {
00069         u8_t pd_busnr;
00070         u8_t pd_dev;
00071         u8_t pd_func;
00072         u8_t pd_baseclass;
00073         u8_t pd_subclass;
00074         u8_t pd_infclass;
00075         u16_t pd_vid;
00076         u16_t pd_did;
00077         u8_t pd_ilr;
00078         u8_t pd_inuse;
00079 
00080         struct bar
00081         {
00082                 int pb_flags;
00083                 int pb_nr;
00084                 u32_t pb_base;
00085                 u32_t pb_size;
00086         } pd_bar[BAM_NR];
00087         int pd_bar_nr;
00088 
00089         char pd_name[M3_STRING];
00090 } pcidev[NR_PCIDEV];
00091 
00092 /* pb_flags */
00093 #define PBF_IO          1       /* I/O else memory */
00094 #define PBF_INCOMPLETE  2       /* not allocated */
00095 
00096 PRIVATE int nr_pcidev= 0;
00097 
00098 /* Work around the limitations of the PCI emulation in QEMU 0.7.1 */
00099 PRIVATE int qemu_pci= 0;
00100 
00101 FORWARD _PROTOTYPE( void pci_intel_init, (void)                         );
00102 FORWARD _PROTOTYPE( void probe_bus, (int busind)                        );
00103 FORWARD _PROTOTYPE( int is_duplicate, (U8_t busnr, U8_t dev, U8_t func) );
00104 FORWARD _PROTOTYPE( void record_irq, (int devind)                       );
00105 FORWARD _PROTOTYPE( void record_bars, (int devind)                      );
00106 FORWARD _PROTOTYPE( void record_bars_bridge, (int devind)               );
00107 FORWARD _PROTOTYPE( void record_bars_cardbus, (int devind)              );
00108 FORWARD _PROTOTYPE( void record_bar, (int devind, int bar_nr)           );
00109 FORWARD _PROTOTYPE( void complete_bridges, (void)                       );
00110 FORWARD _PROTOTYPE( void complete_bars, (void)                          );
00111 FORWARD _PROTOTYPE( void update_bridge4dev_io, (int devind,
00112                                         u32_t io_base, u32_t io_size)   );
00113 FORWARD _PROTOTYPE( int get_freebus, (void)                             );
00114 FORWARD _PROTOTYPE( int do_isabridge, (int busind)                      );
00115 FORWARD _PROTOTYPE( void do_pcibridge, (int busind)                     );
00116 FORWARD _PROTOTYPE( int get_busind, (int busnr)                         );
00117 FORWARD _PROTOTYPE( int do_piix, (int devind)                           );
00118 FORWARD _PROTOTYPE( int do_amd_isabr, (int devind)                      );
00119 FORWARD _PROTOTYPE( int do_sis_isabr, (int devind)                      );
00120 FORWARD _PROTOTYPE( int do_via_isabr, (int devind)                      );
00121 FORWARD _PROTOTYPE( void report_vga, (int devind)                       );
00122 FORWARD _PROTOTYPE( char *pci_vid_name, (U16_t vid)                     );
00123 FORWARD _PROTOTYPE( char *pci_baseclass_name, (U8_t baseclass)          );
00124 FORWARD _PROTOTYPE( char *pci_subclass_name, (U8_t baseclass,
00125                                         U8_t subclass, U8_t infclass)   );
00126 FORWARD _PROTOTYPE( void ntostr, (unsigned n, char **str, char *end)    );
00127 FORWARD _PROTOTYPE( u16_t pci_attr_rsts, (int devind)                   );
00128 FORWARD _PROTOTYPE( void pci_attr_wsts, (int devind, U16_t value)       );
00129 FORWARD _PROTOTYPE( u16_t pcibr_std_rsts, (int busind)          );
00130 FORWARD _PROTOTYPE( void pcibr_std_wsts, (int busind, U16_t value)      );
00131 FORWARD _PROTOTYPE( u16_t pcibr_cb_rsts, (int busind)           );
00132 FORWARD _PROTOTYPE( void pcibr_cb_wsts, (int busind, U16_t value)       );
00133 FORWARD _PROTOTYPE( u16_t pcibr_via_rsts, (int busind)                  );
00134 FORWARD _PROTOTYPE( void pcibr_via_wsts, (int busind, U16_t value)      );
00135 FORWARD _PROTOTYPE( u8_t pcii_rreg8, (int busind, int devind, int port) );
00136 FORWARD _PROTOTYPE( u16_t pcii_rreg16, (int busind, int devind,
00137                                                         int port)       );
00138 FORWARD _PROTOTYPE( u32_t pcii_rreg32, (int busind, int devind,
00139                                                         int port)       );
00140 FORWARD _PROTOTYPE( void pcii_wreg8, (int busind, int devind, int port,
00141                                                         U8_t value)     );
00142 FORWARD _PROTOTYPE( void pcii_wreg16, (int busind, int devind, int port,
00143                                                         U16_t value)    );
00144 FORWARD _PROTOTYPE( void pcii_wreg32, (int busind, int devind, int port,
00145                                                         u32_t value)    );
00146 FORWARD _PROTOTYPE( u16_t pcii_rsts, (int busind)                       );
00147 FORWARD _PROTOTYPE( void pcii_wsts, (int busind, U16_t value)           );
00148 FORWARD _PROTOTYPE( void print_capabilities, (int devind)               );
00149 
00150 /*===========================================================================*
00151  *                      helper functions for I/O                             *
00152  *===========================================================================*/
00153 PUBLIC unsigned pci_inb(U16_t port) {
00154         u32_t value;
00155         int s;
00156         if ((s=sys_inb(port, &value)) !=OK)
00157                 printf("PCI: warning, sys_inb failed: %d\n", s);
00158         return value;
00159 }
00160 PUBLIC unsigned pci_inw(U16_t port) {
00161         u32_t value;
00162         int s;
00163         if ((s=sys_inw(port, &value)) !=OK)
00164                 printf("PCI: warning, sys_inw failed: %d\n", s);
00165         return value;
00166 }
00167 PUBLIC unsigned pci_inl(U16_t port) {
00168         U32_t value;
00169         int s;
00170         if ((s=sys_inl(port, &value)) !=OK)
00171                 printf("PCI: warning, sys_inl failed: %d\n", s);
00172         return value;
00173 }
00174 PUBLIC void pci_outb(U16_t port, U8_t value) {
00175         int s;
00176         if ((s=sys_outb(port, value)) !=OK)
00177                 printf("PCI: warning, sys_outb failed: %d\n", s);
00178 }
00179 PUBLIC void pci_outw(U16_t port, U16_t value) {
00180         int s;
00181         if ((s=sys_outw(port, value)) !=OK)
00182                 printf("PCI: warning, sys_outw failed: %d\n", s);
00183 }
00184 PUBLIC void pci_outl(U16_t port, U32_t value) {
00185         int s;
00186         if ((s=sys_outl(port, value)) !=OK)
00187                 printf("PCI: warning, sys_outl failed: %d\n", s);
00188 }
00189 
00190 /*===========================================================================*
00191  *                              pci_init                                     *
00192  *===========================================================================*/
00193 PUBLIC void pci_init()
00194 {
00195         static int first_time= 1;
00196 
00197         long v;
00198 
00199         if (!first_time)
00200                 return;
00201 
00202         v= 0;
00203         env_parse("qemu_pci", "d", 0, &v, 0, 1);
00204         qemu_pci= v;
00205 
00206         v= 0;
00207         env_parse("pci_debug", "d", 0, &v, 0, 1);
00208         debug= v;
00209 
00210         /* We don't expect to interrupted */
00211         assert(first_time == 1);
00212         first_time= -1;
00213 
00214         /* Only Intel (compatible) PCI controllers are supported at the
00215          * moment.
00216          */
00217         pci_intel_init();
00218 
00219         first_time= 0;
00220 }
00221 
00222 /*===========================================================================*
00223  *                              pci_find_dev                                 *
00224  *===========================================================================*/
00225 PUBLIC int pci_find_dev(bus, dev, func, devindp)
00226 u8_t bus;
00227 u8_t dev;
00228 u8_t func;
00229 int *devindp;
00230 {
00231         int devind;
00232 
00233         for (devind= 0; devind < nr_pcidev; devind++)
00234         {
00235                 if (pcidev[devind].pd_busnr == bus &&
00236                         pcidev[devind].pd_dev == dev &&
00237                         pcidev[devind].pd_func == func)
00238                 {
00239                         break;
00240                 }
00241         }
00242         if (devind >= nr_pcidev)
00243                 return 0;
00244         if (pcidev[devind].pd_inuse)
00245                 return 0;
00246         *devindp= devind;
00247         return 1;
00248 }
00249 
00250 /*===========================================================================*
00251  *                              pci_first_dev                                *
00252  *===========================================================================*/
00253 PUBLIC int pci_first_dev(devindp, vidp, didp)
00254 int *devindp;
00255 u16_t *vidp;
00256 u16_t *didp;
00257 {
00258         int devind;
00259 
00260         for (devind= 0; devind < nr_pcidev; devind++)
00261         {
00262                 if (!pcidev[devind].pd_inuse)
00263                         break;
00264         }
00265         if (devind >= nr_pcidev)
00266                 return 0;
00267         *devindp= devind;
00268         *vidp= pcidev[devind].pd_vid;
00269         *didp= pcidev[devind].pd_did;
00270         return 1;
00271 }
00272 
00273 /*===========================================================================*
00274  *                              pci_next_dev                                 *
00275  *===========================================================================*/
00276 PUBLIC int pci_next_dev(devindp, vidp, didp)
00277 int *devindp;
00278 u16_t *vidp;
00279 u16_t *didp;
00280 {
00281         int devind;
00282 
00283         for (devind= *devindp+1; devind < nr_pcidev; devind++)
00284         {
00285                 if (!pcidev[devind].pd_inuse)
00286                         break;
00287         }
00288         if (devind >= nr_pcidev)
00289                 return 0;
00290         *devindp= devind;
00291         *vidp= pcidev[devind].pd_vid;
00292         *didp= pcidev[devind].pd_did;
00293         return 1;
00294 }
00295 
00296 /*===========================================================================*
00297  *                              pci_reserve3                                 *
00298  *===========================================================================*/
00299 PUBLIC void pci_reserve3(devind, proc, name)
00300 int devind;
00301 int proc;
00302 char *name;
00303 {
00304         int i, r;
00305         u8_t ilr;
00306         struct io_range ior;
00307         struct mem_range mr;
00308 
00309         assert(devind <= nr_pcidev);
00310         assert(!pcidev[devind].pd_inuse);
00311         pcidev[devind].pd_inuse= 1;
00312         strcpy(pcidev[devind].pd_name, name);
00313 
00314         for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
00315         {
00316                 if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE)
00317                 {
00318                         printf("pci_reserve3: BAR %d is incomplete\n", i);
00319                         continue;
00320                 }
00321                 if (pcidev[devind].pd_bar[i].pb_flags & PBF_IO)
00322                 {
00323                         ior.ior_base= pcidev[devind].pd_bar[i].pb_base;
00324                         ior.ior_limit= ior.ior_base +
00325                                 pcidev[devind].pd_bar[i].pb_size-1;
00326 
00327                         if(debug) {
00328                            printf(
00329                 "pci_reserve3: for proc %d, adding I/O range [0x%x..0x%x]\n",
00330                                 proc, ior.ior_base, ior.ior_limit);
00331                         }
00332                         r= sys_privctl(proc, SYS_PRIV_ADD_IO, 0, &ior);
00333                         if (r != OK)
00334                         {
00335                                 printf("sys_privctl failed for proc %d: %d\n",
00336                                         proc, r);
00337                         }
00338                 }
00339                 else
00340                 {
00341                         mr.mr_base= pcidev[devind].pd_bar[i].pb_base;
00342                         mr.mr_limit= mr.mr_base +
00343                                 pcidev[devind].pd_bar[i].pb_size-1;
00344 
00345                         if(debug) {
00346                            printf(
00347         "pci_reserve3: for proc %d, should add memory range [0x%x..0x%x]\n",
00348                                 proc, mr.mr_base, mr.mr_limit);
00349                         }
00350                         r= sys_privctl(proc, SYS_PRIV_ADD_MEM, 0, &mr);
00351                         if (r != OK)
00352                         {
00353                                 printf("sys_privctl failed for proc %d: %d\n",
00354                                         proc, r);
00355                         }
00356                 }
00357         }
00358         ilr= pcidev[devind].pd_ilr;
00359         if (ilr != PCI_ILR_UNKNOWN)
00360         {
00361                 if(debug) printf("pci_reserve3: adding IRQ %d\n", ilr);
00362                 r= sys_privctl(proc, SYS_PRIV_ADD_IRQ, ilr, NULL);
00363                 if (r != OK)
00364                 {
00365                         printf("sys_privctl failed for proc %d: %d\n",
00366                                 proc, r);
00367                 }
00368         }
00369 }
00370 
00371 /*===========================================================================*
00372  *                              pci_release                                  *
00373  *===========================================================================*/
00374 PUBLIC void pci_release(name)
00375 char *name;
00376 {
00377         int i;
00378 
00379         for (i= 0; i<nr_pcidev; i++)
00380         {
00381                 if (!pcidev[i].pd_inuse)
00382                         continue;
00383                 if (strcmp(pcidev[i].pd_name, name) != 0)
00384                         continue;
00385                 pcidev[i].pd_inuse= 0;
00386         }
00387 }
00388 
00389 /*===========================================================================*
00390  *                              pci_ids                                      *
00391  *===========================================================================*/
00392 PUBLIC void pci_ids(devind, vidp, didp)
00393 int devind;
00394 u16_t *vidp;
00395 u16_t *didp;
00396 {
00397         assert(devind <= nr_pcidev);
00398         *vidp= pcidev[devind].pd_vid;
00399         *didp= pcidev[devind].pd_did;
00400 }
00401 
00402 /*===========================================================================*
00403  *                              pci_rescan_bus                               *
00404  *===========================================================================*/
00405 PUBLIC void pci_rescan_bus(busnr)
00406 u8_t busnr;
00407 {
00408         int busind;
00409 
00410         busind= get_busind(busnr);
00411         probe_bus(busind);
00412 
00413         /* Allocate bus numbers for uninitialized bridges */
00414         complete_bridges();
00415 
00416         /* Allocate I/O and memory resources for uninitialized devices */
00417         complete_bars();
00418 }
00419 
00420 /*===========================================================================*
00421  *                              pci_slot_name                                *
00422  *===========================================================================*/
00423 PUBLIC char *pci_slot_name(devind)
00424 int devind;
00425 {
00426         static char label[]= "ddd.ddd.ddd";
00427         char *end;
00428         char *p;
00429 
00430         p= label;
00431         end= label+sizeof(label);
00432 
00433         ntostr(pcidev[devind].pd_busnr, &p, end);
00434         *p++= '.';
00435 
00436         ntostr(pcidev[devind].pd_dev, &p, end);
00437         *p++= '.';
00438 
00439         ntostr(pcidev[devind].pd_func, &p, end);
00440 
00441         return label;
00442 }
00443 
00444 /*===========================================================================*
00445  *                              pci_dev_name                                 *
00446  *===========================================================================*/
00447 PUBLIC char *pci_dev_name(vid, did)
00448 u16_t vid;
00449 u16_t did;
00450 {
00451         int i;
00452 
00453         for (i= 0; pci_device_table[i].name; i++)
00454         {
00455                 if (pci_device_table[i].vid == vid &&
00456                         pci_device_table[i].did == did)
00457                 {
00458                         return pci_device_table[i].name;
00459                 }
00460         }
00461         return NULL;
00462 }
00463 
00464 /*===========================================================================*
00465  *                              pci_attr_r8                                  *
00466  *===========================================================================*/
00467 PUBLIC u8_t pci_attr_r8(devind, port)
00468 int devind;
00469 int port;
00470 {
00471         int busnr, busind;
00472 
00473         busnr= pcidev[devind].pd_busnr;
00474         busind= get_busind(busnr);
00475         return pcibus[busind].pb_rreg8(busind, devind, port);
00476 }
00477 
00478 /*===========================================================================*
00479  *                              pci_attr_r16                                 *
00480  *===========================================================================*/
00481 PUBLIC u16_t pci_attr_r16(devind, port)
00482 int devind;
00483 int port;
00484 {
00485         int busnr, busind;
00486 
00487         busnr= pcidev[devind].pd_busnr;
00488         busind= get_busind(busnr);
00489         return pcibus[busind].pb_rreg16(busind, devind, port);
00490 }
00491 
00492 /*===========================================================================*
00493  *                              pci_attr_r32                                 *
00494  *===========================================================================*/
00495 PUBLIC u32_t pci_attr_r32(devind, port)
00496 int devind;
00497 int port;
00498 {
00499         int busnr, busind;
00500 
00501         busnr= pcidev[devind].pd_busnr;
00502         busind= get_busind(busnr);
00503         return pcibus[busind].pb_rreg32(busind, devind, port);
00504 }
00505 
00506 /*===========================================================================*
00507  *                              pci_attr_w8                                  *
00508  *===========================================================================*/
00509 PUBLIC void pci_attr_w8(devind, port, value)
00510 int devind;
00511 int port;
00512 u16_t value;
00513 {
00514         int busnr, busind;
00515 
00516         busnr= pcidev[devind].pd_busnr;
00517         busind= get_busind(busnr);
00518         pcibus[busind].pb_wreg8(busind, devind, port, value);
00519 }
00520 
00521 /*===========================================================================*
00522  *                              pci_attr_w16                                 *
00523  *===========================================================================*/
00524 PUBLIC void pci_attr_w16(devind, port, value)
00525 int devind;
00526 int port;
00527 u16_t value;
00528 {
00529         int busnr, busind;
00530 
00531         busnr= pcidev[devind].pd_busnr;
00532         busind= get_busind(busnr);
00533         pcibus[busind].pb_wreg16(busind, devind, port, value);
00534 }
00535 
00536 /*===========================================================================*
00537  *                              pci_attr_w32                                 *
00538  *===========================================================================*/
00539 PUBLIC void pci_attr_w32(devind, port, value)
00540 int devind;
00541 int port;
00542 u32_t value;
00543 {
00544         int busnr, busind;
00545 
00546         busnr= pcidev[devind].pd_busnr;
00547         busind= get_busind(busnr);
00548         pcibus[busind].pb_wreg32(busind, devind, port, value);
00549 }
00550 
00551 /*===========================================================================*
00552  *                              pci_intel_init                               *
00553  *===========================================================================*/
00554 PRIVATE void pci_intel_init()
00555 {
00556         /* Try to detect a know PCI controller. Read the Vendor ID and
00557          * the Device ID for function 0 of device 0.
00558          * Two times the value 0xffff suggests a system without a (compatible)
00559          * PCI controller. 
00560          */
00561         u32_t bus, dev, func;
00562         u16_t vid, did;
00563         int s, i, r, busind, busnr;
00564         char *dstr;
00565 
00566         bus= 0;
00567         dev= 0;
00568         func= 0;
00569 
00570         vid= PCII_RREG16_(bus, dev, func, PCI_VID);
00571         did= PCII_RREG16_(bus, dev, func, PCI_DID);
00572 #if USER_SPACE
00573         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
00574                 printf("PCI: warning, sys_outl failed: %d\n", s);
00575 #else
00576         outl(PCII_CONFADD, PCII_UNSEL);
00577 #endif
00578 
00579         if (vid == 0xffff && did == 0xffff)
00580                 return; /* Nothing here */
00581 
00582 #if 0
00583         for (i= 0; pci_intel_ctrl[i].vid; i++)
00584         {
00585                 if (pci_intel_ctrl[i].vid == vid &&
00586                         pci_intel_ctrl[i].did == did)
00587                 {
00588                         break;
00589                 }
00590         }
00591 
00592         if (!pci_intel_ctrl[i].vid)
00593         {
00594                 printf("pci_intel_init (warning): unknown PCI-controller:\n"
00595                         "\tvendor %04X (%s), device %04X\n",
00596                         vid, pci_vid_name(vid), did);
00597         }
00598 #endif
00599 
00600         if (nr_pcibus >= NR_PCIBUS)
00601                 panic("PCI","too many PCI busses", nr_pcibus);
00602         busind= nr_pcibus;
00603         nr_pcibus++;
00604         pcibus[busind].pb_type= PBT_INTEL_HOST;
00605         pcibus[busind].pb_needinit= 0;
00606         pcibus[busind].pb_isabridge_dev= -1;
00607         pcibus[busind].pb_isabridge_type= 0;
00608         pcibus[busind].pb_devind= -1;
00609         pcibus[busind].pb_busnr= 0;
00610         pcibus[busind].pb_rreg8= pcii_rreg8;
00611         pcibus[busind].pb_rreg16= pcii_rreg16;
00612         pcibus[busind].pb_rreg32= pcii_rreg32;
00613         pcibus[busind].pb_wreg8= pcii_wreg8;
00614         pcibus[busind].pb_wreg16= pcii_wreg16;
00615         pcibus[busind].pb_wreg32= pcii_wreg32;
00616         pcibus[busind].pb_rsts= pcii_rsts;
00617         pcibus[busind].pb_wsts= pcii_wsts;
00618 
00619         dstr= pci_dev_name(vid, did);
00620         if (!dstr)
00621                 dstr= "unknown device";
00622         if (debug)
00623         {
00624                 printf("pci_intel_init: %s (%04X/%04X)\n",
00625                         dstr, vid, did);
00626         }
00627 
00628         probe_bus(busind);
00629 
00630         r= do_isabridge(busind);
00631         if (r != OK)
00632         {
00633                 busnr= pcibus[busind].pb_busnr;
00634 
00635                 /* Disable all devices for this bus */
00636                 for (i= 0; i<nr_pcidev; i++)
00637                 {
00638                         if (pcidev[i].pd_busnr != busnr)
00639                                 continue;
00640                         pcidev[i].pd_inuse= 1;
00641                 }
00642                 return;
00643         }
00644 
00645         /* Look for PCI bridges */
00646         do_pcibridge(busind);
00647 
00648         /* Allocate bus numbers for uninitialized bridges */
00649         complete_bridges();
00650 
00651         /* Allocate I/O and memory resources for uninitialized devices */
00652         complete_bars();
00653 }
00654 
00655 /*===========================================================================*
00656  *                              probe_bus                                    *
00657  *===========================================================================*/
00658 PRIVATE void probe_bus(busind)
00659 int busind;
00660 {
00661         u32_t dev, func, t3;
00662         u16_t vid, did, sts;
00663         u8_t headt;
00664         u8_t baseclass, subclass, infclass;
00665         int devind, busnr;
00666         char *s, *dstr;
00667 
00668 #if DEBUG
00669 printf("probe_bus(%d)\n", busind);
00670 #endif
00671         if (nr_pcidev >= NR_PCIDEV)
00672                 panic("PCI","too many PCI devices", nr_pcidev);
00673         devind= nr_pcidev;
00674 
00675         busnr= pcibus[busind].pb_busnr;
00676         for (dev= 0; dev<32; dev++)
00677         {
00678 
00679                 for (func= 0; func < 8; func++)
00680                 {
00681                         pcidev[devind].pd_busnr= busnr;
00682                         pcidev[devind].pd_dev= dev;
00683                         pcidev[devind].pd_func= func;
00684 
00685                         pci_attr_wsts(devind, 
00686                                 PSR_SSE|PSR_RMAS|PSR_RTAS);
00687                         vid= pci_attr_r16(devind, PCI_VID);
00688                         did= pci_attr_r16(devind, PCI_DID);
00689                         headt= pci_attr_r8(devind, PCI_HEADT);
00690                         sts= pci_attr_rsts(devind);
00691 
00692 #if 0
00693                         printf("vid 0x%x, did 0x%x, headt 0x%x, sts 0x%x\n",
00694                                 vid, did, headt, sts);
00695 #endif
00696 
00697                         if (vid == NO_VID)
00698                         {
00699                                 if (func == 0)
00700                                         break;  /* Nothing here */
00701 
00702                                 /* Scan all functions of a multifunction
00703                                  * device.
00704                                  */
00705                                 continue;
00706                         }
00707 
00708                         if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS))
00709                         {
00710                                 if (qemu_pci)
00711                                 {
00712                                         printf(
00713                         "pci: ignoring bad value 0x%x in sts for QEMU\n",
00714                                         sts & (PSR_SSE|PSR_RMAS|PSR_RTAS));
00715                                 }
00716                                 else
00717                                 {
00718                                         if (func == 0)
00719                                                 break;  /* Nothing here */
00720 
00721                                         /* Scan all functions of a
00722                                          * multifunction device.
00723                                          */
00724                                         continue;
00725                                 }
00726                         }
00727 
00728                         dstr= pci_dev_name(vid, did);
00729                         if (debug)
00730                         {
00731                                 if (dstr)
00732                                 {
00733                                         printf("%d.%lu.%lu: %s (%04X/%04X)\n",
00734                                                 busind, (unsigned long)dev,
00735                                                 (unsigned long)func, dstr,
00736                                                 vid, did);
00737                                 }
00738                                 else
00739                                 {
00740                                         printf(
00741                 "%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n",
00742                                                 busind, (unsigned long)dev,
00743                                                 (unsigned long)func, vid,
00744                                                 pci_vid_name(vid), did);
00745                                 }
00746                                 printf("Device index: %d\n", devind);
00747                                 printf("Subsystem: Vid 0x%x, did 0x%x\n",
00748                                         pci_attr_r16(devind, PCI_SUBVID),
00749                                         pci_attr_r16(devind, PCI_SUBDID));
00750                         }
00751 
00752                         baseclass= pci_attr_r8(devind, PCI_BCR);
00753                         subclass= pci_attr_r8(devind, PCI_SCR);
00754                         infclass= pci_attr_r8(devind, PCI_PIFR);
00755                         s= pci_subclass_name(baseclass, subclass, infclass);
00756                         if (!s)
00757                                 s= pci_baseclass_name(baseclass);
00758                         {
00759                                 if (!s)
00760                                         s= "(unknown class)";
00761                         }
00762                         if (debug)
00763                         {
00764                                 printf("\tclass %s (%X/%X/%X)\n", s,
00765                                         baseclass, subclass, infclass);
00766                         }
00767 
00768                         if (is_duplicate(busnr, dev, func))
00769                         {
00770                                 printf("\tduplicate!\n");
00771                                 if (func == 0 && !(headt & PHT_MULTIFUNC))
00772                                         break;
00773                                 continue;
00774                         }
00775 
00776                         devind= nr_pcidev;
00777                         nr_pcidev++;
00778                         pcidev[devind].pd_baseclass= baseclass;
00779                         pcidev[devind].pd_subclass= subclass;
00780                         pcidev[devind].pd_infclass= infclass;
00781                         pcidev[devind].pd_vid= vid;
00782                         pcidev[devind].pd_did= did;
00783                         pcidev[devind].pd_inuse= 0;
00784                         pcidev[devind].pd_bar_nr= 0;
00785                         record_irq(devind);
00786                         switch(headt & PHT_MASK)
00787                         {
00788                         case PHT_NORMAL:
00789                                 record_bars(devind);
00790                                 break;
00791                         case PHT_BRIDGE:
00792                                 record_bars_bridge(devind);
00793                                 break;
00794                         case PHT_CARDBUS:
00795                                 record_bars_cardbus(devind);
00796                                 break;
00797                         default:
00798                                 printf("\t%d.%d.%d: unknown header type %d\n",
00799                                         busind, dev, func,
00800                                         headt & PHT_MASK);
00801                                 break;
00802                         }
00803                         if (debug)
00804                                 print_capabilities(devind);
00805 
00806                         t3= ((baseclass << 16) | (subclass << 8) | infclass);
00807                         if (t3 == PCI_T3_VGA || t3 == PCI_T3_VGA_OLD)
00808                                 report_vga(devind);
00809 
00810                         if (nr_pcidev >= NR_PCIDEV)
00811                           panic("PCI","too many PCI devices", nr_pcidev);
00812                         devind= nr_pcidev;
00813 
00814                         if (func == 0 && !(headt & PHT_MULTIFUNC))
00815                                 break;
00816                 }
00817         }
00818 }
00819 
00820 /*===========================================================================*
00821  *                              is_duplicate                                 *
00822  *===========================================================================*/
00823 PRIVATE int is_duplicate(busnr, dev, func)
00824 u8_t busnr;
00825 u8_t dev;
00826 u8_t func;
00827 {
00828         int i;
00829 
00830         for (i= 0; i<nr_pcidev; i++)
00831         {
00832                 if (pcidev[i].pd_busnr == busnr &&
00833                         pcidev[i].pd_dev == dev &&
00834                         pcidev[i].pd_func == func)
00835                 {
00836                         return 1;
00837                 }
00838         }
00839         return 0;
00840 }
00841 
00842 /*===========================================================================*
00843  *                              record_irq                                   *
00844  *===========================================================================*/
00845 PRIVATE void record_irq(devind)
00846 int devind;
00847 {
00848         int ilr, ipr, busnr, busind, cb_devind;
00849 
00850         ilr= pci_attr_r8(devind, PCI_ILR);
00851         ipr= pci_attr_r8(devind, PCI_IPR);
00852         if (ilr == 0)
00853         {
00854                 static int first= 1;
00855                 if (ipr && first && debug)
00856                 {
00857                         first= 0;
00858                         printf("PCI: strange, BIOS assigned IRQ0\n");
00859                 }
00860                 ilr= PCI_ILR_UNKNOWN;
00861         }
00862         pcidev[devind].pd_ilr= ilr;
00863         if (ilr == PCI_ILR_UNKNOWN && !ipr)
00864         {
00865         }
00866         else if (ilr != PCI_ILR_UNKNOWN && ipr)
00867         {
00868                 if (debug)
00869                         printf("\tIRQ %d for INT%c\n", ilr, 'A' + ipr-1);
00870         }
00871         else if (ilr != PCI_ILR_UNKNOWN)
00872         {
00873                 printf(
00874         "PCI: IRQ %d is assigned, but device %d.%d.%d does not need it\n",
00875                         ilr, pcidev[devind].pd_busnr, pcidev[devind].pd_dev,
00876                         pcidev[devind].pd_func);
00877         }
00878         else
00879         {
00880                 /* Check for cardbus devices */
00881                 busnr= pcidev[devind].pd_busnr;
00882                 busind= get_busind(busnr);
00883                 if (pcibus[busind].pb_type == PBT_CARDBUS)
00884                 {
00885                         cb_devind= pcibus[busind].pb_devind;
00886                         ilr= pcidev[cb_devind].pd_ilr;
00887                         if (ilr != PCI_ILR_UNKNOWN)
00888                         {
00889                                 if (debug)
00890                                 {
00891                                         printf(
00892                                         "assigning IRQ %d to Cardbus device\n",
00893                                                 ilr);
00894                                 }
00895                                 pci_attr_w8(devind, PCI_ILR, ilr);
00896                                 pcidev[devind].pd_ilr= ilr;
00897                                 return;
00898                         }
00899                 }
00900                 if(debug) {
00901                         printf(
00902                 "PCI: device %d.%d.%d uses INT%c but is not assigned any IRQ\n",
00903                         pcidev[devind].pd_busnr, pcidev[devind].pd_dev,
00904                         pcidev[devind].pd_func, 'A' + ipr-1);
00905                 }
00906         }
00907 }
00908 
00909 /*===========================================================================*
00910  *                              record_bars                                  *
00911  *===========================================================================*/
00912 PRIVATE void record_bars(devind)
00913 int devind;
00914 {
00915         int i, j, reg, prefetch, type, clear_01, clear_23, pb_nr;
00916         u32_t bar, bar2;
00917 
00918         for (i= 0, reg= PCI_BAR; reg <= PCI_BAR_6; i++, reg += 4)
00919         {
00920                 record_bar(devind, i);
00921         }
00922 
00923         /* Special case code for IDE controllers in compatibility mode */
00924         if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE &&
00925                 pcidev[devind].pd_subclass == PCI_MS_IDE)
00926         {
00927                 /* IDE device */
00928                 clear_01= 0;
00929                 clear_23= 0;
00930                 if (!(pcidev[devind].pd_infclass & PCI_IDE_PRI_NATIVE))
00931                 {
00932                         if (debug)
00933                         {
00934                                 printf(
00935         "primary channel is not in native mode, clearing BARs 0 and 1\n");
00936                         }
00937                         clear_01= 1;
00938                 }
00939                 if (!(pcidev[devind].pd_infclass & PCI_IDE_SEC_NATIVE))
00940                 {
00941                         if (debug)
00942                         {
00943                                 printf(
00944         "primary channel is not in native mode, clearing BARs 2 and 3\n");
00945                         }
00946                         clear_23= 1;
00947                 }
00948 
00949                 j= 0;
00950                 for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
00951                 {
00952                         pb_nr= pcidev[devind].pd_bar[i].pb_nr;
00953                         if ((pb_nr == 0 || pb_nr == 1) && clear_01)
00954                         {
00955                                 if (debug) printf("skipping bar %d\n", pb_nr);
00956                                 continue;       /* Skip */
00957                         }
00958                         if ((pb_nr == 2 || pb_nr == 3) && clear_23)
00959                         {
00960                                 if (debug) printf("skipping bar %d\n", pb_nr);
00961                                 continue;       /* Skip */
00962                         }
00963                         if (i == j)
00964                                 continue;       /* No need to copy */
00965                         pcidev[devind].pd_bar[j]=
00966                                 pcidev[devind].pd_bar[i];
00967                         j++;
00968                 }
00969                 pcidev[devind].pd_bar_nr= j;
00970         }
00971 }
00972 
00973 /*===========================================================================*
00974  *                              record_bars_bridge                           *
00975  *===========================================================================*/
00976 PRIVATE void record_bars_bridge(devind)
00977 int devind;
00978 {
00979         u32_t base, limit, size;
00980 
00981         record_bar(devind, 0);
00982         record_bar(devind, 1);
00983 
00984         base= ((pci_attr_r8(devind, PPB_IOBASE) & PPB_IOB_MASK) << 8) |
00985                 (pci_attr_r16(devind, PPB_IOBASEU16) << 16);
00986         limit= 0xff |
00987                 ((pci_attr_r8(devind, PPB_IOLIMIT) & PPB_IOL_MASK) << 8) |
00988                 ((~PPB_IOL_MASK & 0xff) << 8) |
00989                 (pci_attr_r16(devind, PPB_IOLIMITU16) << 16);
00990         size= limit-base + 1;
00991         if (debug)
00992         {
00993                 printf("\tI/O window: base 0x%x, limit 0x%x, size %d\n",
00994                         base, limit, size);
00995         }
00996 
00997         base= ((pci_attr_r16(devind, PPB_MEMBASE) & PPB_MEMB_MASK) << 16);
00998         limit= 0xffff |
00999                 ((pci_attr_r16(devind, PPB_MEMLIMIT) & PPB_MEML_MASK) << 16) |
01000                 ((~PPB_MEML_MASK & 0xffff) << 16);
01001         size= limit-base + 1;
01002         if (debug)
01003         {
01004                 printf("\tMemory window: base 0x%x, limit 0x%x, size 0x%x\n",
01005                         base, limit, size);
01006         }
01007 
01008         /* Ignore the upper 32 bits */
01009         base= ((pci_attr_r16(devind, PPB_PFMEMBASE) & PPB_PFMEMB_MASK) << 16);
01010         limit= 0xffff |
01011                 ((pci_attr_r16(devind, PPB_PFMEMLIMIT) &
01012                         PPB_PFMEML_MASK) << 16) |
01013                 ((~PPB_PFMEML_MASK & 0xffff) << 16);
01014         size= limit-base + 1;
01015         if (debug)
01016         {
01017                 printf(
01018         "\tPrefetchable memory window: base 0x%x, limit 0x%x, size 0x%x\n",
01019                         base, limit, size);
01020         }
01021 }
01022 
01023 /*===========================================================================*
01024  *                              record_bars_cardbus                          *
01025  *===========================================================================*/
01026 PRIVATE void record_bars_cardbus(devind)
01027 int devind;
01028 {
01029         u32_t base, limit, size;
01030 
01031         record_bar(devind, 0);
01032 
01033         base= pci_attr_r32(devind, CBB_MEMBASE_0);
01034         limit= pci_attr_r32(devind, CBB_MEMLIMIT_0) |
01035                 (~CBB_MEML_MASK & 0xffffffff);
01036         size= limit-base + 1;
01037         if (debug)
01038         {
01039                 printf("\tMemory window 0: base 0x%x, limit 0x%x, size %d\n",
01040                         base, limit, size);
01041         }
01042 
01043         base= pci_attr_r32(devind, CBB_MEMBASE_1);
01044         limit= pci_attr_r32(devind, CBB_MEMLIMIT_1) |
01045                 (~CBB_MEML_MASK & 0xffffffff);
01046         size= limit-base + 1;
01047         if (debug)
01048         {
01049                 printf("\tMemory window 1: base 0x%x, limit 0x%x, size %d\n",
01050                         base, limit, size);
01051         }
01052 
01053         base= pci_attr_r32(devind, CBB_IOBASE_0);
01054         limit= pci_attr_r32(devind, CBB_IOLIMIT_0) |
01055                 (~CBB_IOL_MASK & 0xffffffff);
01056         size= limit-base + 1;
01057         if (debug)
01058         {
01059                 printf("\tI/O window 0: base 0x%x, limit 0x%x, size %d\n",
01060                         base, limit, size);
01061         }
01062 
01063         base= pci_attr_r32(devind, CBB_IOBASE_1);
01064         limit= pci_attr_r32(devind, CBB_IOLIMIT_1) |
01065                 (~CBB_IOL_MASK & 0xffffffff);
01066         size= limit-base + 1;
01067         if (debug)
01068         {
01069                 printf("\tI/O window 1: base 0x%x, limit 0x%x, size %d\n",
01070                         base, limit, size);
01071         }
01072 }
01073 
01074 /*===========================================================================*
01075  *                              record_bar                                   *
01076  *===========================================================================*/
01077 PRIVATE void record_bar(devind, bar_nr)
01078 int devind;
01079 int bar_nr;
01080 {
01081         int reg, prefetch, type, dev_bar_nr;
01082         u32_t bar, bar2;
01083 
01084         reg= PCI_BAR+4*bar_nr;
01085 
01086         bar= pci_attr_r32(devind, reg);
01087         if (bar & PCI_BAR_IO)
01088         {
01089                 /* Size register */
01090                 pci_attr_w32(devind, reg, 0xffffffff);
01091                 bar2= pci_attr_r32(devind, reg);
01092                 pci_attr_w32(devind, reg, bar);
01093 
01094                 bar &= ~(u32_t)3;       /* Clear non-address bits */
01095                 bar2 &= ~(u32_t)3;
01096                 bar2= (~bar2 & 0xffff)+1;
01097                 if (debug)
01098                 {
01099                         printf("\tbar_%d: %d bytes at 0x%x I/O\n",
01100                                 bar_nr, bar2, bar);
01101                 }
01102 
01103                 dev_bar_nr= pcidev[devind].pd_bar_nr++;
01104                 assert(dev_bar_nr < BAR_NR);
01105                 pcidev[devind].pd_bar[dev_bar_nr].pb_flags= PBF_IO;
01106                 pcidev[devind].pd_bar[dev_bar_nr].pb_base= bar;
01107                 pcidev[devind].pd_bar[dev_bar_nr].pb_size= bar2;
01108                 pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr;
01109                 if (bar == 0)
01110                 {
01111                         pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= 
01112                                 PBF_INCOMPLETE;
01113                 }
01114         }
01115         else
01116         {
01117                 /* Size register */
01118                 pci_attr_w32(devind, reg, 0xffffffff);
01119                 bar2= pci_attr_r32(devind, reg);
01120                 pci_attr_w32(devind, reg, bar);
01121 
01122                 if (bar2 == 0)
01123                         return; /* Reg. is not implemented */
01124 
01125                 prefetch= !!(bar & PCI_BAR_PREFETCH);
01126                 type= (bar & PCI_BAR_TYPE);
01127                 bar &= ~(u32_t)0xf;     /* Clear non-address bits */
01128                 bar2 &= ~(u32_t)0xf;
01129                 bar2= (~bar2)+1;
01130                 if (debug)
01131                 {
01132                         printf("\tbar_%d: 0x%x bytes at 0x%x%s memory\n",
01133                                 bar_nr, bar2, bar,
01134                                 prefetch ? " prefetchable" : "");
01135                         if (type != 0)
01136                                 printf("type = 0x%x\n", type);
01137                 }
01138 
01139                 dev_bar_nr= pcidev[devind].pd_bar_nr++;
01140                 assert(dev_bar_nr < BAR_NR);
01141                 pcidev[devind].pd_bar[dev_bar_nr].pb_flags= 0;
01142                 pcidev[devind].pd_bar[dev_bar_nr].pb_base= bar;
01143                 pcidev[devind].pd_bar[dev_bar_nr].pb_size= bar2;
01144                 pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr;
01145                 if (bar == 0)
01146                 {
01147                         pcidev[devind].pd_bar[dev_bar_nr].pb_flags |= 
01148                                 PBF_INCOMPLETE;
01149                 }
01150         }
01151 }
01152 
01153 /*===========================================================================*
01154  *                              complete_bridges                             *
01155  *===========================================================================*/
01156 PRIVATE void complete_bridges()
01157 {
01158         int i, freebus, devind, prim_busnr;
01159 
01160         for (i= 0; i<nr_pcibus; i++)
01161         {
01162                 if (!pcibus[i].pb_needinit)
01163                         continue;
01164                 printf("should allocate bus number for bus %d\n", i);
01165                 freebus= get_freebus();
01166                 printf("got bus number %d\n", freebus);
01167 
01168                 devind= pcibus[i].pb_devind;
01169 
01170                 prim_busnr= pcidev[devind].pd_busnr;
01171                 if (prim_busnr != 0)
01172                 {
01173                         printf(
01174         "complete_bridge: updating subordinate bus number not implemented\n");
01175                 }
01176 
01177                 pcibus[i].pb_needinit= 0;
01178                 pcibus[i].pb_busnr= freebus;
01179 
01180                 printf("devind = %d\n", devind);
01181                 printf("prim_busnr= %d\n", prim_busnr);
01182 
01183                 pci_attr_w8(devind, PPB_PRIMBN, prim_busnr);
01184                 pci_attr_w8(devind, PPB_SECBN, freebus);
01185                 pci_attr_w8(devind, PPB_SUBORDBN, freebus);
01186 
01187                 printf("CR = 0x%x\n", pci_attr_r16(devind, PCI_CR));
01188                 printf("SECBLT = 0x%x\n", pci_attr_r8(devind, PPB_SECBLT));
01189                 printf("BRIDGECTRL = 0x%x\n",
01190                         pci_attr_r16(devind, PPB_BRIDGECTRL));
01191         }
01192 }
01193 
01194 /*===========================================================================*
01195  *                              complete_bars                                *
01196  *===========================================================================*/
01197 PRIVATE void complete_bars()
01198 {
01199         int i, j, r, bar_nr, reg;
01200         u32_t memgap_low, memgap_high, iogap_low, iogap_high, io_high,
01201                 base, size, v32, diff1, diff2;
01202         char *cp, *next;
01203         char memstr[256];
01204 
01205         r= env_get_param("memory", memstr, sizeof(memstr));
01206         if (r != OK)
01207                 panic("pci", "env_get_param failed", r);
01208         
01209         /* Set memgap_low to just above physical memory */
01210         memgap_low= 0;
01211         cp= memstr;
01212         while (*cp != '\0')
01213         {
01214                 base= strtoul(cp, &next, 16);
01215                 if (next == cp || *next != ':')
01216                 {
01217                         printf("pci: bad memory environment string '%s'\n",
01218                                 memstr);
01219                         panic(NULL, NULL, NO_NUM);
01220                 }
01221                 cp= next+1;
01222                 size= strtoul(cp, &next, 16);
01223                 if (next == cp || (*next != ',' && *next != '\0'))
01224                 {
01225                         printf("pci: bad memory environment string '%s'\n",
01226                                 memstr);
01227                         panic(NULL, NULL, NO_NUM);
01228                 }
01229                 cp= next+1;
01230 
01231                 if (base+size > memgap_low)
01232                         memgap_low= base+size;
01233         }
01234 
01235         memgap_high= 0xfe000000;        /* Leave space for the CPU (APIC) */
01236 
01237         if (debug)
01238         {
01239                 printf("complete_bars: initial gap: [0x%x .. 0x%x>\n",
01240                         memgap_low, memgap_high);
01241         }
01242 
01243         /* Find the lowest memory base */
01244         for (i= 0; i<nr_pcidev; i++)
01245         {
01246                 for (j= 0; j<pcidev[i].pd_bar_nr; j++)
01247                 {
01248                         if (pcidev[i].pd_bar[j].pb_flags & PBF_IO)
01249                                 continue;
01250                         if (pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE)
01251                                 continue;
01252                         base= pcidev[i].pd_bar[j].pb_base;
01253                         size= pcidev[i].pd_bar[j].pb_size;
01254 
01255                         if (base >= memgap_high)
01256                                 continue;       /* Not in the gap */
01257                         if (base+size <= memgap_low)
01258                                 continue;       /* Not in the gap */
01259 
01260                         /* Reduce the gap by the smallest amount */
01261                         diff1= base+size-memgap_low;
01262                         diff2= memgap_high-base;
01263 
01264                         if (diff1 < diff2)
01265                                 memgap_low= base+size;
01266                         else
01267                                 memgap_high= base;
01268                 }
01269         }
01270 
01271         if (debug)
01272         {
01273                 printf("complete_bars: intermediate gap: [0x%x .. 0x%x>\n",
01274                         memgap_low, memgap_high);
01275         }
01276 
01277         /* Should check main memory size */
01278         if (memgap_high < memgap_low)
01279         {
01280                 printf("pci: bad memory gap: [0x%x .. 0x%x>\n",
01281                         memgap_low, memgap_high);
01282                 panic(NULL, NULL, NO_NUM);
01283         }
01284 
01285         iogap_high= 0x10000;
01286         iogap_low= 0x400;
01287 
01288         /* Find the free I/O space */
01289         for (i= 0; i<nr_pcidev; i++)
01290         {
01291                 for (j= 0; j<pcidev[i].pd_bar_nr; j++)
01292                 {
01293                         if (!(pcidev[i].pd_bar[j].pb_flags & PBF_IO))
01294                                 continue;
01295                         if (pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE)
01296                                 continue;
01297                         base= pcidev[i].pd_bar[j].pb_base;
01298                         size= pcidev[i].pd_bar[j].pb_size;
01299                         if (base >= iogap_high)
01300                                 continue;
01301                         if (base+size <= iogap_low)
01302                                 continue;
01303 #if 0
01304                         if (debug)
01305                         {
01306                                 printf(
01307                 "pci device %d (%04x/%04x), bar %d: base 0x%x, size 0x%x\n",
01308                                         i, pcidev[i].pd_vid, pcidev[i].pd_did,
01309                                         j, base, size);
01310                         }
01311 #endif
01312                         if (base+size-iogap_low < iogap_high-base)
01313                                 iogap_low= base+size;
01314                         else
01315                                 iogap_high= base;
01316                 }
01317         }
01318 
01319         if (iogap_high < iogap_low)
01320         {
01321                 if (debug)
01322                 {
01323                         printf("iogap_high too low, should panic\n");
01324                 }
01325                 else
01326                         panic("pci", "iogap_high too low", iogap_high);
01327         }
01328         if (debug)
01329                 printf("I/O range = [0x%x..0x%x>\n", iogap_low, iogap_high);
01330 
01331         for (i= 0; i<nr_pcidev; i++)
01332         {
01333                 for (j= 0; j<pcidev[i].pd_bar_nr; j++)
01334                 {
01335                         if (pcidev[i].pd_bar[j].pb_flags & PBF_IO)
01336                                 continue;
01337                         if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
01338                                 continue;
01339                         size= pcidev[i].pd_bar[j].pb_size;
01340                         if (size < PAGE_SIZE)
01341                                 size= PAGE_SIZE;
01342                         base= memgap_high-size;
01343                         base &= ~(u32_t)(size-1);
01344                         if (base < memgap_low)
01345                                 panic("pci", "memory base too low", base);
01346                         memgap_high= base;
01347                         bar_nr= pcidev[i].pd_bar[j].pb_nr;
01348                         reg= PCI_BAR + 4*bar_nr;
01349                         v32= pci_attr_r32(i, reg);
01350                         pci_attr_w32(i, reg, v32 | base);
01351                         if (debug)
01352                         {
01353                                 printf(
01354                 "complete_bars: allocated 0x%x size %d to %d.%d.%d, bar_%d\n",
01355                                         base, size, pcidev[i].pd_busnr,
01356                                         pcidev[i].pd_dev, pcidev[i].pd_func,
01357                                         bar_nr);
01358                         }
01359                         pcidev[i].pd_bar[j].pb_base= base;
01360                         pcidev[i].pd_bar[j].pb_flags &= ~PBF_INCOMPLETE;
01361                 }
01362 
01363                 io_high= iogap_high;
01364                 for (j= 0; j<pcidev[i].pd_bar_nr; j++)
01365                 {
01366                         if (!(pcidev[i].pd_bar[j].pb_flags & PBF_IO))
01367                                 continue;
01368                         if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
01369                                 continue;
01370                         size= pcidev[i].pd_bar[j].pb_size;
01371                         base= iogap_high-size;
01372                         base &= ~(u32_t)(size-1);
01373 
01374                         /* Assume that ISA compatibility is required. Only
01375                          * use the lowest 256 bytes out of every 1024 bytes.
01376                          */
01377                         base &= 0xfcff;
01378 
01379                         if (base < iogap_low)
01380                                 panic("pci", "I/O base too low", base);
01381 
01382                         iogap_high= base;
01383                         bar_nr= pcidev[i].pd_bar[j].pb_nr;
01384                         reg= PCI_BAR + 4*bar_nr;
01385                         v32= pci_attr_r32(i, reg);
01386                         pci_attr_w32(i, reg, v32 | base);
01387                         if (debug)
01388                         {
01389                                 printf(
01390                 "complete_bars: allocated 0x%x size %d to %d.%d.%d, bar_%d\n",
01391                                         base, size, pcidev[i].pd_busnr,
01392                                         pcidev[i].pd_dev, pcidev[i].pd_func,
01393                                         bar_nr);
01394                         }
01395                         pcidev[i].pd_bar[j].pb_base= base;
01396                         pcidev[i].pd_bar[j].pb_flags &= ~PBF_INCOMPLETE;
01397 
01398                 }
01399                 if (iogap_high != io_high)
01400                 {
01401                         update_bridge4dev_io(i, iogap_high,
01402                                 io_high-iogap_high);
01403                 }
01404         }
01405 
01406         for (i= 0; i<nr_pcidev; i++)
01407         {
01408                 for (j= 0; j<pcidev[i].pd_bar_nr; j++)
01409                 {
01410                         if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
01411                                 continue;
01412                         printf("should allocate resources for device %d\n", i);
01413                 }
01414         }
01415 }
01416 
01417 /*===========================================================================*
01418  *                              update_bridge4dev_io                         *
01419  *===========================================================================*/
01420 PRIVATE void update_bridge4dev_io(devind, io_base, io_size)
01421 int devind;
01422 u32_t io_base;
01423 u32_t io_size;
01424 {
01425         int busnr, busind, type, br_devind;
01426         u16_t v16;
01427 
01428         busnr= pcidev[devind].pd_busnr;
01429         busind= get_busind(busnr);
01430         type= pcibus[busind].pb_type;
01431         if (type == PBT_INTEL_HOST)
01432                 return; /* Nothing to do for host controller */
01433         if (type == PBT_PCIBRIDGE)
01434         {
01435                 printf(
01436                 "update_bridge4dev_io: not implemented for PCI bridges\n");
01437                 return; 
01438         }
01439         if (type != PBT_CARDBUS)
01440                 panic("pci", "update_bridge4dev_io: strange bus type", type);
01441 
01442         if (debug)
01443         {
01444                 printf("update_bridge4dev_io: adding 0x%x at 0x%x\n",
01445                         io_size, io_base);
01446         }
01447         br_devind= pcibus[busind].pb_devind;
01448         pci_attr_w32(br_devind, CBB_IOLIMIT_0, io_base+io_size-1);
01449         pci_attr_w32(br_devind, CBB_IOBASE_0, io_base);
01450 
01451         /* Enable I/O access. Enable busmaster access as well. */
01452         v16= pci_attr_r16(devind, PCI_CR);
01453         pci_attr_w16(devind, PCI_CR, v16 | PCI_CR_IO_EN | PCI_CR_MAST_EN);
01454 }
01455 
01456 /*===========================================================================*
01457  *                              get_freebus                                  *
01458  *===========================================================================*/
01459 PRIVATE int get_freebus()
01460 {
01461         int i, freebus;
01462 
01463         freebus= 1;
01464         for (i= 0; i<nr_pcibus; i++)
01465         {
01466                 if (pcibus[i].pb_needinit)
01467                         continue;
01468                 if (pcibus[i].pb_type == PBT_INTEL_HOST)
01469                         continue;
01470                 if (pcibus[i].pb_busnr <= freebus)
01471                         freebus= pcibus[i].pb_busnr+1;
01472                 printf("get_freebus: should check suboridinate bus number\n");
01473         }
01474         return freebus;
01475 }
01476 
01477 /*===========================================================================*
01478  *                              do_isabridge                                 *
01479  *===========================================================================*/
01480 PRIVATE int do_isabridge(busind)
01481 int busind;
01482 {
01483         int i, j, r, type, busnr, unknown_bridge, bridge_dev;
01484         u16_t vid, did;
01485         u32_t t3;
01486         char *dstr;
01487 
01488         unknown_bridge= -1;
01489         bridge_dev= -1;
01490         j= 0;   /* lint */
01491         vid= did= 0;    /* lint */
01492         busnr= pcibus[busind].pb_busnr;
01493         for (i= 0; i< nr_pcidev; i++)
01494         {
01495                 if (pcidev[i].pd_busnr != busnr)
01496                         continue;
01497                 t3= ((pcidev[i].pd_baseclass << 16) |
01498                         (pcidev[i].pd_subclass << 8) | pcidev[i].pd_infclass);
01499                 if (t3 == PCI_T3_ISA)
01500                 {
01501                         /* ISA bridge. Report if no supported bridge is
01502                          * found.
01503                          */
01504                         unknown_bridge= i;
01505                 }
01506 
01507                 vid= pcidev[i].pd_vid;
01508                 did= pcidev[i].pd_did;
01509                 for (j= 0; pci_isabridge[j].vid != 0; j++)
01510                 {
01511                         if (pci_isabridge[j].vid != vid)
01512                                 continue;
01513                         if (pci_isabridge[j].did != did)
01514                                 continue;
01515                         if (pci_isabridge[j].checkclass &&
01516                                 unknown_bridge != i)
01517                         {
01518                                 /* This part of multifunction device is
01519                                  * not the bridge.
01520                                  */
01521                                 continue;
01522                         }
01523                         break;
01524                 }
01525                 if (pci_isabridge[j].vid)
01526                 {
01527                         bridge_dev= i;
01528                         break;
01529                 }
01530         }
01531 
01532         if (bridge_dev != -1)
01533         {
01534                 dstr= pci_dev_name(vid, did);
01535                 if (!dstr)
01536                         dstr= "unknown device";
01537                 if (debug)
01538                 {
01539                         printf("found ISA bridge (%04X/%04X) %s\n",
01540                                 vid, did, dstr);
01541                 }
01542                 pcibus[busind].pb_isabridge_dev= bridge_dev;
01543                 type= pci_isabridge[j].type;
01544                 pcibus[busind].pb_isabridge_type= type;
01545                 switch(type)
01546                 {
01547                 case PCI_IB_PIIX:
01548                         r= do_piix(bridge_dev);
01549                         break;
01550                 case PCI_IB_VIA:
01551                         r= do_via_isabr(bridge_dev);
01552                         break;
01553                 case PCI_IB_AMD:
01554                         r= do_amd_isabr(bridge_dev);
01555                         break;
01556                 case PCI_IB_SIS:
01557                         r= do_sis_isabr(bridge_dev);
01558                         break;
01559                 default:
01560                         panic("PCI","unknown ISA bridge type", type);
01561                 }
01562                 return r;
01563         }
01564 
01565         if (unknown_bridge == -1)
01566         {
01567                 if (debug)
01568                 {
01569                         printf("(warning) no ISA bridge found on bus %d\n",
01570                                 busind);
01571                 }
01572                 return 0;
01573         }
01574         if (debug)
01575         {
01576                 printf(
01577                 "(warning) unsupported ISA bridge %04X/%04X for bus %d\n",
01578                         pcidev[unknown_bridge].pd_vid,
01579                         pcidev[unknown_bridge].pd_did, busind);
01580         }
01581         return 0;
01582 }
01583 
01584 /*===========================================================================*
01585  *                              do_pcibridge                                 *
01586  *===========================================================================*/
01587 PRIVATE void do_pcibridge(busind)
01588 int busind;
01589 {
01590         int i, devind, busnr;
01591         int ind, type;
01592         u16_t vid, did;
01593         u8_t sbusn, baseclass, subclass, infclass, headt;
01594         u32_t t3;
01595 
01596         vid= did= 0;    /* lint */
01597         busnr= pcibus[busind].pb_busnr;
01598         for (devind= 0; devind< nr_pcidev; devind++)
01599         {
01600 #if 0
01601                 printf("do_pcibridge: trying %u.%u.%u\n",
01602                         pcidev[devind].pd_busind, pcidev[devind].pd_dev, 
01603                         pcidev[devind].pd_func);
01604 #endif
01605 
01606                 if (pcidev[devind].pd_busnr != busnr)
01607                 {
01608 #if 0
01609                         printf("wrong bus\n");
01610 #endif
01611                         continue;
01612                 }
01613 
01614                 vid= pcidev[devind].pd_vid;
01615                 did= pcidev[devind].pd_did;
01616                 for (i= 0; pci_pcibridge[i].vid != 0; i++)
01617                 {
01618                         if (pci_pcibridge[i].vid != vid)
01619                                 continue;
01620                         if (pci_pcibridge[i].did != did)
01621                                 continue;
01622                         break;
01623                 }
01624                 type= pci_pcibridge[i].type;
01625                 if (pci_pcibridge[i].vid == 0)
01626                 {
01627                         headt= pci_attr_r8(devind, PCI_HEADT);
01628                         type= 0;
01629                         if ((headt & PHT_MASK) == PHT_BRIDGE)
01630                                 type= PCI_PPB_STD;
01631                         else if ((headt & PHT_MASK) == PHT_CARDBUS)
01632                                 type= PCI_PPB_CB;
01633                         else
01634                         {
01635 #if 0
01636                                 printf("not a bridge\n");
01637 #endif
01638                                 continue;       /* Not a bridge */
01639                         }
01640 
01641                         baseclass= pci_attr_r8(devind, PCI_BCR);
01642                         subclass= pci_attr_r8(devind, PCI_SCR);
01643                         infclass= pci_attr_r8(devind, PCI_PIFR);
01644                         t3= ((baseclass << 16) | (subclass << 8) | infclass);
01645                         if (type == PCI_PPB_STD &&
01646                                 t3 != PCI_T3_PCI2PCI &&
01647                                 t3 != PCI_T3_PCI2PCI_SUBTR)
01648                         {
01649                                 printf(
01650 "Unknown PCI class %02x:%02x:%02x for PCI-to-PCI bridge, device %04X/%04X\n",
01651                                         baseclass, subclass, infclass,
01652                                         vid, did);
01653                                 continue;
01654                          }
01655                         if (type == PCI_PPB_CB &&
01656                                 t3 != PCI_T3_CARDBUS)
01657                         {
01658                                 printf(
01659 "Unknown PCI class %02x:%02x:%02x for Cardbus bridge, device %04X/%04X\n",
01660                                         baseclass, subclass, infclass,
01661                                         vid, did);
01662                                 continue;
01663                          }
01664                 }
01665 
01666                 if (debug)
01667                 {
01668                         printf("%u.%u.%u: PCI-to-PCI bridge: %04X/%04X\n",
01669                                 pcidev[devind].pd_busnr,
01670                                 pcidev[devind].pd_dev, 
01671                                 pcidev[devind].pd_func, vid, did);
01672                 }
01673 
01674                 /* Assume that the BIOS initialized the secondary bus
01675                  * number.
01676                  */
01677                 sbusn= pci_attr_r8(devind, PPB_SECBN);
01678 #if DEBUG
01679                 printf("sbusn = %d\n", sbusn);
01680                 printf("subordn = %d\n", pci_attr_r8(devind, PPB_SUBORDBN));
01681 #endif
01682 
01683                 if (nr_pcibus >= NR_PCIBUS)
01684                         panic("PCI","too many PCI busses", nr_pcibus);
01685                 ind= nr_pcibus;
01686                 nr_pcibus++;
01687                 pcibus[ind].pb_type= PBT_PCIBRIDGE;
01688                 pcibus[ind].pb_needinit= 1;
01689                 pcibus[ind].pb_isabridge_dev= -1;
01690                 pcibus[ind].pb_isabridge_type= 0;
01691                 pcibus[ind].pb_devind= devind;
01692                 pcibus[ind].pb_busnr= sbusn;
01693                 pcibus[ind].pb_rreg8= pcibus[busind].pb_rreg8;
01694                 pcibus[ind].pb_rreg16= pcibus[busind].pb_rreg16;
01695                 pcibus[ind].pb_rreg32= pcibus[busind].pb_rreg32;
01696                 pcibus[ind].pb_wreg8= pcibus[busind].pb_wreg8;
01697                 pcibus[ind].pb_wreg16= pcibus[busind].pb_wreg16;
01698                 pcibus[ind].pb_wreg32= pcibus[busind].pb_wreg32;
01699                 switch(type)
01700                 {
01701                 case PCI_PPB_STD:
01702                         pcibus[ind].pb_rsts= pcibr_std_rsts;
01703                         pcibus[ind].pb_wsts= pcibr_std_wsts;
01704                         break;
01705                 case PCI_PPB_CB:
01706                         pcibus[ind].pb_type= PBT_CARDBUS;
01707                         pcibus[ind].pb_rsts= pcibr_cb_rsts;
01708                         pcibus[ind].pb_wsts= pcibr_cb_wsts;
01709                         break;
01710                 case PCI_AGPB_VIA:
01711                         pcibus[ind].pb_rsts= pcibr_via_rsts;
01712                         pcibus[ind].pb_wsts= pcibr_via_wsts;
01713                         break;
01714                 default:
01715                     panic("PCI","unknown PCI-PCI bridge type", type);
01716                 }
01717                 if (sbusn == 0)
01718                 {
01719                         printf("Secondary bus number not initialized\n");
01720                         continue;
01721                 }
01722                 pcibus[ind].pb_needinit= 0;
01723 
01724                 probe_bus(ind);
01725 
01726                 /* Look for PCI bridges */
01727                 do_pcibridge(ind);
01728         }
01729 }
01730 
01731 /*===========================================================================*
01732  *                              get_busind                                           *
01733  *===========================================================================*/
01734 PRIVATE int get_busind(busnr)
01735 int busnr;
01736 {
01737         int i;
01738 
01739         for (i= 0; i<nr_pcibus; i++)
01740         {
01741                 if (pcibus[i].pb_busnr == busnr)
01742                         return i;
01743         }
01744         panic("pci", "get_busind: can't find bus", busnr);
01745 }
01746 
01747 /*===========================================================================*
01748  *                              do_piix                                      *
01749  *===========================================================================*/
01750 PRIVATE int do_piix(devind)
01751 int devind;
01752 {
01753         int i, s, dev, func, irqrc, irq;
01754         u32_t elcr1, elcr2, elcr;
01755 
01756 #if DEBUG
01757         printf("in piix\n");
01758 #endif
01759         dev= pcidev[devind].pd_dev;
01760         func= pcidev[devind].pd_func;
01761 #if USER_SPACE
01762         if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1)))
01763                 printf("Warning, sys_inb failed: %d\n", s);
01764         if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2)))
01765                 printf("Warning, sys_inb failed: %d\n", s);
01766 #else
01767         elcr1= inb(PIIX_ELCR1);
01768         elcr2= inb(PIIX_ELCR2);
01769 #endif
01770         elcr= elcr1 | (elcr2 << 8);
01771         for (i= 0; i<4; i++)
01772         {
01773                 irqrc= pci_attr_r8(devind, PIIX_PIRQRCA+i);
01774                 if (irqrc & PIIX_IRQ_DI)
01775                 {
01776                         if (debug)
01777                                 printf("INT%c: disabled\n", 'A'+i);
01778                 }
01779                 else
01780                 {
01781                         irq= irqrc & PIIX_IRQ_MASK;
01782                         if (debug)
01783                                 printf("INT%c: %d\n", 'A'+i, irq);
01784                         if (!(elcr & (1 << irq)))
01785                         {
01786                                 if (debug)
01787                                 {
01788                                         printf(
01789                                 "(warning) IRQ %d is not level triggered\n", 
01790                                                 irq);
01791                                 }
01792                         }
01793                         irq_mode_pci(irq);
01794                 }
01795         }
01796         return 0;
01797 }
01798 
01799 /*===========================================================================*
01800  *                              do_amd_isabr                                 *
01801  *===========================================================================*/
01802 PRIVATE int do_amd_isabr(devind)
01803 int devind;
01804 {
01805         int i, busnr, dev, func, xdevind, irq, edge;
01806         u8_t levmask;
01807         u16_t pciirq;
01808 
01809         /* Find required function */
01810         func= AMD_ISABR_FUNC;
01811         busnr= pcidev[devind].pd_busnr;
01812         dev= pcidev[devind].pd_dev;
01813 
01814         /* Fake a device with the required function */
01815         if (nr_pcidev >= NR_PCIDEV)
01816                 panic("PCI","too many PCI devices", nr_pcidev);
01817         xdevind= nr_pcidev;
01818         pcidev[xdevind].pd_busnr= busnr;
01819         pcidev[xdevind].pd_dev= dev;
01820         pcidev[xdevind].pd_func= func;
01821         pcidev[xdevind].pd_inuse= 1;
01822         nr_pcidev++;
01823 
01824         levmask= pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV);
01825         pciirq= pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE);
01826         for (i= 0; i<4; i++)
01827         {
01828                 edge= (levmask >> i) & 1;
01829                 irq= (pciirq >> (4*i)) & 0xf;
01830                 if (!irq)
01831                 {
01832                         if (debug)
01833                                 printf("INT%c: disabled\n", 'A'+i);
01834                 }
01835                 else
01836                 {
01837                         if (debug)
01838                                 printf("INT%c: %d\n", 'A'+i, irq);
01839                         if (edge && debug)
01840                         {
01841                                 printf(
01842                                 "(warning) IRQ %d is not level triggered\n",
01843                                         irq);
01844                         }
01845                         irq_mode_pci(irq);
01846                 }
01847         }
01848         nr_pcidev--;
01849         return 0;
01850 }
01851 
01852 /*===========================================================================*
01853  *                              do_sis_isabr                                 *
01854  *===========================================================================*/
01855 PRIVATE int do_sis_isabr(devind)
01856 int devind;
01857 {
01858         int i, dev, func, irq;
01859 
01860         dev= pcidev[devind].pd_dev;
01861         func= pcidev[devind].pd_func;
01862         irq= 0; /* lint */
01863         for (i= 0; i<4; i++)
01864         {
01865                 irq= pci_attr_r8(devind, SIS_ISABR_IRQ_A+i);
01866                 if (irq & SIS_IRQ_DISABLED)
01867                 {
01868                         if (debug)
01869                                 printf("INT%c: disabled\n", 'A'+i);
01870                 }
01871                 else
01872                 {
01873                         irq &= SIS_IRQ_MASK;
01874                         if (debug)
01875                                 printf("INT%c: %d\n", 'A'+i, irq);
01876                         irq_mode_pci(irq);
01877                 }
01878         }
01879         return 0;
01880 }
01881 
01882 /*===========================================================================*
01883  *                              do_via_isabr                                 *
01884  *===========================================================================*/
01885 PRIVATE int do_via_isabr(devind)
01886 int devind;
01887 {
01888         int i, dev, func, irq, edge;
01889         u8_t levmask;
01890 
01891         dev= pcidev[devind].pd_dev;
01892         func= pcidev[devind].pd_func;
01893         levmask= pci_attr_r8(devind, VIA_ISABR_EL);
01894         irq= 0; /* lint */
01895         edge= 0; /* lint */
01896         for (i= 0; i<4; i++)
01897         {
01898                 switch(i)
01899                 {
01900                 case 0:
01901                         edge= (levmask & VIA_ISABR_EL_INTA);
01902                         irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R2) >> 4;
01903                         break;
01904                 case 1:
01905                         edge= (levmask & VIA_ISABR_EL_INTB);
01906                         irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R2);
01907                         break;
01908                 case 2:
01909                         edge= (levmask & VIA_ISABR_EL_INTC);
01910                         irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R3) >> 4;
01911                         break;
01912                 case 3:
01913                         edge= (levmask & VIA_ISABR_EL_INTD);
01914                         irq= pci_attr_r8(devind, VIA_ISABR_IRQ_R1) >> 4;
01915                         break;
01916                 default:
01917                         assert(0);
01918                 }
01919                 irq &= 0xf;
01920                 if (!irq)
01921                 {
01922                         if (debug)
01923                                 printf("INT%c: disabled\n", 'A'+i);
01924                 }
01925                 else
01926                 {
01927                         if (debug)
01928                                 printf("INT%c: %d\n", 'A'+i, irq);
01929                         if (edge && debug)
01930                         {
01931                                 printf(
01932                                 "(warning) IRQ %d is not level triggered\n",
01933                                         irq);
01934                         }
01935                         irq_mode_pci(irq);
01936                 }
01937         }
01938         return 0;
01939 }
01940 
01941 
01942 /*===========================================================================*
01943  *                              report_vga                                   *
01944  *===========================================================================*/
01945 PRIVATE void report_vga(devind)
01946 int devind;
01947 {
01948         /* Report the amount of video memory. This is needed by the X11R6
01949          * postinstall script to chmem the X server. Hopefully this can be
01950          * removed when we get virtual memory.
01951          */
01952         size_t amount, size;
01953         int i;
01954 
01955         amount= 0;
01956         for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
01957         {
01958                 if (pcidev[devind].pd_bar[i].pb_flags & PBF_IO)
01959                         continue;
01960                 size= pcidev[devind].pd_bar[i].pb_size;
01961                 if (size < amount)
01962                         continue;
01963                 amount= size;
01964         }
01965         if (size != 0)
01966         {
01967                 printf("PCI: video memory for device at %d.%d.%d: %d bytes\n",
01968                         pcidev[devind].pd_busnr,
01969                         pcidev[devind].pd_dev,
01970                         pcidev[devind].pd_func,
01971                         amount);
01972         }
01973 }
01974 
01975 
01976 /*===========================================================================*
01977  *                              pci_vid_name                                 *
01978  *===========================================================================*/
01979 PRIVATE char *pci_vid_name(vid)
01980 u16_t vid;
01981 {
01982         int i;
01983 
01984         for (i= 0; pci_vendor_table[i].name; i++)
01985         {
01986                 if (pci_vendor_table[i].vid == vid)
01987                         return pci_vendor_table[i].name;
01988         }
01989         return "unknown";
01990 }
01991 
01992 /*===========================================================================*
01993  *                              pci_baseclass_name                           *
01994  *===========================================================================*/
01995 PRIVATE char *pci_baseclass_name(baseclass)
01996 u8_t baseclass;
01997 {
01998         int i;
01999 
02000         for (i= 0; pci_baseclass_table[i].name; i++)
02001         {
02002                 if (pci_baseclass_table[i].baseclass == baseclass)
02003                         return pci_baseclass_table[i].name;
02004         }
02005         return NULL;
02006 }
02007 
02008 /*===========================================================================*
02009  *                              pci_subclass_name                            *
02010  *===========================================================================*/
02011 PRIVATE char *pci_subclass_name(baseclass, subclass, infclass)
02012 u8_t baseclass;
02013 u8_t subclass;
02014 u8_t infclass;
02015 {
02016         int i;
02017 
02018         for (i= 0; pci_subclass_table[i].name; i++)
02019         {
02020                 if (pci_subclass_table[i].baseclass != baseclass)
02021                         continue;
02022                 if (pci_subclass_table[i].subclass != subclass)
02023                         continue;
02024                 if (pci_subclass_table[i].infclass != infclass &&
02025                         pci_subclass_table[i].infclass != (u16_t)-1)
02026                 {
02027                         continue;
02028                 }
02029                 return pci_subclass_table[i].name;
02030         }
02031         return NULL;
02032 }
02033 
02034 /*===========================================================================*
02035  *                              ntostr                                       *
02036  *===========================================================================*/
02037 PRIVATE void ntostr(n, str, end)
02038 unsigned n;
02039 char **str;
02040 char *end;
02041 {
02042         char tmpstr[20];
02043         int i;
02044 
02045         if (n == 0)
02046         {
02047                 tmpstr[0]= '0';
02048                 i= 1;
02049         }
02050         else
02051         {
02052                 for (i= 0; n; i++)
02053                 {
02054                         tmpstr[i]= '0' + (n%10);
02055                         n /= 10;
02056                 }
02057         }
02058         for (; i>0; i--)
02059         {
02060                 if (*str == end)
02061                 {
02062                         break;
02063                 }
02064                 **str= tmpstr[i-1];
02065                 (*str)++;
02066         }
02067         if (*str == end)        
02068                 end[-1]= '\0';
02069         else
02070                 **str= '\0';
02071 }
02072 
02073 /*===========================================================================*
02074  *                              pci_attr_rsts                                *
02075  *===========================================================================*/
02076 PRIVATE u16_t pci_attr_rsts(devind)
02077 int devind;
02078 {
02079         int busnr, busind;
02080 
02081         busnr= pcidev[devind].pd_busnr;
02082         busind= get_busind(busnr);
02083         return pcibus[busind].pb_rsts(busind);
02084 }
02085                                 
02086 
02087 /*===========================================================================*
02088  *                              pcibr_std_rsts                               *
02089  *===========================================================================*/
02090 PRIVATE u16_t pcibr_std_rsts(busind)
02091 int busind;
02092 {
02093         int devind;
02094 
02095         devind= pcibus[busind].pb_devind;
02096         return pci_attr_r16(devind, PPB_SSTS);
02097 }
02098 
02099 /*===========================================================================*
02100  *                              pcibr_std_wsts                               *
02101  *===========================================================================*/
02102 PRIVATE void pcibr_std_wsts(busind, value)
02103 int busind;
02104 u16_t value;
02105 {
02106         int devind;
02107         devind= pcibus[busind].pb_devind;
02108 
02109 #if 0
02110         printf("pcibr_std_wsts(%d, 0x%X), devind= %d\n", 
02111                 busind, value, devind);
02112 #endif
02113         pci_attr_w16(devind, PPB_SSTS, value);
02114 }
02115 
02116 /*===========================================================================*
02117  *                              pcibr_cb_rsts                                *
02118  *===========================================================================*/
02119 PRIVATE u16_t pcibr_cb_rsts(busind)
02120 int busind;
02121 {
02122         int devind;
02123         devind= pcibus[busind].pb_devind;
02124 
02125         return pci_attr_r16(devind, CBB_SSTS);
02126 }
02127 
02128 /*===========================================================================*
02129  *                              pcibr_cb_wsts                                *
02130  *===========================================================================*/
02131 PRIVATE void pcibr_cb_wsts(busind, value)
02132 int busind;
02133 u16_t value;
02134 {
02135         int devind;
02136         devind= pcibus[busind].pb_devind;
02137 
02138 #if 0
02139         printf("pcibr_cb_wsts(%d, 0x%X), devind= %d\n", 
02140                 busind, value, devind);
02141 #endif
02142         pci_attr_w16(devind, CBB_SSTS, value);
02143 }
02144 
02145 /*===========================================================================*
02146  *                              pcibr_via_rsts                               *
02147  *===========================================================================*/
02148 PRIVATE u16_t pcibr_via_rsts(busind)
02149 int busind;
02150 {
02151         int devind;
02152         devind= pcibus[busind].pb_devind;
02153 
02154         return 0;
02155 }
02156 
02157 /*===========================================================================*
02158  *                              pcibr_via_wsts                               *
02159  *===========================================================================*/
02160 PRIVATE void pcibr_via_wsts(busind, value)
02161 int busind;
02162 u16_t value;
02163 {
02164         int devind;
02165         devind= pcibus[busind].pb_devind;
02166 
02167 #if 0
02168         printf("pcibr_via_wsts(%d, 0x%X), devind= %d (not implemented)\n", 
02169                 busind, value, devind);
02170 #endif
02171 }
02172 
02173 /*===========================================================================*
02174  *                              pci_attr_wsts                                *
02175  *===========================================================================*/
02176 PRIVATE void pci_attr_wsts(devind, value)
02177 int devind;
02178 u16_t value;
02179 {
02180         int busnr, busind;
02181 
02182         busnr= pcidev[devind].pd_busnr;
02183         busind= get_busind(busnr);
02184         pcibus[busind].pb_wsts(busind, value);
02185 }
02186                                 
02187 
02188 /*===========================================================================*
02189  *                              pcii_rreg8                                   *
02190  *===========================================================================*/
02191 PRIVATE u8_t pcii_rreg8(busind, devind, port)
02192 int busind;
02193 int devind;
02194 int port;
02195 {
02196         u8_t v;
02197         int s;
02198 
02199         v= PCII_RREG8_(pcibus[busind].pb_busnr, 
02200                 pcidev[devind].pd_dev, pcidev[devind].pd_func,
02201                 port);
02202 #if USER_SPACE
02203         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02204                 printf("PCI: warning, sys_outl failed: %d\n", s);
02205 #else
02206         outl(PCII_CONFADD, PCII_UNSEL);
02207 #endif
02208 #if 0
02209         printf("pcii_rreg8(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
02210                 busind, devind, port,
02211                 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
02212                 pcidev[devind].pd_func, v);
02213 #endif
02214         return v;
02215 }
02216 
02217 /*===========================================================================*
02218  *                              pcii_rreg16                                  *
02219  *===========================================================================*/
02220 PRIVATE u16_t pcii_rreg16(busind, devind, port)
02221 int busind;
02222 int devind;
02223 int port;
02224 {
02225         u16_t v;
02226         int s;
02227 
02228         v= PCII_RREG16_(pcibus[busind].pb_busnr, 
02229                 pcidev[devind].pd_dev, pcidev[devind].pd_func,
02230                 port);
02231 #if USER_SPACE
02232         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02233                 printf("PCI: warning, sys_outl failed: %d\n");
02234 #else
02235         outl(PCII_CONFADD, PCII_UNSEL);
02236 #endif
02237 #if 0
02238         printf("pcii_rreg16(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
02239                 busind, devind, port,
02240                 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
02241                 pcidev[devind].pd_func, v);
02242 #endif
02243         return v;
02244 }
02245 
02246 /*===========================================================================*
02247  *                              pcii_rreg32                                  *
02248  *===========================================================================*/
02249 PRIVATE u32_t pcii_rreg32(busind, devind, port)
02250 int busind;
02251 int devind;
02252 int port;
02253 {
02254         u32_t v;
02255         int s;
02256 
02257         v= PCII_RREG32_(pcibus[busind].pb_busnr, 
02258                 pcidev[devind].pd_dev, pcidev[devind].pd_func,
02259                 port);
02260 #if USER_SPACE
02261         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02262                 printf("PCI: warning, sys_outl failed: %d\n", s);
02263 #else
02264         outl(PCII_CONFADD, PCII_UNSEL);
02265 #endif
02266 #if 0
02267         printf("pcii_rreg32(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
02268                 busind, devind, port,
02269                 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
02270                 pcidev[devind].pd_func, v);
02271 #endif
02272         return v;
02273 }
02274 
02275 /*===========================================================================*
02276  *                              pcii_wreg8                                   *
02277  *===========================================================================*/
02278 PRIVATE void pcii_wreg8(busind, devind, port, value)
02279 int busind;
02280 int devind;
02281 int port;
02282 u8_t value;
02283 {
02284         int s;
02285 #if 0
02286         printf("pcii_wreg8(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
02287                 busind, devind, port, value,
02288                 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
02289                 pcidev[devind].pd_func);
02290 #endif
02291         PCII_WREG8_(pcibus[busind].pb_busnr, 
02292                 pcidev[devind].pd_dev, pcidev[devind].pd_func,
02293                 port, value);
02294 #if USER_SPACE
02295         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02296                 printf("PCI: warning, sys_outl failed: %d\n", s);
02297 #else
02298         outl(PCII_CONFADD, PCII_UNSEL);
02299 #endif
02300 }
02301 
02302 /*===========================================================================*
02303  *                              pcii_wreg16                                  *
02304  *===========================================================================*/
02305 PRIVATE void pcii_wreg16(busind, devind, port, value)
02306 int busind;
02307 int devind;
02308 int port;
02309 u16_t value;
02310 {
02311         int s;
02312 #if 0
02313         printf("pcii_wreg16(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
02314                 busind, devind, port, value,
02315                 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
02316                 pcidev[devind].pd_func);
02317 #endif
02318         PCII_WREG16_(pcibus[busind].pb_busnr, 
02319                 pcidev[devind].pd_dev, pcidev[devind].pd_func,
02320                 port, value);
02321 #if USER_SPACE
02322         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02323                 printf("PCI: warning, sys_outl failed: %d\n", s);
02324 #else
02325         outl(PCII_CONFADD, PCII_UNSEL);
02326 #endif
02327 }
02328 
02329 /*===========================================================================*
02330  *                              pcii_wreg32                                  *
02331  *===========================================================================*/
02332 PRIVATE void pcii_wreg32(busind, devind, port, value)
02333 int busind;
02334 int devind;
02335 int port;
02336 u32_t value;
02337 {
02338         int s;
02339 #if 0
02340         printf("pcii_wreg32(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
02341                 busind, devind, port, value,
02342                 pcibus[busind].pb_bus, pcidev[devind].pd_dev,
02343                 pcidev[devind].pd_func);
02344 #endif
02345         PCII_WREG32_(pcibus[busind].pb_busnr, 
02346                 pcidev[devind].pd_dev, pcidev[devind].pd_func,
02347                 port, value);
02348 #if USER_SPACE
02349         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02350                 printf("PCI: warning, sys_outl failed: %d\n");
02351 #else
02352         outl(PCII_CONFADD, PCII_UNSEL);
02353 #endif
02354 }
02355 
02356 /*===========================================================================*
02357  *                              pcii_rsts                                    *
02358  *===========================================================================*/
02359 PRIVATE u16_t pcii_rsts(busind)
02360 int busind;
02361 {
02362         u16_t v;
02363         int s;
02364 
02365         v= PCII_RREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR);
02366 #if USER_SPACE
02367         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02368                 printf("PCI: warning, sys_outl failed: %d\n", s);
02369 #else
02370         outl(PCII_CONFADD, PCII_UNSEL);
02371 #endif
02372         return v;
02373 }
02374 
02375 /*===========================================================================*
02376  *                              pcii_wsts                                    *
02377  *===========================================================================*/
02378 PRIVATE void pcii_wsts(busind, value)
02379 int busind;
02380 u16_t value;
02381 {
02382         int s;
02383         PCII_WREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR, value);
02384 #if USER_SPACE
02385         if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
02386                 printf("PCI: warning, sys_outl failed: %d\n", s);
02387 #else
02388         outl(PCII_CONFADD, PCII_UNSEL);
02389 #endif
02390 }
02391 
02392 
02393 /*===========================================================================*
02394  *                              print_capabilities                           *
02395  *===========================================================================*/
02396 PRIVATE void print_capabilities(devind)
02397 int devind;
02398 {
02399         u8_t status, capptr, type, next;
02400         char *str;
02401 
02402         /* Check capabilities bit in the device status register */
02403         status= pci_attr_r16(devind, PCI_SR);
02404         if (!(status & PSR_CAPPTR))
02405                 return;
02406 
02407         capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK);
02408         while (capptr != 0)
02409         {
02410                 type = pci_attr_r8(devind, capptr+CAP_TYPE);
02411                 next= (pci_attr_r8(devind, capptr+CAP_NEXT) & PCI_CP_MASK);
02412                 switch(type)
02413                 {
02414                 case 1: str= "PCI Power Management"; break;
02415                 case 2: str= "AGP"; break;
02416                 case 3: str= "Vital Product Data"; break;
02417                 case 4: str= "Slot Identification"; break;
02418                 case 5: str= "Message Signaled Interrupts"; break;
02419                 case 6: str= "CompactPCI Hot Swap"; break;
02420                 case 8: str= "AMD HyperTransport"; break;
02421                 case 0xf: str= "AMD I/O MMU"; break;
02422                 defuault: str= "(unknown type)"; break;
02423                 }
02424 
02425                 printf(" @0x%x: capability type 0x%x: %s\n",
02426                         capptr, type, str);
02427                 capptr= next;
02428         }
02429 }
02430 
02431 /*
02432  * $PchId: pci.c,v 1.7 2003/08/07 09:06:51 philip Exp $
02433  */

Generated on Fri Apr 14 22:57:17 2006 for minix by  doxygen 1.4.6