Annotation of lucent/sys/src/9/pc/f002527, revision 1.1.1.1

1.1       root        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: #include "devtab.h"
                      9: 
                     10: /*
                     11:  *  Support for up to 4 Slot card slots.  Generalizing above that is hard
                     12:  *  since addressing is not obvious. - presotto
                     13:  *
                     14:  *  WARNING: This has never been tried with more than one card slot.
                     15:  */
                     16: 
                     17: /*
                     18:  *  Intel 82365SL PCIC controller for the PCMCIA or
                     19:  *  Cirrus Logic PD6710/PD6720 which is mostly register compatible
                     20:  */
                     21: enum
                     22: {
                     23:        /*
                     24:         *  registers indices
                     25:         */
                     26:        Rid=            0x0,            /* identification and revision */
                     27:        Ris=            0x1,            /* interface status */
                     28:        Rpc=            0x2,            /* power control */
                     29:         Foutena=        (1<<7),        /*  output enable */
                     30:         Fautopower=     (1<<5),        /*  automatic power switching */
                     31:         Fcardena=       (1<<4),        /*  PC card enable */
                     32:        Rigc=           0x3,            /* interrupt and general control */
                     33:         Fiocard=        (1<<5),        /*  I/O card (vs memory) */
                     34:         Fnotreset=      (1<<6),        /*  reset if not set */ 
                     35:         FSMIena=        (1<<4),        /*  enable change interrupt on SMI */ 
                     36:        Rcsc=           0x4,            /* card status change */
                     37:        Rcscic=         0x5,            /* card status change interrupt config */
                     38:         Fchangeena=     (1<<3),        /*  card changed */
                     39:         Fbwarnena=      (1<<1),        /*  card battery warning */
                     40:         Fbdeadena=      (1<<0),        /*  card battery dead */
                     41:        Rwe=            0x6,            /* address window enable */
                     42:         Fmem16=         (1<<5),        /*  use A23-A12 to decode address */
                     43:        Rio=            0x7,            /* I/O control */
                     44:         Fwidth16=       (1<<0),        /*  16 bit data width */
                     45:         Fiocs16=        (1<<1),        /*  IOCS16 determines data width */
                     46:         Ftiming=        (1<<3),        /*  timing register to use */
                     47:        Riobtm0lo=      0x8,            /* I/O address 0 start low byte */
                     48:        Riobtm0hi=      0x9,            /* I/O address 0 start high byte */
                     49:        Riotop0lo=      0xa,            /* I/O address 0 stop low byte */
                     50:        Riotop0hi=      0xb,            /* I/O address 0 stop high byte */
                     51:        Riobtm1lo=      0xc,            /* I/O address 1 start low byte */
                     52:        Riobtm1hi=      0xd,            /* I/O address 1 start high byte */
                     53:        Riotop1lo=      0xe,            /* I/O address 1 stop low byte */
                     54:        Riotop1hi=      0xf,            /* I/O address 1 stop high byte */
                     55:        Rmap=           0x10,           /* map 0 */
                     56: 
                     57:        /*
                     58:         *  CL-PD67xx extension registers
                     59:         */
                     60:        Rmisc1=         0x16,           /* misc control 1 */
                     61:         F5Vdetect=      (1<<0),
                     62:         Fvcc3V=         (1<<1),
                     63:         Fpmint=         (1<<2),
                     64:         Fpsirq=         (1<<3),
                     65:         Fspeaker=       (1<<4),
                     66:         Finpack=        (1<<7),
                     67:        Rfifo=          0x17,           /* fifo control */
                     68:         Fflush=         (1<<7),        /*  flush fifo */
                     69:        Rmisc2=         0x1E,           /* misc control 2 */
                     70:         Flowpow=        (1<<1),        /*  low power mode */
                     71:        Rchipinfo=      0x1F,           /* chip information */
                     72:        Ratactl=        0x26,           /* ATA control */
                     73: 
                     74:        /*
                     75:         *  offsets into the system memory address maps
                     76:         */
                     77:        Mbtmlo=         0x0,            /* System mem addr mapping start low byte */
                     78:        Mbtmhi=         0x1,            /* System mem addr mapping start high byte */
                     79:         F16bit=         (1<<7),        /*  16-bit wide data path */
                     80:        Mtoplo=         0x2,            /* System mem addr mapping stop low byte */
                     81:        Mtophi=         0x3,            /* System mem addr mapping stop high byte */
                     82:         Ftimer1=        (1<<6),        /*  timer set 1 */
                     83:        Mofflo=         0x4,            /* Card memory offset address low byte */
                     84:        Moffhi=         0x5,            /* Card memory offset address high byte */
                     85:         Fregactive=     (1<<6),        /*  attribute memory */
                     86: 
                     87:        Mbits=          13,             /* msb of Mchunk */
                     88:        Mchunk=         1<<Mbits,       /* logical mapping granularity */
                     89:        Nmap=           4,              /* max number of maps to use */
                     90: 
                     91:        /*
                     92:         *  configuration registers - they start at an offset in attribute
                     93:         *  memory found in the CIS.
                     94:         */
                     95:        Rconfig=        0,
                     96:         Creset=         (1<<7),        /*  reset device */
                     97:         Clevel=         (1<<6),        /*  level sensitive interrupt line */
                     98: 
                     99:        Maxctab=        8,              /* maximum configuration table entries */
                    100: };
                    101: 
                    102: #define MAP(x,o)       (Rmap + (x)*0x8 + o)
                    103: 
                    104: typedef struct I82365  I82365;
                    105: typedef struct Slot    Slot;
                    106: typedef struct Conftab Conftab;
                    107: 
                    108: /* a controller */
                    109: enum
                    110: {
                    111:        Ti82365,
                    112:        Tpd6710,
                    113:        Tpd6720,
                    114: };
                    115: struct I82365
                    116: {
                    117:        int     type;
                    118:        int     dev;
                    119:        int     nslot;
                    120:        int     xreg;           /* index register address */
                    121:        int     dreg;           /* data register address */
                    122: };
                    123: static I82365 *controller[4];
                    124: static int ncontroller;
                    125: 
                    126: /* configuration table entry */
                    127: struct Conftab
                    128: {
                    129:        int     index;
                    130:        ushort  irqs;           /* legal irqs */
                    131:        ushort  port;           /* port address */
                    132:        uchar   irqtype;
                    133:        uchar   nioregs;        /* number of io registers */
                    134:        uchar   bit16;          /* true for 16 bit access */
                    135:        uchar   vpp1;
                    136:        uchar   vpp2;
                    137:        uchar   memwait;
                    138:        ulong   maxwait;
                    139:        ulong   readywait;
                    140:        ulong   otherwait;
                    141: };
                    142: 
                    143: /* a card slot */
                    144: struct Slot
                    145: {
                    146:        Lock;
                    147:        int     ref;
                    148: 
                    149:        I82365  *cp;            /* controller for this slot */
                    150:        long    memlen;         /* memory length */
                    151:        uchar   base;           /* index register base */
                    152:        uchar   slotno;         /* slot number */
                    153: 
                    154:        /* status */
                    155:        uchar   special;        /* in use for a special device */
                    156:        uchar   already;        /* already inited */
                    157:        uchar   occupied;
                    158:        uchar   battery;
                    159:        uchar   wrprot;
                    160:        uchar   powered;
                    161:        uchar   configed;
                    162:        uchar   enabled;
                    163:        uchar   busy;
                    164: 
                    165:        /* cis info */
                    166:        char    verstr[512];    /* version string */
                    167:        uchar   cpresent;       /* config registers present */
                    168:        ulong   caddr;          /* relative address of config registers */
                    169:        int     nctab;          /* number of config table entries */
                    170:        Conftab ctab[Maxctab];
                    171:        Conftab *def;           /* default conftab */
                    172: 
                    173:        /* for walking through cis */
                    174:        int     cispos;         /* current position scanning cis */
                    175:        uchar   *cisbase;
                    176: 
                    177:        /* memory maps */
                    178:        Lock    mlock;          /* lock down the maps */
                    179:        int     time;
                    180:        PCMmap  mmap[Nmap];     /* maps, last is always for the kernel */
                    181: };
                    182: static Slot    *slot;
                    183: static Slot    *lastslot;
                    184: static nslot;
                    185: 
                    186: static void    cisread(Slot*);
                    187: static void    i82365intr(Ureg*, void*);
                    188: static int     pcmio(int, ISAConf*);
                    189: static long    pcmread(int, int, void*, long, ulong);
                    190: static long    pcmwrite(int, int, void*, long, ulong);
                    191: 
                    192: /*
                    193:  *  reading and writing card registers
                    194:  */
                    195: static uchar
                    196: rdreg(Slot *pp, int index)
                    197: {
                    198:        outb(pp->cp->xreg, pp->base + index);
                    199:        return inb(pp->cp->dreg);
                    200: }
                    201: static void
                    202: wrreg(Slot *pp, int index, uchar val)
                    203: {
                    204:        outb(pp->cp->xreg, pp->base + index);
                    205:        outb(pp->cp->dreg, val);
                    206: }
                    207: 
                    208: /*
                    209:  *  get info about card
                    210:  */
                    211: static void
                    212: slotinfo(Slot *pp)
                    213: {
                    214:        uchar isr;
                    215: 
                    216:        isr = rdreg(pp, Ris);
                    217:        pp->occupied = (isr & (3<<2)) == (3<<2);
                    218:        pp->powered = isr & (1<<6);
                    219:        pp->battery = (isr & 3) == 3;
                    220:        pp->wrprot = isr & (1<<4);
                    221:        pp->busy = isr & (1<<5);
                    222: }
                    223: 
                    224: static int
                    225: vcode(int volt)
                    226: {
                    227:        switch(volt){
                    228:        case 5:
                    229:                return 1;
                    230:        case 12:
                    231:                return 2;
                    232:        default:
                    233:                return 0;
                    234:        }
                    235: }
                    236: 
                    237: /*
                    238:  *  enable the slot card
                    239:  */
                    240: static void
                    241: slotena(Slot *pp)
                    242: {
                    243:        if(pp->enabled)
                    244:                return;
                    245: 
                    246:        /* power up and unreset, wait's are empirical (???) */
                    247:        wrreg(pp, Rpc, Fautopower|Foutena|Fcardena);
                    248:        delay(300);
                    249:        wrreg(pp, Rigc, 0);
                    250:        delay(100);
                    251:        wrreg(pp, Rigc, Fnotreset);
                    252:        delay(500);
                    253: 
                    254:        /* get configuration */
                    255:        slotinfo(pp);
                    256:        if(pp->occupied){
                    257:                cisread(pp);
                    258:                pp->enabled = 1;
                    259:        } else
                    260:                wrreg(pp, Rpc, Fautopower);
                    261: }
                    262: 
                    263: /*
                    264:  *  disable the slot card
                    265:  */
                    266: static void
                    267: slotdis(Slot *pp)
                    268: {
                    269:        wrreg(pp, Rpc, 0);      /* turn off card power */
                    270:        wrreg(pp, Rwe, 0);      /* no windows */
                    271:        pp->enabled = 0;
                    272: }
                    273: 
                    274: /*
                    275:  *  status change interrupt
                    276:  */
                    277: static void
                    278: i82365intr(Ureg *ur, void *a)
                    279: {
                    280:        uchar csc, was;
                    281:        Slot *pp;
                    282: 
                    283:        USED(ur,a);
                    284:        if(slot == 0)
                    285:                return;
                    286: 
                    287:        for(pp = slot; pp < lastslot; pp++){
                    288:                csc = rdreg(pp, Rcsc);
                    289:                was = pp->occupied;
                    290:                slotinfo(pp);
                    291:                if(csc & (1<<3) && was != pp->occupied){
                    292:                        if(pp->occupied)
                    293:                                print("slot%d card inserted\n", pp->slotno);
                    294:                        else {
                    295:                                print("slot%d card removed\n", pp->slotno);
                    296:                                slotdis(pp);
                    297:                        }
                    298:                }
                    299:        }
                    300: }
                    301: 
                    302: enum
                    303: {
                    304:        Mshift= 12,
                    305:        Mgran=  (1<<Mshift),    /* granularity of maps */
                    306:        Mmask=  ~(Mgran-1),     /* mask for address bits important to the chip */
                    307: };
                    308: 
                    309: /*
                    310:  *  get a map for pc card region, return corrected len
                    311:  */
                    312: PCMmap*
                    313: pcmmap(int slotno, ulong offset, int len, int attr)
                    314: {
                    315:        Slot *pp;
                    316:        uchar we, bit;
                    317:        PCMmap *m, *nm;
                    318:        int i;
                    319:        ulong e;
                    320: 
                    321:        pp = slot + slotno;
                    322:        lock(&pp->mlock);
                    323: 
                    324:        /* convert offset to granularity */
                    325:        if(len <= 0)
                    326:                len = 1;
                    327:        e = ROUND(offset+len, Mgran);
                    328:        offset &= Mmask;
                    329:        len = e - offset;
                    330: 
                    331:        /* look for a map that covers the right area */
                    332:        we = rdreg(pp, Rwe);
                    333:        bit = 1;
                    334:        nm = 0;
                    335:        for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){
                    336:                if((we & bit))
                    337:                if(m->attr == attr)
                    338:                if(offset >= m->ca && e <= m->cea){
                    339: 
                    340:                        m->ref++;
                    341:                        unlock(&pp->mlock);
                    342:                        return m;
                    343:                }
                    344:                bit <<= 1;
                    345:                if(nm == 0 && m->ref == 0)
                    346:                        nm = m;
                    347:        }
                    348:        m = nm;
                    349:        if(m == 0){
                    350:                unlock(&pp->mlock);
                    351:                return 0;
                    352:        }
                    353: 
                    354:        /* if isa space isn't big enough, free it and get more */
                    355:        if(m->len < len){
                    356:                if(m->isa){
                    357:                        putisa(m->isa, m->len);
                    358:                        m->len = 0;
                    359:                }
                    360:                m->isa = getisa(0, len, Mgran)&~KZERO;
                    361:                if(m->isa == 0){
                    362:                        print("pcmmap: out of isa space\n");
                    363:                        unlock(&pp->mlock);
                    364:                        return 0;
                    365:                }
                    366:                m->len = len;
                    367:        }
                    368: 
                    369:        /* set up new map */
                    370:        m->ca = offset;
                    371:        m->cea = m->ca + m->len;
                    372:        m->attr = attr;
                    373:        i = m-pp->mmap;
                    374:        bit = 1<<i;
                    375:        wrreg(pp, Rwe, we & ~bit);              /* disable map before changing it */
                    376:        wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift);
                    377:        wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
                    378:        wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
                    379:        wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
                    380:        offset -= m->isa;
                    381:        offset &= (1<<25)-1;
                    382:        offset >>= Mshift;
                    383:        wrreg(pp, MAP(i, Mofflo), offset);
                    384:        wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
                    385:        wrreg(pp, Rwe, we | bit);               /* enable map */
                    386:        m->ref = 1;
                    387: 
                    388:        unlock(&pp->mlock);
                    389:        return m;
                    390: }
                    391: 
                    392: void
                    393: pcmunmap(int slotno, PCMmap* m)
                    394: {
                    395:        Slot *pp;
                    396: 
                    397:        pp = slot + slotno;
                    398:        lock(&pp->mlock);
                    399:        m->ref--;
                    400:        unlock(&pp->mlock);
                    401: }
                    402: 
                    403: 
                    404: static void
                    405: increfp(Slot *pp)
                    406: {
                    407:        lock(pp);
                    408:        if(pp->ref++ == 0)
                    409:                slotena(pp);
                    410:        unlock(pp);
                    411: }
                    412: 
                    413: static void
                    414: decrefp(Slot *pp)
                    415: {
                    416:        lock(pp);
                    417:        if(pp->ref-- == 1)
                    418:                slotdis(pp);
                    419:        unlock(pp);
                    420: }
                    421: 
                    422: /*
                    423:  *  look for a card whose version contains 'idstr'
                    424:  */
                    425: int
                    426: pcmspecial(char *idstr, ISAConf *isa)
                    427: {
                    428:        Slot *pp;
                    429:        extern char *strstr(char*, char*);
                    430: 
                    431:        i82365reset();
                    432:        for(pp = slot; pp < lastslot; pp++){
                    433:                if(pp->special)
                    434:                        continue;       /* already taken */
                    435:                increfp(pp);
                    436: 
                    437:                if(pp->occupied)
                    438:                if(strstr(pp->verstr, idstr))
                    439:                if(isa == 0 || pcmio(pp->slotno, isa) == 0){
                    440:                        pp->special = 1;
                    441:                        return pp->slotno;
                    442:                }
                    443: 
                    444:                decrefp(pp);
                    445:        }
                    446:        return -1;
                    447: }
                    448: 
                    449: void
                    450: pcmspecialclose(int slotno)
                    451: {
                    452:        Slot *pp;
                    453: 
                    454:        if(slotno >= nslot)
                    455:                panic("pcmspecialclose");
                    456:        pp = slot + slotno;
                    457:        pp->special = 0;
                    458:        decrefp(pp);
                    459: }
                    460: 
                    461: enum
                    462: {
                    463:        Qdir,
                    464:        Qmem,
                    465:        Qattr,
                    466:        Qctl,
                    467: };
                    468: 
                    469: #define SLOTNO(c)      ((c->qid.path>>8)&0xff)
                    470: #define TYPE(c)                (c->qid.path&0xff)
                    471: #define QID(s,t)       (((s)<<8)|(t))
                    472: 
                    473: static int
                    474: pcmgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
                    475: {
                    476:        int slotno;
                    477:        Qid qid;
                    478:        long len;
                    479:        Slot *pp;
                    480:        char name[NAMELEN];
                    481: 
                    482:        USED(tab, ntab);
                    483:        if(i>=3*nslot)
                    484:                return -1;
                    485:        slotno = i/3;
                    486:        pp = slot + slotno;
                    487:        len = 0;
                    488:        switch(i%3){
                    489:        case 0:
                    490:                qid.path = QID(slotno, Qmem);
                    491:                sprint(name, "pcm%dmem", slotno);
                    492:                len = pp->memlen;
                    493:                break;
                    494:        case 1:
                    495:                qid.path = QID(slotno, Qattr);
                    496:                sprint(name, "pcm%dattr", slotno);
                    497:                len = pp->memlen;
                    498:                break;
                    499:        case 2:
                    500:                qid.path = QID(slotno, Qctl);
                    501:                sprint(name, "pcm%dctl", slotno);
                    502:                break;
                    503:        }
                    504:        qid.vers = 0;
                    505:        devdir(c, qid, name, len, eve, 0660, dp);
                    506:        return 1;
                    507: }
                    508: 
                    509: static char *chipname[] =
                    510: {
                    511: [Ti82365]      "Intel 82365SL",
                    512: [Tpd6710]      "Cirrus Logic PD6710",
                    513: [Tpd6720]      "Cirrus Logic PD6720",
                    514: };
                    515: 
                    516: static I82365*
                    517: i82386probe(int x, int d, int dev)
                    518: {
                    519:        uchar c;
                    520:        I82365 *cp;
                    521: 
                    522:        outb(x, Rid + (dev<<7));
                    523:        c = inb(d);
                    524:        if((c & 0xf0) != 0x80)
                    525:                return 0;               /* not this family */
                    526: 
                    527:        cp = xalloc(sizeof(I82365));
                    528:        cp->xreg = x;
                    529:        cp->dreg = d;
                    530:        cp->dev = dev;
                    531:        cp->type = Ti82365;
                    532:        cp->nslot = 2;
                    533: 
                    534:        switch(c){
                    535:        case 0x82:
                    536:        case 0x83:
                    537:                /* could be a cirrus */
                    538:                outb(x, Rchipinfo + (dev<<7));
                    539:                outb(d, 0);
                    540:                c = inb(d);
                    541:                if((c & 0xdf) == 0xdc){
                    542:                        c = inb(d);
                    543:                        if((c & 0xdf) != 0x0c)
                    544:                                break;
                    545:                }
                    546:                if(c & 0x40){
                    547:                        cp->type = Tpd6720;
                    548:                } else {
                    549:                        cp->type = Tpd6710;
                    550:                        cp->nslot = 1;
                    551:                }
                    552:                break;
                    553:        }
                    554: 
                    555:        print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot,
                    556:                chipname[cp->type]);
                    557: 
                    558:        /* low power mode */
                    559:        outb(x, Rmisc2 + (dev<<7));
                    560:        outb(d, Flowpow);
                    561: 
                    562:        controller[ncontroller++] = cp;
                    563:        return cp;
                    564: }
                    565: 
                    566: static void
                    567: i82365dump(Slot *pp)
                    568: {
                    569:        int i;
                    570: 
                    571:        for(i = 0; i < 0x40; i++){
                    572:                if((i&0x7) == 0)
                    573:                        print("\n%ux:   ", i);
                    574:                print("%ux ", rdreg(pp, i));
                    575:        }
                    576:        print("\n");
                    577: }
                    578: 
                    579: /*
                    580:  *  set up for slot cards
                    581:  */
                    582: void
                    583: i82365reset(void)
                    584: {
                    585:        static int already;
                    586:        int i, j;
                    587:        I82365 *cp;
                    588:        Slot *pp;
                    589: 
                    590:        if(already)
                    591:                return;
                    592:        already = 1;
                    593: 
                    594:        /* look for controllers */
                    595:        i82386probe(0x3E0, 0x3E1, 0);
                    596:        i82386probe(0x3E0, 0x3E1, 1);
                    597:        i82386probe(0x3E2, 0x3E3, 0);
                    598:        i82386probe(0x3E2, 0x3E3, 1);
                    599:        for(i = 0; i < ncontroller; i++)
                    600:                nslot += controller[i]->nslot;
                    601:        slot = xalloc(nslot * sizeof(Slot));
                    602: 
                    603:        /* if the card is there turn on 5V power to keep its battery alive */
                    604:        lastslot = slot;
                    605:        for(i = 0; i < ncontroller; i++){
                    606:                cp = controller[i];
                    607:                for(j = 0; j < cp->nslot; j++){
                    608:                        pp = lastslot++;
                    609:                        pp->slotno = pp - slot;
                    610:                        pp->memlen = 64*MB;
                    611:                        pp->base = (cp->dev<<7) | (j<<6);
                    612:                        pp->cp = cp;
                    613:                        slotdis(pp);
                    614: 
                    615:                        /* interrupt on status change */
                    616:                        wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena);
                    617:                }
                    618:        }
                    619: 
                    620:        /* for card management interrupts */
                    621:        setvec(PCMCIAvec, i82365intr, 0);
                    622: }
                    623: 
                    624: void
                    625: i82365init(void)
                    626: {
                    627: }
                    628: 
                    629: Chan *
                    630: i82365attach(char *spec)
                    631: {
                    632:        return devattach('y', spec);
                    633: }
                    634: 
                    635: Chan *
                    636: i82365clone(Chan *c, Chan *nc)
                    637: {
                    638:        return devclone(c, nc);
                    639: }
                    640: 
                    641: int
                    642: i82365walk(Chan *c, char *name)
                    643: {
                    644:        return devwalk(c, name, 0, 0, pcmgen);
                    645: }
                    646: 
                    647: void
                    648: i82365stat(Chan *c, char *db)
                    649: {
                    650:        devstat(c, db, 0, 0, pcmgen);
                    651: }
                    652: 
                    653: Chan *
                    654: i82365open(Chan *c, int omode)
                    655: {
                    656:        if(c->qid.path == CHDIR){
                    657:                if(omode != OREAD)
                    658:                        error(Eperm);
                    659:        } else
                    660:                increfp(slot + SLOTNO(c));
                    661:        c->mode = openmode(omode);
                    662:        c->flag |= COPEN;
                    663:        c->offset = 0;
                    664:        return c;
                    665: }
                    666: 
                    667: void
                    668: i82365create(Chan *c, char *name, int omode, ulong perm)
                    669: {
                    670:        USED(c, name, omode, perm);
                    671:        error(Eperm);
                    672: }
                    673: 
                    674: void
                    675: i82365remove(Chan *c)
                    676: {
                    677:        USED(c);
                    678:        error(Eperm);
                    679: }
                    680: 
                    681: void
                    682: i82365wstat(Chan *c, char *dp)
                    683: {
                    684:        USED(c, dp);
                    685:        error(Eperm);
                    686: }
                    687: 
                    688: void
                    689: i82365close(Chan *c)
                    690: {
                    691:        if(c->flag & COPEN)
                    692:                if(c->qid.path != CHDIR)
                    693:                        decrefp(slot+SLOTNO(c));
                    694: }
                    695: 
                    696: /* a memmove using only bytes */
                    697: static void
                    698: memmoveb(uchar *to, uchar *from, int n)
                    699: {
                    700:        while(n-- > 0)
                    701:                *to++ = *from++;
                    702: }
                    703: 
                    704: /* a memmove using only shorts & bytes */
                    705: static void
                    706: memmoves(uchar *to, uchar *from, int n)
                    707: {
                    708:        ushort *t, *f;
                    709: 
                    710:        if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){
                    711:                while(n-- > 0)
                    712:                        *to++ = *from++;
                    713:        } else {
                    714:                n = n/2;
                    715:                t = (ushort*)to;
                    716:                f = (ushort*)from;
                    717:                while(n-- > 0)
                    718:                        *t++ = *f++;
                    719:        }
                    720: }
                    721: 
                    722: static long
                    723: pcmread(int slotno, int attr, void *a, long n, ulong offset)
                    724: {
                    725:        int i, len;
                    726:        PCMmap *m;
                    727:        ulong ka;
                    728:        uchar *ac;
                    729:        Slot *pp;
                    730: 
                    731:        pp = slot + slotno;
                    732:        if(pp->memlen < offset)
                    733:                return 0;
                    734:        if(pp->memlen < offset + n)
                    735:                n = pp->memlen - offset;
                    736: 
                    737:        m = 0;
                    738:        if(waserror()){
                    739:                if(m)
                    740:                        pcmunmap(pp->slotno, m);
                    741:                nexterror();
                    742:        }
                    743: 
                    744:        ac = a;
                    745:        for(len = n; len > 0; len -= i){
                    746:                m = pcmmap(pp->slotno, offset, 0, attr);
                    747:                if(m == 0)
                    748:                        error("can't map PCMCIA card");
                    749:                if(offset + len > m->cea)
                    750:                        i = m->cea - offset;
                    751:                else
                    752:                        i = len;
                    753:                ka = KZERO|(m->isa + offset - m->ca);
                    754:                memmoveb(ac, (void*)ka, i);
                    755:                pcmunmap(pp->slotno, m);
                    756:                offset += i;
                    757:                ac += i;
                    758:        }
                    759: 
                    760:        poperror();
                    761:        return n;
                    762: }
                    763: 
                    764: long
                    765: i82365read(Chan *c, void *a, long n, ulong offset)
                    766: {
                    767:        char *cp, buf[2048];
                    768:        ulong p;
                    769:        Slot *pp;
                    770: 
                    771:        p = TYPE(c);
                    772:        switch(p){
                    773:        case Qdir:
                    774:                return devdirread(c, a, n, 0, 0, pcmgen);
                    775:        case Qmem:
                    776:        case Qattr:
                    777:                return pcmread(SLOTNO(c), p==Qattr, a, n, offset);
                    778:        case Qctl:
                    779:                cp = buf;
                    780:                pp = slot + SLOTNO(c);
                    781:                if(pp->occupied)
                    782:                        cp += sprint(cp, "occupied\n");
                    783:                if(pp->enabled)
                    784:                        cp += sprint(cp, "enabled\n");
                    785:                if(pp->powered)
                    786:                        cp += sprint(cp, "powered\n");
                    787:                if(pp->configed)
                    788:                        cp += sprint(cp, "configed\n");
                    789:                if(pp->wrprot)
                    790:                        cp += sprint(cp, "write protected\n");
                    791:                if(pp->busy)
                    792:                        cp += sprint(cp, "busy\n");
                    793:                cp += sprint(cp, "battery lvl %d\n", pp->battery);
                    794: {
                    795:        int i;
                    796: 
                    797:        for(i = 0; i < 0x40; i++){
                    798:                if((i&0x7) == 0)
                    799:                        cp += sprint(cp, "\n%ux:        ", i);
                    800:                cp += sprint(cp, "%ux ", rdreg(pp, i));
                    801:        }
                    802:        cp += sprint(cp, "\n");
                    803: }
                    804:                *cp = 0;
                    805:                return readstr(offset, a, n, buf);
                    806:        default:
                    807:                n=0;
                    808:                break;
                    809:        }
                    810:        return n;
                    811: }
                    812: 
                    813: static long
                    814: pcmwrite(int dev, int attr, void *a, long n, ulong offset)
                    815: {
                    816:        int i, len;
                    817:        PCMmap *m;
                    818:        ulong ka;
                    819:        uchar *ac;
                    820:        Slot *pp;
                    821: 
                    822:        pp = slot + dev;
                    823:        if(pp->memlen < offset)
                    824:                return 0;
                    825:        if(pp->memlen < offset + n)
                    826:                n = pp->memlen - offset;
                    827: 
                    828:        m = 0;
                    829:        if(waserror()){
                    830:                if(m)
                    831:                        pcmunmap(pp->slotno, m);
                    832:                nexterror();
                    833:        }
                    834: 
                    835:        ac = a;
                    836:        for(len = n; len > 0; len -= i){
                    837:                m = pcmmap(pp->slotno, offset, 0, attr);
                    838:                if(m == 0)
                    839:                        error("can't map PCMCIA card");
                    840:                if(offset + len > m->cea)
                    841:                        i = m->cea - offset;
                    842:                else
                    843:                        i = len;
                    844:                ka = KZERO|(m->isa + offset - m->ca);
                    845:                memmoveb((void*)ka, ac, i);
                    846:                pcmunmap(pp->slotno, m);
                    847:                offset += i;
                    848:                ac += i;
                    849:        }
                    850: 
                    851:        poperror();
                    852:        return n;
                    853: }
                    854: 
                    855: long
                    856: i82365write(Chan *c, void *a, long n, ulong offset)
                    857: {
                    858:        ulong p;
                    859:        Slot *pp;
                    860: 
                    861:        p = TYPE(c);
                    862:        switch(p){
                    863:        case Qmem:
                    864:        case Qattr:
                    865:                pp = slot + SLOTNO(c);
                    866:                if(pp->occupied == 0 || pp->enabled == 0)
                    867:                        error(Eio);
                    868:                n = pcmwrite(pp->slotno, p == Qattr, a, n, offset);
                    869:                if(n < 0)
                    870:                        error(Eio);
                    871:                break;
                    872:        default:
                    873:                error(Ebadusefd);
                    874:        }
                    875:        return n;
                    876: }
                    877: 
                    878: /*
                    879:  *  configure the Slot for IO.  We assume very heavily that we can read
                    880:  *  cofiguration info from the CIS.  If not, we won't set up correctly.
                    881:  */
                    882: static int
                    883: pcmio(int slotno, ISAConf *isa)
                    884: {
                    885:        uchar we, x, *p;
                    886:        Slot *pp;
                    887:        Conftab *ct;
                    888:        PCMmap *m;
                    889:        int irq;
                    890: 
                    891:        irq = isa->irq;
                    892:        if(irq == 2)
                    893:                irq = 9;
                    894: 
                    895:        if(slotno > nslot)
                    896:                return -1;
                    897:        pp = slot + slotno;
                    898: 
                    899:        if(!pp->occupied)
                    900:                return -1;
                    901: 
                    902:        /* find a configuration with the right port */
                    903:        for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){
                    904:                if(ct->nioregs && ct->port == isa->port && ((1<<irq) & ct->irqs))
                    905:                        break;
                    906:        }
                    907: 
                    908:        /* if non found, settle for one with the some ioregs */
                    909:        if(ct == &pp->ctab[pp->nctab])
                    910:                for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++)
                    911:                        if(ct->nioregs && ((1<<irq) & ct->irqs))
                    912:                                break;
                    913: 
                    914:        if(ct == &pp->ctab[pp->nctab])
                    915:                return -1;
                    916: 
                    917:        /* route interrupts */
                    918:        isa->irq = irq;
                    919:        wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
                    920:        
                    921:        /* set power and enable device */
                    922:        x = vcode(ct->vpp1);
                    923:        wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena);
                    924: 
                    925:        /* 16-bit data path */
                    926:        if(ct->bit16)
                    927:                x = Fiocs16|Fwidth16;
                    928:        else
                    929:                x = 0;
                    930:        wrreg(pp, Rio, Ftiming|x);
                    931: 
                    932:        /* enable io port map 0 */
                    933:        if(isa->port == 0)
                    934:                isa->port = ct->port;
                    935:        we = rdreg(pp, Rwe);
                    936:        wrreg(pp, Riobtm0lo, isa->port);
                    937:        wrreg(pp, Riobtm0hi, isa->port>>8);
                    938:        wrreg(pp, Riotop0lo, (isa->port+ct->nioregs-1));
                    939:        wrreg(pp, Riotop0hi, (isa->port+ct->nioregs-1)>>8);
                    940:        wrreg(pp, Rwe, we | (1<<6));
                    941: 
                    942:        /* only touch Rconfig if it is present */
                    943:        if(pp->cpresent & (1<<Rconfig)){
                    944:                /*  Reset adapter */
                    945:                m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1);
                    946:                p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca));
                    947: 
                    948:                /* set configuration and interrupt type */
                    949:                x = ct->index;
                    950:                if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
                    951:                        x |= Clevel;
                    952:                *p = x;
                    953:                delay(5);
                    954: 
                    955:                pcmunmap(slotno, m);
                    956:        }
                    957:        return 0;
                    958: }
                    959: 
                    960: /*
                    961:  *  read and crack the card information structure enough to set
                    962:  *  important parameters like power
                    963:  */
                    964: static void    tcfig(Slot*, int);
                    965: static void    tentry(Slot*, int);
                    966: static void    tvers1(Slot*, int);
                    967: 
                    968: static void (*parse[256])(Slot*, int) =
                    969: {
                    970: [0x15] tvers1,
                    971: [0x1A] tcfig,
                    972: [0x1B] tentry,
                    973: };
                    974: 
                    975: static int
                    976: readc(Slot *pp, uchar *x)
                    977: {
                    978:        if(pp->cispos >= Mchunk)
                    979:                return 0;
                    980:        *x = pp->cisbase[2*pp->cispos];
                    981:        pp->cispos++;
                    982:        return 1;
                    983: }
                    984: 
                    985: static void
                    986: cisread(Slot *pp)
                    987: {
                    988:        uchar link;
                    989:        uchar type;
                    990:        int this, i;
                    991:        PCMmap *m;
                    992: 
                    993:        memset(pp->ctab, 0, sizeof(pp->ctab));
                    994:        pp->caddr = 0;
                    995:        pp->cpresent = 0;
                    996:        pp->configed = 0;
                    997:        pp->nctab = 0;
                    998: 
                    999:        m = pcmmap(pp->slotno, 0, 0, 1);
                   1000:        if(m == 0)
                   1001:                return;
                   1002:        pp->cisbase = (uchar*)(KZERO|m->isa);
                   1003:        pp->cispos = 0;
                   1004: 
                   1005:        /* loop through all the tuples */
                   1006:        for(i = 0; i < 1000; i++){
                   1007:                this = pp->cispos;
                   1008:                if(readc(pp, &type) != 1)
                   1009:                        break;
                   1010:                if(readc(pp, &link) != 1)
                   1011:                        break;
                   1012:                if(parse[type])
                   1013:                        (*parse[type])(pp, type);
                   1014:                if(link == 0xff)
                   1015:                        break;
                   1016:                pp->cispos = this + (2+link);
                   1017:        }
                   1018:        pcmunmap(pp->slotno, m);
                   1019: }
                   1020: 
                   1021: static ulong
                   1022: getlong(Slot *pp, int size)
                   1023: {
                   1024:        uchar c;
                   1025:        int i;
                   1026:        ulong x;
                   1027: 
                   1028:        x = 0;
                   1029:        for(i = 0; i < size; i++){
                   1030:                if(readc(pp, &c) != 1)
                   1031:                        break;
                   1032:                x |= c<<(i*8);
                   1033:        }
                   1034:        return x;
                   1035: }
                   1036: 
                   1037: static void
                   1038: tcfig(Slot *pp, int ttype)
                   1039: {
                   1040:        uchar size, rasize, rmsize;
                   1041:        uchar last;
                   1042: 
                   1043:        USED(ttype);
                   1044:        if(readc(pp, &size) != 1)
                   1045:                return;
                   1046:        rasize = (size&0x3) + 1;
                   1047:        rmsize = ((size>>2)&0xf) + 1;
                   1048:        if(readc(pp, &last) != 1)
                   1049:                return;
                   1050:        pp->caddr = getlong(pp, rasize);
                   1051:        pp->cpresent = getlong(pp, rmsize);
                   1052: }
                   1053: 
                   1054: static ulong vexp[8] =
                   1055: {
                   1056:        1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
                   1057: };
                   1058: static ulong vmant[16] =
                   1059: {
                   1060:        10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
                   1061: };
                   1062: 
                   1063: static ulong
                   1064: microvolt(Slot *pp)
                   1065: {
                   1066:        uchar c;
                   1067:        ulong microvolts;
                   1068:        ulong exp;
                   1069: 
                   1070:        if(readc(pp, &c) != 1)
                   1071:                return 0;
                   1072:        exp = vexp[c&0x7];
                   1073:        microvolts = vmant[(c>>3)&0xf]*exp;
                   1074:        while(c & 0x80){
                   1075:                if(readc(pp, &c) != 1)
                   1076:                        return 0;
                   1077:                switch(c){
                   1078:                case 0x7d:
                   1079:                        break;          /* high impedence when sleeping */
                   1080:                case 0x7e:
                   1081:                case 0x7f:
                   1082:                        microvolts = 0; /* no connection */
                   1083:                        break;
                   1084:                default:
                   1085:                        exp /= 10;
                   1086:                        microvolts += exp*(c&0x7f);
                   1087:                }
                   1088:        }
                   1089:        return microvolts;
                   1090: }
                   1091: 
                   1092: static ulong
                   1093: nanoamps(Slot *pp)
                   1094: {
                   1095:        uchar c;
                   1096:        ulong nanoamps;
                   1097: 
                   1098:        if(readc(pp, &c) != 1)
                   1099:                return 0;
                   1100:        nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf];
                   1101:        while(c & 0x80){
                   1102:                if(readc(pp, &c) != 1)
                   1103:                        return 0;
                   1104:                if(c == 0x7d || c == 0x7e || c == 0x7f)
                   1105:                        nanoamps = 0;
                   1106:        }
                   1107:        return nanoamps;
                   1108: }
                   1109: 
                   1110: /*
                   1111:  *  only nominal voltage is important for config
                   1112:  */
                   1113: static ulong
                   1114: power(Slot *pp)
                   1115: {
                   1116:        uchar feature;
                   1117:        ulong mv;
                   1118: 
                   1119:        mv = 0;
                   1120:        if(readc(pp, &feature) != 1)
                   1121:                return 0;
                   1122:        if(feature & 1)
                   1123:                mv = microvolt(pp);
                   1124:        if(feature & 2)
                   1125:                microvolt(pp);
                   1126:        if(feature & 4)
                   1127:                microvolt(pp);
                   1128:        if(feature & 8)
                   1129:                nanoamps(pp);
                   1130:        if(feature & 0x10)
                   1131:                nanoamps(pp);
                   1132:        if(feature & 0x20)
                   1133:                nanoamps(pp);
                   1134:        if(feature & 0x40)
                   1135:                nanoamps(pp);
                   1136:        return mv/1000000;
                   1137: }
                   1138: 
                   1139: static ulong mantissa[16] =
                   1140: { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };
                   1141: 
                   1142: static ulong exponent[8] =
                   1143: { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };
                   1144: 
                   1145: static ulong
                   1146: ttiming(Slot *pp, int scale)
                   1147: {
                   1148:        uchar unscaled;
                   1149:        ulong nanosecs;
                   1150: 
                   1151:        if(readc(pp, &unscaled) != 1)
                   1152:                return 0;
                   1153:        nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
                   1154:        nanosecs = nanosecs * vexp[scale];
                   1155:        return nanosecs;
                   1156: }
                   1157: 
                   1158: static void
                   1159: timing(Slot *pp, Conftab *ct)
                   1160: {
                   1161:        uchar c, i;
                   1162: 
                   1163:        if(readc(pp, &c) != 1)
                   1164:                return;
                   1165:        i = c&0x3;
                   1166:        if(i != 3)
                   1167:                ct->maxwait = ttiming(pp, i);           /* max wait */
                   1168:        i = (c>>2)&0x7;
                   1169:        if(i != 7)
                   1170:                ct->readywait = ttiming(pp, i);         /* max ready/busy wait */
                   1171:        i = (c>>5)&0x7;
                   1172:        if(i != 7)
                   1173:                ct->otherwait = ttiming(pp, i);         /* reserved wait */
                   1174: }
                   1175: 
                   1176: void
                   1177: iospaces(Slot *pp, Conftab *ct)
                   1178: {
                   1179:        uchar c;
                   1180:        int i;
                   1181:        ulong len;
                   1182: 
                   1183:        if(readc(pp, &c) != 1)
                   1184:                return;
                   1185: 
                   1186:        ct->nioregs = 1<<(c&0x1f);
                   1187:        ct->bit16 = ((c>>5)&3) >= 2;
                   1188:        if((c & 0x80) == 0)
                   1189:                return;
                   1190: 
                   1191:        if(readc(pp, &c) != 1)
                   1192:                return;
                   1193: 
                   1194:        for(i = (c&0xf)+1; i; i--){
                   1195:                ct->port = getlong(pp, (c>>4)&0x3);
                   1196:                len = getlong(pp, (c>>6)&0x3);
                   1197:                USED(len);
                   1198:        }
                   1199: }
                   1200: 
                   1201: static void
                   1202: irq(Slot *pp, Conftab *ct)
                   1203: {
                   1204:        uchar c;
                   1205: 
                   1206:        if(readc(pp, &c) != 1)
                   1207:                return;
                   1208:        ct->irqtype = c & 0xe0;
                   1209:        if(c & 0x10)
                   1210:                ct->irqs = getlong(pp, 2);
                   1211:        else
                   1212:                ct->irqs = 1<<(c&0xf);
                   1213:        ct->irqs &= 0xDEB8;             /* levels available to card */
                   1214: }
                   1215: 
                   1216: static void
                   1217: memspace(Slot *pp, int asize, int lsize, int host)
                   1218: {
                   1219:        ulong haddress, address, len;
                   1220: 
                   1221:        len = getlong(pp, lsize)*256;
                   1222:        address = getlong(pp, asize)*256;
                   1223:        USED(len, address);
                   1224:        if(host){
                   1225:                haddress = getlong(pp, asize)*256;
                   1226:                USED(haddress);
                   1227:        }
                   1228: }
                   1229: 
                   1230: void
                   1231: tentry(Slot *pp, int ttype)
                   1232: {
                   1233:        uchar c, i, feature;
                   1234:        Conftab *ct;
                   1235: 
                   1236:        USED(ttype);
                   1237: 
                   1238:        if(pp->nctab >= Maxctab)
                   1239:                return;
                   1240:        if(readc(pp, &c) != 1)
                   1241:                return;
                   1242:        ct = &pp->ctab[pp->nctab++];
                   1243: 
                   1244:        /* copy from last default config */
                   1245:        if(pp->def)
                   1246:                *ct = *pp->def;
                   1247: 
                   1248:        ct->index = c & 0x3f;
                   1249: 
                   1250:        /* is this the new default? */
                   1251:        if(c & 0x40)
                   1252:                pp->def = ct;
                   1253: 
                   1254:        /* memory wait specified? */
                   1255:        if(c & 0x80){
                   1256:                if(readc(pp, &i) != 1)
                   1257:                        return;
                   1258:                if(i&0x80)
                   1259:                        ct->memwait = 1;
                   1260:        }
                   1261: 
                   1262:        if(readc(pp, &feature) != 1)
                   1263:                return;
                   1264:        switch(feature&0x3){
                   1265:        case 1:
                   1266:                ct->vpp1 = ct->vpp2 = power(pp);
                   1267:                break;
                   1268:        case 2:
                   1269:                power(pp);
                   1270:                ct->vpp1 = ct->vpp2 = power(pp);
                   1271:                break;
                   1272:        case 3:
                   1273:                power(pp);
                   1274:                ct->vpp1 = power(pp);
                   1275:                ct->vpp2 = power(pp);
                   1276:                break;
                   1277:        default:
                   1278:                break;
                   1279:        }
                   1280:        if(feature&0x4)
                   1281:                timing(pp, ct);
                   1282:        if(feature&0x8)
                   1283:                iospaces(pp, ct);
                   1284:        if(feature&0x10)
                   1285:                irq(pp, ct);
                   1286:        switch((feature>>5)&0x3){
                   1287:        case 1:
                   1288:                memspace(pp, 0, 2, 0);
                   1289:                break;
                   1290:        case 2:
                   1291:                memspace(pp, 2, 2, 0);
                   1292:                break;
                   1293:        case 3:
                   1294:                if(readc(pp, &c) != 1)
                   1295:                        return;
                   1296:                for(i = 0; i <= (c&0x7); i++)
                   1297:                        memspace(pp, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
                   1298:                break;
                   1299:        }
                   1300:        pp->configed++;
                   1301: }
                   1302: 
                   1303: void
                   1304: tvers1(Slot *pp, int ttype)
                   1305: {
                   1306:        uchar c, major, minor;
                   1307:        int  i;
                   1308: 
                   1309:        USED(ttype);
                   1310:        if(readc(pp, &major) != 1)
                   1311:                return;
                   1312:        if(readc(pp, &minor) != 1)
                   1313:                return;
                   1314:        for(i = 0; i < sizeof(pp->verstr)-1; i++){
                   1315:                if(readc(pp, &c) != 1)
                   1316:                        return;
                   1317:                if(c == 0)
                   1318:                        c = '\n';
                   1319:                if(c == 0xff)
                   1320:                        break;
                   1321:                pp->verstr[i] = c;
                   1322:        }
                   1323:        pp->verstr[i] = 0;
                   1324: }
                   1325: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.