2 #include "../port/lib.h"
7 #include "../port/error.h"
8 #include "../port/netif.h"
9 #include "../port/etherif.h"
14 Etcr = Saturn + 0x0c00,
15 Etsr = Saturn + 0x0c02,
16 Ercr = Saturn + 0x0c04,
17 Ersr = Saturn + 0x0c06,
18 Eisr = Saturn + 0x0d04,
19 Eimr = Saturn + 0x0d06,
20 Emacaddr0 = Saturn + 0x0e02,
21 Miicr = Saturn + 0x0f02,
22 Miiwdr = Saturn + 0x0f04,
23 Miirdr = Saturn + 0x0f06,
25 Ethermem = 0xf2c00000,
28 Ntx = 2, // Nrx + Ntx must be 16
31 Ersr_rxevent = RBIT(0, ushort),
33 Ercr_rxenab = RBIT(0, ushort),
34 Ercr_auienab = RBIT(2, ushort),
35 Etcr_txstart = RBIT(1, ushort),
36 Etcr_retries = 0xf<<8,
37 Ei_txecall = RBIT(0, ushort),
38 Ei_txretry = RBIT(2, ushort),
39 Ei_txdefer = RBIT(3, ushort),
40 Ei_txcrs = RBIT(4, ushort),
41 Ei_txdone = RBIT(5, ushort),
42 Ei_rxcrcerr = RBIT(8, ushort),
43 Ei_rxdrib = RBIT(9, ushort),
44 Ei_rxdone = RBIT(10, ushort),
45 Ei_rxshort = RBIT(11, ushort),
46 Ei_rxlong = RBIT(12, ushort),
49 Miicr_read = RBIT(10, ushort),
50 Miicr_preambledis = RBIT(12, ushort),
51 Miicr_accack = RBIT(14, ushort),
52 Miicr_accbsy = RBIT(15, ushort),
60 int ntx; /* number of entries in transmit ring */
64 ulong interrupts; /* statistics */
68 static ushort*etcr=(ushort*)Etcr;
69 static ushort*etsr=(ushort*)Etsr;
70 static ushort*ercr=(ushort*)Ercr;
71 static ushort*ersr=(ushort*)Ersr;
72 static ushort*eimr=(ushort*)Eimr;
73 static ushort*eisr=(ushort*)Eisr;
74 static ushort*miicr=(ushort*)Miicr;
75 static ushort*miirdr=(ushort*)Miirdr;
78 txfill(Ether*ether, Ctlr*ctlr)
85 if((b=qget(ether->oq)) == nil)
89 dst = (ushort*)(Ethermem+(ctlr->txempty+Nrx)*Etherfsize);
91 memmove(&dst[1], b->rp, len);
94 if(ctlr->txempty==Ntx)
103 if(ctlr->ntx==0 || ctlr->txbusy)
106 *etcr = Etcr_txstart|Etcr_retries|(ctlr->txfull+Nrx);
109 static void interrupt(Ureg*, void*);
112 transmit(Ether*ether)
125 interrupt(Ureg*, void*arg)
136 return; /* not ours */
145 iprint("interrupt: no interrupt source?\n");
148 if((*etcr&Etcr_txstart)==0){
153 if(ctlr->txfull==Ntx)
161 iprint("interrupt: bogus tx interrupt\n");
166 rx=*ersr&Ersr_rxfpmask;
167 while(ctlr->rxlast!=rx){
170 if(ctlr->rxlast >= Nrx)
173 pkt = (Etherpkt*)(Ethermem+ctlr->rxlast*Etherfsize);
175 if((b = iallocb(len+sizeof(ushort))) != nil){
176 memmove(b->wp, pkt, len+sizeof(ushort));
177 b->rp += sizeof(ushort);
182 rx=*ersr&Ersr_rxfpmask;
188 iprint("ethersaturn: txretry!\n");
196 iprint("interrupt: unhandled interrupts %.4uX\n", ie);
206 ctlr = malloc(sizeof(*ctlr));
207 memset(ctlr, 0, sizeof(*ctlr));
211 ether->transmit = transmit;
212 ether->irq = Vecether;
214 memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);
216 *ercr = Ercr_rxenab|Ercr_auienab|(Nrx-1);
217 *eimr = Ei_rxdone|Ei_txretry|Ei_txdone;
219 iprint("reset: ercr %.4uX\n", *ercr);
221 intrenable(ether->irq, interrupt, ether, ether->name);
227 ethersaturnlink(void)
229 addethercard("saturn", reset);