From 83cbbe5909226b38e19b19fc7cb9ac5852655ae9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 12 Mar 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-03-12 --- pc/devi82365.c | 93 +++++++++++--------------- pc/ether589.c | 137 +++++++++++++++++++++++++------------- pc/memory.c | 5 +- pc/pci.c | 167 ++++++++++++++++++++--------------------------- pc/vgaclgd542x.c | 4 +- 5 files changed, 207 insertions(+), 199 deletions(-) diff --git a/pc/devi82365.c b/pc/devi82365.c index 36af438ae608d310d659045acbef6bac6bf8486a..79403fdc4e10ef4c405c398659aac547b27ea486 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -356,7 +356,7 @@ pcmmap(int slotno, ulong offset, int len, int attr) umbfree(m->isa, m->len); m->len = 0; } - m->isa = umbmalloc(0, len, Mgran)&~KZERO; + m->isa = PADDR(umbmalloc(0, len, Mgran)); if(m->isa == 0){ print("pcmmap: out of isa space\n"); unlock(&pp->mlock); @@ -515,12 +515,12 @@ static char *chipname[] = static I82365* i82386probe(int x, int d, int dev) { - uchar c; + uchar c, id; I82365 *cp; outb(x, Rid + (dev<<7)); - c = inb(d); - if((c & 0xf0) != 0x80) + id = inb(d); + if((id & 0xf0) != 0x80) return 0; /* not this family */ cp = xalloc(sizeof(I82365)); @@ -530,9 +530,10 @@ i82386probe(int x, int d, int dev) cp->type = Ti82365; cp->nslot = 2; - switch(c){ + switch(id){ case 0x82: case 0x83: + case 0x84: /* could be a cirrus */ outb(x, Rchipinfo + (dev<<7)); outb(d, 0); @@ -559,7 +560,8 @@ i82386probe(int x, int d, int dev) outb(d, c|0xC0); outb(x, Rid + (dev<<7)); c = inb(d); - print("ctlr id %uX\n", c & 0xFF); + if(c != id && !(c & 0x08)) + print("#y%d: id %uX changed to %uX\n", ncontroller, id, c); if(c & 0x08) cp->type = Tvg46x; outb(x, 0x3A + (dev<<7)); @@ -567,8 +569,7 @@ i82386probe(int x, int d, int dev) outb(d, c & ~0xC0); } - print("pcmcia controller%d is a %d slot %s\n", ncontroller, cp->nslot, - chipname[cp->type]); + print("#y%d: %d slot %s\n", ncontroller, cp->nslot, chipname[cp->type]); /* low power mode */ outb(x, Rmisc2 + (dev<<7)); @@ -712,7 +713,6 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset) { int i, len; PCMmap *m; - ulong ka; uchar *ac; Slot *pp; @@ -738,8 +738,7 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset) i = m->cea - offset; else i = len; - ka = KZERO|(m->isa + offset - m->ca); - memmoveb(ac, (void*)ka, i); + memmoveb(ac, KADDR(m->isa + offset - m->ca), i); pcmunmap(pp->slotno, m); offset += i; ac += i; @@ -752,50 +751,42 @@ pcmread(int slotno, int attr, void *a, long n, ulong offset) static long i82365read(Chan *c, void *a, long n, ulong offset) { - char *cp, buf[2048]; - ulong p; + char *p; + int len; Slot *pp; - p = TYPE(c); - switch(p){ + switch(TYPE(c)){ case Qdir: return devdirread(c, a, n, 0, 0, pcmgen); case Qmem: case Qattr: - return pcmread(SLOTNO(c), p==Qattr, a, n, offset); + return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, offset); case Qctl: - cp = buf; + p = malloc(READSTR); + len = 0; pp = slot + SLOTNO(c); + if(pp->occupied) - cp += sprint(cp, "occupied\n"); + len += snprint(p+len, READSTR-len, "occupied\n"); if(pp->enabled) - cp += sprint(cp, "enabled\n"); + len += snprint(p+len, READSTR-len, "enabled\n"); if(pp->powered) - cp += sprint(cp, "powered\n"); + len += snprint(p+len, READSTR-len, "powered\n"); if(pp->configed) - cp += sprint(cp, "configed\n"); + len += snprint(p+len, READSTR-len, "configed\n"); if(pp->wrprot) - cp += sprint(cp, "write protected\n"); + len += snprint(p+len, READSTR-len, "write protected\n"); if(pp->busy) - cp += sprint(cp, "busy\n"); - cp += sprint(cp, "battery lvl %d\n", pp->battery); -{ - int i; + len += snprint(p+len, READSTR-len, "busy\n"); + snprint(p+len, READSTR-len, "battery lvl %d\n", pp->battery); - for(i = 0; i < 0x40; i++){ - if((i&0x7) == 0) - cp += sprint(cp, "\n%ux: ", i); - cp += sprint(cp, "%ux ", rdreg(pp, i)); - } - cp += sprint(cp, "\n"); -} - *cp = 0; - return readstr(offset, a, n, buf); - default: - n=0; - break; + n = readstr(offset, a, n, p); + free(p); + + return n; } - return n; + error(Ebadarg); + return -1; /* not reached */ } static long @@ -803,7 +794,6 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset) { int i, len; PCMmap *m; - ulong ka; uchar *ac; Slot *pp; @@ -829,8 +819,7 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset) i = m->cea - offset; else i = len; - ka = KZERO|(m->isa + offset - m->ca); - memmoveb((void*)ka, ac, i); + memmoveb(KADDR(m->isa + offset - m->ca), ac, i); pcmunmap(pp->slotno, m); offset += i; ac += i; @@ -843,12 +832,10 @@ pcmwrite(int dev, int attr, void *a, long n, ulong offset) static long i82365write(Chan *c, void *a, long n, ulong offset) { - ulong p; Slot *pp; char buf[32]; - p = TYPE(c); - switch(p){ + switch(TYPE(c)){ case Qctl: if(n >= sizeof(buf)) n = sizeof(buf) - 1; @@ -861,20 +848,19 @@ i82365write(Chan *c, void *a, long n, ulong offset) /* set vpp on card */ if(strncmp(buf, "vpp", 3) == 0) wrreg(pp, Rpc, vcode(atoi(buf+3))|Fautopower|Foutena|Fcardena); - break; + return n; case Qmem: case Qattr: pp = slot + SLOTNO(c); if(pp->occupied == 0 || pp->enabled == 0) error(Eio); - n = pcmwrite(pp->slotno, p == Qattr, a, n, offset); + n = pcmwrite(pp->slotno, TYPE(c) == Qattr, a, n, offset); if(n < 0) error(Eio); - break; - default: - error(Ebadusefd); + return n; } - return n; + error(Ebadarg); + return -1; /* not reached */ } Dev i82365devtab = { @@ -1000,7 +986,7 @@ pcmio(int slotno, ISAConf *isa) if(pp->cpresent & (1<caddr + Rconfig, 1, 1); - p = (uchar*)(KZERO|(m->isa + pp->caddr + Rconfig - m->ca)); + p = KADDR(m->isa + pp->caddr + Rconfig - m->ca); /* set configuration and interrupt type */ x = ct->index; @@ -1056,7 +1042,7 @@ cisread(Slot *pp) m = pcmmap(pp->slotno, 0, 0, 1); if(m == 0) return; - pp->cisbase = (uchar*)(KZERO|m->isa); + pp->cisbase = KADDR(m->isa); pp->cispos = 0; /* loop through all the tuples */ @@ -1381,4 +1367,3 @@ tvers1(Slot *pp, int ttype) } pp->verstr[i] = 0; } - diff --git a/pc/ether589.c b/pc/ether589.c index 7139bbf1bbec925f687ffa13d3b30ae53fcd70ad..fd940b8199de17001de0928076383f51c31b2433 100644 --- a/pc/ether589.c +++ b/pc/ether589.c @@ -1,3 +1,10 @@ +/* + * 3C589 and 3C562. + * To do: + * check xcvr10Base2 still works (is GlobalReset necessary?). + * pull the station address out of the card space for the 3C562, + * it has no EEPROM. + */ #include "u.h" #include "../port/lib.h" #include "mem.h" @@ -9,58 +16,100 @@ #include "etherif.h" -enum { - GlobalReset = 0x00, /* Global Reset */ - SelectWindow = 0x01, /* SelectWindow command */ - - Command = 0x0E, /* all windows */ - Status = 0x0E, - - XcvrTypeMask = 0xC000, /* Transceiver Type Select */ - Xcvr10BaseT = 0x0000, - XcvrAUI = 0x4000, - XcvrBNC = 0xC000, - - ManufacturerID = 0x00, /* window 0 */ - ProductID = 0x02, - ConfigControl = 0x04, - AddressConfig = 0x06, - ResourceConfig = 0x08, - EEPROMcmd = 0x0A, - EEPROMdata = 0x0C, - - FIFOdiag = 0x04, /* window 4 */ - MediaStatus = 0x0A, - - /* MediaStatus bits */ - JabberEna = 0x0040, /* Jabber Enabled (writeable) */ - LinkBeatEna = 0x0080, /* Link Beat Enabled (writeable) */ - LinkBeatOk = 0x0800, /* Valid link beat detected (ro) */ +enum { /* all windows */ + CommandR = 0x000E, + IntStatusR = 0x000E, }; -#define COMMAND(port, cmd, a) outs(port+Command, ((cmd)<<11)|(a)) +enum { /* Commands */ + GlobalReset = 0x0000, + SelectRegisterWindow = 0x0001, + RxReset = 0x0005, + TxReset = 0x000B, + AcknowledgeInterrupt = 0x000D, +}; + +enum { /* IntStatus bits */ + commandInProgress = 0x1000, +}; + +#define COMMAND(port, cmd, a) outs((port)+CommandR, ((cmd)<<11)|(a)) +#define STATUS(port) ins((port)+IntStatusR) + +enum { /* Window 0 - setup */ + Wsetup = 0x0000, + /* registers */ + ManufacturerID = 0x0000, /* 3C5[08]*, 3C59[27] */ + ProductID = 0x0002, /* 3C5[08]*, 3C59[27] */ + ConfigControl = 0x0004, /* 3C5[08]*, 3C59[27] */ + AddressConfig = 0x0006, /* 3C5[08]*, 3C59[27] */ + ResourceConfig = 0x0008, /* 3C5[08]*, 3C59[27] */ + EepromCommand = 0x000A, + EepromData = 0x000C, + /* AddressConfig Bits */ + autoSelect9 = 0x0080, + xcvrMask9 = 0xC000, + /* ConfigControl bits */ + Ena = 0x0001, + base10TAvailable9 = 0x0200, + coaxAvailable9 = 0x1000, + auiAvailable9 = 0x2000, + /* EepromCommand bits */ + EepromReadRegister = 0x0080, + EepromBusy = 0x8000, +}; + +enum { /* Window 1 - operating set */ + Wop = 0x0001, +}; + +enum { /* Window 3 - FIFO management */ + Wfifo = 0x0003, + /* registers */ + InternalConfig = 0x0000, /* 3C509B, 3C589, 3C59[0257] */ + /* InternalConfig bits */ + xcvr10BaseT = 0x00000000, + xcvr10Base2 = 0x00300000, +}; + +enum { /* Window 4 - diagnostic */ + Wdiagnostic = 0x0004, + /* registers */ + MediaStatus = 0x000A, + /* MediaStatus bits */ + linkBeatDetect = 0x0800, +}; extern int etherelnk3reset(Ether*); static int -configASIC(Ether *ether, int port, int xcvr) +configASIC(Ether* ether, int port, int xcvr) { + int x; + /* set Window 0 configuration registers */ - COMMAND(port, SelectWindow, 0); - outs(port+ConfigControl, 1); + COMMAND(port, SelectRegisterWindow, Wsetup); + outs(port+ConfigControl, Ena); /* IRQ must be 3 on 3C589/3C562 */ outs(port + ResourceConfig, 0x3F00); - /* ROM size & base - must be set before we can access ROM */ - /* transceiver type is 2 for 'figure it out' */ - outs(port + AddressConfig, xcvr); + x = ins(port+AddressConfig) & ~xcvrMask9; + x |= (xcvr>>20)<<14; + outs(port+AddressConfig, x); + + COMMAND(port, TxReset, 0); + while(STATUS(port) & commandInProgress) + ; + COMMAND(port, RxReset, 0); + while(STATUS(port) & commandInProgress) + ; return etherelnk3reset(ether); } static int -reset(Ether *ether) +reset(Ether* ether) { int slot; int port; @@ -74,27 +123,27 @@ reset(Ether *ether) if((slot = pcmspecial(ether->type, ether)) < 0) return -1; - /* try configuring as a 10baseT */ - if(configASIC(ether, port, Xcvr10BaseT) < 0){ + /* try configuring as a 10BaseT */ + if(configASIC(ether, port, xcvr10BaseT) < 0){ pcmspecialclose(slot); return -1; } delay(100); - COMMAND(port, SelectWindow, 4); - if(ins(port+MediaStatus) & LinkBeatOk){ - /* reselect window 1 for normal operation */ - COMMAND(port, SelectWindow, 1); - print("10baseT %s\n", ether->type); + COMMAND(port, SelectRegisterWindow, Wdiagnostic); + if(ins(port+MediaStatus) & linkBeatDetect){ + COMMAND(port, SelectRegisterWindow, Wop); + print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, ether->type); return 0; } /* try configuring as a 10base2 */ COMMAND(port, GlobalReset, 0); - if(configASIC(ether, port, XcvrBNC) < 0){ + if(configASIC(ether, port, xcvr10Base2) < 0){ pcmspecialclose(slot); return -1; } - print("BNC %s\n", ether->type); + print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, ether->type); + return 0; } diff --git a/pc/memory.c b/pc/memory.c index 1b7d68622b9e1b727a557023ca1444fa0fbbd526..d46dd3c1f3a87ed9620381426b0402b70a1fb8c3 100644 --- a/pc/memory.c +++ b/pc/memory.c @@ -223,7 +223,7 @@ umbscan(void) * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up * for grabs; check anyway. */ - p = KADDR(0xC8000); + p = KADDR(0xC0000); while(p < (uchar*)KADDR(0xE0000)){ p[0] = 0xCC; p[2*KB-1] = 0xCC; @@ -235,7 +235,8 @@ umbscan(void) p += p[2]*512; continue; } - mapfree(&rmapumb, PADDR(p), 2*KB); + if(p[0] == 0xFF && p[1] == 0xFF) + mapfree(&rmapumb, PADDR(p), 2*KB); } else mapfree(&rmapumbrw, PADDR(p), 2*KB); diff --git a/pc/pci.c b/pc/pci.c index dff67be3279332c6648100edff655b4b803c3d8c..a97a9dbb60d5efc89be3521499065e13a91f5d74 100644 --- a/pc/pci.c +++ b/pc/pci.c @@ -31,8 +31,6 @@ static Pcidev* pciroot; static Pcidev* pcilist; static Pcidev* pcitail; -static int pcicfgrw8(int, int, int, int); -static int pcicfgrw16(int, int, int, int); static int pcicfgrw32(int, int, int, int); static int @@ -40,7 +38,7 @@ pciscan(int bno, Pcidev** list) { ulong v; Pcidev *p, *head, *tail; - int dno, fno, i, l, maxfno, maxubn, rno, sbn, tbdf, ubn; + int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn; maxubn = bno; head = nil; @@ -70,19 +68,51 @@ pciscan(int bno, Pcidev** list) pcilist = p; pcitail = p; - p->intl = pcicfgrw8(tbdf, PciINTL, 0, 1); - p->ccru = pcicfgrw16(tbdf, PciCCRu, 0, 1); - - rno = PciBAR0 - 4; - for(i = 0; i < nelem(p->mem); i++) { - rno += 4; - p->mem[i].bar = pcicfgrw32(tbdf, rno, 0, 1); - if(i > 0 && p->ccru == ((0x06<<8)|0x04)) - continue; - pcicfgrw32(tbdf, rno, -1, 0); - v = pcicfgrw32(tbdf, rno, 0, 1); - pcicfgrw32(tbdf, rno, p->mem[i].bar, 0); - p->mem[i].size = -(v & ~0xF); + p->intl = pcicfgr8(p, PciINTL); + p->ccru = pcicfgr16(p, PciCCRu); + + /* + * If the device is a multi-function device adjust the + * loop count so all possible functions are checked. + */ + hdt = pcicfgr8(p, PciHDT); + if(hdt & 0x80) + maxfno = MaxFNO; + + /* + * If appropriate, read the base address registers + * and work out the sizes. + */ + switch(p->ccru>>8){ + + case 0x01: /* mass storage controller */ + case 0x02: /* network controller */ + case 0x03: /* display controller */ + case 0x04: /* multimedia device */ + case 0x07: /* simple communication controllers */ + case 0x08: /* base system peripherals */ + case 0x09: /* input devices */ + case 0x0A: /* docking stations */ + case 0x0B: /* processors */ + case 0x0C: /* serial bus controllers */ + if((hdt & 0x7F) != 0) + break; + rno = PciBAR0 - 4; + for(i = 0; i < nelem(p->mem); i++){ + rno += 4; + p->mem[i].bar = pcicfgr32(p, rno); + pcicfgw32(p, rno, -1); + v = pcicfgr32(p, rno); + pcicfgw32(p, rno, p->mem[i].bar); + p->mem[i].size = -(v & ~0xF); + } + break; + + case 0x00: + case 0x05: /* memory controller */ + case 0x06: /* bridge device */ + default: + break; } if(head != nil) @@ -90,34 +120,14 @@ pciscan(int bno, Pcidev** list) else head = p; tail = p; - - /* - * If the device is a multi-function device adjust the - * loop count so all possible functions are checked. - */ - l = pcicfgrw8(tbdf, PciHDT, 0, 1); - if(l & 0x80) - maxfno = MaxFNO; } } *list = head; for(p = head; p != nil; p = p->link){ /* - * Find bridges and recursively descend the tree. - * Special case the Intel 82454GX Host-to-PCI bridge, - * there can be two of them. - * Otherwise, only descend PCI-to-PCI bridges. + * Find PCI-PCI bridges and recursively descend the tree. */ - if(p->ccru == ((0x06<<8)|0) && p->vid == 0x8086 && p->did == 0x84C4){ - tbdf = p->tbdf; - if((sbn = pcicfgrw8(tbdf, 0x4A, 0, 1)) == 0) - continue; - ubn = pcicfgrw8(tbdf, 0x4B, 0, 1); - maxubn = ubn; - pciscan(sbn, &p->bridge); - continue; - } if(p->ccru != ((0x06<<8)|0x04)) continue; @@ -129,9 +139,8 @@ pciscan(int bno, Pcidev** list) * buses are behind this one; the final value is set on the way * back up. */ - tbdf = p->tbdf; - sbn = pcicfgrw8(tbdf, PciSBN, 0, 1); - ubn = pcicfgrw8(tbdf, PciUBN, 0, 1); + sbn = pcicfgr8(p, PciSBN); + ubn = pcicfgr8(p, PciUBN); if(sbn == 0 || ubn == 0){ sbn = maxubn+1; /* @@ -142,13 +151,13 @@ pciscan(int bno, Pcidev** list) * * Initialisation of the bridge should be done here. */ - pcicfgrw32(tbdf, PciPCR, 0xFFFF0000, 0); + pcicfgw32(p, PciPCR, 0xFFFF0000); l = (MaxUBN<<16)|(sbn<<8)|bno; - pcicfgrw32(tbdf, PciPBN, l, 0); - pcicfgrw16(tbdf, PciSPSR, 0xFFFF, 0); + pcicfgw32(p, PciPBN, l); + pcicfgw16(p, PciSPSR, 0xFFFF); maxubn = pciscan(sbn, &p->bridge); l = (maxubn<<16)|(sbn<<8)|bno; - pcicfgrw32(tbdf, PciPBN, l, 0); + pcicfgw32(p, PciPBN, l); } else{ maxubn = ubn; @@ -162,6 +171,10 @@ pciscan(int bno, Pcidev** list) static void pcicfginit(void) { + char *p; + int bno; + Pcidev **list; + lock(&pcicfginitlock); if(pcicfgmode == -1){ /* @@ -169,7 +182,7 @@ pcicfginit(void) * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses * a DWORD at 0xCF8 and another at 0xCFC and will pass through * any non-DWORD accesses as normal I/O cycles. There shouldn't be - * a device behind theses addresses so if Mode2 accesses fail try + * a device behind these addresses so if Mode2 accesses fail try * for Mode1 (which is preferred, Mode2 is deprecated). */ outb(PciCSE, 0); @@ -185,8 +198,18 @@ pcicfginit(void) } } - if(pcicfgmode > 0) - pciscan(0, &pciroot); + if(pcicfgmode > 0){ + if(p = getconf("*pcimaxdno")) + pcimaxdno = strtoul(p, 0, 0); + + list = &pciroot; + for(bno = 0; bno < 256; bno++){ + bno = pciscan(bno, list); + while(*list && (*list)->link) + list = &(*list)->link; + } + + } } unlock(&pcicfginitlock); } @@ -361,19 +384,6 @@ pcicfgw32(Pcidev* pcidev, int rno, int data) pcicfgrw32(pcidev->tbdf, rno, data, 0); } -ulong -pcibarsize(Pcidev* p, int rno) -{ - ulong v, size; - - v = pcicfgrw32(p->tbdf, rno, 0, 1); - pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); - size = pcicfgrw32(p->tbdf, rno, 0, 1); - pcicfgrw32(p->tbdf, rno, v, 0); - - return -(size & ~0x0F); -} - Pcidev* pcimatch(Pcidev* prev, int vid, int did) { @@ -423,43 +433,6 @@ pcihinv(Pcidev* p) } } -/* - * Hack for now to get SYMBIOS controller on-line. - */ -void* -pcimemmap(int tbdf, int rno, ulong *paddr) -{ - long size; - ulong p, v; - - if(pcicfgmode == -1) - pcicfginit(); - - v = pcicfgrw32(tbdf, rno, 0, 1); - if(v & 1){ - print("pcimemmap: not a memory base register\n"); - return 0; - } - if(v & 6){ - print("pcimemmap: only 32 bit relocs supported\n"); - return 0; - } - v = 0xFFFFFFFF; - pcicfgrw32(tbdf, rno, v, 0); - v = pcicfgrw32(tbdf, rno, 0, 1); - /* - * Clear out bottom bits and negate to find size. - * If none can be found could try for UPA memory here. - */ - size = -(v & ~0x0F); - v = umbmalloc(0, size, size); - p = PADDR(v); - if(paddr) - *paddr = p; - pcicfgrw32(tbdf, rno, p, 0); - return (void*)v; -} - void pcireset(void) { diff --git a/pc/vgaclgd542x.c b/pc/vgaclgd542x.c index 3a0d0481cbd5152cbd8ac2aa45a93135be718f46..db25ae8409b24b2d153a492a318cb6453a57f27e 100644 --- a/pc/vgaclgd542x.c +++ b/pc/vgaclgd542x.c @@ -58,8 +58,8 @@ clgd542xenable(VGAscr* scr) /* * Disable the cursor. */ - sr12 = vgaxi(Seqx, 0x12) & ~0x01; - vgaxo(Seqx, 0x12, sr12); + sr12 = vgaxi(Seqx, 0x12); + vgaxo(Seqx, 0x12, sr12 & ~0x01); /* * Cursor colours.