📄 devi82365.c
字号:
*to++ = *from++; } else { n = n/2; t = (ushort*)to; f = (ushort*)from; while(n-- > 0) *t++ = *f++; }}static longpcmread(int slotno, int attr, void *a, long n, vlong off){ int i, len; PCMmap *m; uchar *ac; Slot *pp; ulong offset = off; pp = slot + slotno; if(pp->memlen < offset) return 0; if(pp->memlen < offset + n) n = pp->memlen - offset; m = 0; if(waserror()){ if(m) pcmunmap(pp->slotno, m); nexterror(); } ac = a; for(len = n; len > 0; len -= i){ m = pcmmap(pp->slotno, offset, 0, attr); if(m == 0) error("can't map PCMCIA card"); if(offset + len > m->cea) i = m->cea - offset; else i = len; memmoveb(ac, KADDR(m->isa + offset - m->ca), i); pcmunmap(pp->slotno, m); offset += i; ac += i; } poperror(); return n;}static longi82365read(Chan *c, void *a, long n, vlong off){ char *p; int len; Slot *pp; ulong offset = off; switch(TYPE(c)){ case Qdir: return devdirread(c, a, n, 0, 0, pcmgen); case Qmem: case Qattr: return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off); case Qctl: p = malloc(READSTR); len = 0; pp = slot + SLOTNO(c); if(pp->occupied) len += snprint(p+len, READSTR-len, "occupied\n"); if(pp->enabled) len += snprint(p+len, READSTR-len, "enabled\n"); if(pp->powered) len += snprint(p+len, READSTR-len, "powered\n"); if(pp->configed) len += snprint(p+len, READSTR-len, "configed\n"); if(pp->wrprot) len += snprint(p+len, READSTR-len, "write protected\n"); if(pp->busy) len += snprint(p+len, READSTR-len, "busy\n"); snprint(p+len, READSTR-len, "battery lvl %d\n", pp->battery); n = readstr(offset, a, n, p); free(p); return n; } error(Ebadarg); return -1; /* not reached */}static longpcmwrite(int dev, int attr, void *a, long n, vlong off){ int i, len; PCMmap *m; uchar *ac; Slot *pp; ulong offset = off; pp = slot + dev; if(pp->memlen < offset) return 0; if(pp->memlen < offset + n) n = pp->memlen - offset; m = 0; if(waserror()){ if(m) pcmunmap(pp->slotno, m); nexterror(); } ac = a; for(len = n; len > 0; len -= i){ m = pcmmap(pp->slotno, offset, 0, attr); if(m == 0) error("can't map PCMCIA card"); if(offset + len > m->cea) i = m->cea - offset; else i = len; memmoveb(KADDR(m->isa + offset - m->ca), ac, i); pcmunmap(pp->slotno, m); offset += i; ac += i; } poperror(); return n;}static longi82365write(Chan *c, void *a, long n, vlong off){ Slot *pp; char buf[32]; switch(TYPE(c)){ case Qctl: if(n >= sizeof(buf)) n = sizeof(buf) - 1; strncpy(buf, a, n); buf[n] = 0; pp = slot + SLOTNO(c); if(!pp->occupied) error(Eio); /* set vpp on card */ if(strncmp(buf, "vpp", 3) == 0) wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena); return n; case Qmem: case Qattr: pp = slot + SLOTNO(c); if(pp->occupied == 0 || pp->enabled == 0) error(Eio); n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, off); if(n < 0) error(Eio); return n; } error(Ebadarg); return -1; /* not reached */}Dev i82365devtab = { 'y', "i82365", i82365reset, devinit, i82365attach, devclone, i82365walk, i82365stat, i82365open, devcreate, i82365close, i82365read, devbread, i82365write, devbwrite, devremove, devwstat,};/* * configure the Slot for IO. We assume very heavily that we can read * configuration info from the CIS. If not, we won't set up correctly. */static intpcmio(int slotno, ISAConf *isa){ uchar we, x, *p; Slot *pp; Conftab *ct, *et, *t; PCMmap *m; int i, index, irq; char *cp; irq = isa->irq; if(irq == 2) irq = 9; if(slotno > nslot) return -1; pp = slot + slotno; if(!pp->occupied) return -1; et = &pp->ctab[pp->nctab]; ct = 0; for(i = 0; i < isa->nopt; i++){ if(strncmp(isa->opt[i], "index=", 6)) continue; index = strtol(&isa->opt[i][6], &cp, 0); if(cp == &isa->opt[i][6] || index >= pp->nctab) return -1; ct = &pp->ctab[index]; } if(ct == 0){ /* assume default is right */ if(pp->def) ct = pp->def; else ct = pp->ctab; /* try for best match */ if(ct->nio == 0 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){ for(t = pp->ctab; t < et; t++) if(t->nio && t->io[0].start == isa->port && ((1<<irq) & t->irqs)){ ct = t; break; } } if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){ for(t = pp->ctab; t < et; t++) if(t->nio && ((1<<irq) & t->irqs)){ ct = t; break; } } if(ct->nio == 0){ for(t = pp->ctab; t < et; t++) if(t->nio){ ct = t; break; } } } if(ct == et || ct->nio == 0) return -1; if(isa->port == 0 && ct->io[0].start == 0) return -1; /* route interrupts */ isa->irq = irq; wrreg(pp, Rigc, irq | Fnotreset | Fiocard); /* set power and enable device */ x = vcode(ct->vpp1); wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); /* 16-bit data path */ if(ct->bit16) x = Ftiming|Fiocs16|Fwidth16; else x = Ftiming; if(ct->nio == 2 && ct->io[1].start) x |= x<<4; wrreg(pp, Rio, x); /* enable io port map 0 */ if(isa->port == 0) isa->port = ct->io[0].start; we = rdreg(pp, Rwe); wrreg(pp, Riobtm0lo, isa->port); wrreg(pp, Riobtm0hi, isa->port>>8); i = isa->port+ct->io[0].len-1; wrreg(pp, Riotop0lo, i); wrreg(pp, Riotop0hi, i>>8); we |= 1<<6; if(ct->nio == 2 && ct->io[1].start){ wrreg(pp, Riobtm1lo, ct->io[1].start); wrreg(pp, Riobtm1hi, ct->io[1].start>>8); i = ct->io[1].start+ct->io[1].len-1; wrreg(pp, Riotop1lo, i); wrreg(pp, Riotop1hi, i>>8); we |= 1<<7; } wrreg(pp, Rwe, we); /* only touch Rconfig if it is present */ if(pp->cpresent & (1<<Rconfig)){ /* Reset adapter */ m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1); p = KADDR(m->isa + pp->caddr + Rconfig - m->ca); /* set configuration and interrupt type */ x = ct->index; if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7)) x |= Clevel; *p = x; delay(5); pcmunmap(slotno, m); } return 0;}/* * read and crack the card information structure enough to set * important parameters like power */static void tcfig(Slot*, Cisdat*, int);static void tentry(Slot*, Cisdat*, int);static void tvers1(Slot*, Cisdat*, int);struct { int n; void (*parse)(Slot*, Cisdat*, int);} cistab[] = { 0x15, tvers1, 0x1A, tcfig, 0x1B, tentry,};static intreadc(Cisdat *pp, uchar *x){ if(pp->cispos >= pp->cislen) return 0; *x = pp->cisbase[pp->cisskip*pp->cispos]; pp->cispos++; return 1;}static intxcistuple(int slotno, int tuple, void *v, int nv, int attr){ PCMmap *m; Cisdat cis; int i, l; uchar *p; uchar type, link; int this; m = pcmmap(slotno, 0, 0, attr); if(m == 0) return -1; cis.cisbase = KADDR(m->isa); cis.cispos = 0; cis.cisskip = attr ? 2 : 1; cis.cislen = Mchunk; /* loop through all the tuples */ for(i = 0; i < 1000; i++){ this = cis.cispos; if(readc(&cis, &type) != 1) break; if(type == 0xFF) break; if(readc(&cis, &link) != 1) break; if(link == 0xFF) break; if(type == tuple) { p = v; for(l=0; l<nv && l<link; l++) if(readc(&cis, p++) != 1) break; pcmunmap(slotno, m); return nv; } cis.cispos = this + (2+link); } pcmunmap(slotno, m); return -1;}intpcmcistuple(int slotno, int tuple, void *v, int nv){ int n; /* try attribute space, then memory */ if((n = xcistuple(slotno, tuple, v, nv, 1)) >= 0) return n; return xcistuple(slotno, tuple, v, nv, 0);}static voidcisread(Slot *pp){ uchar v[256]; int i, nv; Cisdat cis; memset(pp->ctab, 0, sizeof(pp->ctab)); pp->caddr = 0; pp->cpresent = 0; pp->configed = 0; pp->nctab = 0; for(i = 0; i < nelem(cistab); i++) { if((nv = pcmcistuple(pp->slotno, cistab[i].n, v, sizeof(v))) >= 0) { cis.cisbase = v; cis.cispos = 0; cis.cisskip = 1; cis.cislen = nv; (*cistab[i].parse)(pp, &cis, cistab[i].n); } }}static ulonggetlong(Cisdat *cis, int size){ uchar c; int i; ulong x; x = 0; for(i = 0; i < size; i++){ if(readc(cis, &c) != 1) break; x |= c<<(i*8); } return x;}static voidtcfig(Slot *pp, Cisdat *cis, int ){ uchar size, rasize, rmsize; uchar last; if(readc(cis, &size) != 1) return; rasize = (size&0x3) + 1; rmsize = ((size>>2)&0xf) + 1; if(readc(cis, &last) != 1) return; pp->caddr = getlong(cis, rasize); pp->cpresent = getlong(cis, rmsize);}static ulong vexp[8] ={ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};static ulong vmant[16] ={ 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,};static ulongmicrovolt(Cisdat *cis){ uchar c; ulong microvolts; ulong exp; if(readc(cis, &c) != 1) return 0; exp = vexp[c&0x7]; microvolts = vmant[(c>>3)&0xf]*exp; while(c & 0x80){ if(readc(cis, &c) != 1) return 0; switch(c){ case 0x7d: break; /* high impedence when sleeping */ case 0x7e: case 0x7f: microvolts = 0; /* no connection */ break; default: exp /= 10; microvolts += exp*(c&0x7f); } } return microvolts;}static ulongnanoamps(Cisdat *cis){ uchar c; ulong nanoamps; if(readc(cis, &c) != 1) return 0; nanoamps = vexp[c&0x7]*vmant[(c>>3)&0xf]; while(c & 0x80){ if(readc(cis, &c) != 1) return 0; if(c == 0x7d || c == 0x7e || c == 0x7f) nanoamps = 0; } return nanoamps;}/* * only nominal voltage is important for config */static ulongpower(Cisdat *cis){ uchar feature; ulong mv; mv = 0; if(readc(cis, &feature) != 1) return 0; if(feature & 1) mv = microvolt(cis); if(feature & 2) microvolt(cis); if(feature & 4) microvolt(cis); if(feature & 8) nanoamps(cis); if(feature & 0x10) nanoamps(cis); if(feature & 0x20) nanoamps(cis); if(feature & 0x40) nanoamps(cis); return mv/1000000;}static ulong mantissa[16] ={ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, };static ulong exponent[8] ={ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, };static ulongttiming(Cisdat *cis, int scale){ uchar unscaled; ulong nanosecs; if(readc(cis, &unscaled) != 1) return 0; nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10; nanosecs = nanosecs * vexp[scale]; return nanosecs;}static voidtiming(Cisdat *cis, Conftab *ct){ uchar c, i; if(readc(cis, &c) != 1) return; i = c&0x3; if(i != 3) ct->maxwait = ttiming(cis, i); /* max wait */ i = (c>>2)&0x7; if(i != 7) ct->readywait = ttiming(cis, i); /* max ready/busy wait */ i = (c>>5)&0x7; if(i != 7) ct->otherwait = ttiming(cis, i); /* reserved wait */}static voidiospaces(Cisdat *cis, Conftab *ct){ uchar c; int i, nio; ct->nio = 0; if(readc(cis, &c) != 1) return; ct->bit16 = ((c>>5)&3) >= 2; if(!(c & 0x80)){ ct->io[0].start = 0; ct->io[0].len = 1<<(c&0x1f); ct->nio = 1; return; } if(readc(cis, &c) != 1) return; nio = (c&0xf)+1; for(i = 0; i < nio; i++){ ct->io[i].start = getlong(cis, (c>>4)&0x3); ct->io[0].len = getlong(cis, (c>>6)&0x3); } ct->nio = nio;}static voidirq(Cisdat *cis, Conftab *ct){ uchar c; if(readc(cis, &c) != 1) return; ct->irqtype = c & 0xe0; if(c & 0x10) ct->irqs = getlong(cis, 2); else ct->irqs = 1<<(c&0xf); ct->irqs &= 0xDEB8; /* levels available to card */}static voidmemspace(Cisdat *cis, int asize, int lsize, int host){ ulong haddress, address, len; len = getlong(cis, lsize)*256; address = getlong(cis, asize)*256; USED(len, address); if(host){ haddress = getlong(cis, asize)*256; USED(haddress); }}static voidtentry(Slot *pp, Cisdat *cis, int ){ uchar c, i, feature; Conftab *ct; if(pp->nctab >= Maxctab) return; if(readc(cis, &c) != 1) return; ct = &pp->ctab[pp->nctab++]; /* copy from last default config */ if(pp->def) *ct = *pp->def; ct->index = c & 0x3f; /* is this the new default? */ if(c & 0x40) pp->def = ct; /* memory wait specified? */ if(c & 0x80){ if(readc(cis, &i) != 1) return; if(i&0x80) ct->memwait = 1; } if(readc(cis, &feature) != 1) return; switch(feature&0x3){ case 1: ct->vpp1 = ct->vpp2 = power(cis); break; case 2: power(cis); ct->vpp1 = ct->vpp2 = power(cis); break; case 3: power(cis); ct->vpp1 = power(cis); ct->vpp2 = power(cis); break; default: break; } if(feature&0x4) timing(cis, ct); if(feature&0x8) iospaces(cis, ct); if(feature&0x10) irq(cis, ct); switch((feature>>5)&0x3){ case 1: memspace(cis, 0, 2, 0); break; case 2: memspace(cis, 2, 2, 0); break; case 3: if(readc(cis, &c) != 1) return; for(i = 0; i <= (c&0x7); i++) memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80); break; } pp->configed++;}static voidtvers1(Slot *pp, Cisdat *cis, int ){ uchar c, major, minor; int i; if(readc(cis, &major) != 1) return; if(readc(cis, &minor) != 1) return; for(i = 0; i < sizeof(pp->verstr)-1; i++){ if(readc(cis, &c) != 1) return; if(c == 0) c = '\n'; if(c == 0xff) break; pp->verstr[i] = c; } pp->verstr[i] = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -