M carrera/devrtc.c => carrera/devrtc.c +60 -125
@@ 20,8 20,6 @@ struct Rtc
int mon;
int year;
};
-static QLock rtclock; /* mutex on clock operations */
-
enum
{
@@ 39,11 37,16 @@ enum
StatusC= 0x0C,
StatusD= 0x0D,
+ Update= 0x80,
+
Nvsize = 4096,
Nclock= 6,
};
+#define GETBCD(v) (((v) & 0x0F) + 10*((v)>>4))
+#define PUTBCD(v) ((v) % 10)|((((v)/10) % 10)<<4)
+
Dirtab rtcdir[]={
"nvram", {Qnvram, 0}, Nvsize, 0664,
"rtc", {Qrtc, 0}, 0, 0664,
@@ 52,10 55,11 @@ Dirtab rtcdir[]={
static ulong rtc2sec(Rtc*);
static void sec2rtc(ulong, Rtc*);
-static uchar statusB;
+static int isbinary;
+static Lock rtclock;
static void
-getstatusB(void)
+rtcreset(void)
{
int i, x;
uchar r;
@@ 68,7 72,7 @@ getstatusB(void)
continue;
*(uchar*)Rtcindex = x|StatusB;
- statusB = *(uchar*)Rtcdata;
+ isbinary = *(uchar*)Rtcdata & 0x04;
break;
}
}
@@ 76,7 80,6 @@ getstatusB(void)
static Chan*
rtcattach(char *spec)
{
- getstatusB();
return devattach('r', spec);
}
@@ 114,106 117,51 @@ rtcclose(Chan *c)
USED(c);
}
-static uchar
-bcd2binary(int reg)
-{
- uchar x;
-
- x = (*(uchar*)Rtcindex)&~0x7f;
- *(uchar*)Rtcindex = x|reg;
- x = *(uchar*)Rtcdata;
- return (x&0xf) + 10*(x>>4);
-}
-
-#define GETBCD(o) ((clock[o]&0xf) + 10*(clock[o]>>4))
-
-static void
-dumprtcstatus(void)
-{
- int i, x;
- uchar status[4], r;
-
- for(i = 0; i < 10000; i++){
- x = (*(uchar*)Rtcindex)&~0x7f;
- *(uchar*)Rtcindex = x|Status;
- r = *(uchar*)Rtcdata;
- if(r & 0x80)
- continue;
-
- status[0] = r;
- *(uchar*)Rtcindex = x|StatusB;
- status[1] = *(uchar*)Rtcdata;
- *(uchar*)Rtcindex = x|StatusC;
- status[2] = *(uchar*)Rtcdata;
- *(uchar*)Rtcindex = x|StatusD;
- status[3] = *(uchar*)Rtcdata;
-
- *(uchar*)Rtcindex = x|Status;
- r = *(uchar*)Rtcdata;
- if((r & 0x80) == 0)
- break;
- }
-
- print("RTC: %uX %uX %uX %uX\n", status[0], status[1], status[2], status[3]);
-}
-
static long
_rtctime(void)
{
Rtc rtc;
int i, x;
- uchar clock[Nclock], r;
- int busy;
+ uchar r;
/* don't do the read until the clock is no longer busy */
- busy = 0;
for(i = 0; i < 10000; i++){
x = (*(uchar*)Rtcindex)&~0x7f;
*(uchar*)Rtcindex = x|Status;
r = *(uchar*)Rtcdata;
- if(r & 0x80){
- busy++;
+ if(r & Update)
continue;
- }
/* read clock values */
*(uchar*)Rtcindex = x|Seconds;
- clock[0] = *(uchar*)Rtcdata;
+ rtc.sec = *(uchar*)Rtcdata;
*(uchar*)Rtcindex = x|Minutes;
- clock[1] = *(uchar*)Rtcdata;
+ rtc.min = *(uchar*)Rtcdata;
*(uchar*)Rtcindex = x|Hours;
- clock[2] = *(uchar*)Rtcdata;
+ rtc.hour = *(uchar*)Rtcdata;
*(uchar*)Rtcindex = x|Mday;
- clock[3] = *(uchar*)Rtcdata;
+ rtc.mday = *(uchar*)Rtcdata;
*(uchar*)Rtcindex = x|Month;
- clock[4] = *(uchar*)Rtcdata;
+ rtc.mon = *(uchar*)Rtcdata;
*(uchar*)Rtcindex = x|Year;
- clock[5] = *(uchar*)Rtcdata;
+ rtc.year = *(uchar*)Rtcdata;
*(uchar*)Rtcindex = x|Status;
r = *(uchar*)Rtcdata;
- if((r & 0x80) == 0)
+ if((r & Update) == 0)
break;
}
- if(statusB & 0x04){
- rtc.sec = clock[0];
- rtc.min = clock[1];
- rtc.hour = clock[2];
- rtc.mday = clock[3];
- rtc.mon = clock[4];
- rtc.year = clock[5];
- }
- else{
+ if(!isbinary){
/*
* convert from BCD
*/
- rtc.sec = GETBCD(0);
- rtc.min = GETBCD(1);
- rtc.hour = GETBCD(2);
- rtc.mday = GETBCD(3);
- rtc.mon = GETBCD(4);
- rtc.year = GETBCD(5);
+ rtc.sec = GETBCD(rtc.sec);
+ rtc.min = GETBCD(rtc.min);
+ rtc.hour = GETBCD(rtc.hour);
+ rtc.mday = GETBCD(rtc.mday);
+ rtc.mon = GETBCD(rtc.mon);
+ rtc.year = GETBCD(rtc.year);
}
/*
@@ 224,17 172,13 @@ _rtctime(void)
return rtc2sec(&rtc);
}
-static Lock rtlock;
-
long
rtctime(void)
{
-#define notdef
-#ifdef notdef
int i;
long t, ot;
- ilock(&rtlock);
+ ilock(&rtclock);
/* loop till we get two reads in a row the same */
t = _rtctime();
@@ 244,22 188,14 @@ rtctime(void)
if(ot == t)
break;
}
- iunlock(&rtlock);
-
- if(i == 100) print("we are boofheads\n");
+ iunlock(&rtclock);
return t;
-#else
- extern ulong boottime;
-
- return boottime+TK2SEC(MACHP(0)->ticks);
-#endif /* notdef */
}
static long
rtcread(Chan *c, void *buf, long n, ulong offset)
{
- ulong t;
uchar *f, *to, *e;
if(c->qid.path & CHDIR)
@@ 267,12 203,7 @@ rtcread(Chan *c, void *buf, long n, ulong offset)
switch(c->qid.path){
case Qrtc:
- qlock(&rtclock);
- t = rtctime();
-dumprtcstatus();
- qunlock(&rtclock);
- n = readnum(offset, buf, n, t, 12);
- return n;
+ return readnum(offset, buf, n, rtctime(), 12);
case Qnvram:
if(offset > Nvsize)
return -1;
@@ 289,20 220,6 @@ dumprtcstatus();
return 0;
}
-static void
-binary2bcd(int reg, uchar val)
-{
- uchar x;
-
- x = (*(uchar*)Rtcindex)&~0x7f;
- *(uchar*)Rtcindex = x|reg;
- if(statusB & 0x04)
- *(uchar*)Rtcdata = val;
- else
- *(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4);
-}
-
-
static long
rtcwrite(Chan *c, void *buf, long n, ulong offset)
{
@@ 310,7 227,7 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
ulong secs;
char *cp, *ep;
uchar *f, *t, *e;
- int s;
+ uchar x;
USED(c);
switch(c->qid.path){
@@ 327,18 244,36 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
}
secs = strtoul(cp, 0, 0);
sec2rtc(secs, &rtc);
-
- /*
- * convert to bcd
- */
- s = splhi();
- binary2bcd(Seconds, rtc.sec);
- binary2bcd(Minutes, rtc.min);
- binary2bcd(Hours, rtc.hour);
- binary2bcd(Mday, rtc.mday);
- binary2bcd(Month, rtc.mon);
- binary2bcd(Year, rtc.year-1970);
- splx(s);
+ rtc.year -= 1970;
+
+ if(!isbinary){
+ /*
+ * convert to bcd
+ */
+ rtc.sec = PUTBCD(rtc.sec);
+ rtc.min = PUTBCD(rtc.min);
+ rtc.hour = PUTBCD(rtc.hour);
+ rtc.mday = PUTBCD(rtc.mday);
+ rtc.mon = PUTBCD(rtc.mon);
+ rtc.year = PUTBCD(rtc.year);
+ }
+
+ ilock(&rtclock);
+ /* set clock values */
+ x = (*(uchar*)Rtcindex)&~0x7f;
+ *(uchar*)Rtcindex = x|Seconds;
+ *(uchar*)Rtcdata = rtc.sec;
+ *(uchar*)Rtcindex = x|Minutes;
+ *(uchar*)Rtcdata = rtc.min;
+ *(uchar*)Rtcindex = x|Hours;
+ *(uchar*)Rtcdata = rtc.hour;
+ *(uchar*)Rtcindex = x|Mday;
+ *(uchar*)Rtcdata = rtc.mday;
+ *(uchar*)Rtcindex = x|Month;
+ *(uchar*)Rtcdata = rtc.mon;
+ *(uchar*)Rtcindex = x|Year;
+ *(uchar*)Rtcdata = rtc.year;
+ iunlock(&rtclock);
return n;
case Qnvram:
@@ 358,7 293,7 @@ rtcwrite(Chan *c, void *buf, long n, ulong offset)
}
Dev rtcdevtab = {
- devreset,
+ rtcreset,
devinit,
rtcattach,
devclone,
M ip/il.c => ip/il.c +1 -1
@@ 184,7 184,7 @@ ilannounce(Conv *c, char **argv, int argc)
char *e;
e = Fsstdannounce(c, argv, argc);
- if(e != nil);
+ if(e != nil)
return e;
e = ilstart(c, IL_LISTEN, 20);
if(e != nil)
M pc/archgeneric.c => pc/archgeneric.c +2 -1
@@ 56,9 56,10 @@ static X86type x86type[] =
{ 5, 1, 23, "P5", },
{ 5, 2, 23, "P54C", },
{ 5, 3, 23, "P24T", }, /* PODP5V83 */
- { 5, 4, 23, "PODP54", },
+ { 5, 4, 23, "P54C MMX", },
{ 5, 5, 23, "PODDX4", },
{ 5, 6, 23, "PODP5", },
+ { 5, 7, 23, "P54C VRT", },
{ 6, 4, 23, "P55CT", },
{ 6, 1, 16, "PentiumPro", },/* determined by trial and error */
M pc/audio.h => pc/audio.h +1 -1
@@ 6,7 6,7 @@ enum
SBswab = 0,
};
-#define seteisadma(a, b) ;
+#define seteisadma(a, b) dmainit(a);
#define CACHELINESZ 8
#define UNCACHED(type, v) (type*)((ulong)(v))
M pc/devether.c => pc/devether.c +11 -0
@@ 145,6 145,17 @@ etheriq(Ether* ether, Block* bp, int freebp)
fx = 0;
ep = ðer->f[Ntypes];
+ /* check for valid multcast addresses */
+ if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(freebp){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (freebp != 0),
M pc/devfloppy.c => pc/devfloppy.c +7 -1
@@ 19,6 19,7 @@
* floppyeject()
* floppysetup0()
* floppysetup1()
+ * dmainit()
* dmasetup()
* dmaend()
*
@@ 143,6 144,8 @@ floppyreset(void)
FDrive *dp;
FType *t;
ulong maxtsize;
+
+ dmainit(DMAchan);
floppysetup0(&fl);
@@ 793,6 796,8 @@ floppyxfer(FDrive *dp, int cmd, void *a, long off, long n)
nexterror();
}
dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread);
+ if(dp->len < 0)
+ error(Eio);
/*
* start operation
@@ 930,7 935,8 @@ floppyformat(FDrive *dp, char *params)
dmaend(DMAchan);
nexterror();
}
- dmasetup(DMAchan, buf, bp-buf, 0);
+ if(dmasetup(DMAchan, buf, bp-buf, 0) < 0)
+ error(Eio);
/*
* start operation
M pc/dma.c => pc/dma.c +25 -14
@@ 79,26 79,33 @@ DMA dma[2] = {
};
/*
- * DMA must be in the first 16 meg. This gets called early by main() to
- * ensure that.
+ * DMA must be in the first 16MB. This gets called early by the
+ * initialisation routines of any devices which require DMA to ensure
+ * the allocated bounce buffers are below the 16MB limit.
*/
void
-dmainit(void)
+dmainit(int chan)
{
- int i, chan;
DMA *dp;
DMAxfer *xp;
+ ulong v;
- for(i = 0; i < 2; i++){
- dp = &dma[i];
- for(chan = 0; chan < 4; chan++){
- xp = &dp->x[chan];
- xp->bva = xspanalloc(BY2PG, BY2PG, 0);
- xp->bpa = PADDR(xp->bva);
- xp->len = 0;
- xp->isread = 0;
- }
+ dp = &dma[(chan>>2)&1];
+ chan = chan & 3;
+ xp = &dp->x[chan];
+ if(xp->bva != nil)
+ return;
+
+ v = (ulong)xalloc(BY2PG+BY2PG);
+ if(v == 0 || PADDR(v) >= 16*MB){
+ print("dmainit: chan %d: 0x%luX out of range\n", chan, v);
+ xfree((void*)v);
+ v = 0;
}
+ xp->bva = (void*)ROUND(v, BY2PG);
+ xp->bpa = PADDR(xp->bva);
+ xp->len = 0;
+ xp->isread = 0;
}
/*
@@ 131,6 138,8 @@ dmasetup(int chan, void *va, long len, int isread)
if((((ulong)va)&0xF0000000) != KZERO
|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
|| pa > 16*MB) {
+ if(xp->bva == nil)
+ return -1;
if(len > BY2PG)
len = BY2PG;
if(!isread)
@@ 205,7 214,8 @@ dmaend(int chan)
memmove(xp->va, xp->bva, xp->len);
xp->len = 0;
}
-
+
+/*
int
dmacount(int chan)
{
@@ 218,3 228,4 @@ dmacount(int chan)
retval |= inb(dp->count[chan]) << 8;
return((retval<<dp->shift)+1);
}
+ */
M pc/etherelnk3.c => pc/etherelnk3.c +6 -1
@@ 457,14 457,17 @@ promiscuous(void* arg, int on)
}
static void
-multicast(void* arg, char *addr, int on)
+multicast(void* arg, uchar *addr, int on)
{
int filter, port;
Ether *ether;
+ USED(addr, on);
+
ether = (Ether*)arg;
port = ether->port;
+print("mutlicast nmaddr == %d\n", ether->nmaddr);
filter = receiveBroadcast|receiveIndividual;
if(ether->nmaddr)
filter |= receiveMulticast;
@@ 1314,6 1317,7 @@ etherelnk3reset(Ether* ether)
rxstatus9 = 1;
break;
}
+ USED(did);
/*
* Check if the adapter's station address is to be overridden.
@@ 1436,6 1440,7 @@ etherelnk3reset(Ether* ether)
ether->ifstat = ifstat;
ether->promiscuous = promiscuous;
+ ether->multicast = multicast;
ether->arg = ether;
return 0;
M pc/fns.h => pc/fns.h +1 -1
@@ 18,7 18,7 @@ void delay(int);
int dmacount(int);
int dmadone(int);
void dmaend(int);
-void dmainit(void);
+void dmainit(int);
long dmasetup(int, void*, long, int);
#define evenaddr(x) /* x86 doesn't care */
void fpenv(FPsave*);
M pc/main.c => pc/main.c +0 -1
@@ 138,7 138,6 @@ main(void)
confinit();
archinit();
xinit();
- dmainit();
trapinit();
printinit();
if(isoldbcom)
M port/netif.c => port/netif.c +78 -14
@@ 9,7 9,8 @@
static int netown(Netfile*, char*, int);
static int openfile(Netif*, int);
static char* matchtoken(char*, char*);
-static void netmulti(Netif*, Netfile*, char*, int);
+static char* netmulti(Netif*, Netfile*, uchar*, int);
+static int parseaddr(uchar*, char*, int);
/*
* set up a new network interface
@@ 215,6 216,7 @@ netifwrite(Netif *nif, Chan *c, void *a, long n)
Netfile *f;
char *p;
char buf[256];
+ uchar binaddr[Nmaxaddr];
if(NETTYPE(c->qid.path) != Nctlqid)
error(Eperm);
@@ 224,6 226,11 @@ netifwrite(Netif *nif, Chan *c, void *a, long n)
memmove(buf, a, n);
buf[n] = 0;
+ if(waserror()){
+ qunlock(nif);
+ nexterror();
+ }
+
qlock(nif);
f = nif->f[NETID(c->qid.path)];
if((p = matchtoken(buf, "connect")) != 0){
@@ 236,11 243,20 @@ netifwrite(Netif *nif, Chan *c, void *a, long n)
if(nif->prom == 1 && nif->promiscuous != nil)
nif->promiscuous(nif->arg, 1);
} else if((p = matchtoken(buf, "addmulti")) != 0){
- netmulti(nif, f, p, 1);
+ if(parseaddr(binaddr, p, nif->alen) < 0)
+ error("bad address");
+ p = netmulti(nif, f, binaddr, 1);
+ if(p)
+ error(p);
} else if((p = matchtoken(buf, "remmulti")) != 0){
- netmulti(nif, f, p, 0);
+ if(parseaddr(binaddr, p, nif->alen) < 0)
+ error("bad address");
+ p = netmulti(nif, f, binaddr, 0);
+ if(p)
+ error(p);
}
qunlock(nif);
+ poperror();
return n;
}
@@ 461,26 477,71 @@ nhgets(void *p)
return (a[0]<<8)|(a[1]<<0);
}
+static ulong
+hash(uchar *a, int len)
+{
+ ulong sum = 0;
+
+ while(len-- > 0)
+ sum = (sum << 1) + *a++;
+ return sum%Nmhash;
+}
+
+int
+activemulti(Netif *nif, uchar *addr, int alen)
+{
+ Netaddr *hp;
+
+ for(hp = nif->mhash[hash(addr, alen)]; hp; hp = hp->hnext)
+ if(memcmp(addr, hp->addr, alen) == 0){
+ if(hp->ref)
+ return 1;
+ else
+ break;
+ }
+ return 0;
+}
+
+static int
+parseaddr(uchar *to, char *from, int alen)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < alen; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
/*
* keep track of multicast addresses
*/
-static void
-netmulti(Netif *nif, Netfile *f, char *addr, int add)
+static char*
+netmulti(Netif *nif, Netfile *f, uchar *addr, int add)
{
Netaddr **l, *ap;
int i;
- uchar hexaddr[Nmaxaddr];
+ ulong h;
if(nif->multicast == nil)
- return;
-
- if(strlen(addr) != 2*nif->alen)
- return;
+ return "interface does not support multicast";
l = &nif->maddr;
i = 0;
for(ap = *l; ap; ap = *l){
- if(strcmp(addr, ap->addr) == 0)
+ if(memcmp(addr, ap->addr, nif->alen) == 0)
break;
i++;
l = &ap->next;
@@ 489,10 550,12 @@ netmulti(Netif *nif, Netfile *f, char *addr, int add)
if(add){
if(ap == 0){
*l = ap = smalloc(sizeof(*ap));
- ap->addr = smalloc(strlen(addr)+1);
- strcpy(ap->addr, addr);
+ memmove(ap->addr, addr, nif->alen);
ap->next = 0;
ap->ref = 1;
+ h = hash(addr, nif->alen);
+ ap->hnext = nif->mhash[h];
+ nif->mhash[h] = ap;
} else {
ap->ref++;
}
@@ 507,7 570,7 @@ netmulti(Netif *nif, Netfile *f, char *addr, int add)
}
} else {
if(ap == 0 || ap->ref == 0)
- return;
+ return 0;
ap->ref--;
if(ap->ref == 0){
nif->nmaddr--;
@@ 519,4 582,5 @@ netmulti(Netif *nif, Netfile *f, char *addr, int add)
f->maddr[i/8] &= ~(1<<(i%8));
}
}
+ return 0;
}
M port/netif.h => port/netif.h +9 -5
@@ 6,6 6,7 @@ typedef struct Netif Netif;
enum
{
Nmaxaddr= 64,
+ Nmhash= 31,
Ncloneqid= 1,
N2ndqid,
@@ 48,8 49,9 @@ struct Netfile
*/
struct Netaddr
{
- Netaddr *next;
- char *addr;
+ Netaddr *next; /* allocation chain */
+ Netaddr *hnext;
+ uchar addr[Nmaxaddr];
int ref;
};
@@ 70,8 72,9 @@ struct Netif
int alen; /* address length */
uchar addr[Nmaxaddr];
uchar bcast[Nmaxaddr];
- Netaddr *maddr; /* multicast addresses */
- int nmaddr; /* number of multicast addresses */
+ Netaddr *maddr; /* known multicast addresses */
+ int nmaddr; /* number of known multicast addresses */
+ Netaddr *mhash[Nmhash]; /* hash table of multicast addresses */
int prom; /* number of promiscuous opens */
int all; /* number of -1 multiplexors */
@@ 89,7 92,7 @@ struct Netif
/* routines for touching the hardware */
void *arg;
void (*promiscuous)(void*, int);
- void (*multicast)(void*, char*, int);
+ void (*multicast)(void*, uchar*, int);
};
void netifinit(Netif*, char*, int, ulong);
@@ 101,6 104,7 @@ Block* netifbread(Netif*, Chan*, long, ulong);
long netifwrite(Netif*, Chan*, void*, long);
void netifwstat(Netif*, Chan*, char*);
void netifstat(Netif*, Chan*, char*);
+int activemulti(Netif*, uchar*, int);
/*
* Ethernet specific
M port/qio.c => port/qio.c +5 -0
@@ 586,6 586,11 @@ qpass(Queue *q, Block *b)
/* sync with qread */
dowakeup = 0;
ilock(q);
+ if(q->len >= q->limit){
+ freeb(b);
+ iunlock(q);
+ return -1;
+ }
/* add buffer to queue */
if(q->bfirst)