📄 devpccard.c
字号:
Cardbus *cb = &cbslots[slotno]; m = isamap(cb, 0, 0, attr); if(m == 0) return -1; cis.cisbase = KADDR(m->isa); cis.cispos = 0; cis.cisskip = attr ? 2 : 1; cis.cislen = m->len; /* 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; n = link; if (link > 1 && subtuple != -1) { if (readc(&cis, &c) != 1) break; subtype = c; n--; } else subtype = -1; if(type == tuple && subtype == subtuple) { p = v; for(l=0; l<nv && l<n; l++) if(readc(&cis, p++) != 1) break; isaunmap(m); return nv; } cis.cispos = this + (2+link); } isaunmap(m); return -1;}static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr){ uchar we, bit; PCMmap *m, *nm; Pcminfo *pi; int i; ulong e; pi = &cb->linfo; /* convert offset to granularity */ if(len <= 0) len = 1; e = ROUND(offset+len, Mgran); offset &= Mmask; len = e - offset; /* look for a map that covers the right area */ we = rdreg(cb, Rwe); bit = 1; nm = 0; for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){ if((we & bit)) if(m->attr == attr) if(offset >= m->ca && e <= m->cea){ m->ref++; return m; } bit <<= 1; if(nm == 0 && m->ref == 0) nm = m; } m = nm; if(m == 0) return 0; /* if isa space isn't big enough, free it and get more */ if(m->len < len){ if(m->isa){ umbfree(m->isa, m->len); m->len = 0; } m->isa = PADDR(umbmalloc(0, len, Mgran)); if(m->isa == 0){ print("isamap: out of isa space\n"); return 0; } m->len = len; } /* set up new map */ m->ca = offset; m->cea = m->ca + m->len; m->attr = attr; i = m - pi->mmap; bit = 1<<i; wrreg(cb, Rwe, we & ~bit); /* disable map before changing it */ wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift); wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit); wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift); wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8))); offset -= m->isa; offset &= (1<<25)-1; offset >>= Mshift; wrreg(cb, MAP(i, Mofflo), offset); wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0)); wrreg(cb, Rwe, we | bit); /* enable map */ m->ref = 1; return m;}static voidisaunmap(PCMmap* m){ m->ref--;}/* * reading and writing card registers */static ucharrdreg(Cardbus *cb, int index){ outb(cb->lindex, cb->lbase + index); return inb(cb->ldata);}static voidwrreg(Cardbus *cb, int index, uchar val){ outb(cb->lindex, cb->lbase + index); outb(cb->ldata, val);}static intreadc(Cisdat *cis, uchar *x){ if(cis->cispos >= cis->cislen) return 0; *x = cis->cisbase[cis->cisskip*cis->cispos]; cis->cispos++; return 1;}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(Cardbus *cb, Cisdat *cis, int ){ uchar size, rasize, rmsize; uchar last; Pcminfo *pi; if(readc(cis, &size) != 1) return; rasize = (size&0x3) + 1; rmsize = ((size>>2)&0xf) + 1; if(readc(cis, &last) != 1) return; pi = &cb->linfo; pi->conf_addr = getlong(cis, rasize); pi->conf_present = getlong(cis, rmsize);}static voidtvers1(Cardbus *cb, Cisdat *cis, int ){ uchar c, major, minor, last; int i; Pcminfo *pi; pi = &cb->linfo; if(readc(cis, &major) != 1) return; if(readc(cis, &minor) != 1) return; last = 0; for(i = 0; i < sizeof(pi->verstr) - 1; i++){ if(readc(cis, &c) != 1) return; if(c == 0) c = ';'; if(c == '\n') c = ';'; if(c == 0xff) break; if(c == ';' && last == ';') continue; pi->verstr[i] = c; last = c; } pi->verstr[i] = 0;}static ulongmicrovolt(Cisdat *cis){ uchar c; ulong microvolts; ulong exp; if(readc(cis, &c) != 1) return 0; exp = exponent[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 = exponent[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 (feature 1) is important for config, * other features must read card to stay in sync. */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 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 * exponent[scale]; return nanosecs;}static voidtiming(Cisdat *cis, PCMconftab *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, PCMconftab *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; /* * For each of the range descriptions read the * start address and the length (value is length-1). */ nio = (c&0xf)+1; for(i = 0; i < nio; i++){ ct->io[i].start = getlong(cis, (c>>4)&0x3); ct->io[i].len = getlong(cis, (c>>6)&0x3)+1; } ct->nio = nio;}static voidirq(Cisdat *cis, PCMconftab *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(Cardbus *cb, Cisdat *cis, int ){ uchar c, i, feature; PCMconftab *ct; Pcminfo *pi; pi = &cb->linfo; if(pi->nctab >= nelem(pi->ctab)) return; if(readc(cis, &c) != 1) return; ct = &pi->ctab[pi->nctab++]; /* copy from last default config */ if(pi->defctab) *ct = *pi->defctab; ct->index = c & 0x3f; /* is this the new default? */ if(c & 0x40) pi->defctab = 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; }}static voidi82365probe(Cardbus *cb, int lindex, int ldata){ uchar c, id; int dev = 0; /* According to the Ricoh spec 00->3F _and_ 80->BF seem to be the same socket A (ditto for B). */ outb(lindex, Rid + (dev<<7)); id = inb(ldata); if((id & 0xf0) != 0x80) return; /* not a memory & I/O card */ if((id & 0x0f) == 0x00) return; /* no revision number, not possible */ cb->lindex = lindex; cb->ldata = ldata; cb->ltype = Ti82365; cb->lbase = (int)(cb - cbslots) * 0x40; switch(id){ case 0x82: case 0x83: case 0x84: /* could be a cirrus */ outb(cb->lindex, Rchipinfo + (dev<<7)); outb(cb->ldata, 0); c = inb(cb->ldata); if((c & 0xc0) != 0xc0) break; c = inb(cb->ldata); if((c & 0xc0) != 0x00) break; if(c & 0x20){ cb->ltype = Tpd6720; } else { cb->ltype = Tpd6710; } break; } /* if it's not a Cirrus, it could be a Vadem... */ if(cb->ltype == Ti82365){ /* unlock the Vadem extended regs */ outb(cb->lindex, 0x0E + (dev<<7)); outb(cb->lindex, 0x37 + (dev<<7)); /* make the id register show the Vadem id */ outb(cb->lindex, 0x3A + (dev<<7)); c = inb(cb->ldata); outb(cb->ldata, c|0xC0); outb(cb->lindex, Rid + (dev<<7)); c = inb(cb->ldata); if(c & 0x08) cb->ltype = Tvg46x; /* go back to Intel compatible id */ outb(cb->lindex, 0x3A + (dev<<7)); c = inb(cb->ldata); outb(cb->ldata, c & ~0xC0); }}static intvcode(int volt){ switch(volt){ case 5: return 1; case 12: return 2; default: return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -