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/cis.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 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "../port/error.h"
    7 #include "io.h"
    8 
    9 enum{
   10         Linktarget = 0x13,
   11 };
   12         
   13 /*
   14  *  read and crack the card information structure enough to set
   15  *  important parameters like power
   16  */
   17 /* cis memory walking */
   18 typedef struct Cisdat {
   19         uchar   *cisbase;
   20         int     cispos;
   21         int     cisskip;
   22         int     cislen;
   23 } Cisdat;
   24 
   25 static void     tcfig(PCMslot*, Cisdat*, int);
   26 static void     tentry(PCMslot*, Cisdat*, int);
   27 static void     tvers1(PCMslot*, Cisdat*, int);
   28 static void     tlonglnkmfc(PCMslot*, Cisdat*, int);
   29 
   30 static int
   31 readc(Cisdat *cis, uchar *x)
   32 {
   33         if(cis->cispos >= cis->cislen)
   34                 return 0;
   35         *x = cis->cisbase[cis->cisskip*cis->cispos];
   36         cis->cispos++;
   37         return 1;
   38 }
   39 
   40 static int
   41 xcistuple(int slotno, int tuple, int subtuple, void *v, int nv, int attr)
   42 {
   43         PCMmap *m;
   44         Cisdat cis;
   45         int i, l;
   46         uchar *p;
   47         uchar type, link, n, c;
   48         int this, subtype;
   49 
   50         m = pcmmap(slotno, 0, 0, attr);
   51         if(m == 0)
   52                 return -1;
   53 
   54         cis.cisbase = KADDR(m->isa);
   55         cis.cispos = 0;
   56         cis.cisskip = attr ? 2 : 1;
   57         cis.cislen = m->len;
   58 
   59         /* loop through all the tuples */
   60         for(i = 0; i < 1000; i++){
   61                 this = cis.cispos;
   62                 if(readc(&cis, &type) != 1)
   63                         break;
   64                 if(type == 0xFF)
   65                         break;
   66                 if(readc(&cis, &link) != 1)
   67                         break;
   68                 if(link == 0xFF)
   69                         break;
   70 
   71                 n = link;
   72                 if(link > 1 && subtuple != -1){
   73                         if(readc(&cis, &c) != 1)
   74                                 break;
   75                         subtype = c;
   76                         n--;
   77                 }else
   78                         subtype = -1;
   79 
   80                 if(type == tuple && subtype == subtuple){
   81                         p = v;
   82                         for(l=0; l<nv && l<n; l++)
   83                                 if(readc(&cis, p++) != 1)
   84                                         break;
   85                         pcmunmap(slotno, m);
   86                         return nv;
   87                 }
   88                 cis.cispos = this + (2+link);
   89         }
   90         pcmunmap(slotno, m);
   91         return -1;
   92 }
   93 
   94 int
   95 pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv)
   96 {
   97         int n;
   98 
   99         /* try attribute space, then memory */
  100         if((n = xcistuple(slotno, tuple, subtuple, v, nv, 1)) >= 0)
  101                 return n;
  102         return xcistuple(slotno, tuple, subtuple, v, nv, 0);
  103 }
  104 
  105 void
  106 pcmcisread(PCMslot *pp)
  107 {
  108         int this;
  109         Cisdat cis;
  110         PCMmap *m;
  111         uchar type, link;
  112 
  113         memset(pp->ctab, 0, sizeof(pp->ctab));
  114         pp->ncfg = 0;
  115         memset(pp->cfg, 0, sizeof(pp->cfg));
  116         pp->configed = 0;
  117         pp->nctab = 0;
  118         pp->verstr[0] = 0;
  119 
  120         /*
  121          * Read all tuples in attribute space.
  122          */
  123         m = pcmmap(pp->slotno, 0, 0, 1);
  124         if(m == 0)
  125                 return;
  126 
  127         cis.cisbase = KADDR(m->isa);
  128         cis.cispos = 0;
  129         cis.cisskip = 2;
  130         cis.cislen = m->len;
  131 
  132         /* loop through all the tuples */
  133         for(;;){
  134                 this = cis.cispos;
  135                 if(readc(&cis, &type) != 1)
  136                         break;
  137                 if(type == 0xFF)
  138                         break;
  139                 if(readc(&cis, &link) != 1)
  140                         break;
  141 
  142                 switch(type){
  143                 default:
  144                         break;
  145                 case 6:
  146                         tlonglnkmfc(pp, &cis, type);
  147                         break;
  148                 case 0x15:
  149                         tvers1(pp, &cis, type);
  150                         break;
  151                 case 0x1A:
  152                         tcfig(pp, &cis, type);
  153                         break;
  154                 case 0x1B:
  155                         tentry(pp, &cis, type);
  156                         break;
  157                 }
  158 
  159                 if(link == 0xFF)
  160                         break;
  161                 cis.cispos = this + (2+link);
  162         }
  163         pcmunmap(pp->slotno, m);
  164 }
  165 
  166 static ulong
  167 getlong(Cisdat *cis, int size)
  168 {
  169         uchar c;
  170         int i;
  171         ulong x;
  172 
  173         x = 0;
  174         for(i = 0; i < size; i++){
  175                 if(readc(cis, &c) != 1)
  176                         break;
  177                 x |= c<<(i*8);
  178         }
  179         return x;
  180 }
  181 
  182 static void
  183 tcfig(PCMslot *pp, Cisdat *cis, int )
  184 {
  185         uchar size, rasize, rmsize;
  186         uchar last;
  187 
  188         if(readc(cis, &size) != 1)
  189                 return;
  190         rasize = (size&0x3) + 1;
  191         rmsize = ((size>>2)&0xf) + 1;
  192         if(readc(cis, &last) != 1)
  193                 return;
  194 
  195         if(pp->ncfg >= 8){
  196                 print("tcfig: too many configuration registers\n");
  197                 return;
  198         }
  199         
  200         pp->cfg[pp->ncfg].caddr = getlong(cis, rasize);
  201         pp->cfg[pp->ncfg].cpresent = getlong(cis, rmsize);
  202         pp->ncfg++;
  203 }
  204 
  205 static ulong vexp[8] =
  206 {
  207         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
  208 };
  209 static ulong vmant[16] =
  210 {
  211         10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
  212 };
  213 
  214 static ulong
  215 microvolt(Cisdat *cis)
  216 {
  217         uchar c;
  218         ulong microvolts;
  219         ulong exp;
  220 
  221         if(readc(cis, &c) != 1)
  222                 return 0;
  223         exp = vexp[c&0x7];
  224         microvolts = vmant[(c>>3)&0xf]*exp;
  225         while(c & 0x80){
  226                 if(readc(cis, &c) != 1)
  227                         return 0;
  228                 switch(c){
  229                 case 0x7d:
  230                         break;          /* high impedence when sleeping */
  231                 case 0x7e:
  232                 case 0x7f:
  233                         microvolts = 0; /* no connection */
  234                         break;
  235                 default:
  236                         exp /= 10;
  237                         microvolts += exp*(c&0x7f);
  238                 }
  239         }
  240         return microvolts;
  241 }
  242 
  243 static ulong
  244 nanoamps(Cisdat *cis)
  245 {
  246         uchar c;
  247         ulong nanoamps;
  248 
  249         if(readc(cis, &c) != 1)
  250                 return 0;
  251         nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
  252         while(c & 0x80){
  253                 if(readc(cis, &c) != 1)
  254                         return 0;
  255                 if(c == 0x7d || c == 0x7e || c == 0x7f)
  256                         nanoamps = 0;
  257         }
  258         return nanoamps;
  259 }
  260 
  261 /*
  262  * only nominal voltage (feature 1) is important for config,
  263  * other features must read card to stay in sync.
  264  */
  265 static ulong
  266 power(Cisdat *cis)
  267 {
  268         uchar feature;
  269         ulong mv;
  270 
  271         mv = 0;
  272         if(readc(cis, &feature) != 1)
  273                 return 0;
  274         if(feature & 1)
  275                 mv = microvolt(cis);
  276         if(feature & 2)
  277                 microvolt(cis);
  278         if(feature & 4)
  279                 microvolt(cis);
  280         if(feature & 8)
  281                 nanoamps(cis);
  282         if(feature & 0x10)
  283                 nanoamps(cis);
  284         if(feature & 0x20)
  285                 nanoamps(cis);
  286         if(feature & 0x40)
  287                 nanoamps(cis);
  288         return mv/1000000;
  289 }
  290 
  291 static ulong mantissa[16] =
  292 { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
  293 
  294 static ulong exponent[8] =
  295 { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
  296 
  297 static ulong
  298 ttiming(Cisdat *cis, int scale)
  299 {
  300         uchar unscaled;
  301         ulong nanosecs;
  302 
  303         if(readc(cis, &unscaled) != 1)
  304                 return 0;
  305         nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
  306         nanosecs = nanosecs * vexp[scale];
  307         return nanosecs;
  308 }
  309 
  310 static void
  311 timing(Cisdat *cis, PCMconftab *ct)
  312 {
  313         uchar c, i;
  314 
  315         if(readc(cis, &c) != 1)
  316                 return;
  317         i = c&0x3;
  318         if(i != 3)
  319                 ct->maxwait = ttiming(cis, i);          /* max wait */
  320         i = (c>>2)&0x7;
  321         if(i != 7)
  322                 ct->readywait = ttiming(cis, i);                /* max ready/busy wait */
  323         i = (c>>5)&0x7;
  324         if(i != 7)
  325                 ct->otherwait = ttiming(cis, i);                /* reserved wait */
  326 }
  327 
  328 static void
  329 iospaces(Cisdat *cis, PCMconftab *ct)
  330 {
  331         uchar c;
  332         int i, nio;
  333 
  334         ct->nio = 0;
  335         if(readc(cis, &c) != 1)
  336                 return;
  337 
  338         ct->bit16 = ((c>>5)&3) >= 2;
  339         if(!(c & 0x80)){
  340                 ct->io[0].start = 0;
  341                 ct->io[0].len = 1<<(c&0x1f);
  342                 ct->nio = 1;
  343                 return;
  344         }
  345 
  346         if(readc(cis, &c) != 1)
  347                 return;
  348 
  349         /*
  350          * For each of the range descriptions read the
  351          * start address and the length (value is length-1).
  352          */
  353         nio = (c&0xf)+1;
  354         for(i = 0; i < nio; i++){
  355                 ct->io[i].start = getlong(cis, (c>>4)&0x3);
  356                 ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
  357         }
  358         ct->nio = nio;
  359 }
  360 
  361 static void
  362 irq(Cisdat *cis, PCMconftab *ct)
  363 {
  364         uchar c;
  365 
  366         if(readc(cis, &c) != 1)
  367                 return;
  368         ct->irqtype = c & 0xe0;
  369         if(c & 0x10)
  370                 ct->irqs = getlong(cis, 2);
  371         else
  372                 ct->irqs = 1<<(c&0xf);
  373         ct->irqs &= 0xDEB8;             /* levels available to card */
  374 }
  375 
  376 static void
  377 memspace(Cisdat *cis, int asize, int lsize, int host)
  378 {
  379         ulong haddress, address, len;
  380 
  381         len = getlong(cis, lsize)*256;
  382         address = getlong(cis, asize)*256;
  383         USED(len, address);
  384         if(host){
  385                 haddress = getlong(cis, asize)*256;
  386                 USED(haddress);
  387         }
  388 }
  389 
  390 static void
  391 tentry(PCMslot *pp, Cisdat *cis, int )
  392 {
  393         uchar c, i, feature;
  394         PCMconftab *ct;
  395 
  396         if(pp->nctab >= nelem(pp->ctab))
  397                 return;
  398         if(readc(cis, &c) != 1)
  399                 return;
  400         ct = &pp->ctab[pp->nctab++];
  401 
  402         /* copy from last default config */
  403         if(pp->def)
  404                 *ct = *pp->def;
  405 
  406         ct->index = c & 0x3f;
  407 
  408         /* is this the new default? */
  409         if(c & 0x40)
  410                 pp->def = ct;
  411 
  412         /* memory wait specified? */
  413         if(c & 0x80){
  414                 if(readc(cis, &i) != 1)
  415                         return;
  416                 if(i&0x80)
  417                         ct->memwait = 1;
  418         }
  419 
  420         if(readc(cis, &feature) != 1)
  421                 return;
  422         switch(feature&0x3){
  423         case 1:
  424                 ct->vpp1 = ct->vpp2 = power(cis);
  425                 break;
  426         case 2:
  427                 power(cis);
  428                 ct->vpp1 = ct->vpp2 = power(cis);
  429                 break;
  430         case 3:
  431                 power(cis);
  432                 ct->vpp1 = power(cis);
  433                 ct->vpp2 = power(cis);
  434                 break;
  435         default:
  436                 break;
  437         }
  438         if(feature&0x4)
  439                 timing(cis, ct);
  440         if(feature&0x8)
  441                 iospaces(cis, ct);
  442         if(feature&0x10)
  443                 irq(cis, ct);
  444         switch((feature>>5)&0x3){
  445         case 1:
  446                 memspace(cis, 0, 2, 0);
  447                 break;
  448         case 2:
  449                 memspace(cis, 2, 2, 0);
  450                 break;
  451         case 3:
  452                 if(readc(cis, &c) != 1)
  453                         return;
  454                 for(i = 0; i <= (c&0x7); i++)
  455                         memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
  456                 break;
  457         }
  458         pp->configed++;
  459 }
  460 
  461 static void
  462 tvers1(PCMslot *pp, Cisdat *cis, int )
  463 {
  464         uchar c, major, minor, last;
  465         int  i;
  466 
  467         if(readc(cis, &major) != 1)
  468                 return;
  469         if(readc(cis, &minor) != 1)
  470                 return;
  471         last = 0;
  472         for(i = 0; i < sizeof(pp->verstr)-1; i++){
  473                 if(readc(cis, &c) != 1)
  474                         return;
  475                 if(c == 0)
  476                         c = ';';
  477                 if(c == '\n')
  478                         c = ';';
  479                 if(c == 0xff)
  480                         break;
  481                 if(c == ';' && last == ';')
  482                         continue;
  483                 pp->verstr[i] = c;
  484                 last = c;
  485         }
  486         pp->verstr[i] = 0;
  487 }
  488 
  489 static void
  490 tlonglnkmfc(PCMslot *pp, Cisdat *cis, int)
  491 {
  492         int i, npos, opos;
  493         uchar nfn, space, expect, type, this, link;
  494 
  495         readc(cis, &nfn);
  496         for(i = 0; i < nfn; i++){
  497                 readc(cis, &space);
  498                 npos        = getlong(cis, 4);
  499                 opos        = cis->cispos;
  500                 cis->cispos = npos;
  501                 expect      = Linktarget;
  502 
  503                 while(1){
  504                         this = cis->cispos;
  505                         if(readc(cis, &type) != 1)
  506                                 break;
  507                         if(type == 0xFF)
  508                                 break;
  509                         if(readc(cis, &link) != 1)
  510                                 break;
  511 
  512                         if(expect && expect != type){
  513                                 print("tlonglnkmfc: expected %X found %X\n",
  514                                         expect, type);
  515                                 break;
  516                         }
  517                         expect = 0;
  518 
  519                         switch(type){
  520                         default:
  521                                 break;
  522                         case 0x15:
  523                                 tvers1(pp, cis, type);
  524                                 break;
  525                         case 0x1A:
  526                                 tcfig(pp, cis, type);
  527                                 break;
  528                         case 0x1B:
  529                                 tentry(pp, cis, type);
  530                                 break;
  531                         }
  532 
  533                         if(link == 0xFF)
  534                                 break;
  535                         cis->cispos = this + (2+link);
  536                 }
  537                 cis->cispos = opos;
  538         }
  539 }

Cache object: 4f89da903725dc695d99909d7ca00917


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