From 5bf63a04db2ab7bd233a9c949499b8a8604f8a42 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 4 Sep 1993 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1993-09-04 --- carrera/clock.c | 2 +- carrera/dat.h | 2 +- carrera/devether.c | 767 +++++++++++++++++++++++++++----------------- carrera/faultmips.c | 2 +- carrera/fns.h | 5 +- carrera/io.h | 21 +- carrera/l.s | 39 ++- carrera/main.c | 35 +- carrera/mem.h | 1 + carrera/mmu.c | 8 +- carrera/trap.c | 76 +++-- port/proc.c | 1 + port/segment.c | 2 - 13 files changed, 608 insertions(+), 353 deletions(-) diff --git a/carrera/clock.c b/carrera/clock.c index 75f819f3b7be344940f1accaf23f2c44e22a17f7..40393236aea0c974a79520e7b6252ac988f89949 100644 --- a/carrera/clock.c +++ b/carrera/clock.c @@ -92,7 +92,7 @@ clock(Ureg *ur) return; if(anyready()) - sched(); /**/ + sched(); /* user profiling clock */ if(ur->status & KUSER) diff --git a/carrera/dat.h b/carrera/dat.h index 4d627f608f9886b2602c6e60e0f0b69ee27b5e29..bdf9be35d3f482e1ac07b1b0840f3471307a3f26 100644 --- a/carrera/dat.h +++ b/carrera/dat.h @@ -146,7 +146,7 @@ struct KMap }; #define VA(k) ((k)->virt) -#define PPN(x) ((x)>>6) +#define PPN(x) ((ulong)(x)>>6) struct Softtlb { diff --git a/carrera/devether.c b/carrera/devether.c index c5b95c0b9c1ace99567808b2799a978c4230e236..f91c56e94cb03fc090419139f1eba804e067af0f 100644 --- a/carrera/devether.c +++ b/carrera/devether.c @@ -8,268 +8,479 @@ #include "../port/netif.h" /* - * ethernet address stored in prom + * National Semiconductor DP83932 + * Systems-Oriented Network Interface Controller + * (SONIC) */ + +#define SONICADDR ((Sonic*)Sonicbase) + +#define RD(rn) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4)) +#define WR(rn, v) (delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = v) + typedef struct { - ulong pad0; - ulong byte; - uvlong pad1; -} Etheraddr; -#define EPCENETPROM EPCSWIN(Etheraddr, 0x2000) + ulong cr; /* command */ + ulong dcr; /* data configuration */ + ulong rcr; /* receive control */ + ulong tcr; /* transmit control */ + ulong imr; /* interrupt mask */ + ulong isr; /* interrupt status */ + ulong utda; /* upper transmit descriptor address */ + ulong ctda; /* current transmit descriptor address */ + ulong pad0x08[5]; /* */ + ulong urda; /* upper receive descriptor address */ + ulong crda; /* current receive descriptor address */ + ulong pad0x0F[4]; /* */ + ulong eobc; /* end of buffer word count */ + ulong urra; /* upper receive resource address */ + ulong rsa; /* resource start address */ + ulong rea; /* resource end address */ + ulong rrp; /* resource read pointer */ + ulong rwp; /* resource write pointer */ + ulong pad0x19[8]; /* */ + ulong cep; /* CAM entry pointer */ + ulong cap2; /* CAM address port 2 */ + ulong cap1; /* CAM address port 1 */ + ulong cap0; /* CAM address port 0 */ + ulong ce; /* CAM enable */ + ulong cdp; /* CAM descriptor pointer */ + ulong cdc; /* CAM descriptor count */ + ulong sr; /* silicon revision */ + ulong wt0; /* watchdog timer 0 */ + ulong wt1; /* watchdog timer 1 */ + ulong rsc; /* receive sequence counter */ + ulong crct; /* CRC error tally */ + ulong faet; /* FAE tally */ + ulong mpt; /* missed packet tally */ + ulong mdt; /* maximum deferral timer */ + ulong pad0x30[15]; /* */ + ulong dcr2; /* data configuration 2 */ +} Sonic; + +enum +{ + Nrb = 16, /* receive buffers */ + Ntb = 8, /* transmit buffers */ +}; + +enum +{ + Htx = 0x0001, /* halt transmission */ + Txp = 0x0002, /* transmit packet(s) */ + Rxdis = 0x0004, /* receiver disable */ + Rxen = 0x0008, /* receiver enable */ + Stp = 0x0010, /* stop timer */ + St = 0x0020, /* start timer */ + Rst = 0x0080, /* software reset */ + Rrra = 0x0100, /* read RRA */ + Lcam = 0x0200, /* load CAM */ + + Dw32 = 0x0020, /* data width select */ + Sterm = 0x0400, /* synchronous termination */ + Lbr = 0x4000, /* latched bus retry */ + Efm = 0x0010, /* Empty fill mode */ + W14tf = 0x0003, /* 14 Word transmit fifo */ + + Prx = 0x0001, /* packet received ok */ + Fae = 0x0004, /* frame alignment error */ + Crc = 0x0008, /* CRC error */ + Lpkt = 0x0040, /* last packet in rba */ + Bc = 0x0080, /* broadcast packet received */ + Pro = 0x1000, /* physical promiscuous mode */ + Brd = 0x2000, /* accept broadcast packets */ + Rnt = 0x4000, /* accept runt packets */ + Err = 0x8000, /* accept packets with errors */ + + Ptx = 0x0001, /* packet transmitted ok */ + Pintr = 0x8000, /* programmable interrupt */ + + Rfo = 0x0001, /* receive fifo overrun */ + MpTally = 0x0002, /* missed packet tally counter rollover */ + FaeTally= 0x0004, /* frame alignment error tally counter rollover */ + CrcTally= 0x0008, /* Crc tally counter rollover */ + Rbae = 0x0010, /* receive buffer area exceeded */ + Rbe = 0x0020, /* receive buffer exhausted */ + Rde = 0x0040, /* receive descriptors exhausted */ + Txer = 0x0100, /* transmit error */ + Txdn = 0x0200, /* transmission done */ + Pktrx = 0x0400, /* packet received */ + Pint = 0x0800, /* programmed interrupt */ + Lcd = 0x1000, /* load CAM done */ + Hbl = 0x2000, /* CD heartbeat lost */ + Br = 0x4000, /* bus retry occurred */ + AllIntr = 0x7771, /* all of the above */ +}; /* - * SEEQ/EDLC device registers + * Receive Resource Descriptor. */ typedef struct { - struct - { - ulong pad; - ulong byte; - } addr[6]; /* address */ - - ulong pad; - ulong tcmd; /* transmit command */ - ulong pad0; - ulong rcmd; /* receive command */ - ulong pad1[5]; - ulong tbaselo; /* low bits of xmit buff base */ - ulong pad2; - ulong tbasehi; /* high bits of xmit buff base */ - ulong pad3; - ulong tlimit; /* xmit buffer limit */ - ulong pad4; - ulong tindex; /* xmit buffer limit */ - ulong pad5; - ulong ttop; /* xmit buffer top */ - ulong pad6; - ulong tbptr; /* xmit buffer byte pointer */ - ulong pad7; - ulong tstat; /* transmit status */ - ulong pad8; - ulong titimer; /* transmit interrupt timer */ - ulong pad9[5]; - ulong rbaselo; /* rcv buffer base addr */ - ulong pad10; - ulong rbasehi; /* high bits of rcv buffer base addr */ - ulong pad11; - ulong rlimit; /* rcv buffer limit */ - ulong pad12; - ulong rindex; /* rcv buffer index */ - ulong pad13; - ulong rtop; /* rcv buffer top */ - ulong pad14; - ulong rbptr; /* rcv buffer byte pointer */ - ulong pad15; - ulong rstat; /* rcv status */ - ulong pad16; - ulong ritimer; /* rcv interrupt timer */ -} EDLCdev; -#define EPCEDLC EPCSWIN(EDLCdev, 0xa200) + uchar pad0[2]; + ushort ptr0; /* buffer pointer in the RRA */ + uchar pad1[2]; + ushort ptr1; + uchar pad2[2]; + ushort wc0; /* buffer word count in the RRA */ + uchar pad3[2]; + ushort wc1; +} RXrsc; /* - * LXT901 device registers + * Receive Packet Descriptor. */ -typedef struct { - ulong pad0; - ulong stat; /* some LXT901 pins + SQE ctrl (r/w) */ - ulong pad1; - ulong collisions; /* total collisions -- 16 bits (r) */ - uchar pad2[7]; - uchar loopback; /* loopback enable -- 1 bit (w) */ - ulong pad3; - ulong edlcself; /* EDLC self rcv enable -- 1 bit (w) */ -} LXTdev; -#define EPCLXT EPCSWIN(LXTdev, 0x8000) - -enum +typedef struct { - /* transmit command bits */ - Tigood= 1<<3, /* interrupt on good xmit */ - Ti16tries= 1<<2, /* interrupt on 16 retries */ - Ticoll= 1<<1, /* interrupt on collision */ - Tiunder= 1<<0, /* interrupt on underflow */ - - /* receive command bits */ - Rmulti= 3<<6, /* recv station/broadcast/multicast */ - Rnormal= 2<<6, /* recv station/broadcast */ - Rall= 1<<6, /* receive all frames */ - Rigood= 1<<5, /* interrupt on good frames */ - Riend= 1<<4, /* interrupt on end of frame */ - Rishort= 1<<3, /* interrupt on short frame */ - Ridrbl= 1<<2, /* interrupt on dribble error */ - Ricrc= 1<<1, /* interrupt on CRC error */ - Riover= 1<<0, /* interrupt on overflow error */ - - Renab= (Rigood|Riend|Rishort|Ridrbl|Ricrc), - - /* receive status bits */ - Rgood= 1<<5, /* good frame */ - Rend= 1<<4, /* end of frame */ - Rshort= 1<<3, /* short frame */ - Rdrbl= 1<<2, /* dribble error */ - Rcrc= 1<<1, /* CRC error */ - Rover= 1<<0, /* overflow error */ - - /* interrupt level for ether */ - ILenet= 0x60, - - /* manifest constants */ - logNxmt= 8, - Nxmt= 1<>16) & 0xFFFF) -/* - * The dance in this code is very dangerous to change. Do not - * change the order of any of the labeled steps. This should run splhi. - */ static void -etherhardreset(void) +reset(Ether *ctlr) { - EDLCdev *edlc = EPCEDLC; - LXTdev *lxt = EPCLXT; - EPCmisc *misc = EPCMISC; - ulong x, i; - - /* step 1: isolate from ether */ - lxt->loopback = 1; - x = lxt->loopback; USED(x); - - /* step 2: shut off transmitter */ - while(edlc->ttop != edlc->tindex) - edlc->ttop = edlc->tindex; - ether.tindex = ether.ttop = edlc->ttop; - - /* step 3: reset edlc */ - misc->set = 0x200; - x = misc->reset; USED(x); - delay(1); /* 1ms but 10micros is enough */ - misc->clr = 0x200; - x = misc->reset; USED(x); - - /* step 4: enable transmitter interrupts */ - edlc->tcmd = Tigood | Ti16tries | Ticoll | Tiunder; - - /* step 5: set address from prom, start receiver, - * and reset receive pointer + int i; + +iprint("reset sonic dcr=#%lux mydcr=#%lux\n", RD(dcr), Sterm|Dw32|Lbr|Efm|W14tf); + /* + * Reset the SONIC, toggle the Rst bit. + * Set the data config register for synchronous termination + * and 32-bit data-path width. + * Clear the descriptor and buffer area. + */ + WR(cr, Rst); + WR(dcr, Sterm|Dw32|Lbr|Efm|W14tf); + WR(cr, 0); + + /* + * Initialise the receive resource area (RRA) and + * the receive descriptor area (RDA). + * + * We use a simple scheme of one packet per descriptor. + * We achieve this by setting the EOBC register to be + * 2 (16-bit words) less than the buffer size; + * thus the size of the receive buffers must be sizeof(Etherpkt)+4. + * Set up the receive descriptors as a ring. */ - for(i = 0; i < Netheraddr; i++) - edlc->addr[i].byte = EPCENETPROM[5-i].byte & 0xff; + for(i = 0; i < Nrb; i++){ + ctlr->rra[i].wc0 = (sizeof(ctlr->rb[0])/2) & 0xFFFF; + ctlr->rra[i].wc1 = ((sizeof(ctlr->rb[0])/2)>>16) & 0xFFFF; - if(ether.prom) - edlc->rcmd = Renab | Rall; - else - edlc->rcmd = Renab | Rnormal; + ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]); + ctlr->rda[i].owner = Interface; + + ctlr->rra[i].ptr0 = ctlr->rda[i].ptr0 = LS16(ctlr->rb[i]); + ctlr->rra[i].ptr1 = ctlr->rda[i].ptr1 = MS16(ctlr->rb[i]); + } + + /* + * Terminate the receive descriptor ring + * and load the SONIC registers to describe the RDA. + */ + ctlr->rda[Nrb-1].link |= Eol; + + WR(crda, LS16(ctlr->rda)); + WR(urda, MS16(ctlr->rda)); + WR(eobc, sizeof(ctlr->rb[0])/2 - 2); + + /* + * Load the SONIC registers to describe the RRA. + * We set the rwp to beyond the area delimited by rsa and + * rea. This means that since we've already allocated all + * the buffers, we'll never get a 'receive buffer area + * exhausted' interrupt and the rrp will just wrap round. + * Tell the SONIC to load the RRA and wait for + * it to complete. + */ + WR(urra, MS16(&ctlr->rra[0])); + WR(rsa, LS16(&ctlr->rra[0])); + WR(rrp, LS16(&ctlr->rra[0])); + WR(rea, LS16(&ctlr->rra[Nrb])); + WR(rwp, LS16(&ctlr->rra[Nrb+1])); + +iprint("wait rra\n"); + WR(cr, Rrra); + while(RD(cr) & Rrra) + ; +iprint("rra done\n"); + + /* + * Initialise the transmit descriptor area (TDA). + * Each descriptor describes one packet, we make no use + * of having the packet in multiple fragments. + * The descriptors are linked in a ring; overlapping transmission + * with buffer queueing will cause some packets to + * go out back-to-back. + * + * Load the SONIC registers to describe the TDA. + */ + for(i = 0; i < Ntb; i++){ + ctlr->tda[i].status = Host; + ctlr->tda[i].config = 0; + ctlr->tda[i].count = 1; + ctlr->tda[i].ptr0 = LS16(ctlr->tb[i]); + ctlr->tda[i].ptr1 = MS16(ctlr->tb[i]); + ctlr->tda[i].link = LS16(&ctlr->tda[NEXT(i, Ntb)]); + } - ether.rindex = edlc->rindex; - ether.rtop = edlc->rtop = RPREV(ether.rindex); + WR(ctda, LS16(&ctlr->tda[0])); + WR(utda, MS16(&ctlr->tda[0])); - /* step 6: attach to ether */ - lxt->loopback = 0; + /* + * Initialise the software receive and transmit + * ring indexes. + */ + ctlr->rh = 0; + ctlr->ri = 0; + ctlr->th = 0; + ctlr->ti = 0; + + /* + * Initialise the CAM descriptor area (CDA). + * We only have one ethernet address to load, + * broadcast is defined by the SONIC as all 1s. + * + * Load the SONIC registers to describe the CDA. + * Tell the SONIC to load the CDA and wait for it + * to complete. + */ + ctlr->cda.cep = 0; + ctlr->cda.cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; + ctlr->cda.cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; + ctlr->cda.cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; + ctlr->cda.ce = 1; + + WR(cdp, LS16(&ctlr->cda)); + WR(cdc, 1); + + WR(cr, Lcam); + while(RD(cr) & Lcam) + ; + + /* + * Configure the receive control, transmit control + * and interrupt-mask registers. + * The SONIC is now initialised, but not enabled. + */ + WR(rcr, Err|Rnt|Brd); + WR(tcr, 0); + WR(imr, AllIntr); +iprint("reset done\n"); } void etherintr(void) { - EDLCdev *edlc = EPCEDLC; - EPCmisc *misc = EPCMISC; - Netfile *f, **fp; - Pbuf *p; int x; ushort t; + Ether *ctlr; + ulong status; + TXpkt *txpkt; + RXpkt *rxpkt; + Etherpkt *p; + Netfile *f, **fp; + + ctlr = ether[0]; - while(edlc->rindex != ether.rindex){ - p = ðer.rbuf[ether.rindex]; - - /* statistics */ - if(p->stat & (Rshort|Rdrbl|Rcrc|Rover)){ - if(p->stat & (Rdrbl|Rcrc)) - ether.crcs++; - if(p->stat & Rover) - ether.overflows++; - if(p->stat & Rshort) - ether.frames++; + for(;;) { + status = RD(isr) & AllIntr; + if(status == 0) + break; + + WR(isr, status); + + /* + * Transmission complete, for good or bad. + */ + if(status & (Txdn|Txer)){ + txpkt = &ctlr->tda[ctlr->ti]; + while(txpkt->status != Host){ + if(txpkt->status == Interface){ + WR(ctda, LS16(txpkt)); + WR(cr, Txp); + break; + } + + if((txpkt->status & Ptx) == 0) + ctlr->oerrs++; + + txpkt->status = Host; + ctlr->ti = NEXT(ctlr->ti, Ntb); + txpkt = &ctlr->tda[ctlr->ti]; + } + status &= ~(Txdn|Txer); } - if(p->stat & Rgood){ - x = (p->rlen[0]<<8) | p->rlen[1]; - t = (p->type[0]<<8) | p->type[1]; - for(fp = ether.f; fp < ðer.f[Ntypes]; fp++){ - f = *fp; - if(f == 0) - continue; - if(f->type == t || f->type < 0) - qproduce(f->in, p->d, x); + + if((status & (Pktrx|Rde)) == 0) + goto noinput; + + /* + * A packet arrived or we ran out of descriptors. + */ + status &= ~(Pktrx|Rde); + rxpkt = &ctlr->rda[ctlr->rh]; + while(rxpkt->owner == Host){ + ctlr->inpackets++; + + /* + * If the packet was received OK, pass it up, + * otherwise log the error. + * SONIC gives us the CRC in the packet, so + * remember to subtract it from the length. + */ + + if(rxpkt->status & Prx) { + x = (rxpkt->count & 0xFFFF)-4; + p = (Etherpkt*)ctlr->rb[ctlr->rh]; + t = (p->type[0]<<8) | p->type[1]; + for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++){ + f = *fp; + if(f == 0) + continue; + if(f->type == t || f->type < 0) + qproduce(f->in, p->d, x); + } } + else + if(rxpkt->status & Fae) + ctlr->frames++; + else + if(rxpkt->status & Crc) + ctlr->crcs++; + else + ctlr->buffs++; + + /* + * Finished with this packet, it becomes the + * last free packet in the ring, so give it Eol, + * and take the Eol bit off the previous packet. + * Move the ring index on. + */ + rxpkt->link |= Eol; + rxpkt->owner = Interface; + ctlr->rda[PREV(ctlr->rh, Nrb)].link &= ~Eol; + ctlr->rh = NEXT(ctlr->rh, Nrb); + + rxpkt = &ctlr->rda[ctlr->rh]; } + status &= ~(Pktrx|Rde); + noinput: + /* + * We get a 'load CAM done' interrupt + * after initialisation. Ignore it. + */ + if(status & Lcd) + status &= ~Lcd; + /* - * because of a chip bug, we have to reset if rtop - * and rindex get too close. + * Warnings that something is afoot. */ - x = edlc->rtop - edlc->rindex; - if(x < 0) - x += Nrcv; - if(x <= 64){ - etherhardreset(); - } else { - edlc->rtop = ether.rindex; - ether.rindex = RSUCC(ether.rindex); + if(status & Hbl){ + print("sonic: cd heartbeat lost\n"); + status &= ~Hbl; } + if(status & Br){ + print("sonic: bus retry occurred\n"); + status &= ~Br; + } + + if(status & AllIntr) + print("sonic %ux\n", status); } - /* reenable holdoff and EPC interrupts */ - misc->clr = 0x10; - misc->set = 0x10; - epcenable(EIenet); } /* @@ -278,75 +489,45 @@ etherintr(void) static void promiscuous(void *arg, int on) { - EDLCdev *edlc = EPCEDLC; + ushort reg; USED(arg); + + reg = RD(rcr); if(on) - edlc->rcmd = Renab | Rall; + WR(rcr, reg|Pro); else - edlc->rcmd = Renab | Rnormal; + WR(rcr, reg&~Pro); } void etherreset(void) { - EDLCdev *edlc = EPCEDLC; - EPCmisc *misc = EPCMISC; - ulong x, i; - - /* setup xmit buffers (pointers on chip assume KSEG0) */ - edlc->tlimit = logNxmt - 1; - ether.tbuf = xspanalloc(Nxmt*sizeof(Pbuf), 512*1024, 0); - x = ((ulong)ether.tbuf) & ~KSEGM; - edlc->tbasehi = 0; - edlc->tbaselo = x; - - /* setup rcv buffers (pointers on chip assume KSEG0) */ - edlc->rlimit = logNrcv - 1; - ether.rbuf = xspanalloc(Nrcv*sizeof(Pbuf), 512*1024, 0); - x = ((ulong)ether.rbuf) & ~KSEGM; - edlc->rbasehi = 0; - edlc->rbaselo = x; - - /* install interrupt handler */ - sethandler(ILenet, etherintr); - setleveldest(ILenet, 0, &EPCINTR->enetdest); - epcenable(EIenet); - - /* turn off receive */ - edlc->rcmd = 0; - - /* stop transmitter, we can't change tindex so we change ttop */ - while(edlc->ttop != edlc->tindex) - edlc->ttop = edlc->tindex; - ether.tindex = ether.ttop = edlc->ttop; - - /* enable transmitter interrupts */ - edlc->tcmd = Tigood | Ti16tries | Ticoll | Tiunder; - - /* set address from prom, start receiver, and reset receive pointer */ - for(i = 0; i < Netheraddr; i++){ - ether.ea[i] = EPCENETPROM[5-i].byte & 0xff; - edlc->addr[i].byte = ether.ea[i]; + Ether *ctlr; + + /* + * Map the device registers and allocate + * memory for the receive/transmit rings. + * Set the physical ethernet address and + * prime the interrupt handler. + */ + if(ether[0] == 0) { + ether[0] = xspanalloc(sizeof(Ether), BY2PG, 64*1024); +/* memmove(ether[0]->ea, eeprom.ea, sizeof(ether[0]->ea)); */ } - ether.rindex = edlc->rindex; - ether.rtop = edlc->rtop = RPREV(ether.rindex); + ctlr = ether[0]; - edlc->rcmd = Renab | Rnormal; + reset(ctlr); - /* set hold off timer value, and enable its interrupts (pulse) */ - misc->set = ho800us; - misc->clr = (~ho800us)&0x180; - misc->clr = 0x10; - misc->set = 0x10; + memset(ctlr->ba, 0xFF, sizeof(ctlr->ba)); /* general network interface structure */ - netifinit(ðer, "ether", Ntypes, 32*1024); - ether.alen = 6; - memmove(ether.addr, ether.ea, 6); - memmove(ether.bcast, etherbcast, 6); - ether.promiscuous = promiscuous; - ether.arg = ðer; + netifinit(ether[0], "ether", Ntypes, 32*1024); + ether[0]->alen = 6; + memmove(ether[0]->addr, ether[0]->ea, 6); + memmove(ether[0]->bcast, ctlr->ba, 6); + ether[0]->promiscuous = promiscuous; + ether[0]->arg = ether[0]; } void @@ -369,13 +550,13 @@ etherclone(Chan *c, Chan *nc) int etherwalk(Chan *c, char *name) { - return netifwalk(ðer, c, name); + return netifwalk(ether[0], c, name); } Chan* etheropen(Chan *c, int omode) { - return netifopen(ðer, c, omode); + return netifopen(ether[0], c, omode); } void @@ -387,30 +568,29 @@ ethercreate(Chan *c, char *name, int omode, ulong perm) void etherclose(Chan *c) { - netifclose(ðer, c); + netifclose(ether[0], c); } long etherread(Chan *c, void *buf, long n, ulong offset) { - return netifread(ðer, c, buf, n, offset); + return netifread(ether[0], c, buf, n, offset); } static int isoutbuf(void *arg) { - EDLCdev *edlc = arg; + Ether *ctlr = arg; - USED(arg); - ether.tindex = edlc->tindex; - return TSUCC(ether.ttop) != ether.tindex; + return ctlr->tda[ctlr->th].status == Host; } long etherwrite(Chan *c, void *buf, long n, ulong offset) { - Pbuf *p; - EDLCdev *edlc = EPCEDLC; + Etherpkt *p; + TXpkt *txpkt; + Ether *ctlr = ether[0]; USED(offset); @@ -419,27 +599,34 @@ etherwrite(Chan *c, void *buf, long n, ulong offset) /* etherif.c handles structure */ if(NETTYPE(c->qid.path) != Ndataqid) - return netifwrite(ðer, c, buf, n); + return netifwrite(ether[0], c, buf, n); /* we handle data */ - qlock(ðer.tlock); - tsleep(ðer.tr, isoutbuf, edlc, 10000); - if(!isoutbuf(edlc)){ + qlock(&ctlr->tlock); + tsleep(&ctlr->tr, isoutbuf, ctlr, 10000); + if(!isoutbuf(ctlr)){ print("ether transmitter jammed\n"); - } else { - p = ðer.tbuf[ether.ttop]; + } + else { + p =(Etherpkt*)ctlr->tb[ctlr->th]; memmove(p->d, buf, n); if(n < 60) { memset(p->d+n, 0, 60-n); n = 60; } - memmove(p->s, ether.ea, sizeof(ether.ea)); - p->tlen[0] = n; - p->tlen[1] = n>>8; - ether.ttop = TSUCC(ether.ttop); - edlc->ttop = ether.ttop; + memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); + + txpkt = &ctlr->tda[ctlr->th]; + txpkt->size = n; + txpkt->fsize = n; + txpkt->link |= Eol; + txpkt->status = Interface; + ctlr->tda[PREV(ctlr->th, Ntb)].link &= ~Eol; + + ctlr->th = NEXT(ctlr->th, Ntb); + WR(cr, Txp); } - qunlock(ðer.tlock); + qunlock(&ctlr->tlock); return n; } @@ -452,11 +639,11 @@ etherremove(Chan *c) void etherstat(Chan *c, char *dp) { - netifstat(ðer, c, dp); + netifstat(ether[0], c, dp); } void etherwstat(Chan *c, char *dp) { - netifwstat(ðer, c, dp); + netifwstat(ether[0], c, dp); } diff --git a/carrera/faultmips.c b/carrera/faultmips.c index bea26573f6307fa1ef56befd0b2ec6cf8574d717..aad01303a48fac68b5645b3f7c2190382c89ccb5 100644 --- a/carrera/faultmips.c +++ b/carrera/faultmips.c @@ -122,7 +122,7 @@ faultmips(Ureg *ur, int user, int code) addr &= ~(BY2PG-1); read = !(code==CTLBM || code==CTLBS); -/* print("fault: %s code %d va %lux pc %lux r31 %lux %lux\n", up->text, code, ur->badvaddr, ur->pc, ur->r31, tlbvirt());/**/ + print("fault: %s code %d va %lux pc %lux r31 %lux %lux\n", up->text, code, ur->badvaddr, ur->pc, ur->r31, tlbvirt());/**/ if(fault(addr, read) == 0) return; diff --git a/carrera/fns.h b/carrera/fns.h index e32a5539c0d246279e28d20d3eb3a57c8653d71b..59591e56398d779c534d5f64d19a01db29b6948f 100644 --- a/carrera/fns.h +++ b/carrera/fns.h @@ -4,7 +4,6 @@ void DEBUG(void); void addportintr(int(*)(void)); void allflush(void*, ulong); -void audiointr(void); void arginit(void); int busprobe(ulong); void cleancache(void); @@ -19,7 +18,6 @@ void consoff(void); int consputc(int); void dcflush(void*, ulong); void dcinvalidate(void*, ulong); -void devportintr(void); void epcenable(ulong); void epcinit(int, int); void evenaddr(ulong); @@ -55,7 +53,6 @@ void kunmap(KMap*); void launchinit(void); void launch(int); void lightbits(int, int); -void lptintr(void); ulong machstatus(void); void mmunewpage(Page*); void mntdump(void); @@ -107,6 +104,8 @@ void Xdelay(int); void NS16552special(int, int, Queue**, Queue**, int (*)(Queue*, int)); void NS16552setup(ulong, ulong); +void NS16552intr(int); +void etherintr(void); #define waserror() setlabel(&up->errlab[up->nerrlab++]) #define kmapperm(x) kmap(x) diff --git a/carrera/io.h b/carrera/io.h index 82e29d92270b303f646d6b84249558ae614dd80e..e127c8e5bb4c0176b5f849b8a1b8ad8aa1c6ba80 100644 --- a/carrera/io.h +++ b/carrera/io.h @@ -9,7 +9,7 @@ enum Clockbase = 0xE0004000, Uart0 = 0xE0006000, Uart1 = 0xE0007000, - UartFREQ = 4233600, + UartFREQ = 8000000, Centronics = 0xE0008000, Nvram = 0xE0009000, NvramRW = 0xE000A000, @@ -21,8 +21,19 @@ enum Diag = 0xE000F000, VideoCTL = 0x60000000, VideoMEM = 0x40000000, - EisaIO = 0xE2000000, - EisaMEM = 0xE3000000, - PromMEM = 0xE1000000, - Intctl = 0xE0100000, + I386ack = 0xE000023f, + Intctlphys = 0xF0000000, + Intctlvirt = 0xE0040000, + Uart1int = (1<<9), + Uart0int = (1<<8), + Mouseint = (1<<7), + Keybint = (1<<6), + Scsiint = (1<<5), + Etherint = (1<<4), + Videoint = (1<<3), + Soundint = (1<<2), + Floppyint = (1<<1), + Parallelint = (1<<0), + Intenareg = 0xE0040004, + Intcause = 0xE0040007 }; diff --git a/carrera/l.s b/carrera/l.s index a106d2be30b6f43d25981c5fbad033d3a020596c..0a2cee128d705c3b17242c461a7af0a2811cfe35 100644 --- a/carrera/l.s +++ b/carrera/l.s @@ -417,7 +417,7 @@ wasuser: MOVW $setR30(SB), R30 CONST (MACHADDR, R1) - ADDU R1, R(MACH) /* R(MACH) = m-> */ + MOVW R1, R(MACH) /* R(MACH) = m-> */ MOVW 8(R(MACH)), R(USER) /* up = m->proc */ MOVW 4(SP), R1 /* first arg for syscall/trap */ BNE R26, notsys @@ -744,17 +744,23 @@ TEXT icflush(SB), $-4 /* icflush(virtaddr, count) */ MOVW 4(FP), R9 MOVW $0, M(STATUS) WAIT + ADDU R1, R9 /* R9 = last address */ + MOVW $(~0x3f), R8 + AND R1, R8 /* R8 = first address, rounded down */ + ADD $0x3f, R9 + AND $(~0x3f), R9 /* round last address up */ + SUB R8, R9 /* R9 = revised count */ icflush1: /* primary cache line size is 16 bytes */ - /* - * Due to a challenge bug PD+HWB DOES NOT WORK - philw - */ - WAIT - WAIT - CACHE SD+HWBI, (R1) - WAIT - WAIT - SUBU $128, R9 - ADDU $128, R1 + CACHE PD+HWB, 0x00(R8) + CACHE PI+HI, 0x00(R8) + CACHE PD+HWB, 0x10(R8) + CACHE PI+HI, 0x10(R8) + CACHE PD+HWB, 0x20(R8) + CACHE PI+HI, 0x20(R8) + CACHE PD+HWB, 0x30(R8) + CACHE PI+HI, 0x30(R8) + SUB $0x40, R9 + ADD $0x40, R8 BGTZ R9, icflush1 MOVW R10, M(STATUS) WAIT @@ -782,11 +788,14 @@ TEXT cleancache(SB), $-4 WAIT MOVW $0, M(STATUS) WAIT - MOVW $(4*1024*1024), R9 + MOVW $(32*1024), R9 ccache: - CACHE SD+IWBI, 0x00(R1) - SUBU $128, R9 - ADDU $128, R1 + CACHE PD+IWBI, 0x00(R1) + WAIT + CACHE PI+IWBI, 0x00(R1) + WAIT + SUBU $16, R9 + ADDU $16, R1 BGTZ R9, ccache MOVW R10, M(STATUS) WAIT diff --git a/carrera/main.c b/carrera/main.c index f6bc43dac17abf121b971719d6ad0287dac505e7..b6849bbec7af1b4402fd52f2ab74d172ea7e07d8 100644 --- a/carrera/main.c +++ b/carrera/main.c @@ -34,7 +34,6 @@ FPsave initfp; void main(void) { - *(uchar*)(Uart0) = '*'; tlbinit(); /* Very early to establish IO mappings */ ioinit(); arginit(); @@ -46,8 +45,10 @@ main(void) kmapinit(); xinit(); printinit(); - NS16552setup(Uart0, UartFREQ); + + NS16552setup(Uart1, UartFREQ); NS16552special(0, 9600, &kbdq, &printq, kbdcr2nl); + vecinit(); iprint("\n\nBrazil\n"); pageinit(); @@ -60,7 +61,6 @@ main(void) schedinit(); } - /* * copy arguments passed by the boot kernel (or ROM) into a temporary buffer. * we do this because the arguments are in memory that may be allocated @@ -72,7 +72,8 @@ struct { char *name; char *val; -}bootenv[] = { +}bootenv[] = +{ {"netaddr=", sysname}, {"console=", consname}, {"bootdisk=", bootdisk}, @@ -141,6 +142,7 @@ machinit(void) n = m->machno; m->stb = &stlb[n][0]; + clockinit(); } @@ -152,9 +154,19 @@ ioinit(void) { ulong phys; + /* + * Map devices + */ phys = PPN(Devicephys)|PTEGLOBL|PTEVALID|PTEWRITE|PTEUNCACHED; + puttlbx(1, Devicevirt, phys, PTEGLOBL, PGSZ64K); - puttlbx(1, Devicevirt, phys, PTEGLOBL, PGSZ256K); + /* + * Map Interrupt control + */ + phys = PPN(Intctlphys)|PTEGLOBL|PTEVALID|PTEWRITE|PTEUNCACHED; + puttlbx(2, Intctlvirt, phys, PTEGLOBL, PGSZ4K); + + *(ushort*)Intenareg = 0xffff; } /* @@ -166,7 +178,8 @@ vecinit(void) memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x100); memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80); memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80); - icflush((ulong*)UTLBMISS, 32*1024); + + icflush((ulong*)UTLBMISS, 8*1024); } void @@ -263,12 +276,8 @@ exit(long type) spllo(); print("cpu %d exiting %d\n", m->machno, type); - timer = 0; - while(active.machs || consactive()) { - if(timer++ > 400) - break; + while(consactive()) delay(10); - } splhi(); for(;;) ; @@ -296,7 +305,7 @@ confinit(void) conf.npage1 = 0; conf.base1 = 0; - conf.upages = (conf.npage*90)/100; + conf.upages = (conf.npage*70)/100; if(top - conf.upages > (256*1024*1024)/BY2PG) conf.upages = top - (256*1024*1024)/BY2PG; @@ -304,7 +313,7 @@ confinit(void) /* set up other configuration parameters */ conf.nproc = 100; - conf.nswap = 262144; + conf.nswap = conf.npage*3; conf.nimage = 200; conf.ipif = 8; conf.ip = 64; diff --git a/carrera/mem.h b/carrera/mem.h index be1c5adb1deca8c708d38f2fa16296df5dd7c5f0..6d5373871b819d930d848e0d6349af08c003ebb6 100644 --- a/carrera/mem.h +++ b/carrera/mem.h @@ -109,6 +109,7 @@ */ #define PGSZ4K (0x00<<13) +#define PGSZ64K (0x0F<<13) #define PGSZ256K (0x3F<<13) #define KUSEG 0x00000000 diff --git a/carrera/mmu.c b/carrera/mmu.c index 31dd3307c19f8f6fa7d477f2b6b43d5799109b87..fc4c441fc3856a3135bf4e455e9f20c764ff3e73 100644 --- a/carrera/mmu.c +++ b/carrera/mmu.c @@ -52,6 +52,8 @@ kmapinit(void) k->next = k+1; k->next = 0; unlock(&kmaplock); + + m->ktlbnext = TLBROFF; } /* @@ -107,7 +109,7 @@ kmap(Page *pg) puttlbx(x, (virt & ~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K); m->ktlbx[x] = 1; if(++x >= NTLB) - m->ktlbnext = 1; + m->ktlbnext = TLBROFF; else m->ktlbnext = x; @@ -164,7 +166,7 @@ kfault(ulong addr) puttlbx(x, (k->virt & ~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K); m->ktlbx[x] = 1; if(++x >= NTLB) - m->ktlbnext = 1; + m->ktlbnext = TLBROFF; else m->ktlbnext = x; } @@ -196,7 +198,7 @@ kmapinval() kunmap(k); } m->kactive = 0; - m->ktlbnext = 1; + m->ktlbnext = TLBROFF; } void diff --git a/carrera/trap.c b/carrera/trap.c index 70eed48939cc2d92f93751508fe3d591d002d35d..aa3303211e209049125cda59ec47375db0e9b32e 100644 --- a/carrera/trap.c +++ b/carrera/trap.c @@ -278,12 +278,46 @@ trap(Ureg *ur) void intr(Ureg *ur) { + uchar devint; ulong cause = ur->cause; m->intr++; cause &= INTR7|INTR6|INTR5|INTR4|INTR3|INTR2|INTR1|INTR0; - iprint("intr %lux\n", cause); + if(cause & INTR3) { + devint = *(uchar*)Intcause; + switch(devint) { + default: + panic("unknown devint=#%lux", devint); + + case 0x28: /* Serial 1 */ + NS16552intr(0); + break; + case 0x24: /* Serial 2 */ + NS16552intr(1); + break; + case 0x14: + etherintr(); + break; + } + cause &= ~INTR3; + } + + if(cause & INTR4) { + devint = *(uchar*)I386ack; + iprint("i386ack=#%lux\n", devint); + cause &= ~INTR4; + } + + if(cause & INTR7) { + clock(ur); + cause &= ~INTR7; + } + + if(cause) { + iprint("cause %lux\n", cause); + exit(1); + } } char* @@ -512,27 +546,31 @@ syscall(Ureg *aur) up->nerrlab = 0; sp = ur->sp; ret = -1; - if(!waserror()) { - if(up->scallnr >= sizeof systab/sizeof systab[0]){ - pprint("bad sys call number %d pc %lux\n", up->scallnr, ur->pc); - postnote(up, 1, "sys: bad sys call", NDebug); - error(Ebadarg); - } - - if(sp & (BY2WD-1)){ - pprint("odd sp in sys call pc %lux sp %lux\n", ur->pc, ur->sp); - postnote(up, 1, "sys: odd stack", NDebug); - error(Ebadarg); - } + if(waserror()) + goto error; - if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs))) - validaddr(sp, sizeof(Sargs), 0); + if(up->scallnr >= sizeof systab/sizeof systab[0]){ + pprint("bad sys call %d pc %lux\n", up->scallnr, ur->pc); + postnote(up, 1, "sys: bad sys call", NDebug); + error(Ebadarg); + } - up->s = *((Sargs*)(sp+BY2WD)); - up->psstate = sysctab[up->scallnr]; - ret = (*systab[up->scallnr])(up->s.args); - poperror(); + if(sp & (BY2WD-1)){ + pprint("odd sp in sys call pc %lux sp %lux\n", ur->pc, ur->sp); + postnote(up, 1, "sys: odd stack", NDebug); + error(Ebadarg); } + + if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs))) + validaddr(sp, sizeof(Sargs), 0); + + up->s = *((Sargs*)(sp+BY2WD)); + up->psstate = sysctab[up->scallnr]; + + ret = (*systab[up->scallnr])(up->s.args); + poperror(); + +error: ur->pc += 4; up->nerrlab = 0; up->psstate = 0; diff --git a/port/proc.c b/port/proc.c index 233bb269eb51524f959ab069686f3257792c03fa..5938e8902c6185546b4b5f268d26270555ed6360 100644 --- a/port/proc.c +++ b/port/proc.c @@ -145,6 +145,7 @@ loop: spllo(); while(runhiq.head == 0 && runloq.head == 0) ; + splhi(); lock(&runhiq); diff --git a/port/segment.c b/port/segment.c index 21e1a9449fcb1aa53cbead6fb38e7d59132c9bf6..d39ae9735558fb7fb03cce1256986bfebb227178 100644 --- a/port/segment.c +++ b/port/segment.c @@ -476,8 +476,6 @@ syssegflush(ulong *arg) j = (soff&(PTEMAPMEM-1))/BY2PG; len = arg[1]+BY2PG; -print("%s segflush 0x%lux %d\n", up->text, arg[0], arg[1]); - for(i = soff/PTEMAPMEM; len > 0 && i < SEGMAPSIZE; i++) { if(s->map[i] == 0) { len -= PTEMAPMEM;