M pc/clock.c => pc/clock.c +1 -0
@@ 54,6 54,7 @@ clock(Ureg *ur, void *arg)
checkalarms();
mouseclock();
+ hardclock();
/*
* process time accounting
M pc/devhard.c => pc/devhard.c +56 -1
@@ 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);
+ }
+}
M pc/ether2000.c => pc/ether2000.c +39 -38
@@ 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);
}
M pc/ether8003.c => pc/ether8003.c +6 -2
@@ 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;
M pc/ether8390.c => pc/ether8390.c +2 -2
@@ 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;
M pc/etherif.h => pc/etherif.h +2 -0
@@ 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))
M pc/fns.h => pc/fns.h +1 -0
@@ 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);