📄 devi82365.c
字号:
outb(x, 0x37 + (dev<<7)); /* make the id register show the Vadem id */ outb(x, 0x3A + (dev<<7)); c = inb(d); outb(d, c|0xC0); outb(x, Rid + (dev<<7)); c = inb(d); if(c & 0x08) cp->type = Tvg46x; /* go back to Intel compatible id */ outb(x, 0x3A + (dev<<7)); c = inb(d); outb(d, c & ~0xC0); } memset(&isa, 0, sizeof(ISAConf)); if(isaconfig("pcmcia", ncontroller, &isa) && isa.irq) cp->irq = isa.irq; else cp->irq = IrqPCMCIA; for(i = 0; i < isa.nopt; i++){ if(cistrncmp(isa.opt[i], "nslot=", 6)) continue; nslot = strtol(&isa.opt[i][6], nil, 0); if(nslot > 0 && nslot <= 2) cp->nslot = nslot; } controller[ncontroller++] = cp; return cp;}static voidi82365dump(PCMslot *pp){ int i; for(i = 0; i < 0x40; i++){ if((i&0x0F) == 0) print("\n%2.2uX: ", i); print("%2.2uX ", rdreg(pp, i)); if(((i+1) & 0x0F) == 0x08) print(" - "); } print("\n");}/* * set up for slot cards */voiddevi82365link(void){ static int already; int i, j; I82365 *cp; PCMslot *pp; char buf[32], *p; if(already) return; already = 1; if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0) return; if(_pcmspecial) return; /* look for controllers if the ports aren't already taken */ if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){ i82365probe(0x3E0, 0x3E1, 0); i82365probe(0x3E0, 0x3E1, 1); if(ncontroller == 0) iofree(0x3E0); } if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){ i = ncontroller; i82365probe(0x3E2, 0x3E3, 0); i82365probe(0x3E2, 0x3E3, 1); if(ncontroller == i) iofree(0x3E2); } if(ncontroller == 0) return; _pcmspecial = pcmcia_pcmspecial; _pcmspecialclose = pcmcia_pcmspecialclose; for(i = 0; i < ncontroller; i++) nslot += controller[i]->nslot; slot = xalloc(nslot * sizeof(PCMslot)); lastslot = slot; for(i = 0; i < ncontroller; i++){ cp = controller[i]; print("#y%d: %d slot %s: port 0x%uX irq %d\n", i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq); for(j = 0; j < cp->nslot; j++){ pp = lastslot++; pp->slotno = pp - slot; pp->memlen = 64*MB; pp->base = (cp->dev<<7) | (j<<6); pp->cp = cp; pp->msec = ~0; pp->verstr[0] = 0; slotdis(pp); /* interrupt on status change */ wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena); rdreg(pp, Rcsc); } /* for card management interrupts */ snprint(buf, sizeof buf, "i82365.%d", i); intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf); }}static Chan*i82365attach(char *spec){ return devattach('y', spec);}static Walkqid*i82365walk(Chan *c, Chan *nc, char **name, int nname){ return devwalk(c, nc, name, nname, 0, 0, pcmgen);}static inti82365stat(Chan *c, uchar *db, int n){ return devstat(c, db, n, 0, 0, pcmgen);}static Chan*i82365open(Chan *c, int omode){ if(c->qid.type & QTDIR){ if(omode != OREAD) error(Eperm); } else increfp(slot + SLOTNO(c)); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c;}static voidi82365close(Chan *c){ if(c->flag & COPEN) if((c->qid.type & QTDIR) == 0) decrefp(slot+SLOTNO(c));}/* a memmove using only bytes */static voidmemmoveb(uchar *to, uchar *from, int n){ while(n-- > 0) *to++ = *from++;}/* a memmove using only shorts & bytes */static voidmemmoves(uchar *to, uchar *from, int n){ ushort *t, *f; if((((ulong)to) & 1) || (((ulong)from) & 1) || (n & 1)){ while(n-- > 0) *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; PCMslot *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("cannot 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, *buf, *e; PCMslot *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: buf = p = malloc(READSTR); e = p + READSTR; pp = slot + SLOTNO(c); buf[0] = 0; if(pp->occupied){ p = seprint(p, e, "occupied\n"); if(pp->verstr[0]) p = seprint(p, e, "version %s\n", pp->verstr); } if(pp->enabled) p = seprint(p, e, "enabled\n"); if(pp->powered) p = seprint(p, e, "powered\n"); if(pp->configed) p = seprint(p, e, "configed\n"); if(pp->wrprot) p = seprint(p, e, "write protected\n"); if(pp->busy) p = seprint(p, e, "busy\n"); seprint(p, e, "battery lvl %d\n", pp->battery); n = readstr(offset, a, n, buf); free(buf); 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; PCMslot *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("cannot 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){ PCMslot *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", devreset, devinit, devshutdown, i82365attach, i82365walk, i82365stat, i82365open, devcreate, i82365close, i82365read, devbread, i82365write, devbwrite, devremove, devwstat,};/* * configure the PCMslot 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; PCMslot *pp; PCMconftab *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 * the 'top' register value includes the last valid address */ 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 */ m = pcmmap(slotno, pp->cfg[0].caddr + Rconfig, 0x20, 1); p = KADDR(m->isa + pp->cfg[0].caddr - m->ca); if(pp->cfg[0].cpresent & (1<<Rconfig)){ /* Reset adapter */ /* set configuration and interrupt type. * if level is possible on the card, use it. */ x = ct->index; if(ct->irqtype & 0x20) x |= Clevel; /* enable the device, enable address decode and * irq enable. */ x |= Cfunc|Cdecode|Cirq; p[0] = x; //delay(5); microdelay(40); } if(pp->cfg[0].cpresent & (1<<Riobase0)){ /* set up the iobase 0 */ p[Riobase0 << 1] = isa->port; p[Riobase1 << 1] = isa->port >> 8; } if(pp->cfg[0].cpresent & (1<<Riosize)) p[Riosize << 1] = ct->io[0].len; pcmunmap(slotno, m); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -