From 9baa62eb05dcbc6b9a565b358ec983fc44e3d99b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 22 Feb 1995 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1995-02-22 --- pc/devata.c | 2 +- pc/devi82365.c | 259 ++++++++++++++++++++++++++----------------------- pc/fns.h | 3 +- pc/main.c | 34 +++++++ pc/ns16552.h | 17 +--- pc/trap.c | 29 +++++- 6 files changed, 202 insertions(+), 142 deletions(-) diff --git a/pc/devata.c b/pc/devata.c index 3a84ed65ea48397b90ecaa6033b2e1e94adf1c05..effcad0e3bb36729e460a8118ec5847d65627863 100644 --- a/pc/devata.c +++ b/pc/devata.c @@ -759,7 +759,7 @@ ataident(Drive *dp) dp->lba = 1; dp->sectors = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); dp->cap = dp->bytes * dp->sectors; -print("\nata%d model %s with %d lba sectors\n", dp->drive, id, dp->sectors); +/*print("\nata%d model %s with %d lba sectors\n", dp->drive, id, dp->sectors);/**/ } else { dp->lba = 0; diff --git a/pc/devi82365.c b/pc/devi82365.c index 23d828fdb8bee7f6ed61b953d5b019974af3e454..21c1cca9b5d398d344196e58cf6cc2583338c455 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -15,7 +15,7 @@ */ /* - * Intel 82365SL PCIC controller for the Slot or + * Intel 82365SL PCIC controller for the PCMCIA or * Cirrus Logic PD6710/PD6720 which is mostly register compatible */ enum @@ -64,6 +64,7 @@ enum Rfifo= 0x17, /* fifo control */ Fflush= (1<<7), /* flush fifo */ Rmisc2= 0x1E, /* misc control 2 */ + Flowpow= (1<<1), /* low power mode */ Rchipinfo= 0x1F, /* chip information */ Ratactl= 0x26, /* ATA control */ @@ -72,12 +73,13 @@ enum */ Mbtmlo= 0x0, /* System mem addr mapping start low byte */ Mbtmhi= 0x1, /* System mem addr mapping start high byte */ + F16bit= (1<<7), /* 16-bit wide data path */ Mtoplo= 0x2, /* System mem addr mapping stop low byte */ Mtophi= 0x3, /* System mem addr mapping stop high byte */ - F16bit= (1<<7), /* 16-bit wide data path */ + Ftimer1= (1<<6), /* timer set 1 */ Mofflo= 0x4, /* Card memory offset address low byte */ Moffhi= 0x5, /* Card memory offset address high byte */ - Fregactive= (1<<6), /* attribute meory */ + Fregactive= (1<<6), /* attribute memory */ Mbits= 13, /* msb of Mchunk */ Mchunk= 1<cp->xreg, pp->base + index); - microdelay(10); return inb(pp->cp->dreg); } static void wrreg(Slot *pp, int index, uchar val) { - microdelay(10); outb(pp->cp->xreg, pp->base + index); - microdelay(10); outb(pp->cp->dreg, val); } @@ -212,9 +210,6 @@ slotinfo(Slot *pp) pp->battery = (isr & 3) == 3; pp->wrprot = isr & (1<<4); pp->busy = isr & (1<<5); - - isr = rdreg(pp, Rigc); - pp->iocard = isr & Fiocard; } static int @@ -236,35 +231,30 @@ vcode(int volt) static void slotena(Slot *pp) { - int x; - if(pp->enabled) return; - if(pp->already == 0){ - pp->already = 1; - - /* interrupt on card status change */ - wrreg(pp, Rigc, Fnotreset); - wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena - | Fbwarnena | Fbdeadena); - } + /* enable the card */ + wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena); + delay(300); /* give the card time to sit up and take notice */ + wrreg(pp, Rigc, 0); + delay(100); + wrreg(pp, Rigc, Fnotreset); + delay(100); + wrreg(pp, Rcscic, ((PCMCIAvec-Int0vec)<<4) | Fchangeena); /* display status */ slotinfo(pp); if(pp->occupied){ - /* enable the card */ - wrreg(pp, Rpc, vcode(5)|Fautopower|Foutena|Fcardena); - pp->enabled = 1; cisread(pp); /* set real power values if we configured successfully */ - if(pp->configed){ - x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2); - wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); - } + if(pp->configed) + wrreg(pp, Rpc, vcode(pp->vpp1)|Fautopower|Foutena|Fcardena); - } + } else + wrreg(pp, Rpc, vcode(5)|Fautopower); + pp->enabled = 1; } /* @@ -273,14 +263,9 @@ slotena(Slot *pp) static void slotdis(Slot *pp) { - int x; - - /* disable the windows into the card */ - wrreg(pp, Rwe, 0); - - /* disable the card */ - x = vcode(5) | (vcode(5)<<2); - wrreg(pp, Rpc, x|Fautopower); + wrreg(pp, Rmisc2, Flowpow); /* low power mode */ + wrreg(pp, Rpc, vcode(5)|Fautopower); /* turn off card */ + wrreg(pp, Rwe, 0); /* no windows */ pp->enabled = 0; } @@ -288,25 +273,24 @@ slotdis(Slot *pp) * status change interrupt */ static void -i82365intr(Ureg *ur) +i82365intr(Ureg *ur, void *a) { - uchar csc; + uchar csc, was; Slot *pp; - USED(ur); + USED(ur,a); + if(slot == 0) + return; + for(pp = slot; pp < lastslot; pp++){ csc = rdreg(pp, Rcsc); + was = pp->occupied; slotinfo(pp); - if(csc & 1) - print("slot card %d battery dead\n", pp->dev); - if(csc & (1<<1)) - print("slot card %d battery warning\n", pp->dev); - if(csc & (1<<3)){ - if(pp->occupied && pp->ref){ - print("slot card %d inserted\n", pp->dev); - slotena(pp); - } else { - print("slot card %d removed\n", pp->dev); + if(csc & (1<<3) && was != pp->occupied){ + if(pp->occupied) + print("slot%d card inserted\n", pp->slotno); + else { + print("slot%d card removed\n", pp->slotno); slotdis(pp); } } @@ -361,7 +345,7 @@ getmap(Slot *pp, ulong offset, int attr) wrreg(pp, MAP(i, Mbtmlo), m->isa>>12); wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(12+8)) | F16bit); wrreg(pp, MAP(i, Mtoplo), (m->isa+Mchunk-1)>>12); - wrreg(pp, MAP(i, Mtophi), (m->isa+Mchunk-1)>>(12+8)); + wrreg(pp, MAP(i, Mtophi), ((m->isa+Mchunk-1)>>(12+8)) | Ftimer1); offset -= m->isa; offset &= (1<<25)-1; offset >>= 12; @@ -389,34 +373,41 @@ decrefp(Slot *pp) unlock(pp); } -char* -pcmspecial(int dev) +/* + * look for a card whose version contains 'idstr' + */ +int +pcmspecial(char *idstr, ISAConf *isa) { Slot *pp; + extern char *strstr(char*, char*); i82365reset(); - if(dev >= nslot) - return 0; - pp = slot + dev; - if(pp->special) - return 0; - increfp(pp); - if(!pp->occupied){ + for(pp = slot; pp < lastslot; pp++){ + if(pp->special) + continue; /* already taken */ + increfp(pp); + + if(pp->occupied) + if(strstr(pp->verstr, idstr)) + if(isa == 0 || pcmio(pp->slotno, isa) == 0){ + pp->special = 1; + return pp->slotno; + } + decrefp(pp); - return 0; } - pp->special = 1; - return pp->verstr; + return -1; } void -pcmspecialclose(int dev) +pcmspecialclose(int slotno) { Slot *pp; - if(dev >= nslot) + if(slotno >= nslot) panic("pcmspecialclose"); - pp = slot + dev; + pp = slot + slotno; pp->special = 0; decrefp(pp); } @@ -429,13 +420,14 @@ enum Qctl, }; -#define DEV(c) (c->qid.path>>8) -#define TYPE(c) (c->qid.path&0xff) +#define SLOTNO(c) ((c->qid.path>>8)&0xff) +#define TYPE(c) (c->qid.path&0xff) +#define QID(s,t) (((s)<<8)|(t)) static int pcmgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) { - int dev; + int slotno; Qid qid; long len; Slot *pp; @@ -444,23 +436,23 @@ pcmgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) USED(tab, ntab); if(i>=3*nslot) return -1; - dev = i/3; - pp = slot + dev; + slotno = i/3; + pp = slot + slotno; len = 0; switch(i%3){ case 0: - qid.path = (dev<<8) | Qmem; - sprint(name, "pcm%dmem", dev); + qid.path = QID(slotno, Qmem); + sprint(name, "pcm%dmem", slotno); len = pp->memlen; break; case 1: - qid.path = (dev<<8) | Qattr; - sprint(name, "pcm%dattr", dev); + qid.path = QID(slotno, Qattr); + sprint(name, "pcm%dattr", slotno); len = pp->memlen; break; case 2: - qid.path = (dev<<8) | Qctl; - sprint(name, "pcm%dctl", dev); + qid.path = QID(slotno, Qctl); + sprint(name, "pcm%dctl", slotno); break; } qid.vers = 0; @@ -538,6 +530,8 @@ i82365reset(void) /* look for controllers */ i82386probe(0x3E0, 0x3E1, 0); i82386probe(0x3E0, 0x3E1, 1); + i82386probe(0x3E2, 0x3E3, 0); + i82386probe(0x3E2, 0x3E3, 1); for(i = 0; i < ncontroller; i++) nslot += controller[i]->nslot; slot = xalloc(nslot * sizeof(Slot)); @@ -547,14 +541,17 @@ i82365reset(void) for(i = 0; i < ncontroller; i++){ cp = controller[i]; for(j = 0; j < cp->nslot; j++){ - lastslot->dev = lastslot - slot; + lastslot->slotno = lastslot - slot; lastslot->memlen = 64*MB; lastslot->base = (cp->dev<<7) | (j<<6); lastslot->cp = cp; - wrreg(lastslot, Rpc, 5|Fautopower); + slotdis(lastslot); lastslot++; } } + + /* for card management interrupts */ + setvec(PCMCIAvec, i82365intr, 0); } void @@ -593,7 +590,7 @@ i82365open(Chan *c, int omode) if(omode != OREAD) error(Eperm); } else - increfp(slot + DEV(c)); + increfp(slot + SLOTNO(c)); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; @@ -624,9 +621,17 @@ i82365wstat(Chan *c, char *dp) void i82365close(Chan *c) { - USED(c); - if(c->qid.path != CHDIR) - decrefp(slot+DEV(c)); + if(c->flag & COPEN) + if(c->qid.path != CHDIR) + decrefp(slot+SLOTNO(c)); +} + +/* a memmove using only bytes */ +static void +memmoveb(uchar *to, uchar *from, int n) +{ + while(n-- > 0) + *to++ = *from++; } /* a memmove using only shorts & bytes */ @@ -648,7 +653,7 @@ memmoves(uchar *to, uchar *from, int n) } long -pcmread(int dev, int attr, void *a, long n, ulong offset) +pcmread(int slotno, int attr, void *a, long n, ulong offset) { int i, len; PCMmap *m; @@ -656,7 +661,7 @@ pcmread(int dev, int attr, void *a, long n, ulong offset) uchar *ac; Slot *pp; - pp = slot + dev; + pp = slot + slotno; if(pp->memlen < offset) return 0; ac = a; @@ -671,17 +676,23 @@ pcmread(int dev, int attr, void *a, long n, ulong offset) else i = len; ka = KZERO|(m->isa + (offset&(Mchunk-1))); - memmoves(ac, (void*)ka, i); + memmoveb(ac, (void*)ka, i); offset += i; ac += i; } return n; } +Block* +i82365bread(Chan *c, long n, ulong offset) +{ + return devbread(c, n, offset); +} + long i82365read(Chan *c, void *a, long n, ulong offset) { - char *cp, buf[128]; + char *cp, buf[2048]; ulong p; Slot *pp; @@ -691,24 +702,22 @@ i82365read(Chan *c, void *a, long n, ulong offset) return devdirread(c, a, n, 0, 0, pcmgen); case Qmem: case Qattr: - pp = slot + DEV(c); + pp = slot + SLOTNO(c); qlock(&pp->mlock); - n = pcmread(DEV(c), p==Qattr, a, n, offset); + n = pcmread(SLOTNO(c), p==Qattr, a, n, offset); qunlock(&pp->mlock); if(n < 0) error(Eio); break; case Qctl: cp = buf; - pp = slot + DEV(c); + pp = slot + SLOTNO(c); if(pp->occupied) cp += sprint(cp, "occupied\n"); if(pp->enabled) cp += sprint(cp, "enabled\n"); if(pp->powered) cp += sprint(cp, "powered\n"); - if(pp->iocard) - cp += sprint(cp, "iocard\n"); if(pp->configed) cp += sprint(cp, "configed\n"); if(pp->wrprot) @@ -716,6 +725,18 @@ i82365read(Chan *c, void *a, long n, ulong offset) if(pp->busy) cp += sprint(cp, "busy\n"); cp += sprint(cp, "battery lvl %d\n", pp->battery); +{ + int i; + + cp += sprint(cp, "x %x d %x b %x\n", pp->cp->xreg, pp->cp->dreg, pp->base); + for(i = 0; i < 0x40; i++){ + cp += sprint(cp, "%2.2ux ", rdreg(pp, i)); + if((i%8) == 7) + cp += sprint(cp, "\n"); + } + if(i%8) + cp += sprint(cp, "\n"); +} *cp = 0; return readstr(offset, a, n, buf); default: @@ -725,10 +746,10 @@ i82365read(Chan *c, void *a, long n, ulong offset) return n; } -Block* -i82365bread(Chan *c, long n, ulong offset) +long +i82365bwrite(Chan *c, Block *bp, ulong offset) { - return devbread(c, n, offset); + return devbwrite(c, bp, offset); } long @@ -753,7 +774,7 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset) else i = len; ka = KZERO|(m->isa + (offset&(Mchunk-1))); - memmoves((void*)ka, ac, i); + memmoveb((void*)ka, ac, i); offset += i; ac += i; } @@ -770,11 +791,11 @@ i82365write(Chan *c, void *a, long n, ulong offset) switch(p){ case Qmem: case Qattr: - pp = slot + DEV(c); + pp = slot + SLOTNO(c); if(pp->occupied == 0 || pp->enabled == 0) error(Eio); qlock(&pp->mlock); - n = pcmwrite(pp->dev, p == Qattr, a, n, offset); + n = pcmwrite(pp->slotno, p == Qattr, a, n, offset); qunlock(&pp->mlock); if(n < 0) error(Eio); @@ -785,12 +806,6 @@ i82365write(Chan *c, void *a, long n, ulong offset) return n; } -long -i82365bwrite(Chan *c, Block *bp, ulong offset) -{ - return devbwrite(c, bp, offset); -} - /* * configure the Slot for IO. We assume very heavily that we can read * cofiguration info from the CIS. If not, we won't set up correctly. @@ -820,7 +835,7 @@ pcmio(int dev, ISAConf *isa) wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); /* set power and enable device */ - x = vcode(pp->vpp1) | (vcode(pp->vpp2)<<2); + x = vcode(pp->vpp1); wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); /* 16-bit data path */ @@ -842,10 +857,10 @@ pcmio(int dev, ISAConf *isa) /* Reset adapter */ x = Creset; pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); - delay(2); + delay(5); x = 0; pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); - delay(2); + delay(5); /* * Set level sensitive (not pulsed) interrupts and @@ -854,7 +869,7 @@ pcmio(int dev, ISAConf *isa) */ x = Clevel | 1; pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); - delay(2); + delay(5); } return 0; } @@ -877,22 +892,20 @@ static void (*parse[256])(Slot*, int) = static int readc(Slot *pp, uchar *x) { - if(pp->cispos > pp->cisbase + Mchunk) + if(pp->cispos >= Mchunk) return 0; - - *x = *(pp->cispos); - pp->cispos += 2; + *x = pp->cisbase[2*pp->cispos]; + pp->cispos++; return 1; } static void cisread(Slot *pp) { - PCMmap *m; uchar link; uchar type; - uchar *this; - int i; + int this, i; + PCMmap *m; pp->vpp1 = pp->vpp2 = 5; pp->bit16 = 0; @@ -901,9 +914,11 @@ cisread(Slot *pp) pp->def = 0; pp->irqs = 0xffff; - /* map in the attribute memory cis should be in */ m = getmap(pp, 0, 1); - pp->cispos = pp->cisbase = (uchar*)(KZERO|m->isa); + if(m == 0) + return; + pp->cisbase = (uchar*)(KZERO|m->isa); + pp->cispos = 0; /* loop through all the tuples */ for(i = 0; i < 1000; i++){ @@ -916,9 +931,7 @@ cisread(Slot *pp) (*parse[type])(pp, type); if(link == 0xff) break; - pp->cispos = this + 2*(2+link); - if(this > pp->cisbase + Mchunk) - break; + pp->cispos = this + (2+link); } } diff --git a/pc/fns.h b/pc/fns.h index 4ecbc18b4c618df214e58617e36c1b763cfcf479..31f3028fec5d5e625b61ac847c366d69df97d7f1 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -6,6 +6,7 @@ void addscsicard(char*, Scsiio (*)(int, ISAConf*)); void bbinit(void); void bigcursor(void); void bootargs(ulong); +int cistrcmp(char*, char*); #define clearmmucache() /* 386 doesn't have one */ void clockinit(void); void config(int); @@ -62,7 +63,7 @@ void outsl(int, void*, int); void pcicreset(void); int pcmio(int, ISAConf*); long pcmread(int, int, void*, long, ulong); -char* pcmspecial(int); +int pcmspecial(char*, ISAConf*); void pcmspecialclose(int); long pcmwrite(int, int, void*, long, ulong); void prflush(void); diff --git a/pc/main.c b/pc/main.c index 5f5fb208bf23cdb0ca346d13c11d71b2aab4c2d8..34b31f8e35b9ddc9b77c080545fb99ce091f1218 100644 --- a/pc/main.c +++ b/pc/main.c @@ -775,3 +775,37 @@ isaconfig(char *class, int ctlrno, ISAConf *isa) } return 0; } + +int +iprint(char *fmt, ...) +{ + char buf[PRINTSIZE]; + int n; + + n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; + screenputs(buf, n); + + return n; +} + +int +cistrcmp(char *a, char *b) +{ + int ac, bc; + + for(;;){ + ac = *a++; + bc = *b++; + + if(ac >= 'A' && ac <= 'Z') + ac = 'a' + (ac - 'A'); + if(bc >= 'A' && bc <= 'Z') + bc = 'a' + (bc - 'A'); + ac -= bc; + if(ac) + return ac; + if(bc == 0) + break; + } + return 0; +} diff --git a/pc/ns16552.h b/pc/ns16552.h index 5ac5eeabafbc75c8afd66141d82825fde6e2a9ac..2dd1c4c7bb7df5d84ace6e65f7fd07a0c0a3bfd6 100644 --- a/pc/ns16552.h +++ b/pc/ns16552.h @@ -115,7 +115,7 @@ ns16552install(void) continue; } - if(strcmp(sc->type, "MP008") == 0 || strcmp(sc->type, "mp008") == 0){ + if(cistrcmp(sc->type, "MP008") == 0){ /* * port gives base port address for uarts * irq is interrupt @@ -135,7 +135,7 @@ ns16552install(void) ns16552setup(port, sc->freq, name); port += 8; } - } else if(strcmp(sc->type, "com") == 0 || strcmp(sc->type, "COM") == 0){ + } else if(cistrcmp(sc->type, "com") == 0){ /* * port gives base port address for the uart * irq is interrupt @@ -147,19 +147,6 @@ ns16552install(void) ns16552setup(sc->port, sc->freq, name); setvec(Int0vec+sc->irq, ns16552intrx, (void*)(nuart-1)); } - nscard++; } } - -int -iprint(char *fmt, ...) -{ - char buf[PRINTSIZE]; - int n; - - n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; - screenputs(buf, n); - - return n; -} diff --git a/pc/trap.c b/pc/trap.c index 03e28deaf062d3666f34a7dbf75867a5d1c6cd0f..b1692e01177c55b790e5ae5e4ecc80b7994a7639 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -31,6 +31,10 @@ enum Int1ctl= 0xA0, /* control port */ Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */ + Icw1= 0x10, /* select bit in ctl register */ + Ocw2= 0x00, + Ocw3= 0x08, + EOI= 0x20, /* non-specific end of interrupt */ Maxhandler= 128, /* max number of interrupt handlers */ @@ -209,6 +213,12 @@ trapinit(void) */ int0mask &= ~0x04; outb(Int0aux, int0mask); + + /* + * Set Ocw3 to return the ISR when ctl read. + */ + outb(Int0ctl, Ocw3|0x03); + outb(Int1ctl, Ocw3|0x03); } char *excname[] = { @@ -249,6 +259,7 @@ trap(Ureg *ur) char buf[ERRLEN]; Handler *h; static int iret_traps; + uchar isr0, isr1; v = ur->trap; @@ -268,10 +279,14 @@ trap(Ureg *ur) * off at this point) */ c = v&~0x7; + isr0 = isr1 = 0x00; if(c==Int0vec || c==Int1vec){ + isr0 = inb(Int0ctl); outb(Int0ctl, EOI); - if(c == Int1vec) + if(c == Int1vec){ + isr1 = inb(Int1ctl); outb(Int1ctl, EOI); + } } if(v>=256 || (h = halloc.ivec[v]) == 0){ @@ -296,9 +311,19 @@ for(;;); if(v >= Int0vec || v < Int0vec+16){ /* an unknown interrupt */ v -= Int0vec; - if(badintr[v]++ == 0 || (badintr[v]%100000) == 0) + /* + * Check for a default IRQ7. This can happen when + * the IRQ input goes away before the acknowledge. + * In this case, a 'default IRQ7' is generated, but + * the corresponding bit in the ISR isn't set. + */ + if(v == 7 && (isr0 & 0x80) == 0) + goto out; + if(badintr[v]++ == 0 || (badintr[v]%100000) == 0){ print("unknown interrupt %d pc=0x%lux: total %d\n", v, ur->pc, badintr[v]); + print("isr0 = 0x%2.2ux, isr1 = 0x%2.2ux\n", isr0, isr1); + } } else { /* unimplemented traps */ print("illegal trap %d pc=0x%lux\n", v, ur->pc);