From 87c314235cbe407affcf3d5321b61a84b6990ee0 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 25 Feb 1995 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1995-02-25 --- pc/dat.h | 15 ++++ pc/devi82365.c | 218 ++++++++++++++++++++++++++++++------------------- pc/ether4100.c | 10 ++- pc/fns.h | 5 +- 4 files changed, 161 insertions(+), 87 deletions(-) diff --git a/pc/dat.h b/pc/dat.h index 1308553610998aeebbc0d2cf92c1ca3b90200df2..2abfabf0bf920176b5b091ffed936e77b239160c 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -7,6 +7,7 @@ typedef struct MMU MMU; typedef struct Mach Mach; typedef struct Notsave Notsave; typedef struct PCArch PCArch; +typedef struct PCMmap PCMmap; typedef struct Page Page; typedef struct PMMU PMMU; typedef struct Segdesc Segdesc; @@ -190,6 +191,20 @@ struct ISAConf { uchar ea[6]; }; +/* + * maps between ISA memory space and PCMCIA card memory space + */ +struct PCMmap +{ + ulong ca; /* card address */ + ulong cea; /* card end address */ + ulong isa; /* ISA address */ + int len; /* length of the ISA area */ + int attr; /* attribute memory */ + int ref; +}; + + /* * SCSI bus */ diff --git a/pc/devi82365.c b/pc/devi82365.c index 3d9a3224982d72f12a402e6ea268e80ad76240fa..8d6e419c614b7f42608a0ccb42db33a884961bb7 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -100,19 +100,8 @@ enum typedef struct I82365 I82365; typedef struct Slot Slot; -typedef struct PCMmap PCMmap; typedef struct Conftab Conftab; -/* maps between ISA memory space and the card memory space */ -struct PCMmap -{ - ulong ca; /* card address */ - ulong cea; /* card end address */ - ulong isa; /* ISA address */ - int attr; /* attribute memory */ - int time; -}; - /* a controller */ enum { @@ -182,17 +171,19 @@ struct Slot uchar *cisbase; /* memory maps */ - QLock mlock; /* lock down the maps */ + Lock mlock; /* lock down the maps */ int time; PCMmap mmap[Nmap]; /* maps, last is always for the kernel */ - int nmap; /* number of maps */ }; static Slot *slot; static Slot *lastslot; static nslot; -static void cisread(Slot*); -static void i82365intr(Ureg*, void*); +static void cisread(Slot*); +static void i82365intr(Ureg*, void*); +static int pcmio(int, ISAConf*); +static long pcmread(int, int, void*, long, ulong); +static long pcmwrite(int, int, void*, long, ulong); /* * reading and writing card registers @@ -304,53 +295,108 @@ i82365intr(Ureg *ur, void *a) } } +enum +{ + Mshift= 12, + Mgran= (1<mlock); + + /* convert offset to granularity */ + if(len <= 0) + len = 1; + e = ROUND(offset+len, Mgran); + offset &= Mmask; + len = e - offset; - /* look for a map that starts in the right place */ + /* look for a map that covers the right area */ we = rdreg(pp, Rwe); bit = 1; - lru = pp->mmap; - for(m = pp->mmap; m < &pp->mmap[pp->nmap]; m++){ - if((we & bit) && m->attr == attr && offset >= m->ca && offset < m->cea){ - m->time = pp->time++; + nm = 0; + for(m = pp->mmap; m < &pp->mmap[Nmap]; m++){ + if((we & bit)) + if(m->attr == attr) + if(offset >= m->ca && e <= m->cea){ + + m->ref++; + unlock(&pp->mlock); return m; } bit <<= 1; - if(lru->time > m->time) - lru = m; + if(nm == 0 && m->ref == 0) + nm = m; + } + m = nm; + if(m == 0){ + unlock(&pp->mlock); + return 0; } - /* use the least recently used */ - m = lru; - offset &= ~(Mchunk - 1); + /* if isa space isn't big enough, free it and get more */ + if(m->len < len){ + if(m->isa){ + putisa(m->isa, m->len); + m->len = 0; + } + m->isa = getisa(0, len, Mgran)&~KZERO; + if(m->isa == 0){ + print("pcmmap: out of isa space\n"); + unlock(&pp->mlock); + return 0; + } + m->len = len; + } + + /* set up new map */ m->ca = offset; - m->cea = m->ca + Mchunk; + m->cea = m->ca + m->len; m->attr = attr; - m->time = pp->time++; - i = m - pp->mmap; + i = m-pp->mmap; bit = 1<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)) /*| Ftimer1/**/); + wrreg(pp, MAP(i, Mbtmlo), m->isa>>Mshift); + wrreg(pp, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit); + wrreg(pp, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift); + wrreg(pp, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8))); offset -= m->isa; offset &= (1<<25)-1; - offset >>= 12; + offset >>= Mshift; wrreg(pp, MAP(i, Mofflo), offset); wrreg(pp, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0)); wrreg(pp, Rwe, we | bit); /* enable map */ + m->ref = 1; + + unlock(&pp->mlock); return m; } +void +pcmunmap(int slotno, PCMmap* m) +{ + Slot *pp; + + pp = slot + slotno; + lock(&pp->mlock); + m->ref--; + unlock(&pp->mlock); +} + + static void increfp(Slot *pp) { @@ -554,15 +600,6 @@ i82365reset(void) } } - /* get ISA address space for memory maps */ - for(i = 0; i < Nmap; i++) - for(pp = slot; pp < lastslot; pp++){ - pp->mmap[i].isa = getisa(0, Mchunk, BY2PG); - if(pp->mmap[i].isa == 0) - break; - pp->nmap++; - } - /* for card management interrupts */ setvec(PCMCIAvec, i82365intr, 0); } @@ -665,7 +702,7 @@ memmoves(uchar *to, uchar *from, int n) } } -long +static long pcmread(int slotno, int attr, void *a, long n, ulong offset) { int i, len; @@ -677,22 +714,33 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset) pp = slot + slotno; if(pp->memlen < offset) return 0; - ac = a; 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){ - if(pp->occupied == 0 || pp->enabled == 0) - error(Eio); - m = getmap(pp, offset, attr); + 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; - ka = KZERO|(m->isa + (offset&(Mchunk-1))); + ka = KZERO|(m->isa + offset - m->ca); memmoveb(ac, (void*)ka, i); + pcmunmap(pp->slotno, m); offset += i; ac += i; } + + poperror(); return n; } @@ -715,13 +763,7 @@ i82365read(Chan *c, void *a, long n, ulong offset) return devdirread(c, a, n, 0, 0, pcmgen); case Qmem: case Qattr: - pp = slot + SLOTNO(c); - qlock(&pp->mlock); - n = pcmread(SLOTNO(c), p==Qattr, a, n, offset); - qunlock(&pp->mlock); - if(n < 0) - error(Eio); - break; + return pcmread(SLOTNO(c), p==Qattr, a, n, offset); case Qctl: cp = buf; pp = slot + SLOTNO(c); @@ -765,7 +807,7 @@ i82365bwrite(Chan *c, Block *bp, ulong offset) return devbwrite(c, bp, offset); } -long +static long pcmwrite(int dev, int attr, void *a, long n, ulong offset) { int i, len; @@ -777,20 +819,33 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset) pp = slot + dev; if(pp->memlen < offset) return 0; - ac = a; 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 = getmap(pp, offset, attr); + 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; - ka = KZERO|(m->isa + (offset&(Mchunk-1))); + ka = KZERO|(m->isa + offset - m->ca); memmoveb((void*)ka, ac, i); + pcmunmap(pp->slotno, m); offset += i; ac += i; } + + poperror(); return n; } @@ -807,9 +862,7 @@ i82365write(Chan *c, void *a, long n, ulong offset) pp = slot + SLOTNO(c); if(pp->occupied == 0 || pp->enabled == 0) error(Eio); - qlock(&pp->mlock); n = pcmwrite(pp->slotno, p == Qattr, a, n, offset); - qunlock(&pp->mlock); if(n < 0) error(Eio); break; @@ -823,24 +876,26 @@ i82365write(Chan *c, void *a, long n, ulong 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. */ -int -pcmio(int dev, ISAConf *isa) +static int +pcmio(int slotno, ISAConf *isa) { - uchar we, x; + uchar we, x, *p; Slot *pp; Conftab *ct; + PCMmap *m; - if(dev > nslot) + if(slotno > nslot) return -1; - pp = slot + dev; + pp = slot + slotno; if(!pp->occupied) return -1; /* find a configuration with the right port */ - for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++) + for(ct = pp->ctab; ct < &pp->ctab[pp->nctab]; ct++){ if(ct->nioregs && ct->port == isa->port) break; + } /* if non found, settle for one with the some ioregs */ if(ct == &pp->ctab[pp->nctab]) @@ -851,14 +906,12 @@ pcmio(int dev, ISAConf *isa) if(ct == &pp->ctab[pp->nctab]) return -1; -print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct->vpp1, ct->bit16, ct->nioregs); - /* route interrupts */ if(isa->irq == 2) isa->irq = 9; wrreg(pp, Rigc, isa->irq | Fnotreset | Fiocard); - /* set power and enable device */ + /* set power and enable slotnoice */ x = vcode(ct->vpp1); wrreg(pp, Rpc, x|Fautopower|Foutena|Fcardena); @@ -868,7 +921,7 @@ print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct- /* enable io port map 0 */ if(isa->port == 0) - isa->port = 0x300; + isa->port = ct->port; we = rdreg(pp, Rwe); wrreg(pp, Riobtm0lo, isa->port); wrreg(pp, Riobtm0hi, isa->port>>8); @@ -879,11 +932,11 @@ print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct- /* only touch Rconfig if it is present */ if(pp->cpresent & (1<caddr + Rconfig); + m = pcmmap(slotno, pp->caddr + Rconfig, 1, 1); + p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca)); + *p = Creset; delay(5); - x = 0; - pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); + *p = 0; delay(5); /* @@ -892,11 +945,11 @@ print("%s\n\tindex %d vpp1 %d bit16 %d nioregs %d\n", pp->verstr, ct->index, ct- * Setting the configuration number enables IO port access. */ if(isa->irq > 7) - x = Clevel | ct->index; + *p = Clevel | ct->index; else - x = ct->index; - pcmwrite(dev, 1, &x, 1, pp->caddr + Rconfig); + *p = ct->index; delay(5); + pcmunmap(slotno, m); } return 0; } @@ -940,7 +993,7 @@ cisread(Slot *pp) pp->configed = 0; pp->nctab = 0; - m = getmap(pp, 0, 1); + m = pcmmap(pp->slotno, 0, 0, 1); if(m == 0) return; pp->cisbase = (uchar*)(KZERO|m->isa); @@ -959,6 +1012,7 @@ cisread(Slot *pp) break; pp->cispos = this + (2+link); } + pcmunmap(pp->slotno, m); } static ulong diff --git a/pc/ether4100.c b/pc/ether4100.c index 6a62aadbf7943095cf8df764c8763c9b5921b649..b7933c464d48de6d1a3afe18a0075b517284eab6 100644 --- a/pc/ether4100.c +++ b/pc/ether4100.c @@ -32,7 +32,8 @@ reset(Ether *ether) Dp8390 *dp8390; ulong port; int i, slot; - uchar x; + uchar x, *p; + PCMmap *m; /* * Set up the software configuration. @@ -80,8 +81,13 @@ reset(Ether *ether) dp8390reset(ether); /* set the ether address */ + m = pcmmap(slot, 0, 0x1000, 1); + if(m == 0) + return -1; + p = (uchar*)(KZERO|m->isa); for(i = 0; i < sizeof(ether->ea); i++) - pcmread(slot, 1, ðer->ea[i], 1, 0xff0+2*i); + ether->ea[i] = p[0xff0+2*i]; + pcmunmap(slot, m); dp8390setea(ether); return 0; diff --git a/pc/fns.h b/pc/fns.h index 31f3028fec5d5e625b61ac847c366d69df97d7f1..6133ab7f81b0417fb56652c72ae1ef14f9a951e1 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -61,11 +61,10 @@ void outss(int, void*, int); void outl(int, ulong); void outsl(int, void*, int); void pcicreset(void); -int pcmio(int, ISAConf*); -long pcmread(int, int, void*, long, ulong); +PCMmap* pcmmap(int, ulong, int, int); int pcmspecial(char*, ISAConf*); void pcmspecialclose(int); -long pcmwrite(int, int, void*, long, ulong); +void pcmunmap(int, PCMmap*); void prflush(void); void prhex(ulong); void printcpufreq(void);