The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mtx/pci.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * PCI support code.
    3  */
    4 #include "u.h"
    5 #include "../port/lib.h"
    6 #include "mem.h"
    7 #include "dat.h"
    8 #include "fns.h"
    9 #include "io.h"
   10 #include "../port/error.h"
   11 
   12 #define DBG     if(0) pcilog
   13 
   14 struct
   15 {
   16         char    output[16384];
   17         int     ptr;
   18 }PCICONS;
   19 
   20 int
   21 pcilog(char *fmt, ...)
   22 {
   23         int n;
   24         va_list arg;
   25         char buf[PRINTSIZE];
   26 
   27         va_start(arg, fmt);
   28         n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
   29         va_end(arg);
   30 
   31         memmove(PCICONS.output+PCICONS.ptr, buf, n);
   32         PCICONS.ptr += n;
   33         return n;
   34 }
   35 
   36 enum
   37 {                                       /* configuration mechanism #1 */
   38         PciADDR         = 0xCF8,        /* CONFIG_ADDRESS */
   39         PciDATA         = 0xCFC,        /* CONFIG_DATA */
   40 
   41                                         /* configuration mechanism #2 */
   42         PciCSE          = 0xCF8,        /* configuration space enable */
   43         PciFORWARD      = 0xCFA,        /* which bus */
   44 
   45         MaxFNO          = 7,
   46         MaxUBN          = 255,
   47 };
   48 
   49 enum
   50 {                                       /* command register */
   51         IOen            = (1<<0),
   52         MEMen           = (1<<1),
   53         MASen           = (1<<2),
   54         MemWrInv        = (1<<4),
   55         PErrEn          = (1<<6),
   56         SErrEn          = (1<<8),
   57 };
   58 
   59 static Lock pcicfglock;
   60 static QLock pcicfginitlock;
   61 static int pcicfgmode = -1;
   62 static int pcimaxbno = 7;
   63 static int pcimaxdno;
   64 static Pcidev* pciroot;
   65 static Pcidev* pcilist;
   66 static Pcidev* pcitail;
   67 
   68 static int pcicfgrw32(int, int, int, int);
   69 static int pcicfgrw8(int, int, int, int);
   70 
   71 static char* bustypes[] = {
   72         "CBUSI",
   73         "CBUSII",
   74         "EISA",
   75         "FUTURE",
   76         "INTERN",
   77         "ISA",
   78         "MBI",
   79         "MBII",
   80         "MCA",
   81         "MPI",
   82         "MPSA",
   83         "NUBUS",
   84         "PCI",
   85         "PCMCIA",
   86         "TC",
   87         "VL",
   88         "VME",
   89         "XPRESS",
   90 };
   91 
   92 #pragma varargck        type    "T"     int
   93 
   94 static int
   95 tbdffmt(Fmt* fmt)
   96 {
   97         char *p;
   98         int l, r, type, tbdf;
   99 
  100         if((p = malloc(READSTR)) == nil)
  101                 return fmtstrcpy(fmt, "(tbdfconv)");
  102                 
  103         switch(fmt->r){
  104         case 'T':
  105                 tbdf = va_arg(fmt->args, int);
  106                 type = BUSTYPE(tbdf);
  107                 if(type < nelem(bustypes))
  108                         l = snprint(p, READSTR, bustypes[type]);
  109                 else
  110                         l = snprint(p, READSTR, "%d", type);
  111                 snprint(p+l, READSTR-l, ".%d.%d.%d",
  112                         BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  113                 break;
  114 
  115         default:
  116                 snprint(p, READSTR, "(tbdfconv)");
  117                 break;
  118         }
  119         r = fmtstrcpy(fmt, p);
  120         free(p);
  121 
  122         return r;
  123 }
  124 
  125 ulong
  126 pcibarsize(Pcidev *p, int rno)
  127 {
  128         ulong v, size;
  129 
  130         v = pcicfgrw32(p->tbdf, rno, 0, 1);
  131         pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
  132         size = pcicfgrw32(p->tbdf, rno, 0, 1);
  133         if(v & 1)
  134                 size |= 0xFFFF0000;
  135         pcicfgrw32(p->tbdf, rno, v, 0);
  136 
  137         return -(size & ~0x0F);
  138 }
  139 
  140 static int
  141 pcisizcmp(void *a, void *b)
  142 {
  143         Pcisiz *aa, *bb;
  144 
  145         aa = a;
  146         bb = b;
  147         return aa->siz - bb->siz;
  148 }
  149 
  150 static ulong
  151 pcimask(ulong v)
  152 {
  153         ulong m;
  154 
  155         m = BI2BY*sizeof(v);
  156         for(m = 1<<(m-1); m != 0; m >>= 1) {
  157                 if(m & v)
  158                         break;
  159         }
  160 
  161         m--;
  162         if((v & m) == 0)
  163                 return v;
  164 
  165         v |= m;
  166         return v+1;
  167 }
  168 
  169 static void
  170 pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
  171 {
  172         Pcidev *p;
  173         int ntb, i, size, rno, hole;
  174         ulong v, mema, ioa, sioa, smema, base, limit;
  175         Pcisiz *table, *tptr, *mtb, *itb;
  176         extern void qsort(void*, long, long, int (*)(void*, void*));
  177 
  178         ioa = *pioa;
  179         mema = *pmema;
  180 
  181         DBG("pcibusmap wr=%d %T mem=%luX io=%luX\n", 
  182                 wrreg, root->tbdf, mema, ioa);
  183 
  184         ntb = 0;
  185         for(p = root; p != nil; p = p->link)
  186                 ntb++;
  187 
  188         ntb *= (PciCIS-PciBAR0)/4;
  189         table = malloc(2*ntb*sizeof(Pcisiz));
  190         itb = table;
  191         mtb = table+ntb;
  192 
  193         /*
  194          * Build a table of sizes
  195          */
  196         for(p = root; p != nil; p = p->link) {
  197                 if(p->ccrb == 0x06) {
  198                         if(p->ccru == 0x04 && p->bridge != nil) {
  199                                 sioa = ioa;
  200                                 smema = mema;
  201                                 pcibusmap(p->bridge, &smema, &sioa, 0);
  202         
  203                                 hole = pcimask(smema-mema);
  204                                 if(hole < (1<<20))
  205                                         hole = 1<<20;
  206                                 p->mema.size = hole;
  207         
  208                                 hole = pcimask(sioa-ioa);
  209                                 if(hole < (1<<12))
  210                                         hole = 1<<12;
  211         
  212                                 p->ioa.size = hole;
  213         
  214                                 itb->dev = p;
  215                                 itb->bar = -1;
  216                                 itb->siz = p->ioa.size;
  217                                 itb++;
  218         
  219                                 mtb->dev = p;
  220                                 mtb->bar = -1;
  221                                 mtb->siz = p->mema.size;
  222                                 mtb++;
  223                         }
  224                         if((pcicfgr8(p, PciHDT)&0x7f) != 0)
  225                                 continue;
  226                 }
  227 
  228                 for(i = 0; i <= 5; i++) {
  229                         rno = PciBAR0 + i*4;
  230                         v = pcicfgrw32(p->tbdf, rno, 0, 1);
  231                         size = pcibarsize(p, rno);
  232                         if(size == 0)
  233                                 continue;
  234 
  235                         if(v & 1) {
  236                                 itb->dev = p;
  237                                 itb->bar = i;
  238                                 itb->siz = size;
  239                                 itb++;
  240                         }
  241                         else {
  242                                 mtb->dev = p;
  243                                 mtb->bar = i;
  244                                 mtb->siz = size;
  245                                 mtb++;
  246                         }
  247 
  248                         p->mem[i].size = size;
  249                 }
  250         }
  251 
  252         /*
  253          * Sort both tables IO smallest first, Memory largest
  254          */
  255         qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
  256         tptr = table+ntb;
  257         qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
  258 
  259         /*
  260          * Allocate IO address space on this bus
  261          */
  262         for(tptr = table; tptr < itb; tptr++) {
  263                 hole = tptr->siz;
  264                 if(tptr->bar == -1)
  265                         hole = 1<<12;
  266                 ioa = (ioa+hole-1) & ~(hole-1);
  267 
  268                 p = tptr->dev;
  269                 if(tptr->bar == -1)
  270                         p->ioa.bar = ioa;
  271                 else {
  272                         p->pcr |= IOen;
  273                         p->mem[tptr->bar].bar = ioa|1;
  274                         if(wrreg)
  275                                 pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
  276                 }
  277 
  278                 ioa += tptr->siz;
  279         }
  280 
  281         /*
  282          * Allocate Memory address space on this bus
  283          */
  284         for(tptr = table+ntb; tptr < mtb; tptr++) {
  285                 hole = tptr->siz;
  286                 if(tptr->bar == -1)
  287                         hole = 1<<20;
  288                 mema = (mema+hole-1) & ~(hole-1);
  289 
  290                 p = tptr->dev;
  291                 if(tptr->bar == -1)
  292                         p->mema.bar = mema;
  293                 else {
  294                         p->pcr |= MEMen;
  295                         p->mem[tptr->bar].bar = mema;
  296                         if(wrreg)
  297                                 pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), mema, 0);
  298                 }
  299                 mema += tptr->siz;
  300         }
  301 
  302         *pmema = mema;
  303         *pioa = ioa;
  304         free(table);
  305 
  306         if(wrreg == 0)
  307                 return;
  308 
  309         /*
  310          * Finally set all the bridge addresses & registers
  311          */
  312         for(p = root; p != nil; p = p->link) {
  313                 if(p->bridge == nil) {
  314                         pcicfgrw8(p->tbdf, PciLTR, 64, 0);
  315 
  316                         p->pcr |= MASen;
  317                         pcicfgrw32(p->tbdf, PciPCR, p->pcr, 0);
  318                         continue;
  319                 }
  320 
  321                 base = p->ioa.bar;
  322                 limit = base+p->ioa.size-1;
  323                 v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
  324                 v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
  325                 pcicfgrw32(p->tbdf, PciIBR, v, 0);
  326                 v = (limit & 0xFFFF0000)|(base>>16);
  327                 pcicfgrw32(p->tbdf, PciIUBR, v, 0);
  328 
  329                 base = p->mema.bar;
  330                 limit = base+p->mema.size-1;
  331                 v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
  332                 pcicfgrw32(p->tbdf, PciMBR, v, 0);
  333 
  334                 /*
  335                  * Disable memory prefetch
  336                  */
  337                 pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
  338                 pcicfgrw8(p->tbdf, PciLTR, 64, 0);
  339 
  340                 /*
  341                  * Enable the bridge
  342                  */
  343                 v = 0xFFFF0000 | IOen | MEMen | MASen;
  344                 pcicfgrw32(p->tbdf, PciPCR, v, 0);
  345 
  346                 sioa = p->ioa.bar;
  347                 smema = p->mema.bar;
  348                 pcibusmap(p->bridge, &smema, &sioa, 1);
  349         }
  350 }
  351 
  352 static int
  353 pcilscan(int bno, Pcidev** list)
  354 {
  355         Pcidev *p, *head, *tail;
  356         int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
  357 
  358         maxubn = bno;
  359         head = nil;
  360         tail = nil;
  361         for(dno = 0; dno <= pcimaxdno; dno++){
  362                 maxfno = 0;
  363                 for(fno = 0; fno <= maxfno; fno++){
  364                         /*
  365                          * For this possible device, form the
  366                          * bus+device+function triplet needed to address it
  367                          * and try to read the vendor and device ID.
  368                          * If successful, allocate a device struct and
  369                          * start to fill it in with some useful information
  370                          * from the device's configuration space.
  371                          */
  372                         tbdf = MKBUS(BusPCI, bno, dno, fno);
  373                         l = pcicfgrw32(tbdf, PciVID, 0, 1);
  374                         if(l == 0xFFFFFFFF || l == 0)
  375                                 continue;
  376                         p = malloc(sizeof(*p));
  377                         p->tbdf = tbdf;
  378                         p->vid = l;
  379                         p->did = l>>16;
  380 
  381                         if(pcilist != nil)
  382                                 pcitail->list = p;
  383                         else
  384                                 pcilist = p;
  385                         pcitail = p;
  386 
  387                         p->rid = pcicfgr8(p, PciRID);
  388                         p->ccrp = pcicfgr8(p, PciCCRp);
  389                         p->ccru = pcicfgr8(p, PciCCRu);
  390                         p->ccrb = pcicfgr8(p, PciCCRb);
  391                         p->pcr = pcicfgr32(p, PciPCR);
  392 
  393                         p->intl = pcicfgr8(p, PciINTL);
  394 
  395                         /*
  396                          * If the device is a multi-function device adjust the
  397                          * loop count so all possible functions are checked.
  398                          */
  399                         hdt = pcicfgr8(p, PciHDT);
  400                         if(hdt & 0x80)
  401                                 maxfno = MaxFNO;
  402 
  403                         /*
  404                          * If appropriate, read the base address registers
  405                          * and work out the sizes.
  406                          */
  407                         switch(p->ccrb) {
  408                         case 0x01:              /* mass storage controller */
  409                         case 0x02:              /* network controller */
  410                         case 0x03:              /* display controller */
  411                         case 0x04:              /* multimedia device */
  412                         case 0x06:              /* bridge device */
  413                         case 0x07:              /* simple comm. controllers */
  414                         case 0x08:              /* base system peripherals */
  415                         case 0x09:              /* input devices */
  416                         case 0x0A:              /* docking stations */
  417                         case 0x0B:              /* processors */
  418                         case 0x0C:              /* serial bus controllers */
  419                                 if((hdt & 0x7F) != 0)
  420                                         break;
  421                                 rno = PciBAR0 - 4;
  422                                 for(i = 0; i < nelem(p->mem); i++) {
  423                                         rno += 4;
  424                                         p->mem[i].bar = pcicfgr32(p, rno);
  425                                         p->mem[i].size = pcibarsize(p, rno);
  426                                 }
  427                                 break;
  428 
  429                         case 0x00:
  430                         case 0x05:              /* memory controller */
  431                         default:
  432                                 break;
  433                         }
  434 
  435                         if(head != nil)
  436                                 tail->link = p;
  437                         else
  438                                 head = p;
  439                         tail = p;
  440                 }
  441         }
  442 
  443         *list = head;
  444         for(p = head; p != nil; p = p->link){
  445                 /*
  446                  * Find PCI-PCI bridges and recursively descend the tree.
  447                  */
  448                 if(p->ccrb != 0x06 || p->ccru != 0x04)
  449                         continue;
  450 
  451                 /*
  452                  * If the secondary or subordinate bus number is not
  453                  * initialised try to do what the PCI BIOS should have
  454                  * done and fill in the numbers as the tree is descended.
  455                  * On the way down the subordinate bus number is set to
  456                  * the maximum as it's not known how many buses are behind
  457                  * this one; the final value is set on the way back up.
  458                  */
  459                 sbn = pcicfgr8(p, PciSBN);
  460                 ubn = pcicfgr8(p, PciUBN);
  461 
  462                 if(sbn == 0 || ubn == 0) {
  463                         sbn = maxubn+1;
  464                         /*
  465                          * Make sure memory, I/O and master enables are
  466                          * off, set the primary, secondary and subordinate
  467                          * bus numbers and clear the secondary status before
  468                          * attempting to scan the secondary bus.
  469                          *
  470                          * Initialisation of the bridge should be done here.
  471                          */
  472                         pcicfgw32(p, PciPCR, 0xFFFF0000);
  473                         l = (MaxUBN<<16)|(sbn<<8)|bno;
  474                         pcicfgw32(p, PciPBN, l);
  475                         pcicfgw16(p, PciSPSR, 0xFFFF);
  476                         maxubn = pcilscan(sbn, &p->bridge);
  477                         l = (maxubn<<16)|(sbn<<8)|bno;
  478 
  479                         pcicfgw32(p, PciPBN, l);
  480                 }
  481                 else {
  482                         maxubn = ubn;
  483                         pcilscan(sbn, &p->bridge);
  484                 }
  485         }
  486 
  487         return maxubn;
  488 }
  489 
  490 int
  491 pciscan(int bno, Pcidev **list)
  492 {
  493         int ubn;
  494 
  495         qlock(&pcicfginitlock);
  496         ubn = pcilscan(bno, list);
  497         qunlock(&pcicfginitlock);
  498         return ubn;
  499 }
  500 
  501 static void
  502 pcicfginit(void)
  503 {
  504         char *p;
  505         int bno;
  506         Pcidev **list;
  507         ulong mema, ioa;
  508 
  509         qlock(&pcicfginitlock);
  510         if(pcicfgmode != -1)
  511                 goto out;
  512 
  513         /*
  514          * Try to determine which PCI configuration mode is implemented.
  515          * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
  516          * a DWORD at 0xCF8 and another at 0xCFC and will pass through
  517          * any non-DWORD accesses as normal I/O cycles. There shouldn't be
  518          * a device behind these addresses so if Mode2 accesses fail try
  519          * for Mode1 (which is preferred, Mode2 is deprecated).
  520          */
  521         outb(PciCSE, 0);
  522         if(inb(PciCSE) == 0){
  523                 pcicfgmode = 2;
  524                 pcimaxdno = 15;
  525         }
  526         else {
  527                 outl(PciADDR, 0);
  528                 if(inl(PciADDR) == 0){
  529                         pcicfgmode = 1;
  530                         pcimaxdno = 31;
  531                 }
  532         }
  533         
  534         if(pcicfgmode < 0)
  535                 goto out;
  536 
  537         fmtinstall('T', tbdffmt);
  538 
  539         if(p = getconf("*pcimaxbno"))
  540                 pcimaxbno = strtoul(p, 0, 0);
  541         if(p = getconf("*pcimaxdno"))
  542                 pcimaxdno = strtoul(p, 0, 0);
  543 
  544         list = &pciroot;
  545         for(bno = 0; bno <= pcimaxbno; bno++) {
  546                 int sbno = bno;
  547                 bno = pcilscan(bno, list);
  548 
  549                 while(*list)
  550                         list = &(*list)->link;
  551 
  552                 if (sbno == 0) {
  553                         Pcidev *pci;
  554 
  555                         /*
  556                           * If we have found a PCI-to-Cardbus bridge, make sure
  557                           * it has no valid mappings anymore.  
  558                           */
  559                         pci = pciroot;
  560                         while (pci) {
  561                                 if (pci->ccrb == 6 && pci->ccru == 7) {
  562                                         ushort bcr;
  563 
  564                                         /* reset the cardbus */
  565                                         bcr = pcicfgr16(pci, PciBCR);
  566                                         pcicfgw16(pci, PciBCR, 0x40 | bcr);
  567                                         delay(50);
  568                                 }
  569                                 pci = pci->link;
  570                         }
  571                 }
  572         }
  573 
  574         if(pciroot == nil)
  575                 goto out;
  576 
  577         /*
  578          * Work out how big the top bus is
  579          */
  580         mema = 0;
  581         ioa = 0;
  582         pcibusmap(pciroot, &mema, &ioa, 0);
  583 
  584         DBG("Sizes: mem=%8.8lux size=%8.8lux io=%8.8lux\n",
  585                 mema, pcimask(mema), ioa);
  586 
  587         /*
  588          * Align the windows and map it
  589          */
  590         ioa = 0x1000;
  591         mema = 0;
  592 
  593         pcilog("Mask sizes: mem=%lux io=%lux\n", mema, ioa);
  594 
  595         pcibusmap(pciroot, &mema, &ioa, 1);
  596         DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
  597 
  598 out:
  599         qunlock(&pcicfginitlock);
  600 }
  601 
  602 static int
  603 pcicfgrw8(int tbdf, int rno, int data, int read)
  604 {
  605         int o, type, x;
  606 
  607         if(pcicfgmode == -1)
  608                 pcicfginit();
  609 
  610         if(BUSBNO(tbdf))
  611                 type = 0x01;
  612         else
  613                 type = 0x00;
  614         x = -1;
  615         if(BUSDNO(tbdf) > pcimaxdno)
  616                 return x;
  617 
  618         lock(&pcicfglock);
  619         switch(pcicfgmode){
  620 
  621         case 1:
  622                 o = rno & 0x03;
  623                 rno &= ~0x03;
  624                 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  625                 if(read)
  626                         x = inb(PciDATA+o);
  627                 else
  628                         outb(PciDATA+o, data);
  629                 outl(PciADDR, 0);
  630                 break;
  631 
  632         case 2:
  633                 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  634                 outb(PciFORWARD, BUSBNO(tbdf));
  635                 if(read)
  636                         x = inb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  637                 else
  638                         outb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  639                 outb(PciCSE, 0);
  640                 break;
  641         }
  642         unlock(&pcicfglock);
  643 
  644         return x;
  645 }
  646 
  647 int
  648 pcicfgr8(Pcidev* pcidev, int rno)
  649 {
  650         return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  651 }
  652 
  653 void
  654 pcicfgw8(Pcidev* pcidev, int rno, int data)
  655 {
  656         pcicfgrw8(pcidev->tbdf, rno, data, 0);
  657 }
  658 
  659 static int
  660 pcicfgrw16(int tbdf, int rno, int data, int read)
  661 {
  662         int o, type, x;
  663 
  664         if(pcicfgmode == -1)
  665                 pcicfginit();
  666 
  667         if(BUSBNO(tbdf))
  668                 type = 0x01;
  669         else
  670                 type = 0x00;
  671         x = -1;
  672         if(BUSDNO(tbdf) > pcimaxdno)
  673                 return x;
  674 
  675         lock(&pcicfglock);
  676         switch(pcicfgmode){
  677 
  678         case 1:
  679                 o = rno & 0x02;
  680                 rno &= ~0x03;
  681                 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  682                 if(read)
  683                         x = ins(PciDATA+o);
  684                 else
  685                         outs(PciDATA+o, data);
  686                 outl(PciADDR, 0);
  687                 break;
  688 
  689         case 2:
  690                 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  691                 outb(PciFORWARD, BUSBNO(tbdf));
  692                 if(read)
  693                         x = ins((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  694                 else
  695                         outs((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  696                 outb(PciCSE, 0);
  697                 break;
  698         }
  699         unlock(&pcicfglock);
  700 
  701         return x;
  702 }
  703 
  704 int
  705 pcicfgr16(Pcidev* pcidev, int rno)
  706 {
  707         return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  708 }
  709 
  710 void
  711 pcicfgw16(Pcidev* pcidev, int rno, int data)
  712 {
  713         pcicfgrw16(pcidev->tbdf, rno, data, 0);
  714 }
  715 
  716 static int
  717 pcicfgrw32(int tbdf, int rno, int data, int read)
  718 {
  719         int type, x;
  720 
  721         if(pcicfgmode == -1)
  722                 pcicfginit();
  723 
  724         if(BUSBNO(tbdf))
  725                 type = 0x01;
  726         else
  727                 type = 0x00;
  728         x = -1;
  729         if(BUSDNO(tbdf) > pcimaxdno)
  730                 return x;
  731 
  732         lock(&pcicfglock);
  733         switch(pcicfgmode){
  734 
  735         case 1:
  736                 rno &= ~0x03;
  737                 outl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
  738                 if(read)
  739                         x = inl(PciDATA);
  740                 else
  741                         outl(PciDATA, data);
  742                 outl(PciADDR, 0);
  743                 break;
  744 
  745         case 2:
  746                 outb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
  747                 outb(PciFORWARD, BUSBNO(tbdf));
  748                 if(read)
  749                         x = inl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
  750                 else
  751                         outl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
  752                 outb(PciCSE, 0);
  753                 break;
  754         }
  755         unlock(&pcicfglock);
  756 
  757         return x;
  758 }
  759 
  760 int
  761 pcicfgr32(Pcidev* pcidev, int rno)
  762 {
  763         return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  764 }
  765 
  766 void
  767 pcicfgw32(Pcidev* pcidev, int rno, int data)
  768 {
  769         pcicfgrw32(pcidev->tbdf, rno, data, 0);
  770 }
  771 
  772 Pcidev*
  773 pcimatch(Pcidev* prev, int vid, int did)
  774 {
  775         if(pcicfgmode == -1)
  776                 pcicfginit();
  777 
  778         if(prev == nil)
  779                 prev = pcilist;
  780         else
  781                 prev = prev->list;
  782 
  783         while(prev != nil){
  784                 if((vid == 0 || prev->vid == vid)
  785                 && (did == 0 || prev->did == did))
  786                         break;
  787                 prev = prev->list;
  788         }
  789         return prev;
  790 }
  791 
  792 Pcidev*
  793 pcimatchtbdf(int tbdf)
  794 {
  795         Pcidev *pcidev;
  796 
  797         if(pcicfgmode == -1)
  798                 pcicfginit();
  799 
  800         for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
  801                 if(pcidev->tbdf == tbdf)
  802                         break;
  803         }
  804         return pcidev;
  805 }
  806 
  807 uchar
  808 pciipin(Pcidev *pci, uchar pin)
  809 {
  810         if (pci == nil)
  811                 pci = pcilist;
  812 
  813         while (pci) {
  814                 uchar intl;
  815 
  816                 if (pcicfgr8(pci, PciINTP) == pin && pci->intl != 0 && pci->intl != 0xff)
  817                         return pci->intl;
  818 
  819                 if (pci->bridge && (intl = pciipin(pci->bridge, pin)) != 0)
  820                         return intl;
  821 
  822                 pci = pci->list;
  823         }
  824         return 0;
  825 }
  826 
  827 static void
  828 pcilhinv(Pcidev* p)
  829 {
  830         int i;
  831         Pcidev *t;
  832 
  833         if(p == nil) {
  834                 putstrn(PCICONS.output, PCICONS.ptr);
  835                 p = pciroot;
  836                 print("bus dev type vid  did intl memory\n");
  837         }
  838         for(t = p; t != nil; t = t->link) {
  839                 print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d  ",
  840                         BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
  841                         t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
  842 
  843                 for(i = 0; i < nelem(p->mem); i++) {
  844                         if(t->mem[i].size == 0)
  845                                 continue;
  846                         print("%d:%.8lux %d ", i,
  847                                 t->mem[i].bar, t->mem[i].size);
  848                 }
  849                 if(t->ioa.bar || t->ioa.size)
  850                         print("ioa:%.8lux %d ", t->ioa.bar, t->ioa.size);
  851                 if(t->mema.bar || t->mema.size)
  852                         print("mema:%.8lux %d ", t->mema.bar, t->mema.size);
  853                 if(t->bridge)
  854                         print("->%d", BUSBNO(t->bridge->tbdf));
  855                 print("\n");
  856         }
  857         while(p != nil) {
  858                 if(p->bridge != nil)
  859                         pcilhinv(p->bridge);
  860                 p = p->link;
  861         }       
  862 }
  863 
  864 void
  865 pcihinv(Pcidev* p)
  866 {
  867         if(pcicfgmode == -1)
  868                 pcicfginit();
  869         qlock(&pcicfginitlock);
  870         pcilhinv(p);
  871         qunlock(&pcicfginitlock);
  872 }
  873 
  874 void
  875 pcireset(void)
  876 {
  877         Pcidev *p;
  878         int pcr;
  879 
  880         if(pcicfgmode == -1)
  881                 pcicfginit();
  882 
  883         for(p = pcilist; p != nil; p = p->list){
  884                 pcr = pcicfgr16(p, PciPCR);
  885                 pcr &= ~0x0004;
  886                 pcicfgw16(p, PciPCR, pcr);
  887         }
  888 }
  889 
  890 void
  891 pcisetbme(Pcidev* p)
  892 {
  893         int pcr;
  894 
  895         pcr = pcicfgr16(p, PciPCR);
  896         pcr |= MASen;
  897         pcicfgw16(p, PciPCR, pcr);
  898 }
  899 
  900 void
  901 pciclrbme(Pcidev* p)
  902 {
  903         int pcr;
  904 
  905         pcr = pcicfgr16(p, PciPCR);
  906         pcr &= ~MASen;
  907         pcicfgw16(p, PciPCR, pcr);
  908 }

Cache object: 2c24e81683f457ad8cb81dac99340b75


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.