From af5e5bd8e9d3c4dde463b256bef7e8ff900486f2 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 28 Jan 1994 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1994-01-28 --- pc/clock.c | 1 + pc/devhard.c | 57 ++++++++++++++++++++++++++++++++++++- pc/ether2000.c | 77 +++++++++++++++++++++++++------------------------- pc/ether8003.c | 8 ++++-- pc/ether8390.c | 4 +-- pc/etherif.h | 2 ++ pc/fns.h | 1 + 7 files changed, 107 insertions(+), 43 deletions(-) diff --git a/pc/clock.c b/pc/clock.c index bd3c524d1cc06e3e93fe56922e7bf99fb5c081a4..cdad603f3d4e6c6f3003509bc1b88b6cda263c6e 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -54,6 +54,7 @@ clock(Ureg *ur, void *arg) checkalarms(); mouseclock(); + hardclock(); /* * process time accounting diff --git a/pc/devhard.c b/pc/devhard.c index ec8b6ebce42515d77096caa925ec695f3d70d89e..f2e4c691e3a20eb5889017871740727de8b2cb91 100644 --- a/pc/devhard.c +++ b/pc/devhard.c @@ -44,6 +44,11 @@ enum Csetbuf= 0xEF, Cinitparam= 0x91, + /* conner specific commands */ + Cstandby= 0xE0, + Cidle= 0xE1, + Cpowerdown= 0xE3, + /* file types */ Qdir= 0, @@ -86,6 +91,8 @@ struct Drive int npart; /* number of real partitions */ Partition p[Npart]; Repl repl; + ulong usetime; + int state; ulong cap; /* total bytes */ int bytes; /* bytes/sector */ @@ -94,6 +101,14 @@ struct Drive long cyl; /* cylinders/drive */ }; +enum +{ + Sspinning, + Sstandby, + Sidle, + Spowerdown, +}; + /* * a controller for 2 drives */ @@ -120,6 +135,7 @@ struct Controller Controller *hardc; Drive *hard; +static int spindowntime; static void hardintr(Ureg*, void*); static long hardxfer(Drive*, Partition*, int, long, long, char*); @@ -170,10 +186,15 @@ hardreset(void) Controller *cp; int drive; uchar equip; + char *p; hard = xalloc(conf.nhard * sizeof(Drive)); hardc = xalloc(((conf.nhard+1)/2) * sizeof(Controller)); + p = getconf("spindowntime"); + if(p) + spindowntime = atoi(p); + /* * read nvram for number of hard drives (2 max) */ @@ -418,7 +439,7 @@ cmdreadywait(Controller *cp) start = m->ticks; while((inb(cp->pbase+Pstatus) & (Sready|Sbusy)) != Sready) - if(TK2MS(m->ticks - start) > 5){ + if(TK2MS(m->ticks - start) > 10){ DPRINT("cmdreadywait failed\n"); error(Eio); } @@ -526,6 +547,8 @@ hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf) } } sleep(&cp->r, cmddone, cp); + dp->state = Sspinning; + dp->usetime = m->ticks; poperror(); if(loop) nexterror(); @@ -1011,3 +1034,35 @@ hardintr(Ureg *ur, void *arg) break; } } + +void +hardclock(void) +{ + int drive; + Drive *dp; + Controller *cp; + int diff; + + if(spindowntime <= 0) + return; + + for(drive = 0; drive < conf.nhard; drive++){ + dp = &hard[drive]; + cp = dp->cp; + if(canqlock(cp) == 0) + continue; + + diff = TK2SEC(m->ticks - dp->usetime); + switch(dp->state){ + case Sspinning: + if(diff >= spindowntime){ + cp->cmd = Cstandby; + outb(cp->pbase+Pdh, 0x20 | (dp->drive<<4) | 0); + outb(cp->pbase+Pcmd, cp->cmd); + dp->state = Sstandby; + } + break; + } + qunlock(dp->cp); + } +} diff --git a/pc/ether2000.c b/pc/ether2000.c index af37329ae92a2af6335dfad892914c0843cc112f..8c35463c53fc8413c73c0e8f8223a39217448ddb 100644 --- a/pc/ether2000.c +++ b/pc/ether2000.c @@ -3,11 +3,11 @@ #include "mem.h" #include "dat.h" #include "fns.h" -#include "../port/error.h" #include "io.h" -#include "devtab.h" +#include "../port/error.h" +#include "../port/netif.h" -#include "ether.h" +#include "etherif.h" /* * Driver written for the 'Notebook Computer Ethernet LAN Adapter', @@ -25,10 +25,12 @@ enum { Reset = 0x18, /* offset from I/O base of reset port */ }; -int -ne2000reset(Ctlr *ctlr) +static int +reset(Ether *ether) { ushort buf[16]; + ulong port; + Dp8390 *dp8390; int i; /* @@ -36,41 +38,35 @@ ne2000reset(Ctlr *ctlr) * Use defaults for port, irq, mem and size * if not specified. */ - if(ctlr->card.port == 0) - ctlr->card.port = 0x300; - if(ctlr->card.irq == 0) - ctlr->card.irq = 2; - if(ctlr->card.mem == 0) - ctlr->card.mem = 0x4000; - if(ctlr->card.size == 0) - ctlr->card.size = 16*1024; + if(ether->port == 0) + ether->port = 0x300; + if(ether->irq == 0) + ether->irq = 2; + if(ether->mem == 0) + ether->mem = 0x4000; + if(ether->size == 0) + ether->size = 16*1024; + port = ether->port; - ctlr->card.reset = ne2000reset; - ctlr->card.attach = dp8390attach; - ctlr->card.mode = dp8390mode; - ctlr->card.read = dp8390read; - ctlr->card.write = dp8390write; - ctlr->card.receive = dp8390receive; - ctlr->card.transmit = dp8390transmit; - ctlr->card.intr = dp8390intr; - ctlr->card.watch = dp8390watch; - ctlr->card.overflow = dp8390overflow; + ether->private = malloc(sizeof(Dp8390)); + dp8390 = ether->private; + dp8390->bit16 = 1; + dp8390->ram = 0; - ctlr->card.bit16 = 1; - ctlr->card.dp8390 = ctlr->card.port; - ctlr->card.data = ctlr->card.port+Data; + dp8390->dp8390 = port; + dp8390->data = port+Data; - ctlr->card.tstart = HOWMANY(ctlr->card.mem, Dp8390BufSz); - ctlr->card.pstart = ctlr->card.tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); - ctlr->card.pstop = ctlr->card.tstart + HOWMANY(ctlr->card.size, Dp8390BufSz); + dp8390->tstart = HOWMANY(ether->mem, Dp8390BufSz); + dp8390->pstart = dp8390->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); + dp8390->pstop = dp8390->tstart + HOWMANY(ether->size, Dp8390BufSz); /* * Reset the board. This is done by doing a read * followed by a write to the Reset address. */ - buf[0] = inb(ctlr->card.port+Reset); + buf[0] = inb(port+Reset); delay(2); - outb(ctlr->card.port+Reset, buf[0]); + outb(port+Reset, buf[0]); /* * Init the (possible) chip, then use the (possible) @@ -81,20 +77,25 @@ ne2000reset(Ctlr *ctlr) * enough, there are other ethernet boards which could * match. */ - dp8390reset(ctlr); + dp8390reset(ether); memset(buf, 0, sizeof(buf)); - dp8390read(ctlr, buf, 0, sizeof(buf)); - if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57) + dp8390read(dp8390, buf, 0, sizeof(buf)); + if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){ + free(ether->private); return -1; + } /* * Stupid machine. We asked for shorts, we got shorts, * although the PROM is a byte array. * Now we can set the ethernet address. */ - for(i = 0; i < sizeof(ctlr->ea); i++) - ctlr->ea[i] = buf[i]; - dp8390setea(ctlr); + if((ether->ea[0]|ether->ea[1]|ether->ea[2]|ether->ea[3]|ether->ea[4]|ether->ea[5]) == 0){ + for(i = 0; i < sizeof(ether->ea); i++) + ether->ea[i] = buf[i]; + } + + dp8390setea(ether); return 0; } @@ -102,5 +103,5 @@ ne2000reset(Ctlr *ctlr) void ether2000link(void) { - addethercard("NE2000", ne2000reset); + addethercard("NE2000", reset); } diff --git a/pc/ether8003.c b/pc/ether8003.c index ae899a15491b70bc3b1dd9662a5a6a20c59c2554..542b788ca432b9154ac0a77fe53dd5a010aa11c7 100644 --- a/pc/ether8003.c +++ b/pc/ether8003.c @@ -66,7 +66,7 @@ static int reset(Ether *ether) { int i; - uchar ic[8], sum; + uchar ea[Eaddrlen], ic[8], sum; ulong port; Dp8390 *dp8390; @@ -95,7 +95,7 @@ reset(Ether *ether) port = ether->port; sum = 0; for(i = 0; i < sizeof(ether->ea); i++){ - ether->ea[i] = inb(port+Lar+i); + ea[i] = inb(port+Lar+i); sum += ether->ea[i]; ic[i] = inb(port+i); } @@ -184,6 +184,10 @@ reset(Ether *ether) * ethernet address. */ dp8390reset(ether); + if((ether->ea[0]|ether->ea[1]|ether->ea[2]|ether->ea[3]|ether->ea[4]|ether->ea[5]) == 0){ + for(i = 0; i < sizeof(ether->ea); i++) + ether->ea[i] = ea[i]; + } dp8390setea(ether); return 0; diff --git a/pc/ether8390.c b/pc/ether8390.c index 4131e0c9e37bb41af4d7465fe0ec94e62ee87d5e..830be1b75346ba1ec17e7dbc0fe1c718c83d6897 100644 --- a/pc/ether8390.c +++ b/pc/ether8390.c @@ -228,7 +228,7 @@ dp8390getea(Ether *ether) dp8390outb(port+Cr, cr); } -static void* +void* dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) { ulong port = dp8390->dp8390; @@ -279,7 +279,7 @@ dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) return to; } -static void* +void* dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len) { ulong port = dp8390->dp8390; diff --git a/pc/etherif.h b/pc/etherif.h index d92c53bd7d26d1ef56c59299c32d708c0534b4bf..ac21c9705f09184da9274914267580a07eada9db 100644 --- a/pc/etherif.h +++ b/pc/etherif.h @@ -40,6 +40,8 @@ typedef struct { extern int dp8390reset(Ether*); extern void dp8390getea(Ether*); extern void dp8390setea(Ether*); +extern void *dp8390read(Dp8390*, void*, ulong, ulong); +extern void *dp8390write(Dp8390*, ulong, void*, ulong); #define NEXT(x, l) (((x)+1)%(l)) #define HOWMANY(x, y) (((x)+((y)-1))/(y)) diff --git a/pc/fns.h b/pc/fns.h index 1f084f02b88c1c5b64a91f22dd8a011df9785393..fceef3721d7143e4ff9a05fa1540982e39073ad1 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -27,6 +27,7 @@ ulong getcr0(void); ulong getcr2(void); char* getconf(char*); ulong getstatus(void); +void hardclock(void); void i8042a20(void); void i8042reset(void); void ident(void);