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/alphapc/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  * To do:
    4  *      initialise bridge mappings if the PCI BIOS didn't.
    5  */
    6 #include "u.h"
    7 #include "../port/lib.h"
    8 #include "mem.h"
    9 #include "dat.h"
   10 #include "fns.h"
   11 #include "io.h"
   12 #include "../port/error.h"
   13 
   14 enum {
   15         MaxFNO          = 7,
   16         MaxUBN          = 255,
   17 };
   18 
   19 enum
   20 {                                       /* command register */
   21         IOen            = (1<<0),
   22         MEMen           = (1<<1),
   23         MASen           = (1<<2),
   24         MemWrInv        = (1<<4),
   25         PErrEn          = (1<<6),
   26         SErrEn          = (1<<8),
   27 };
   28 
   29 static Lock pcicfglock;
   30 static Lock pcicfginitlock;
   31 static int pcicfgmode = -1;
   32 static int pcimaxdno;
   33 static Pcidev* pciroot;
   34 static Pcidev* pcilist;
   35 static Pcidev* pcitail;
   36 
   37 static int pcicfgrw32(int, int, int, int);
   38 
   39 uchar   *vgabios;
   40 
   41 static int
   42 pciscan(int bno, Pcidev** list)
   43 {
   44         ulong v;
   45         Pcidev *p, *head, *tail;
   46         int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
   47 
   48         maxubn = bno;
   49         head = nil;
   50         tail = nil;
   51         for(dno = 0; dno <= pcimaxdno; dno++){
   52                 maxfno = 0;
   53                 for(fno = 0; fno <= maxfno; fno++){
   54                         /*
   55                          * For this possible device, form the
   56                          * bus+device+function triplet needed to address it
   57                          * and try to read the vendor and device ID.
   58                          * If successful, allocate a device struct and
   59                          * start to fill it in with some useful information
   60                          * from the device's configuration space.
   61                          */
   62                         tbdf = MKBUS(BusPCI, bno, dno, fno);
   63                         l = pcicfgrw32(tbdf, PciVID, 0, 1);
   64                         if(l == 0xFFFFFFFF || l == 0)
   65                                 continue;
   66 /* optional safety checks:
   67                         if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
   68                                 continue;
   69                         if(l != pcicfgrw32(tbdf, PciVID, 0, 1))
   70                                 continue;
   71                         if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
   72                                 continue;
   73 */
   74                         p = malloc(sizeof(*p));
   75                         p->tbdf = tbdf;
   76                         p->vid = l;
   77                         p->did = l>>16;
   78 
   79                         if(pcilist != nil)
   80                                 pcitail->list = p;
   81                         else
   82                                 pcilist = p;
   83                         pcitail = p;
   84 
   85                         p->rid = pcicfgr8(p, PciRID);
   86                         p->ccrp = pcicfgr8(p, PciCCRp);
   87                         p->ccru = pcicfgr8(p, PciCCRu);
   88                         p->ccrb = pcicfgr8(p, PciCCRb);
   89                         p->pcr = pcicfgr32(p, PciPCR);
   90 
   91                         p->intl = pcicfgr8(p, PciINTL);
   92 
   93                         /*
   94                          * If the device is a multi-function device adjust the
   95                          * loop count so all possible functions are checked.
   96                          */
   97                         hdt = pcicfgr8(p, PciHDT);
   98                         if(hdt & 0x80)
   99                                 maxfno = MaxFNO;
  100 
  101                         /*
  102                          * If appropriate, read the base address registers
  103                          * and work out the sizes.
  104                          */
  105                         switch(p->ccrb){
  106 
  107                         case 0x03:              /* display controller */
  108                                 if(vgabios == nil) {
  109                                         v = pcicfgr32(p, PciROM);
  110                                         pcicfgw32(p, PciROM, v|1);      /* enable decode */
  111                                         vgabios = kmapv(((uvlong)0x88<<32LL)|(v&~0xffff), 0x10000);
  112                                         // print("VGA BIOS %lux -> %lux\n", v, vgabios);
  113                                 }
  114                                 /* fall through */
  115                         case 0x01:              /* mass storage controller */
  116                         case 0x02:              /* network controller */
  117                         case 0x04:              /* multimedia device */
  118                         case 0x07:              /* simple communication controllers */
  119                         case 0x08:              /* base system peripherals */
  120                         case 0x09:              /* input devices */
  121                         case 0x0A:              /* docking stations */
  122                         case 0x0B:              /* processors */
  123                         case 0x0C:              /* serial bus controllers */
  124                                 if((hdt & 0x7F) != 0)
  125                                         break;
  126                                 rno = PciBAR0 - 4;
  127                                 for(i = 0; i < nelem(p->mem); i++){
  128                                         rno += 4;
  129                                         p->mem[i].bar = pcicfgr32(p, rno);
  130                                         pcicfgw32(p, rno, -1);
  131                                         v = pcicfgr32(p, rno);
  132                                         pcicfgw32(p, rno, p->mem[i].bar);
  133                                         p->mem[i].size = -(v & ~0xF);
  134                                 }
  135                                 break;
  136 
  137                         case 0x00:
  138                         case 0x05:              /* memory controller */
  139                         case 0x06:              /* bridge device */
  140                         default:
  141                                 break;
  142                         }
  143 
  144                         if(head != nil)
  145                                 tail->link = p;
  146                         else
  147                                 head = p;
  148                         tail = p;
  149                 }
  150         }
  151 
  152         *list = head;
  153         for(p = head; p != nil; p = p->link){
  154                 /*
  155                  * Find PCI-PCI bridges and recursively descend the tree.
  156                  */
  157                 if(p->ccrb != 0x06 || p->ccru != 0x04)
  158                         continue;
  159 
  160                 /*
  161                  * If the secondary or subordinate bus number is not initialised
  162                  * try to do what the PCI BIOS should have done and fill in the
  163                  * numbers as the tree is descended. On the way down the subordinate
  164                  * bus number is set to the maximum as it's not known how many
  165                  * buses are behind this one; the final value is set on the way
  166                  * back up.
  167                  */
  168                 sbn = pcicfgr8(p, PciSBN);
  169                 ubn = pcicfgr8(p, PciUBN);
  170                 if(sbn == 0 || ubn == 0){
  171                         sbn = maxubn+1;
  172                         /*
  173                          * Make sure memory, I/O and master enables are off,
  174                          * set the primary, secondary and subordinate bus numbers
  175                          * and clear the secondary status before attempting to
  176                          * scan the secondary bus.
  177                          *
  178                          * Initialisation of the bridge should be done here.
  179                          */
  180                         pcicfgw32(p, PciPCR, 0xFFFF0000);
  181                         l = (MaxUBN<<16)|(sbn<<8)|bno;
  182                         pcicfgw32(p, PciPBN, l);
  183                         pcicfgw16(p, PciSPSR, 0xFFFF);
  184                         maxubn = pciscan(sbn, &p->bridge);
  185                         l = (maxubn<<16)|(sbn<<8)|bno;
  186                         pcicfgw32(p, PciPBN, l);
  187                 }
  188                 else{
  189                         maxubn = ubn;
  190                         pciscan(sbn, &p->bridge);
  191                 }
  192         }
  193 
  194         return maxubn;
  195 }
  196 
  197 static void
  198 pcicfginit(void)
  199 {
  200         char *p;
  201 
  202         lock(&pcicfginitlock);
  203         if(pcicfgmode == -1){
  204                 pcicfgmode = 0;
  205                 pcimaxdno = 15;         /* was 20; what is correct value??? */
  206                 if(p = getconf("*pcimaxdno"))
  207                         pcimaxdno = strtoul(p, 0, 0);
  208                 pciscan(0, &pciroot);
  209         }
  210         unlock(&pcicfginitlock);
  211 }
  212 
  213 static int
  214 pcicfgrw8(int tbdf, int rno, int data, int read)
  215 {
  216         int x;
  217         uchar *p;
  218 
  219         if(pcicfgmode == -1)
  220                 pcicfginit();
  221         x = -1;
  222         if(BUSDNO(tbdf) > pcimaxdno)
  223                 return x;
  224 
  225         p = (uchar*)arch->pcicfg(tbdf, rno);
  226         if(read)
  227                 x = *p;
  228         else
  229                 *p = data;
  230 
  231         return x;
  232 }
  233 
  234 int
  235 pcicfgr8(Pcidev* pcidev, int rno)
  236 {
  237         return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
  238 }
  239 
  240 void
  241 pcicfgw8(Pcidev* pcidev, int rno, int data)
  242 {
  243         pcicfgrw8(pcidev->tbdf, rno, data, 0);
  244 }
  245 
  246 static int
  247 pcicfgrw16(int tbdf, int rno, int data, int read)
  248 {
  249         int x;
  250         ushort *p;
  251 
  252         if(pcicfgmode == -1)
  253                 pcicfginit();
  254         x = -1;
  255         if(BUSDNO(tbdf) > pcimaxdno)
  256                 return x;
  257 
  258         p = (ushort*)arch->pcicfg(tbdf, rno);
  259         if(read)
  260                 x = *p;
  261         else
  262                 *p = data;
  263 
  264         return x;
  265 }
  266 
  267 int
  268 pcicfgr16(Pcidev* pcidev, int rno)
  269 {
  270         return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
  271 }
  272 
  273 void
  274 pcicfgw16(Pcidev* pcidev, int rno, int data)
  275 {
  276         pcicfgrw16(pcidev->tbdf, rno, data, 0);
  277 }
  278 
  279 static int
  280 pcicfgrw32(int tbdf, int rno, int data, int read)
  281 {
  282         int x;
  283         ulong *p;
  284 
  285         if(pcicfgmode == -1)
  286                 pcicfginit();
  287         x = -1;
  288         if(BUSDNO(tbdf) > pcimaxdno)
  289                 return x;
  290 
  291         p = (ulong*)arch->pcicfg(tbdf, rno);
  292         if(read)
  293                 x = *p;
  294         else
  295                 *p = data;
  296 
  297         return x;
  298 }
  299 
  300 int
  301 pcicfgr32(Pcidev* pcidev, int rno)
  302 {
  303         return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
  304 }
  305 
  306 void
  307 pcicfgw32(Pcidev* pcidev, int rno, int data)
  308 {
  309         pcicfgrw32(pcidev->tbdf, rno, data, 0);
  310 }
  311 
  312 Pcidev*
  313 pcimatch(Pcidev* prev, int vid, int did)
  314 {
  315         if(pcicfgmode == -1)
  316                 pcicfginit();
  317 
  318         if(prev == nil)
  319                 prev = pcilist;
  320         else
  321                 prev = prev->list;
  322 
  323         while(prev != nil) {
  324                 if((vid == 0 || prev->vid == vid)
  325                 && (did == 0 || prev->did == did))
  326                         break;
  327                 prev = prev->list;
  328         }
  329         return prev;
  330 }
  331 
  332 Pcidev*
  333 pcimatchtbdf(int tbdf)
  334 {
  335         Pcidev *pcidev;
  336 
  337         if(pcicfgmode == -1)
  338                 pcicfginit();
  339 
  340         for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
  341                 if(pcidev->tbdf == tbdf)
  342                         break;
  343         }
  344         return pcidev;
  345 }
  346 
  347 void
  348 pcihinv(Pcidev* p)
  349 {
  350         int i;
  351         Pcidev *t;
  352 
  353         if(pcicfgmode == -1)
  354                 pcicfginit();
  355         if(p == nil) {
  356                 p = pciroot;
  357                 print("bus dev type vid  did intl memory\n");
  358         }
  359         for(t = p; t != nil; t = t->link) {
  360                 print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %2d  ",
  361                         BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
  362                         t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
  363 
  364                 for(i = 0; i < nelem(p->mem); i++) {
  365                         if(t->mem[i].size == 0)
  366                                 continue;
  367                         print("%d:%.8lux %d ", i,
  368                                 t->mem[i].bar, t->mem[i].size);
  369                 }
  370                 print("\n");
  371         }
  372         while(p != nil) {
  373                 if(p->bridge != nil)
  374                         pcihinv(p->bridge);
  375                 p = p->link;
  376         }
  377 }
  378 
  379 void
  380 pcireset(void)
  381 {
  382         Pcidev *p;
  383         int pcr;
  384 
  385         if(pcicfgmode == -1)
  386                 pcicfginit();
  387 
  388         for(p = pcilist; p != nil; p = p->list){
  389                 pcr = pcicfgr16(p, PciPSR);
  390                 pcicfgw16(p, PciPSR, pcr & ~0x04);
  391         }
  392 }
  393 
  394 void
  395 pcisetbme(Pcidev* p)
  396 {
  397         int pcr;
  398 
  399         pcr = pcicfgr16(p, PciPCR);
  400         pcr |= MASen;
  401         pcicfgw16(p, PciPCR, pcr);
  402 }
  403 
  404 void
  405 pciclrbme(Pcidev* p)
  406 {
  407         int pcr;
  408 
  409         pcr = pcicfgr16(p, PciPCR);
  410         pcr &= ~MASen;
  411         pcicfgw16(p, PciPCR, pcr);
  412 }

Cache object: 72acd86d4a4d6359ba26a3876cf05f7d


[ 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.