M pc/devfloppy.c => pc/devfloppy.c +4 -0
@@ 455,6 455,10 @@ floppywrite(Chan *c, void *a, long n)
} else if(SNCMP(aa, "reset") == 0){
fl.confused = 1;
floppyon(dp);
+ } else if(SNCMP(aa, "fast") == 0){
+ cpuspeed(1);
+ } else if(SNCMP(aa, "slow") == 0){
+ cpuspeed(0);
}
qunlock(&fl);
break;
M pc/fns.h => pc/fns.h +2 -0
@@ 5,6 5,7 @@ void meminit(void);
void clock(Ureg*);
void clockinit(void);
void config(int);
+int cpuspeed(int);
void delay(int);
void dmaend(int);
long dmasetup(int, void*, long, int);
@@ 29,6 30,7 @@ void mmuinit(void);
int modem(int);
void outb(int, int);
void outss(int, void*, int);
+int pmuwrbit(int, int, int);
void prhex(ulong);
void procrestore(Proc*, uchar*);
void procsave(uchar*, int);
M pc/main.c => pc/main.c +11 -0
@@ 476,6 476,17 @@ modem(int onoff)
return pmuwrbit(1, 1^onoff, 5);
}
+/*
+ * CPU speed
+ * onoff == 0 means 2 MHZ
+ * onoff == 1 means 20 MHZ
+ */
+int
+cpuspeed(int speed)
+{
+ return pmuwrbit(0, speed, 0);
+}
+
void
buzz(int f, int d)
{
M port/devarp.c => port/devarp.c +75 -128
@@ 9,36 9,42 @@
#include "devtab.h"
+#define ARP_FREE 0
+#define ARP_OK 1
+#define ARP_ASKED 2
+#define ARP_TEMP 0
+#define ARP_PERM 1
+#define Arphashsize 32
+#define ARPHASH(p) arphash[((p[2]^p[3])%Arphashsize)]
+
+typedef struct Arpcache Arpcache;
+struct Arpcache {
+ uchar status;
+ uchar type;
+ uchar eip[4];
+ uchar et[6];
+ Arpcache *hash;
+ Arpcache **hashhd;
+ Arpcache *frwd;
+ Arpcache *prev;
+};
+
Arpstats arpstats;
Arpcache *arplruhead, *arplrutail;
Arpcache *arp, **arphash;
Queue *Servq;
+Lock larphash;
+
+void arpiput(Queue *, Block *);
+void arpoput(Queue *, Block *);
+void arpopn(Queue *, Stream *);
+void arpcls(Queue *);
+void arpenter(Arpentry*, int);
+void arpflush(void);
+int arpdelete(char*);
+void arplinkhead(Arpcache*);
+int arplookup(uchar*, uchar*);
-typedef struct Arpq Arpq;
-struct Arpq
-{
- uchar ip[4];
- uchar *etheraddr;
- Block *bp;
- Queue *put;
- ulong time;
- Arpq *next;
-};
-
-struct arpalloc
-{
- Lock;
- Lock list;
- Lock hash;
- Arpq *free;
- Arpq *head;
- Arpq *tail;
-}arpalloc;
-
-void arpiput(Queue *, Block *);
-void arpoput(Queue *, Block *);
-void arpopn(Queue *, Stream *);
-void arpcls(Queue *);
Qinfo arpinfo = { arpiput, arpoput, arpopn, arpcls, "arp" };
#define ARP_ENTRYLEN 50
@@ 253,8 259,6 @@ arpwrite(Chan *c, char *a, long n, ulong offset)
void
arpopn(Queue *q, Stream *s)
{
- if(!Servq)
- Servq = RD(q);
}
void
@@ 273,7 277,40 @@ arpiput(Queue *q, Block *bp)
void
arpoput(Queue *q, Block *bp)
{
- PUTNEXT(q, bp);
+ uchar ip[4];
+ Etherhdr *eh;
+
+ if(bp->type != M_DATA) {
+ if(Servq == 0 && streamparse("arpd", bp)) {
+print("setting arp channel\n");
+ Servq = RD(q);
+ freeb(bp);
+ }
+ else
+ PUTNEXT(q, bp);
+ return;
+ }
+
+ if(!Servq) {
+ print("arp: No server, packet dropped\n");
+ freeb(bp);
+ return;
+ }
+
+ eh = (Etherhdr *)bp->rptr;
+ iproute(eh->dst, ip);
+
+ /* Send downstream to the ethernet */
+ if(arplookup(ip, eh->d)) {
+print("arp hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+ PUTNEXT(q, bp);
+ return;
+ }
+print("arp miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+
+ /* Return the packet to the arp server for address resolution */
+ memmove(eh->d, ip, sizeof(ip));
+ PUTNEXT(Servq, bp);
}
int
@@ 281,77 318,19 @@ arplookup(uchar *ip, uchar *et)
{
Arpcache *ap;
- lock(&arpalloc.hash);
+ lock(&larphash);
for(ap = ARPHASH(ip); ap; ap = ap->hash) {
if(ap->status == ARP_OK && memcmp(ap->eip, ip, sizeof(ap->eip)) == 0) {
memmove(et, ap->et, sizeof(ap->et));
arplinkhead(ap);
- unlock(&arpalloc.hash);
+ unlock(&larphash);
arpstats.hit++;
return 1;
}
}
- unlock(&arpalloc.hash);
- return 0;
-}
-
-void
-arpsendpkt(uchar *unroutedip, uchar *ether, Queue *put, Block *bp)
-{
- Arpq *aq;
- Block *nbp;
- uchar ip[4];
-
- if(!Servq) {
- print("arp: No server\n");
- freeb(bp);
- return;
- }
-
- iproute(unroutedip, ip);
- if(arplookup(ip, ether)) {
-print("hit %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
- PUTNEXT(put, bp);
- return;
- }
-print("miss %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
-
- /* Send the request out to the user level arp daemon */
- nbp = allocb(sizeof(ip));
- memmove(nbp->rptr, ip, sizeof(ip));
- nbp->wptr += sizeof(ip);
- nbp->flags |= S_DELIM;
- PUTNEXT(Servq, nbp);
arpstats.miss++;
-
- lock(&arpalloc);
- if(aq = arpalloc.free)
- arpalloc.free = aq->next;
- unlock(&arpalloc);
-
- if(aq == 0) {
- freeb(bp);
- return;
- }
-
- /* Stash the work away until the arp completes or times out */
- memmove(aq->ip, ip, sizeof(aq->ip));
- aq->etheraddr = ether;
- aq->bp = bp;
- aq->put = put;
- aq->time = MACHP(0)->ticks;
-
- lock(&arpalloc.list);
- if(arpalloc.head) {
- arpalloc.tail->next = aq;
- arpalloc.tail = aq;
- }
- else {
- arpalloc.tail = aq;
- arpalloc.head = aq;
- }
- aq->next = 0;
- unlock(&arpalloc.list);
+ unlock(&larphash);
+ return 0;
}
void
@@ 371,7 350,7 @@ arpenter(Arpentry *ape, int type)
/* Update an entry if we have one already */
l = &ARPHASH(ape->ipaddr);
- lock(&arpalloc.hash);
+ lock(&larphash);
for(ap = *l; ap; ap = ap->hash) {
if(ap->status == ARP_OK && memcmp(ap->eip, ape->ipaddr, sizeof(ap->eip)) == 0) {
if(ap->type != ARP_PERM) {
@@ 379,7 358,7 @@ arpenter(Arpentry *ape, int type)
memmove(ap->et, ape->etaddr, sizeof(ap->et));
ap->status = ARP_OK;
}
- unlock(&arpalloc.hash);
+ unlock(&larphash);
return;
}
}
@@ 390,7 369,7 @@ arpenter(Arpentry *ape, int type)
if(!ap) {
print("arp: too many permanent entries\n");
- unlock(&arpalloc.hash);
+ unlock(&larphash);
return;
}
@@ 408,43 387,11 @@ arpenter(Arpentry *ape, int type)
ap->status = ARP_OK;
memmove(ap->eip, ape->ipaddr, sizeof(ape->ipaddr));
memmove(ap->et, ape->etaddr, sizeof(ape->etaddr));
- ap->ip = nhgetl(ap->eip);
ap->hashhd = l;
ap->hash = *l;
*l = ap;
arplinkhead(ap);
- unlock(&arpalloc.hash);
- pusharpq();
-}
-
-void
-pusharpq(void)
-{
- int sent;
- Arpq *aq, *prev;
-
-loop: prev = 0;
- lock(&arpalloc.list);
- for(aq = arpalloc.head; aq; aq = aq->next) {
- if(arplookup(aq->ip, aq->etheraddr)) {
- if(prev)
- prev->next = aq->next;
- else
- arpalloc.head = 0;
- if(aq->next == 0)
- arpalloc.tail = prev;
- unlock(&arpalloc.list);
- PUTNEXT(aq->put, aq->bp);
-
- lock(&arpalloc);
- aq->next = arpalloc.free;
- arpalloc.free = aq;
- unlock(&arpalloc);
- goto loop;
- }
- prev = aq;
- }
- unlock(&arpalloc.list);
+ unlock(&larphash);
}
int
@@ 464,14 411,14 @@ arpdelete(char *addr)
ptr = strchr(ptr, ':')+1;
}
- lock(&arpalloc.hash);
+ lock(&larphash);
for(ap = arplruhead; ap; ap = ap->frwd) {
if(memcmp(ap->et, ptr, sizeof(ap->et)) == 0) {
ap->status = ARP_FREE;
break;
}
}
- unlock(&arpalloc.hash);
+ unlock(&larphash);
}
void
M port/devip.c => port/devip.c +5 -2
@@ 176,14 176,14 @@ ipopen(Chan *c, int omode)
error(Ebadarg);
break;
case iplistenqid:
- if(cp->stproto != &tcpinfo &&
- cp->stproto != &ilinfo)
+ if(cp->stproto != &tcpinfo && cp->stproto != &ilinfo)
error(Eprotonosup);
if(cp->backlog == 0)
cp->backlog = 3;
streamopen(c, &ipinfo);
+
if(c->stream->devq->next->info != cp->stproto)
pushq(c->stream, cp->stproto);
@@ 196,6 196,7 @@ ipopen(Chan *c, int omode)
break;
case Sdataqid:
streamopen(c, &ipinfo);
+
if(c->stream->devq->next->info != cp->stproto)
pushq(c->stream, cp->stproto);
@@ 207,6 208,7 @@ ipopen(Chan *c, int omode)
break;
case Sctlqid:
streamopen(c, &ipinfo);
+
if(c->stream->devq->next->info != cp->stproto)
pushq(c->stream, cp->stproto);
break;
@@ 697,6 699,7 @@ print("listen awoke\n");
new->newcon = 0;
c->qid.path = CHDIR|STREAMQID(new-base, ipchanqid);
devwalk(c, "ctl", 0, 0, streamgen);
+
streamopen(c, &ipinfo);
pushq(c->stream, new->stproto);
new->ref--;
M port/ipdat.h => port/ipdat.h +1 -6
@@ 429,11 429,6 @@ Block *btrim(Block*, int, int);
Block *ip_reassemble(int, Block*, Etherhdr*);
Ipconv *portused(Ipconv *, Port);
Port nextport(Ipconv *, Port);
-void arpenter(Arpentry*, int);
-void arpflush(void);
-int arpdelete(char*);
-void pusharpq(void);
-void arplinkhead(Arpcache*);
Fragq *ipfragallo(void);
void ipfragfree(Fragq*);
void iproute(uchar*, uchar*);
@@ 486,7 481,6 @@ void tcp_acktimer(void *);
Ipconv *ipclonecon(Chan *);
void iplisten(Chan *, Ipconv *, Ipconv *);
void iloutoforder(Ipconv*, Ilhdr*, Block*);
-void arpsendpkt(uchar*, uchar*, Queue*, Block*);
#define fmtaddr(xx) (xx>>24)&0xff,(xx>>16)&0xff,(xx>>8)&0xff,xx&0xff
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ 508,4 502,5 @@ extern Qinfo tcpinfo;
extern Qinfo ipinfo;
extern Qinfo udpinfo;
extern Qinfo ilinfo;
+extern Qinfo arpinfo;
extern Queue *Ipoutput;
M port/stip.c => port/stip.c +3 -4
@@ 198,9 198,9 @@ ipetheroput(Queue *q, Block *bp)
eh->cksum[1] = 0;
hnputs(eh->cksum, ip_csum(&eh->vihl));
- /* Finally put in the ethernet level information */
+ /* Finally put in the type and pass down to the arp layer */
hnputs(eh->type, ET_IP);
- arpsendpkt(eh->dst, eh->d, Etherq, bp);
+ PUTNEXT(Etherq, bp);
return;
}
@@ 263,9 263,8 @@ ipetheroput(Queue *q, Block *bp)
feh->cksum[1] = 0;
hnputs(feh->cksum, ip_csum(&feh->vihl));
nb->flags |= S_DELIM;
- arpsendpkt(feh->dst, feh->d, Etherq, nb);
+ PUTNEXT(Etherq, nb);
}
-
drop:
freeb(bp);
}