Annotation of lucent/sys/src/9/pc/f002527, revision 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.