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/port/devpnp.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  *      ISA PNP 1.0 support + access to PCI configuration space
    3  *
    4  *      TODO
    5  *              - implement PNP card configuration (setting io bases etc)
    6  *              - write user program to drive PNP configuration...
    7  *              - extend PCI raw access to configuration space (writes, byte/short access?)
    8  *              - implement PCI access to memory/io space/BIOS ROM
    9  *              - use c->aux instead of performing lookup on each read/write?
   10  */
   11 #include        "u.h"
   12 #include        "../port/lib.h"
   13 #include        "mem.h"
   14 #include        "dat.h"
   15 #include        "fns.h"
   16 #include        "io.h"
   17 #include        "../port/error.h"
   18 
   19 typedef struct Pnp Pnp;
   20 typedef struct Card Card;
   21 
   22 struct Pnp
   23 {
   24         QLock;
   25         int             rddata;
   26         int             debug;
   27         Card            *cards;
   28 };
   29 
   30 struct Card
   31 {
   32         int             csn;
   33         ulong   id1;
   34         ulong   id2;
   35         char            *cfgstr;
   36         int             ncfg;
   37         Card*   next;
   38 };
   39 
   40 static Pnp      pnp;
   41 
   42 #define DPRINT  if(pnp.debug) print
   43 #define XPRINT  if(1) print
   44 
   45 enum {
   46         Address = 0x279,
   47         WriteData = 0xa79,
   48 
   49         Qtopdir = 0,
   50 
   51         Qpnpdir,
   52         Qpnpctl,
   53         Qcsnctl,
   54         Qcsnraw,
   55 
   56         Qpcidir,
   57         Qpcictl,
   58         Qpciraw,
   59 };
   60 
   61 #define TYPE(q)         ((ulong)(q).path & 0x0F)
   62 #define CSN(q)          (((ulong)(q).path>>4) & 0xFF)
   63 #define QID(c, t)       (((c)<<4)|(t))
   64 
   65 static Dirtab topdir[] = {
   66         ".",    { Qtopdir, 0, QTDIR },  0,      0555,
   67         "pnp",  { Qpnpdir, 0, QTDIR },  0,      0555,
   68         "pci",  { Qpcidir, 0, QTDIR },  0,      0555,
   69 };
   70 
   71 static Dirtab pnpdir[] = {
   72         ".",    { Qpnpdir, 0, QTDIR },  0,      0555,
   73         "ctl",  { Qpnpctl, 0, 0 },      0,      0666,
   74 };
   75 
   76 extern Dev pnpdevtab;
   77 static int wrconfig(Card*, char*);
   78 
   79 static char key[32] =
   80 {
   81         0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,
   82         0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,
   83         0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,
   84         0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39,
   85 };
   86 
   87 static void
   88 cmd(int reg, int val)
   89 {
   90         outb(Address, reg);
   91         outb(WriteData, val);
   92 }
   93 
   94 /* Send initiation key, putting each card in Sleep state */
   95 static void
   96 initiation(void)
   97 {
   98         int i;
   99 
  100         /* ensure each card's LFSR is reset */
  101         outb(Address, 0x00);
  102         outb(Address, 0x00);
  103 
  104         /* send initiation key */
  105         for (i = 0; i < 32; i++)
  106                 outb(Address, key[i]);
  107 }
  108 
  109 /* isolation protocol... */
  110 static int
  111 readbit(int rddata)
  112 {
  113         int r1, r2;
  114 
  115         r1 = inb(rddata);
  116         r2 = inb(rddata);
  117         microdelay(250);
  118         return (r1 == 0x55) && (r2 == 0xaa);
  119 }
  120 
  121 static int
  122 isolate(int rddata, ulong *id1, ulong *id2)
  123 {
  124         int i, csum, bit;
  125         uchar *p, id[9];
  126 
  127         outb(Address, 0x01);    /* point to serial isolation register */
  128         delay(1);
  129         csum = 0x6a;
  130         for(i = 0; i < 64; i++){
  131                 bit = readbit(rddata);
  132                 csum = (csum>>1) | (((csum&1) ^ ((csum>>1)&1) ^ bit)<<7);
  133                 p = &id[i>>3];
  134                 *p = (*p>>1) | (bit<<7);
  135         }
  136         for(; i < 72; i++){
  137                 p = &id[i>>3];
  138                 *p = (*p>>1) | (readbit(rddata)<<7);
  139         }
  140         *id1 = (id[3]<<24)|(id[2]<<16)|(id[1]<<8)|id[0];
  141         *id2 = (id[7]<<24)|(id[6]<<16)|(id[5]<<8)|id[4];
  142         if(*id1 == 0)
  143                 return 0;
  144         if(id[8] != csum)
  145                 DPRINT("pnp: bad checksum id1 %lux id2 %lux csum %x != %x\n", *id1, *id2, csum, id[8]); /**/
  146         return id[8] == csum;
  147 }
  148 
  149 static int
  150 getresbyte(int rddata)
  151 {
  152         int tries = 0;
  153 
  154         outb(Address, 0x05);
  155         while ((inb(rddata) & 1) == 0)
  156                 if (tries++ > 1000000)
  157                         error("pnp: timeout waiting for resource data\n");
  158         outb(Address, 0x04);
  159         return inb(rddata);
  160 }
  161 
  162 static char *
  163 serial(ulong id1, ulong id2)
  164 {
  165         int i1, i2, i3;
  166         ulong x;
  167         static char buf[20];
  168 
  169         i1 = (id1>>2)&31;
  170         i2 = ((id1<<3)&24)+((id1>>13)&7);
  171         i3 = (id1>>8)&31;
  172         x = (id1>>8)&0xff00|(id1>>24)&0x00ff;
  173         if (i1 > 0 && i1 < 27 && i2 > 0 && i2 < 27 && i3 > 0 && i3 < 27 && (id1 & (1<<7)) == 0)
  174                 snprint(buf, sizeof(buf), "%c%c%c%.4lux.%lux", 'A'+i1-1, 'A'+i2-1, 'A'+i3-1, x, id2);
  175         else
  176                 snprint(buf, sizeof(buf), "%.4lux%.4lux.%lux", (id1<<8)&0xff00|(id1>>8)&0x00ff, x, id2);
  177         return buf;
  178 }
  179 
  180 static Card *
  181 findcsn(int csn, int create, int dolock)
  182 {
  183         Card *c, *nc, **l;
  184 
  185         if(dolock)
  186                 qlock(&pnp);
  187         l = &pnp.cards;
  188         for(c = *l; c != nil; c = *l) {
  189                 if(c->csn == csn)
  190                         goto done;
  191                 if(c->csn > csn)
  192                         break;
  193                 l = &c->next;
  194         }
  195         if(create) {
  196                 *l = nc = malloc(sizeof(Card));
  197                 nc->next = c;
  198                 nc->csn = csn;
  199                 c = nc;
  200         }
  201 done:
  202         if(dolock)
  203                 qunlock(&pnp);
  204         return c;
  205 }
  206 
  207 static int
  208 newcsn(void)
  209 {
  210         int csn;
  211         Card *c;
  212 
  213         csn = 1;
  214         for(c = pnp.cards; c != nil; c = c->next) {
  215                 if(c->csn > csn)
  216                         break;
  217                 csn = c->csn+1;
  218         }
  219         return csn;
  220 }
  221 
  222 static int
  223 pnpncfg(int rddata)
  224 {
  225         int i, n, x, ncfg, n1, n2;
  226 
  227         ncfg = 0;
  228         for (;;) {
  229                 x = getresbyte(rddata);
  230                 if((x & 0x80) == 0) {
  231                         n = (x&7)+1;
  232                         for(i = 1; i < n; i++)
  233                                 getresbyte(rddata);
  234                 }
  235                 else {
  236                         n1 = getresbyte(rddata);
  237                         n2 = getresbyte(rddata);
  238                         n = (n2<<8)|n1 + 3;
  239                         for (i = 3; i < n; i++)
  240                                 getresbyte(rddata);
  241                 }
  242                 ncfg += n;
  243                 if((x>>3) == 0x0f)
  244                         break;
  245         }
  246         return ncfg;
  247 }
  248 
  249 /* look for cards, and assign them CSNs */
  250 static int
  251 pnpscan(int rddata, int dawn)
  252 {
  253         Card *c;
  254         int csn;
  255         ulong id1, id2;
  256 
  257         initiation();                           /* upsilon sigma */
  258         cmd(0x02, 0x04+0x01);           /* reset CSN on all cards and reset logical devices */
  259         delay(1);                                       /* delay after resetting cards */
  260 
  261         cmd(0x03, 0);                           /* Wake all cards with a CSN of 0 */
  262         cmd(0x00, rddata>>2);           /* Set the READ_DATA port on all cards */
  263         while(isolate(rddata, &id1, &id2)) {
  264                 for(c = pnp.cards; c != nil; c = c->next)
  265                         if(c->id1 == id1 && c->id2 == id2)
  266                                 break;
  267                 if(c == nil) {
  268                         csn = newcsn();
  269                         c = findcsn(csn, 1, 0);
  270                         c->id1 = id1;
  271                         c->id2 = id2;
  272                 }
  273                 else if(c->cfgstr != nil) {
  274                         if(!wrconfig(c, c->cfgstr))
  275                                 print("pnp%d: bad cfg: %s\n", c->csn, c->cfgstr);
  276                         c->cfgstr = nil;
  277                 }
  278                 cmd(0x06, c->csn);              /* set the card's csn */
  279                 if(dawn)
  280                         print("pnp%d: %s\n", c->csn, serial(id1, id2));
  281                 c->ncfg = pnpncfg(rddata);
  282                 cmd(0x03, 0);           /* Wake all cards with a CSN of 0, putting this card to sleep */
  283         }
  284         cmd(0x02, 0x02);                        /* return cards to Wait for Key state */
  285         if(pnp.cards != 0) {
  286                 pnp.rddata = rddata;
  287                 return 1;
  288         }
  289         return 0;
  290 }
  291 
  292 static void
  293 pnpreset(void)
  294 {
  295         Card *c;
  296         ulong id1, id2;
  297         int csn, i1, i2, i3, x;
  298         char *s, *p, buf[20];
  299         ISAConf isa;
  300 
  301         memset(&isa, 0, sizeof(ISAConf));
  302         pnp.rddata = -1;
  303         if (isaconfig("pnp", 0, &isa) == 0)
  304                 return;
  305         if(isa.port < 0x203 || isa.port > 0x3ff)
  306                 return;
  307         for(csn = 1; csn < 256; csn++) {
  308                 sprint(buf, "pnp%d", csn);
  309                 s = getconf(buf);
  310                 if(s == 0)
  311                         continue;
  312                 if(strlen(s) < 8 || s[7] != '.' || s[0] < 'A' || s[0] > 'Z' || s[1] < 'A' || s[1] > 'Z' || s[2] < 'A' || s[2] > 'Z') {
  313 bad:
  314                         print("pnp%d: bad conf string %s\n", csn, s);
  315                         continue;       
  316                 }
  317                 i1 = s[0]-'A'+1;
  318                 i2 = s[1]-'A'+1;
  319                 i3 = s[2]-'A'+1;
  320                 x = strtoul(&s[3], 0, 16);
  321                 id1 = (i1<<2)|((i2>>3)&3)|((i2&7)<<13)|(i3<<8)|((x&0xff)<<24)|((x&0xff00)<<8);
  322                 id2 = strtoul(&s[8], &p, 16);
  323                 if(*p == ' ')
  324                         p++;
  325                 else if(*p == '\0')
  326                         p = nil;
  327                 else
  328                         goto bad;
  329                 c = findcsn(csn, 1, 0);
  330                 c->id1 = id1;
  331                 c->id2 = id2;
  332                 c->cfgstr = p;
  333         }
  334         pnpscan(isa.port, 1);
  335 }
  336 
  337 static int
  338 csngen(Chan *c, int t, int csn, Card *cp, Dir *dp)
  339 {
  340         Qid q;
  341 
  342         switch(t) {
  343         case Qcsnctl:
  344                 q = (Qid){QID(csn, Qcsnctl), 0, 0};
  345                 sprint(up->genbuf, "csn%dctl", csn);
  346                 devdir(c, q, up->genbuf, 0, eve, 0664, dp);
  347                 return 1;
  348         case Qcsnraw:
  349                 q = (Qid){QID(csn, Qcsnraw), 0, 0};
  350                 sprint(up->genbuf, "csn%draw", csn);
  351                 devdir(c, q, up->genbuf, cp->ncfg, eve, 0444, dp);
  352                 return 1;
  353         }
  354         return -1;
  355 }
  356 
  357 static int
  358 pcigen(Chan *c, int t, int tbdf, Dir *dp)
  359 {
  360         Qid q;
  361 
  362         q = (Qid){BUSBDF(tbdf)|t, 0, 0};
  363         switch(t) {
  364         case Qpcictl:
  365                 sprint(up->genbuf, "%d.%d.%dctl", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  366                 devdir(c, q, up->genbuf, 0, eve, 0444, dp);
  367                 return 1;
  368         case Qpciraw:
  369                 sprint(up->genbuf, "%d.%d.%draw", BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
  370                 devdir(c, q, up->genbuf, 128, eve, 0660, dp);
  371                 return 1;
  372         }
  373         return -1;
  374 }
  375 
  376 static int
  377 pnpgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
  378 {
  379         Qid q;
  380         Card *cp;
  381         Pcidev *p;
  382         int csn, tbdf;
  383 
  384         switch(TYPE(c->qid)){
  385         case Qtopdir:
  386                 if(s == DEVDOTDOT){
  387                         q = (Qid){QID(0, Qtopdir), 0, QTDIR};
  388                         sprint(up->genbuf, "#%C", pnpdevtab.dc);
  389                         devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  390                         return 1;
  391                 }
  392                 return devgen(c, nil, topdir, nelem(topdir), s, dp);
  393         case Qpnpdir:
  394                 if(s == DEVDOTDOT){
  395                         q = (Qid){QID(0, Qtopdir), 0, QTDIR};
  396                         sprint(up->genbuf, "#%C", pnpdevtab.dc);
  397                         devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  398                         return 1;
  399                 }
  400                 if(s < nelem(pnpdir)-1)
  401                         return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp);
  402                 s -= nelem(pnpdir)-1;
  403                 qlock(&pnp);
  404                 cp = pnp.cards;
  405                 while(s >= 2 && cp != nil) {
  406                         s -= 2;
  407                         cp = cp->next;
  408                 }
  409                 qunlock(&pnp);
  410                 if(cp == nil)
  411                         return -1;
  412                 return csngen(c, s+Qcsnctl, cp->csn, cp, dp);
  413         case Qpnpctl:
  414                 return devgen(c, nil, pnpdir, nelem(pnpdir), s, dp);
  415         case Qcsnctl:
  416         case Qcsnraw:
  417                 csn = CSN(c->qid);
  418                 cp = findcsn(csn, 0, 1);
  419                 if(cp == nil)
  420                         return -1;
  421                 return csngen(c, TYPE(c->qid), csn, cp, dp);
  422         case Qpcidir:
  423                 if(s == DEVDOTDOT){
  424                         q = (Qid){QID(0, Qtopdir), 0, QTDIR};
  425                         sprint(up->genbuf, "#%C", pnpdevtab.dc);
  426                         devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  427                         return 1;
  428                 }
  429                 p = pcimatch(nil, 0, 0);
  430                 while(s >= 2 && p != nil) {
  431                         p = pcimatch(p, 0, 0);
  432                         s -= 2;
  433                 }
  434                 if(p == nil)
  435                         return -1;
  436                 return pcigen(c, s+Qpcictl, p->tbdf, dp);
  437         case Qpcictl:
  438         case Qpciraw:
  439                 tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
  440                 p = pcimatchtbdf(tbdf);
  441                 if(p == nil)
  442                         return -1;
  443                 return pcigen(c, TYPE(c->qid), tbdf, dp);
  444         default:
  445                 break;
  446         }
  447         return -1;
  448 }
  449 
  450 static Chan*
  451 pnpattach(char *spec)
  452 {
  453         return devattach(pnpdevtab.dc, spec);
  454 }
  455 
  456 Walkqid*
  457 pnpwalk(Chan* c, Chan *nc, char** name, int nname)
  458 {
  459         return devwalk(c, nc, name, nname, (Dirtab *)0, 0, pnpgen);
  460 }
  461 
  462 static int
  463 pnpstat(Chan* c, uchar* dp, int n)
  464 {
  465         return devstat(c, dp, n, (Dirtab *)0, 0L, pnpgen);
  466 }
  467 
  468 static Chan*
  469 pnpopen(Chan *c, int omode)
  470 {
  471         c = devopen(c, omode, (Dirtab*)0, 0, pnpgen);
  472         switch(TYPE(c->qid)){
  473         default:
  474                 break;
  475         }
  476         return c;
  477 }
  478 
  479 static void
  480 pnpclose(Chan*)
  481 {
  482 }
  483 
  484 static long
  485 pnpread(Chan *c, void *va, long n, vlong offset)
  486 {
  487         ulong x;
  488         Card *cp;
  489         Pcidev *p;
  490         char buf[256], *ebuf, *w;
  491         char *a = va;
  492         int csn, i, tbdf, r;
  493 
  494         switch(TYPE(c->qid)){
  495         case Qtopdir:
  496         case Qpnpdir:
  497         case Qpcidir:
  498                 return devdirread(c, a, n, (Dirtab *)0, 0L, pnpgen);
  499         case Qpnpctl:
  500                 if(pnp.rddata > 0)
  501                         sprint(up->genbuf, "enabled %#x\n", pnp.rddata);
  502                 else
  503                         sprint(up->genbuf, "disabled\n");
  504                 return readstr(offset, a, n, up->genbuf);
  505         case Qcsnraw:
  506                 csn = CSN(c->qid);
  507                 cp = findcsn(csn, 0, 1);
  508                 if(cp == nil)
  509                         error(Egreg);
  510                 if(offset+n > cp->ncfg)
  511                         n = cp->ncfg - offset;
  512                 qlock(&pnp);
  513                 initiation();
  514                 cmd(0x03, csn);                         /* Wake up the card */
  515                 for(i = 0; i < offset+9; i++)           /* 9 == skip serial + csum */
  516                         getresbyte(pnp.rddata);
  517                 for(i = 0; i < n; i++)
  518                         a[i] = getresbyte(pnp.rddata);
  519                 cmd(0x03, 0);                                   /* Wake all cards with a CSN of 0, putting this card to sleep */
  520                 cmd(0x02, 0x02);                                /* return cards to Wait for Key state */
  521                 qunlock(&pnp);
  522                 break;
  523         case Qcsnctl:
  524                 csn = CSN(c->qid);
  525                 cp = findcsn(csn, 0, 1);
  526                 if(cp == nil)
  527                         error(Egreg);
  528                 sprint(up->genbuf, "%s\n", serial(cp->id1, cp->id2));
  529                 return readstr(offset, a, n, up->genbuf);
  530         case Qpcictl:
  531                 tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
  532                 p = pcimatchtbdf(tbdf);
  533                 if(p == nil)
  534                         error(Egreg);
  535                 ebuf = buf+sizeof buf-1;        /* -1 for newline */
  536                 w = seprint(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d",
  537                         p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl);
  538                 for(i=0; i<nelem(p->mem); i++){
  539                         if(p->mem[i].size == 0)
  540                                 continue;
  541                         w = seprint(w, ebuf, " %d:%.8lux %d", i, p->mem[i].bar, p->mem[i].size);
  542                 }
  543                 *w++ = '\n';
  544                 *w = '\0';
  545                 return readstr(offset, a, n, buf);
  546         case Qpciraw:
  547                 tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
  548                 p = pcimatchtbdf(tbdf);
  549                 if(p == nil)
  550                         error(Egreg);
  551                 if(offset > 256)
  552                         return 0;
  553                 if(n+offset > 256)
  554                         n = 256-offset;
  555                 r = offset;
  556                 if(!(r & 3) && n == 4){
  557                         x = pcicfgr32(p, r);
  558                         PBIT32(a, x);
  559                         return 4;
  560                 }
  561                 if(!(r & 1) && n == 2){
  562                         x = pcicfgr16(p, r);
  563                         PBIT16(a, x);
  564                         return 2;
  565                 }
  566                 for(i = 0; i <  n; i++){
  567                         x = pcicfgr8(p, r);
  568                         PBIT8(a, x);
  569                         a++;
  570                         r++;
  571                 }
  572                 return i;
  573         default:
  574                 error(Egreg);
  575         }
  576         return n;
  577 }
  578 
  579 static long
  580 pnpwrite(Chan *c, void *va, long n, vlong offset)
  581 {
  582         Card *cp;
  583         Pcidev *p;
  584         ulong port, x;
  585         char *a, buf[256];
  586         int csn, i, r, tbdf;
  587 
  588         if(n >= sizeof(buf))
  589                 n = sizeof(buf)-1;
  590         a = va;
  591         strncpy(buf, a, n);
  592         buf[n] = 0;
  593 
  594         switch(TYPE(c->qid)){
  595         case Qpnpctl:
  596                 if(strncmp(buf, "port ", 5) == 0) {
  597                         port = strtoul(buf+5, 0, 0);
  598                         if(port < 0x203 || port > 0x3ff)
  599                                 error("bad value for rddata port");
  600                         qlock(&pnp);
  601                         if(waserror()) {
  602                                 qunlock(&pnp);
  603                                 nexterror();
  604                         }
  605                         if(pnp.rddata > 0)
  606                                 error("pnp port already set");
  607                         if(!pnpscan(port, 0))
  608                                 error("no cards found");
  609                         qunlock(&pnp);
  610                         poperror();
  611                 }
  612                 else if(strncmp(buf, "debug ", 6) == 0)
  613                         pnp.debug = strtoul(buf+6, 0, 0);
  614                 else
  615                         error(Ebadctl);
  616                 break;
  617         case Qcsnctl:
  618                 csn = CSN(c->qid);
  619                 cp = findcsn(csn, 0, 1);
  620                 if(cp == nil)
  621                         error(Egreg);
  622                 if(!wrconfig(cp, buf))
  623                         error(Ebadctl);
  624                 break;
  625         case Qpciraw:
  626                 tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path);
  627                 p = pcimatchtbdf(tbdf);
  628                 if(p == nil)
  629                         error(Egreg);
  630                 if(offset > 256)
  631                         return 0;
  632                 if(n+offset > 256)
  633                         n = 256-offset;
  634                 r = offset;
  635                 if(!(r & 3) && n == 4){
  636                         x = GBIT32(a);
  637                         pcicfgw32(p, r, x);
  638                         return 4;
  639                 }
  640                 if(!(r & 1) && n == 2){
  641                         x = GBIT16(a);
  642                         pcicfgw16(p, r, x);
  643                         return 2;
  644                 }
  645                 for(i = 0; i <  n; i++){
  646                         x = GBIT8(a);
  647                         pcicfgw8(p, r, x);
  648                         a++;
  649                         r++;
  650                 }
  651                 return i;
  652         default:
  653                 error(Egreg);
  654         }
  655         return n;
  656 }
  657 
  658 static int
  659 wrconfig(Card *c, char *cmd)
  660 {
  661         /* This should implement setting of I/O bases, etc */
  662         USED(c, cmd);
  663         return 1;
  664 }
  665 
  666 
  667 Dev pnpdevtab = {
  668         '$',
  669         "pnp",
  670 
  671         pnpreset,
  672         devinit,
  673         devshutdown,
  674         pnpattach,
  675         pnpwalk,
  676         pnpstat,
  677         pnpopen,
  678         devcreate,
  679         pnpclose,
  680         pnpread,
  681         devbread,
  682         pnpwrite,
  683         devbwrite,
  684         devremove,
  685         devwstat,
  686 };

Cache object: c391207021d9ec35a42e1b7930825b22


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