M carrera/clock.c => carrera/clock.c +1 -1
@@ 92,7 92,7 @@ clock(Ureg *ur)
return;
if(anyready())
- sched(); /**/
+ sched();
/* user profiling clock */
if(ur->status & KUSER)
M carrera/dat.h => carrera/dat.h +1 -1
@@ 146,7 146,7 @@ struct KMap
};
#define VA(k) ((k)->virt)
-#define PPN(x) ((x)>>6)
+#define PPN(x) ((ulong)(x)>>6)
struct Softtlb
{
M carrera/devether.c => carrera/devether.c +477 -290
@@ 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<<logNxmt,
- Tmask= Nxmt-1,
- logNrcv= 8,
- Nrcv= 1<<logNrcv,
- Rmask= Nrcv-1,
- Ntypes= 8,
-
- /* hold off values */
- ho800us= 0x100, /* 800 us hold-off */
- ho1500us= 0x080, /* 1500 us hold-off */
- ho2500us= 0x000, /* 2500 us hold-off */
-};
-
-#define RSUCC(i) (((i)+1)&Rmask)
-#define RPREV(i) (((i)-1)&Rmask)
-#define TSUCC(i) (((i)+1)&Tmask)
-#define TPREV(i) (((i)-1)&Tmask)
+ uchar pad0[2];
+ ushort status; /* receive status */
+ uchar pad1[2];
+ ushort count; /* packet byte count */
+ uchar pad2[2];
+ ushort ptr0; /* buffer pointer */
+ uchar pad3[2];
+ ushort ptr1;
+ uchar pad4[2];
+ ushort seqno; /* */
+ uchar pad5[2];
+ ushort link; /* descriptor link and EOL */
+ uchar pad6[2];
+ ushort owner; /* in use */
+} RXpkt;
/*
- * a hardware packet buffer
+ * Transmit Packet Descriptor.
*/
typedef struct
{
- uchar tlen[2]; /* transmit length */
- uchar d[Eaddrlen];
- uchar s[Eaddrlen];
- uchar type[2];
- uchar data[1500];
- uchar pad1[2043-ETHERMAXTU];
- uchar stat;
- uchar rlen[2]; /* receive length */
-} Pbuf;
+ uchar pad0[2];
+ ushort status; /* transmit status */
+ uchar pad1[2];
+ ushort config; /* */
+ uchar pad2[2];
+ ushort size; /* byte count of entire packet */
+ uchar pad3[2];
+ ushort count; /* fragment count */
+ uchar pad4[2];
+ ushort ptr0; /* packet pointer */
+ uchar pad5[2];
+ ushort ptr1;
+ uchar pad6[2];
+ ushort fsize; /* fragment size */
+ uchar pad7[2];
+ ushort link; /* descriptor link */
+} TXpkt;
+
+enum{
+ Eol = 1, /* end of list bit in descriptor link */
+ Host = 0, /* descriptor belongs to host */
+ Interface = -1, /* descriptor belongs to interface */
+
+ Nether = 1,
+ Ntypes= 8,
+};
+/*
+ * CAM Descriptor
+ */
+typedef struct {
+ uchar pad0[2];
+ ushort cep; /* CAM entry pointer */
+ uchar pad1[2];
+ ushort cap0; /* CAM address port 0 */
+ uchar pad2[2];
+ ushort cap1; /* CAM address port 1 */
+ uchar pad3[2];
+ ushort cap2; /* CAM address port 2 */
+ uchar pad4[2];
+ ushort ce; /* CAM enable */
+} Cam;
+
+typedef struct Ether Ether;
struct Ether
{
uchar ea[6];
+ uchar ba[6];
- int rindex; /* first rcv buffer owned by hardware */
- int rtop; /* first rcv buffer owned by software */
- int tindex; /* first rcv buffer owned by hardware */
- int ttop; /* first rcv buffer owned by software */
-
- Pbuf *tbuf; /* transmit buffers */
- Pbuf *rbuf; /* receive buffers */
+ Sonic *sonic; /* SONIC registers */
QLock tlock; /* lock for grabbing transmitter queue */
Rendez tr; /* wait here for free xmit buffer */
+ int th; /* first transmit buffer owned by host */
+ int ti; /* first transmit buffer owned by interface */
+
+ int rh; /* first receive buffer owned by host */
+ int ri; /* first receive buffer owned by interface */
+
+ RXrsc rra[Nrb]; /* receive resource area */
+ RXpkt rda[Nrb]; /* receive descriptor area */
+ uchar rb[Nrb][sizeof(Etherpkt)+4]; /* receive buffer area */
+ TXpkt tda[Ntb]; /* transmit descriptor area */
+ uchar tb[Ntb][sizeof(Etherpkt)]; /* transmit buffer area */
+ Cam cda; /* CAM descriptor area */
Netif;
-} ether;
+};
+Ether *ether[Nether];
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define LS16(addr) (PADDR(addr) & 0xFFFF)
+#define MS16(addr) ((PADDR(addr)>>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);
}
M carrera/faultmips.c => carrera/faultmips.c +1 -1
@@ 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;
M carrera/fns.h => carrera/fns.h +2 -3
@@ 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)
M carrera/io.h => carrera/io.h +16 -5
@@ 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
};
M carrera/l.s => carrera/l.s +24 -15
@@ 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
M carrera/main.c => carrera/main.c +22 -13
@@ 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;
M carrera/mem.h => carrera/mem.h +1 -0
@@ 109,6 109,7 @@
*/
#define PGSZ4K (0x00<<13)
+#define PGSZ64K (0x0F<<13)
#define PGSZ256K (0x3F<<13)
#define KUSEG 0x00000000
M carrera/mmu.c => carrera/mmu.c +5 -3
@@ 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
M carrera/trap.c => carrera/trap.c +57 -19
@@ 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;
M port/proc.c => port/proc.c +1 -0
@@ 145,6 145,7 @@ loop:
spllo();
while(runhiq.head == 0 && runloq.head == 0)
;
+
splhi();
lock(&runhiq);
M port/segment.c => port/segment.c +0 -2
@@ 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;