xref: /inferno-os/os/boot/rpcg/etherscc.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 /*
2  * SCCn ethernet
3  */
4 
5 #include "u.h"
6 #include "lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 
12 #include "etherif.h"
13 
14 enum {
15 	Nrdre		= 32,	/* receive descriptor ring entries */
16 	Ntdre		= 4,	/* transmit descriptor ring entries */
17 
18 	Rbsize		= ETHERMAXTU+4,		/* ring buffer size (+4 for CRC) */
19 	Bufsize		= (Rbsize+7)&~7,	/* aligned */
20 };
21 
22 enum {
23 	/* ether-specific Rx BD bits */
24 	RxMiss=		1<<8,
25 	RxeLG=		1<<5,
26 	RxeNO=		1<<4,
27 	RxeSH=		1<<3,
28 	RxeCR=		1<<2,
29 	RxeOV=		1<<1,
30 	RxeCL=		1<<0,
31 	RxError=		(RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL),	/* various error flags */
32 
33 	/* ether-specific Tx BD bits */
34 	TxPad=		1<<14,	/* pad short frames */
35 	TxTC=		1<<10,	/* transmit CRC */
36 	TxeDEF=		1<<9,
37 	TxeHB=		1<<8,
38 	TxeLC=		1<<7,
39 	TxeRL=		1<<6,
40 	TxeUN=		1<<1,
41 	TxeCSL=		1<<0,
42 
43 	/* scce */
44 	RXB=	1<<0,
45 	TXB=	1<<1,
46 	BSY=		1<<2,
47 	RXF=		1<<3,
48 	TXE=		1<<4,
49 
50 	/* gsmrl */
51 	ENR=	1<<5,
52 	ENT=	1<<4,
53 
54 	/* port A */
55 	RXD1=	SIBIT(15),
56 	TXD1=	SIBIT(14),
57 
58 	/* port B */
59 	RTS1=	IBIT(19),
60 
61 	/* port C */
62 	CTS1=	SIBIT(11),
63 	CD1=	SIBIT(10),
64 };
65 
66 typedef struct Etherparam Etherparam;
67 struct Etherparam {
68 	SCCparam;
69 	ulong	c_pres;		/* preset CRC */
70 	ulong	c_mask;		/* constant mask for CRC */
71 	ulong	crcec;		/* CRC error counter */
72 	ulong	alec;		/* alighnment error counter */
73 	ulong	disfc;		/* discard frame counter */
74 	ushort	pads;		/* short frame PAD characters */
75 	ushort	ret_lim;	/* retry limit threshold */
76 	ushort	ret_cnt;	/* retry limit counter */
77 	ushort	mflr;		/* maximum frame length reg */
78 	ushort	minflr;		/* minimum frame length reg */
79 	ushort	maxd1;		/* maximum DMA1 length reg */
80 	ushort	maxd2;		/* maximum DMA2 length reg */
81 	ushort	maxd;		/* rx max DMA */
82 	ushort	dma_cnt;	/* rx dma counter */
83 	ushort	max_b;		/* max bd byte count */
84 	ushort	gaddr[4];		/* group address filter */
85 	ulong	tbuf0_data0;	/* save area 0 - current frm */
86 	ulong	tbuf0_data1;	/* save area 1 - current frm */
87 	ulong	tbuf0_rba0;
88 	ulong	tbuf0_crc;
89 	ushort	tbuf0_bcnt;
90 	ushort	paddr[3];	/* physical address LSB to MSB increasing */
91 	ushort	p_per;		/* persistence */
92 	ushort	rfbd_ptr;	/* rx first bd pointer */
93 	ushort	tfbd_ptr;	/* tx first bd pointer */
94 	ushort	tlbd_ptr;	/* tx last bd pointer */
95 	ulong	tbuf1_data0;	/* save area 0 - next frame */
96 	ulong	tbuf1_data1;	/* save area 1 - next frame */
97 	ulong	tbuf1_rba0;
98 	ulong	tbuf1_crc;
99 	ushort	tbuf1_bcnt;
100 	ushort	tx_len;		/* tx frame length counter */
101 	ushort	iaddr[4];		/* individual address filter*/
102 	ushort	boff_cnt;	/* back-off counter */
103 	ushort	taddr[3];	/* temp address */
104 };
105 
106 typedef struct {
107 	SCC*	scc;
108 	int	port;
109 	int	cpm;
110 
111 	BD*	rdr;				/* receive descriptor ring */
112 	void*	rrb;				/* receive ring buffers */
113 	int	rdrx;				/* index into rdr */
114 
115 	BD*	tdr;				/* transmit descriptor ring */
116 	void*	trb;				/* transmit ring buffers */
117 	int	tdrx;				/* index into tdr */
118 } Mot;
119 static Mot mot[MaxEther];
120 
121 static	int	sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
122 static	int	sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
123 static	int	sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
124 static	int	sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
125 
126 static void
127 attach(Ctlr *ctlr)
128 {
129 	mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
130 	eieio();
131 }
132 
133 static void
134 transmit(Ctlr *ctlr)
135 {
136 	int len;
137 	Mot *motp;
138 	Block *b;
139 	BD *tdre;
140 
141 	motp = &mot[ctlr->ctlrno];
142 	while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
143 		b = qget(ctlr->oq);
144 		if(b == 0)
145 			break;
146 
147 		/*
148 		 * Copy the packet to the transmit buffer.
149 		 */
150 		len = BLEN(b);
151 		memmove(KADDR(tdre->addr), b->rp, len);
152 
153 		/*
154 		 * Give ownership of the descriptor to the chip, increment the
155 		 * software ring descriptor pointer and tell the chip to poll.
156 		 */
157 		tdre->length = len;
158 		eieio();
159 		tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
160 		eieio();
161 		motp->scc->todr = 1<<15;	/* transmit now */
162 		eieio();
163 		motp->tdrx = NEXT(motp->tdrx, Ntdre);
164 
165 		freeb(b);
166 
167 	}
168 }
169 
170 static void
171 interrupt(Ureg*, void *ap)
172 {
173 	int len, events, status;
174 	Mot *motp;
175 	BD *rdre;
176 	Block *b;
177 	Ctlr *ctlr;
178 
179 	ctlr = ap;
180 	motp = &mot[ctlr->ctlrno];
181 
182 	/*
183 	 * Acknowledge all interrupts and whine about those that shouldn't
184 	 * happen.
185 	 */
186 	events = motp->scc->scce;
187 	eieio();
188 	motp->scc->scce = events;
189 	eieio();
190 	if(events & (TXE|BSY|RXB))
191 		print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
192 	//print(" %ux|", events);
193 	/*
194 	 * Receiver interrupt: run round the descriptor ring logging
195 	 * errors and passing valid receive data up to the higher levels
196 	 * until we encounter a descriptor still owned by the chip.
197 	 */
198 	if(events & (RXF|RXB) || 1){
199 		rdre = &motp->rdr[motp->rdrx];
200 		while(((status = rdre->status) & BDEmpty) == 0){
201 			if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
202 				//if(status & RxBuff)
203 				//	ctlr->buffs++;
204 				if(status & (1<<2))
205 					ctlr->crcs++;
206 				if(status & (1<<1))
207 					ctlr->overflows++;
208 				//print("eth rx: %ux\n", status);
209 				if(status & RxError)
210 					print("~");
211 				else if((status & BDLast) == 0)
212 					print("@");
213 			}
214 			else{
215 				/*
216 				 * We have a packet. Read it into the next
217 				 * free ring buffer, if any.
218 				 */
219 				len = rdre->length-4;
220 				if((b = iallocb(len)) != 0){
221 					memmove(b->wp, KADDR(rdre->addr), len);
222 					b->wp += len;
223 					etheriq(ctlr, b, 1);
224 				}
225 			}
226 
227 			/*
228 			 * Finished with this descriptor, reinitialise it,
229 			 * give it back to the chip, then on to the next...
230 			 */
231 			rdre->length = 0;
232 			rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
233 			eieio();
234 
235 			motp->rdrx = NEXT(motp->rdrx, Nrdre);
236 			rdre = &motp->rdr[motp->rdrx];
237 		}
238 	}
239 
240 	/*
241 	 * Transmitter interrupt: handle anything queued for a free descriptor.
242 	 */
243 	if(events & TXB)
244 		transmit(ctlr);
245 	if(events & TXE)
246 		cpmop(RestartTx, motp->cpm, 0);
247 }
248 
249 static void
250 ringinit(Mot* motp)
251 {
252 	int i, x;
253 
254 	/*
255 	 * Initialise the receive and transmit buffer rings. The ring
256 	 * entries must be aligned on 16-byte boundaries.
257 	 */
258 	if(motp->rdr == 0)
259 		motp->rdr = bdalloc(Nrdre);
260 	if(motp->rrb == 0)
261 		motp->rrb = ialloc(Nrdre*Bufsize, 0);
262 	x = PADDR(motp->rrb);
263 	for(i = 0; i < Nrdre; i++){
264 		motp->rdr[i].length = 0;
265 		motp->rdr[i].addr = x;
266 		motp->rdr[i].status = BDEmpty|BDInt;
267 		x += Bufsize;
268 	}
269 	motp->rdr[i-1].status |= BDWrap;
270 	motp->rdrx = 0;
271 
272 	if(motp->tdr == 0)
273 		motp->tdr = bdalloc(Ntdre);
274 	if(motp->trb == 0)
275 		motp->trb = ialloc(Ntdre*Bufsize, 0);
276 	x = PADDR(motp->trb);
277 	for(i = 0; i < Ntdre; i++){
278 		motp->tdr[i].addr = x;
279 		motp->tdr[i].length = 0;
280 		motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
281 		x += Bufsize;
282 	}
283 	motp->tdr[i-1].status |= BDWrap;
284 	motp->tdrx = 0;
285 }
286 
287 /*
288  * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
289  * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
290  * and those for the 860/821 development board for SCC1.
291  */
292 static void
293 sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
294 {
295 	int i, rcs, tcs, w;
296 	Etherparam *p;
297 	IMM *io;
298 
299 
300 	i = 2*(ctlr->port-1);
301 	io = ioplock();
302 	w = (TXD1|RXD1)<<i;	/* TXDn and RXDn in port A */
303 	io->papar |= w;	/* enable TXDn and RXDn pins */
304 	io->padir &= ~w;
305 	io->paodr &= ~w;	/* not open drain */
306 
307 	w = (CD1|CTS1)<<i;	/* CLSN and RENA: CDn and CTSn in port C */
308 	io->pcpar &= ~w;	/* enable CLSN (CTSn) and RENA (CDn) */
309 	io->pcdir &= ~w;
310 	io->pcso |= w;
311 	iopunlock();
312 
313 	/* clocks and transceiver control: details depend on the board's wiring */
314 	archetherenable(ctlr->cpm, &rcs, &tcs);
315 
316 	sccnmsi(ctlr->port, rcs, tcs);	/* connect the clocks */
317 
318 	p = (Etherparam*)KADDR(sccparam[ctlr->port]);
319 	memset(p, 0, sizeof(*p));
320 	p->rfcr = 0x18;
321 	p->tfcr = 0x18;
322 	p->mrblr = Bufsize;
323 	p->rbase = PADDR(ctlr->rdr);
324 	p->tbase = PADDR(ctlr->tdr);
325 
326 	cpmop(InitRxTx, ctlr->cpm, 0);
327 
328 	p->c_pres = ~0;
329 	p->c_mask = 0xDEBB20E3;
330 	p->crcec = 0;
331 	p->alec = 0;
332 	p->disfc = 0;
333 	p->pads = 0x8888;
334 	p->ret_lim = 0xF;
335 	p->mflr = Rbsize;
336 	p->minflr = ETHERMINTU+4;
337 	p->maxd1 = Bufsize;
338 	p->maxd2 = Bufsize;
339 	p->p_per = 0;	/* only moderate aggression */
340 
341 	for(i=0; i<Eaddrlen; i+=2)
342 		p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i];	/* it's not the obvious byte order */
343 
344 	scc->psmr = (2<<10)|(5<<1);	/* 32-bit CRC, ignore 22 bits before SFD */
345 	scc->dsr = 0xd555;
346 	scc->gsmrh = 0;	/* normal operation */
347 	scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC;	/* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
348 	eieio();
349 	scc->scce = ~0;	/* clear all events */
350 	eieio();
351 	scc->sccm = TXE | RXF | TXB;	/* enable interrupts */
352 	eieio();
353 
354 	io = ioplock();
355 	w = RTS1<<(ctlr->port-1);	/* enable TENA pin (RTSn) */
356 	io->pbpar |= w;
357 	io->pbdir |= w;
358 	iopunlock();
359 
360 	/* gsmrl enable is deferred until attach */
361 }
362 
363 /*
364  * Prepare the SCCx ethernet for booting.
365  */
366 int
367 sccethreset(Ctlr* ctlr)
368 {
369 	uchar ea[Eaddrlen];
370 	Mot *motp;
371 	SCC *scc;
372 	char line[50], def[50];
373 
374 	/*
375 	 * Since there's no EPROM, insist that the configuration entry
376 	 * (see conf.c and flash.c) holds the Ethernet address.
377 	 */
378 	memset(ea, 0, Eaddrlen);
379 	if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
380 		print("no preset Ether address\n");
381 		for(;;){
382 			strcpy(def, "00108bf12900");	/* valid MAC address to be used only for initial configuration */
383 			if(getstr("ether MAC address", line, sizeof(line), def) < 0)
384 				return -1;
385 			if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
386 				break;
387 			print("invalid MAC address\n");
388 		}
389 	}
390 
391 	scc = IOREGS(sccreg[ctlr->card.port], SCC);
392 	ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
393 
394 	motp = &mot[ctlr->ctlrno];
395 	motp->scc = scc;
396 	motp->port = ctlr->card.port;
397 	motp->cpm = sccid[ctlr->card.port];
398 
399 	ringinit(motp);
400 
401 	sccsetup(motp, scc, ctlr->card.ea);
402 
403 	/* enable is deferred until attach */
404 
405 	ctlr->card.reset = sccethreset;
406 	ctlr->card.attach = attach;
407 	ctlr->card.transmit = transmit;
408 	ctlr->card.intr = interrupt;
409 
410 	return 0;
411 }
412