From cc7c0a00335c2b22b73532aa854854cdde1577c3 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 24 May 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-05-24 --- pc/etherec2t.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ port/devsd.c | 22 +++++++-- 2 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 pc/etherec2t.c diff --git a/pc/etherec2t.c b/pc/etherec2t.c new file mode 100644 index 0000000000000000000000000000000000000000..1e78de08201475355c2542bc079dc8ea8846f95e --- /dev/null +++ b/pc/etherec2t.c @@ -0,0 +1,121 @@ +/* + * Linksys Combo PCMCIA EthernetCard (EC2T). + * Supposedly an NE2000 clone, see the comments in ether2000.c + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" + +#include "etherif.h" +#include "ether8390.h" +enum { + Data = 0x10, /* offset from I/O base of data port */ + Reset = 0x1F, /* offset from I/O base of reset port */ +}; + +static int +reset(Ether* ether) +{ + ushort buf[16]; + ulong port; + Dp8390 *ctlr; + int i, slot; + uchar ea[Eaddrlen]; + + /* + * Set up the software configuration. + * Use defaults for port, irq, mem and size + * if not specified. + * The manual says 16KB memory, the box + * says 32KB. The manual seems to be correct. + */ + if(ether->port == 0) + ether->port = 0x300; + if(ether->irq == 0) + ether->irq = 9; + if(ether->mem == 0) + ether->mem = 0x4000; + if(ether->size == 0) + ether->size = 16*1024; + port = ether->port; + + if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0) + return -1; + if((slot = pcmspecial(ether->type, ether)) < 0){ + iofree(port); + return -1; + } + + ether->ctlr = malloc(sizeof(Dp8390)); + ctlr = ether->ctlr; + ctlr->width = 2; + ctlr->ram = 0; + + ctlr->port = port; + ctlr->data = port+Data; + + ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz); + ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); + ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz); + + ctlr->dummyrr = 1; + for(i = 0; i < ether->nopt; i++){ + if(strcmp(ether->opt[i], "nodummyrr")) + continue; + ctlr->dummyrr = 0; + break; + } + + /* + * Reset the board. This is done by doing a read + * followed by a write to the Reset address. + */ + buf[0] = inb(port+Reset); + delay(2); + outb(port+Reset, buf[0]); + delay(2); + + /* + * Init the (possible) chip, then use the (possible) + * chip to read the (possible) PROM for ethernet address + * and a marker byte. + * Could just look at the DP8390 command register after + * initialisation has been tried, but that wouldn't be + * enough, there are other ethernet boards which could + * match. + */ + dp8390reset(ether); + memset(buf, 0, sizeof(buf)); + dp8390read(ctlr, buf, 0, sizeof(buf)); + if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){ + pcmspecialclose(slot); + iofree(ether->port); + free(ether->ctlr); + return -1; + } + + /* + * Stupid machine. Shorts were asked for, + * shorts were delivered, although the PROM is a byte array. + * Set the ethernet address. + */ + memset(ea, 0, Eaddrlen); + if(memcmp(ea, ether->ea, Eaddrlen) == 0){ + for(i = 0; i < sizeof(ether->ea); i++) + ether->ea[i] = buf[i]; + } + dp8390setea(ether); + + return 0; +} + +void +etherec2tlink(void) +{ + addethercard("EC2T", reset); +} diff --git a/port/devsd.c b/port/devsd.c index dca67018c051ab83e318094bf0220057414da4b2..0b48502c4c8109ad3c8c00651fecab153d0678fb 100644 --- a/port/devsd.c +++ b/port/devsd.c @@ -62,7 +62,7 @@ sdaddpart(SDunit* unit, char* name, ulong start, ulong end) partno = i; break; } - if(strcmp(name, pp->name) == 0){ + if(strncmp(name, pp->name, NAMELEN) == 0){ if(pp->start == start && pp->end == end) return; error(Ebadctl); @@ -110,6 +110,8 @@ sddelpart(SDunit* unit, char* name) } if(i >= SDnpart) error(Ebadctl); + if(strncmp(up->user, pp->user, NAMELEN) && !iseve()) + error(Eperm); if(pp->nopen) error(Einuse); pp->valid = 0; @@ -156,6 +158,9 @@ sdinitpart(SDunit* unit) * Use partitions passed from boot program, * e.g. * sdC0=dos 63 123123/plan9 123123 456456 + * This happens before /boot sets hostname so the + * partitions will have the null-string for user. + * The gen functions patch it up. */ for(p = getconf(unit->name); p != nil; p = q){ if(q = strchr(p, '/')) @@ -332,6 +337,8 @@ sd2gen(Chan* c, int i, Dir* dp) pp = &unit->part[PART(c->qid)]; l = (pp->end - pp->start) * (vlong)unit->secsize; q = (Qid){QID(UNIT(c->qid), PART(c->qid), Qpart), c->qid.vers}; + if(pp->user[0] == '\0') + strncpy(pp->user, eve, NAMELEN); devdir(c, q, pp->name, l, pp->user, pp->perm, dp); return 1; } @@ -404,6 +411,8 @@ sdgen(Chan* c, Dirtab*, int, int s, Dir* dp) } l = (pp->end - pp->start) * (vlong)unit->secsize; q = (Qid){QID(UNIT(c->qid), i, Qpart), c->qid.vers}; + if(pp->user[0] == '\0') + strncpy(pp->user, eve, NAMELEN); devdir(c, q, pp->name, l, pp->user, pp->perm, dp); qunlock(&unit->ctl); return 1; @@ -605,7 +614,8 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) offset = off%unit->secsize; if(write){ if(offset || (len%unit->secsize)){ - if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) + l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); + if(l < 0) error(Eio); if(l < (nb*unit->secsize)){ nb = l/unit->secsize; @@ -615,7 +625,8 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) } } memmove(b+offset, a, len); - if((l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno)) < 0) + l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno); + if(l < 0) error(Eio); if(l < offset) len = 0; @@ -623,7 +634,8 @@ sdbio(Chan* c, int write, char* a, long len, vlong off) len = l - offset; } else { - if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) + l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); + if(l < 0) error(Eio); if(l < offset) len = 0; @@ -872,7 +884,7 @@ sdwstat(Chan* c, char* dp) pp = &unit->part[PART(c->qid)]; if(!pp->valid) error(Enonexist); - if(strcmp(up->user, pp->user) && !iseve()) + if(strncmp(up->user, pp->user, NAMELEN) && !iseve()) error(Eperm); convM2D(dp, &d);