xref: /csrg-svn/sys/news3400/if/if_lance.c (revision 53897)
1*53897Smckusick /*
2*53897Smckusick  * Copyright (c) 1992 The Regents of the University of California.
3*53897Smckusick  * All rights reserved.
4*53897Smckusick  *
5*53897Smckusick  * This code is derived from software contributed to Berkeley by
6*53897Smckusick  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7*53897Smckusick  *
8*53897Smckusick  * %sccs.include.redist.c%
9*53897Smckusick  *
10*53897Smckusick  * from: $Hdr: if_lance.c,v 4.300 91/06/09 06:25:58 root Rel41 $ SONY
11*53897Smckusick  *
12*53897Smckusick  *	@(#)if_lance.c	7.1 (Berkeley) 06/04/92
13*53897Smckusick  */
14*53897Smckusick 
15*53897Smckusick /*
16*53897Smckusick  * if_lance: Am7990 LANCE driver
17*53897Smckusick  *
18*53897Smckusick  * This driver is available only for single CPU machine.
19*53897Smckusick  */
20*53897Smckusick 
21*53897Smckusick #define	LANCE_LED
22*53897Smckusick 
23*53897Smckusick #include "en.h"
24*53897Smckusick 
25*53897Smckusick #if NEN > 0
26*53897Smckusick 
27*53897Smckusick #include "../include/fix_machine_type.h"
28*53897Smckusick #include "../include/adrsmap.h"
29*53897Smckusick 
30*53897Smckusick #include "param.h"
31*53897Smckusick 
32*53897Smckusick #include "../if/lancereg.h"
33*53897Smckusick #include "../if/if_lance.h"
34*53897Smckusick 
35*53897Smckusick #ifdef mips
36*53897Smckusick #define	VOLATILE	volatile
37*53897Smckusick #else
38*53897Smckusick #define	VOLATILE
39*53897Smckusick #endif
40*53897Smckusick 
41*53897Smckusick #ifdef LANCE_LED
42*53897Smckusick #ifdef news3400
43*53897Smckusick #define	LED_ON	{ \
44*53897Smckusick 	VOLATILE u_char *p = (u_char *)DEBUG_PORT; \
45*53897Smckusick 	*p = DP_WRITE | (*p & ~DP_LED2); \
46*53897Smckusick }
47*53897Smckusick #define	LED_OFF	{ \
48*53897Smckusick 	VOLATILE u_char *p = (u_char *)DEBUG_PORT; \
49*53897Smckusick 	*p = DP_WRITE | (*p | DP_LED2); \
50*53897Smckusick }
51*53897Smckusick #else /* news3400 */
52*53897Smckusick #define	LED_ON
53*53897Smckusick #define	LED_OFF
54*53897Smckusick #endif /* news3400 */
55*53897Smckusick #else /* LANCE_LED */
56*53897Smckusick #define	LED_ON
57*53897Smckusick #define	LED_OFF
58*53897Smckusick #endif /* LANCE_LED */
59*53897Smckusick 
60*53897Smckusick /*
61*53897Smckusick  *	LANCE memory configuration
62*53897Smckusick  */
63*53897Smckusick #define	INIT_BLOCK		0x000000
64*53897Smckusick #define	RECV_MSG_DESC		0x000100
65*53897Smckusick #define	XMIT_MSG_DESC		0x000200
66*53897Smckusick #ifdef mips
67*53897Smckusick #define	RECV_BUFFER		(0x000300 + 2)
68*53897Smckusick 				/* for data alignment to long word */
69*53897Smckusick #else /* mips */
70*53897Smckusick #define	RECV_BUFFER		0x000300
71*53897Smckusick #endif /* mips */
72*53897Smckusick #define	XMIT_BUFFER		(RECV_BUFFER+(RECV_BUFFER_SIZE*RECV_BUFFERS))
73*53897Smckusick 
74*53897Smckusick #define	RECV_RING_LEN		3	/* log2(8) */
75*53897Smckusick #define	XMIT_RING_LEN		1	/* log2(2) */
76*53897Smckusick 
77*53897Smckusick #define	RECV_BUFFER_SIZE	0x600
78*53897Smckusick #define	XMIT_BUFFER_SIZE	0x600
79*53897Smckusick 
80*53897Smckusick #define	RECV_BUFFERS		(1 << RECV_RING_LEN)
81*53897Smckusick #define	XMIT_BUFFERS		(1 << XMIT_RING_LEN)
82*53897Smckusick 
83*53897Smckusick /*
84*53897Smckusick  *	Initialization block
85*53897Smckusick  */
86*53897Smckusick struct init_block init_block = {
87*53897Smckusick 	0,
88*53897Smckusick 	0, 0, 0, 0, 0, 0,
89*53897Smckusick 	0, 0, 0, 0, 0, 0, 0, 0,
90*53897Smckusick 	RECV_MSG_DESC & 0xffff,
91*53897Smckusick 	(RECV_RING_LEN << 13) | (RECV_MSG_DESC >> 16),
92*53897Smckusick 	XMIT_MSG_DESC & 0xffff,
93*53897Smckusick 	(XMIT_RING_LEN << 13) | (XMIT_MSG_DESC >> 16)
94*53897Smckusick };
95*53897Smckusick 
96*53897Smckusick /*
97*53897Smckusick  *	LANCE control block
98*53897Smckusick  */
99*53897Smckusick Lance_chan lancesw[NEN] = {
100*53897Smckusick       {	(Lance_reg *)LANCE_PORT,
101*53897Smckusick 	(caddr_t)LANCE_MEMORY,
102*53897Smckusick 	(caddr_t)ETHER_ID },
103*53897Smckusick #if NEN > 1
104*53897Smckusick       {	(Lance_reg *)LANCE_PORT1,
105*53897Smckusick 	(caddr_t)LANCE_MEMORY1,
106*53897Smckusick 	(caddr_t)ETHER_ID1 },
107*53897Smckusick #endif /* NEN > 1 */
108*53897Smckusick #if NEN > 2
109*53897Smckusick       {	(Lance_reg *)LANCE_PORT2,
110*53897Smckusick 	(caddr_t)LANCE_MEMORY2,
111*53897Smckusick 	(caddr_t)ETHER_ID2 },
112*53897Smckusick #endif /* NEN > 2 */
113*53897Smckusick };
114*53897Smckusick 
115*53897Smckusick lance_probe(chan)
116*53897Smckusick 	int chan;
117*53897Smckusick {
118*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
119*53897Smckusick 	VOLATILE int *p = (VOLATILE int *)lance->lance_memory;
120*53897Smckusick 
121*53897Smckusick 	if (badaddr(lance->lance_addr, 1))
122*53897Smckusick 		return (0);
123*53897Smckusick 
124*53897Smckusick 	*p = 0x12345678;
125*53897Smckusick 
126*53897Smckusick 	return (*p == 0x12345678);
127*53897Smckusick }
128*53897Smckusick 
129*53897Smckusick lance_open(chan)
130*53897Smckusick 	int chan;
131*53897Smckusick {
132*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
133*53897Smckusick 	register recv_msg_desc *rmd;
134*53897Smckusick 	register xmit_msg_desc *tmd;
135*53897Smckusick 	register struct init_block *ib;
136*53897Smckusick 	register int buffer, i;
137*53897Smckusick 
138*53897Smckusick 	if ((lance->lance_flags & LANCE_ACTIVE) == 0) {
139*53897Smckusick 		if (lance->lance_addr == (Lance_reg *)0)
140*53897Smckusick 			return (-1);
141*53897Smckusick 
142*53897Smckusick 		lance_write_reg(chan, CSR0, CSR_STOP);
143*53897Smckusick 
144*53897Smckusick 		rmd = (recv_msg_desc *)
145*53897Smckusick 		    (RECV_MSG_DESC + lance->lance_memory);
146*53897Smckusick 		lance->lance_last_rmd =
147*53897Smckusick 		    (lance->lance_rmd = rmd) + RECV_BUFFERS - 1;
148*53897Smckusick 		buffer = RECV_BUFFER;
149*53897Smckusick 		for (i = 0; i < RECV_BUFFERS; i++) {
150*53897Smckusick 			rmd->rmd_ladr = buffer & 0xffff;
151*53897Smckusick 			rmd->rmd_stat = RMD_OWN | (buffer >> 16);
152*53897Smckusick 			rmd->rmd_bcnt = -RECV_BUFFER_SIZE;
153*53897Smckusick 			rmd->rmd_mcnt = 0;
154*53897Smckusick 			rmd++;
155*53897Smckusick 			buffer += RECV_BUFFER_SIZE;
156*53897Smckusick 		}
157*53897Smckusick 
158*53897Smckusick 		tmd = (xmit_msg_desc *)
159*53897Smckusick 		    (XMIT_MSG_DESC + lance->lance_memory);
160*53897Smckusick 		lance->lance_last_tmd =
161*53897Smckusick 			(lance->lance_tmd = tmd) + XMIT_BUFFERS - 1;
162*53897Smckusick 		buffer = XMIT_BUFFER;
163*53897Smckusick 		for (i = 0; i < XMIT_BUFFERS; i++) {
164*53897Smckusick 			tmd->tmd_ladr = buffer & 0xffff;
165*53897Smckusick 			tmd->tmd_stat = buffer >> 16;
166*53897Smckusick 			tmd->tmd_bcnt = 0;
167*53897Smckusick 			tmd++;
168*53897Smckusick 			buffer += XMIT_BUFFER_SIZE;
169*53897Smckusick 		}
170*53897Smckusick 		get_hard_addr(chan, lance->lance_stats.ens_addr);
171*53897Smckusick 
172*53897Smckusick 		ib = (struct init_block *)(INIT_BLOCK + lance->lance_memory);
173*53897Smckusick 		lance->lance_ib = ib;
174*53897Smckusick 		*ib = init_block;
175*53897Smckusick 		ib->ib_padr[0] = lance->lance_stats.ens_addr[1];
176*53897Smckusick 		ib->ib_padr[1] = lance->lance_stats.ens_addr[0];
177*53897Smckusick 		ib->ib_padr[2] = lance->lance_stats.ens_addr[3];
178*53897Smckusick 		ib->ib_padr[3] = lance->lance_stats.ens_addr[2];
179*53897Smckusick 		ib->ib_padr[4] = lance->lance_stats.ens_addr[5];
180*53897Smckusick 		ib->ib_padr[5] = lance->lance_stats.ens_addr[4];
181*53897Smckusick 
182*53897Smckusick 		if (lance->lance_flags & LANCE_PROM)
183*53897Smckusick 			ib->ib_mode |= IB_PROM;
184*53897Smckusick 
185*53897Smckusick 		lance->lance_flags |= LANCE_ACTIVE;
186*53897Smckusick 		lance_init(chan);
187*53897Smckusick 
188*53897Smckusick 		if (lance_read_reg(chan, CSR0) !=
189*53897Smckusick 		    (CSR_INEA|CSR_RXON|CSR_TXON|CSR_STRT|CSR_INIT)) {
190*53897Smckusick 			lance->lance_flags &= ~LANCE_ACTIVE;
191*53897Smckusick 			return (-1);
192*53897Smckusick 		}
193*53897Smckusick 
194*53897Smckusick 	}
195*53897Smckusick 
196*53897Smckusick 	return (0);
197*53897Smckusick }
198*53897Smckusick 
199*53897Smckusick lance_close(chan)
200*53897Smckusick 	int chan;
201*53897Smckusick {
202*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
203*53897Smckusick 
204*53897Smckusick 	lance_write_reg(chan, CSR0, CSR_STOP);
205*53897Smckusick 	lance->lance_flags &= ~LANCE_ACTIVE;
206*53897Smckusick 
207*53897Smckusick }
208*53897Smckusick 
209*53897Smckusick #define	RECEIVE(lance, rmd)	{ \
210*53897Smckusick 	register int i; \
211*53897Smckusick 	(rmd) = (lance)->lance_last_rmd + 1; \
212*53897Smckusick 	if ((rmd) >= (lance)->lance_rmd + RECV_BUFFERS) \
213*53897Smckusick 		(rmd) = (lance)->lance_rmd; \
214*53897Smckusick 	if (((rmd)->rmd_stat & RMD_OWN) == 0) \
215*53897Smckusick 		(lance)->lance_last_rmd = (rmd); \
216*53897Smckusick 	else \
217*53897Smckusick 		(rmd) = NULL; \
218*53897Smckusick }
219*53897Smckusick #define	RECV_BUF(lance, rmd)	(char *)((rmd)->rmd_ladr \
220*53897Smckusick 					+ (((rmd)->rmd_stat & RMD_HADR) << 16) \
221*53897Smckusick 					+ (lance)->lance_memory)
222*53897Smckusick #define	RECV_CNT(rmd)		((rmd)->rmd_mcnt - 4)
223*53897Smckusick #define	RECV_ERR(rmd)		((rmd)->rmd_stat & RMD_ERR)
224*53897Smckusick #define	RELEASE_RECV_BUF(rmd)	{ \
225*53897Smckusick 	(rmd)->rmd_mcnt = 0; \
226*53897Smckusick 	(rmd)->rmd_stat = ((rmd)->rmd_stat & RMD_HADR) | RMD_OWN; \
227*53897Smckusick }
228*53897Smckusick 
229*53897Smckusick 
230*53897Smckusick caddr_t
231*53897Smckusick get_recv_buffer(chan)
232*53897Smckusick 	int chan;
233*53897Smckusick {
234*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
235*53897Smckusick 	register recv_msg_desc *rmd;
236*53897Smckusick 
237*53897Smckusick next:
238*53897Smckusick 	RECEIVE(lance, rmd);
239*53897Smckusick 	if (rmd == NULL)
240*53897Smckusick 		return (NULL);
241*53897Smckusick 
242*53897Smckusick #ifdef news700
243*53897Smckusick 	lance_led();
244*53897Smckusick #endif /* news700 */
245*53897Smckusick 
246*53897Smckusick 	if (RECV_ERR(rmd)) {
247*53897Smckusick 		recv_error(lance, rmd);
248*53897Smckusick 		RELEASE_RECV_BUF(rmd);
249*53897Smckusick 		goto next;
250*53897Smckusick 	}
251*53897Smckusick 
252*53897Smckusick 	return (RECV_BUF(lance, rmd));
253*53897Smckusick }
254*53897Smckusick 
255*53897Smckusick get_recv_length(chan)
256*53897Smckusick 	int chan;
257*53897Smckusick {
258*53897Smckusick 
259*53897Smckusick 	return (RECV_CNT(lancesw[chan].lance_last_rmd));
260*53897Smckusick }
261*53897Smckusick 
262*53897Smckusick free_recv_buffer(chan)
263*53897Smckusick 	int chan;
264*53897Smckusick {
265*53897Smckusick 	register recv_msg_desc *rmd = lancesw[chan].lance_last_rmd;
266*53897Smckusick 
267*53897Smckusick 	RELEASE_RECV_BUF(rmd);
268*53897Smckusick }
269*53897Smckusick 
270*53897Smckusick #define	GET_XMIT_BUF(lance, tmd)	{ \
271*53897Smckusick 	(tmd) = (lance)->lance_last_tmd + 1; \
272*53897Smckusick 	if ((tmd) >= (lance)->lance_tmd + XMIT_BUFFERS) \
273*53897Smckusick 		(tmd) = (lance)->lance_tmd; \
274*53897Smckusick 	if ((tmd)->tmd_stat & TMD_OWN) \
275*53897Smckusick 		(tmd) = NULL; \
276*53897Smckusick 	else \
277*53897Smckusick 		(lance)->lance_last_tmd = (tmd); \
278*53897Smckusick }
279*53897Smckusick #define	XMIT_BUF(lance, tmd)	(char *)((tmd)->tmd_ladr \
280*53897Smckusick 					+ (((tmd)->tmd_stat & TMD_HADR) << 16) \
281*53897Smckusick 					+ (lance)->lance_memory)
282*53897Smckusick #define	XMIT_ERR(tmd)		((tmd)->tmd_stat & TMD_ERR)
283*53897Smckusick #define	TRANSMIT(lance, tmd, count)	{ \
284*53897Smckusick 	(tmd)->tmd_bcnt = -(count); \
285*53897Smckusick 	(tmd)->tmd_error = 0; \
286*53897Smckusick 	(tmd)->tmd_stat = ((tmd)->tmd_stat & TMD_HADR) | (TMD_OWN|TMD_STP|TMD_ENP); \
287*53897Smckusick 	(lance)->lance_addr->rap = CSR0; \
288*53897Smckusick 	(lance)->lance_addr->rdp = (CSR_INEA|CSR_TDMD); \
289*53897Smckusick }
290*53897Smckusick 
291*53897Smckusick caddr_t
292*53897Smckusick get_xmit_buffer(chan)
293*53897Smckusick 	int chan;
294*53897Smckusick {
295*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
296*53897Smckusick 	register xmit_msg_desc *tmd;
297*53897Smckusick 
298*53897Smckusick 	GET_XMIT_BUF(lance, tmd);
299*53897Smckusick 	if (tmd == NULL)
300*53897Smckusick 		return (NULL);
301*53897Smckusick 	return (XMIT_BUF(lance, tmd));
302*53897Smckusick }
303*53897Smckusick 
304*53897Smckusick lance_transmit(chan, count)
305*53897Smckusick 	int chan;
306*53897Smckusick 	int count;
307*53897Smckusick {
308*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
309*53897Smckusick 	register xmit_msg_desc *tmd;
310*53897Smckusick 
311*53897Smckusick 	tmd = lance->lance_last_tmd;
312*53897Smckusick 	TRANSMIT(lance, tmd, count);
313*53897Smckusick 
314*53897Smckusick #ifdef news700
315*53897Smckusick 	lance_led();
316*53897Smckusick #endif /* news700 */
317*53897Smckusick }
318*53897Smckusick 
319*53897Smckusick lance_xmit_error(chan)
320*53897Smckusick 	int chan;
321*53897Smckusick {
322*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
323*53897Smckusick 	register xmit_msg_desc *tmd;
324*53897Smckusick 
325*53897Smckusick 	tmd = lance->lance_last_tmd;
326*53897Smckusick 	if (XMIT_ERR(tmd)) {
327*53897Smckusick 		xmit_error(lance, tmd);
328*53897Smckusick 		return (1);
329*53897Smckusick 	}
330*53897Smckusick 
331*53897Smckusick 	return (0);
332*53897Smckusick }
333*53897Smckusick 
334*53897Smckusick lance_collision(chan)
335*53897Smckusick 	int chan;
336*53897Smckusick {
337*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
338*53897Smckusick 
339*53897Smckusick 	if (lance->lance_last_tmd->tmd_stat & (TMD_MORE|TMD_ONE)) {
340*53897Smckusick 		lance->lance_stats.ens_collis++;
341*53897Smckusick 		return (1);
342*53897Smckusick 	}
343*53897Smckusick 
344*53897Smckusick 	return (0);
345*53897Smckusick }
346*53897Smckusick 
347*53897Smckusick lance_get_addr(chan, addr)
348*53897Smckusick 	int chan;
349*53897Smckusick 	caddr_t addr;
350*53897Smckusick {
351*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
352*53897Smckusick 
353*53897Smckusick 	bcopy(lance->lance_stats.ens_addr, addr,
354*53897Smckusick 		sizeof(lance->lance_stats.ens_addr));
355*53897Smckusick }
356*53897Smckusick 
357*53897Smckusick lance_prom_mode(chan, cmd)
358*53897Smckusick 	int chan;
359*53897Smckusick {
360*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
361*53897Smckusick 
362*53897Smckusick 	lance_close(chan);
363*53897Smckusick 	if (cmd)
364*53897Smckusick 		lance->lance_flags |= LANCE_PROM;
365*53897Smckusick 	else
366*53897Smckusick 		lance->lance_flags &= ~LANCE_PROM;
367*53897Smckusick 	lance_open(chan);
368*53897Smckusick }
369*53897Smckusick 
370*53897Smckusick lance_get_status(chan, addr)
371*53897Smckusick 	int chan;
372*53897Smckusick 	caddr_t addr;
373*53897Smckusick {
374*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
375*53897Smckusick 	register int s;
376*53897Smckusick 
377*53897Smckusick 	s = splimp();
378*53897Smckusick 	bcopy(&lance->lance_stats.ens_frames, addr,
379*53897Smckusick 	    sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr));
380*53897Smckusick 	bzero(&lance->lance_stats.ens_frames,
381*53897Smckusick 	    sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr));
382*53897Smckusick 	(void) splx(s);
383*53897Smckusick }
384*53897Smckusick 
385*53897Smckusick lance_intr()
386*53897Smckusick {
387*53897Smckusick 	register Lance_chan *lance;
388*53897Smckusick 	register Lance_reg *reg;
389*53897Smckusick 	register int stat, chan;
390*53897Smckusick 	int retval = 0;
391*53897Smckusick 
392*53897Smckusick 	LED_ON;
393*53897Smckusick 
394*53897Smckusick 	for (chan = 0, lance = lancesw; chan < NEN ; lance++, chan++) {
395*53897Smckusick 		if ((lance->lance_flags & LANCE_ACTIVE) == 0)
396*53897Smckusick 			continue;
397*53897Smckusick 
398*53897Smckusick 		reg = lance->lance_addr;
399*53897Smckusick 		reg->rap = CSR0;
400*53897Smckusick 		stat = reg->rdp & ~CSR_INEA;
401*53897Smckusick 		if ((stat & CSR_INTR) == 0)
402*53897Smckusick 			continue;
403*53897Smckusick 
404*53897Smckusick 		retval = 1;
405*53897Smckusick 		reg->rdp = stat;
406*53897Smckusick 		reg->rdp = CSR_INEA;
407*53897Smckusick 
408*53897Smckusick 		if (stat & CSR_ERR) {
409*53897Smckusick 			if (stat & CSR_BABL)
410*53897Smckusick 				printf("lance %d error: babl\n", chan);
411*53897Smckusick 			if (stat & CSR_MISS)
412*53897Smckusick 				lance->lance_stats.ens_lost++;
413*53897Smckusick 			if (stat & CSR_MERR)
414*53897Smckusick 				printf("lance %d error: merr\n", chan);
415*53897Smckusick 		}
416*53897Smckusick 		if (stat & CSR_RINT) {
417*53897Smckusick 			lance->lance_stats.ens_frames++;
418*53897Smckusick 			enrint(chan);
419*53897Smckusick 		}
420*53897Smckusick 		if (stat & CSR_TINT) {
421*53897Smckusick 			lance->lance_stats.ens_xmit++;
422*53897Smckusick 			enxint(chan);
423*53897Smckusick 		}
424*53897Smckusick 		if (stat & CSR_IDON)
425*53897Smckusick 			lance->lance_flags |= LANCE_IDON;
426*53897Smckusick 	}
427*53897Smckusick 
428*53897Smckusick 	LED_OFF;
429*53897Smckusick 
430*53897Smckusick 	return (retval);
431*53897Smckusick }
432*53897Smckusick 
433*53897Smckusick lance_init(chan)
434*53897Smckusick 	int chan;
435*53897Smckusick {
436*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
437*53897Smckusick 	register int s;
438*53897Smckusick 
439*53897Smckusick 	s = splimp();
440*53897Smckusick 	lance_write_reg(chan, CSR1, INIT_BLOCK & 0xffff);
441*53897Smckusick 	lance_write_reg(chan, CSR2, INIT_BLOCK >> 16);
442*53897Smckusick 	lance_write_reg(chan, CSR3, CSR_BSWP|CSR_BCON);
443*53897Smckusick 
444*53897Smckusick 	lance_write_reg(chan, CSR0, CSR_INEA|CSR_STRT|CSR_INIT);
445*53897Smckusick 	(void) splx(s);
446*53897Smckusick 
447*53897Smckusick 	while ((lance->lance_flags & LANCE_IDON) == 0)
448*53897Smckusick 		;
449*53897Smckusick }
450*53897Smckusick 
451*53897Smckusick recv_error(lance, rmd)
452*53897Smckusick 	register Lance_chan *lance;
453*53897Smckusick 	register recv_msg_desc *rmd;
454*53897Smckusick {
455*53897Smckusick 	register int status = rmd->rmd_stat;
456*53897Smckusick 	register int chan = lance - lancesw;
457*53897Smckusick 
458*53897Smckusick 	if (status & RMD_FRAM)
459*53897Smckusick 		lance->lance_stats.ens_align++;
460*53897Smckusick 	if (status & RMD_OFLO)
461*53897Smckusick 		printf("lance %d recv error: overflow\n", chan);
462*53897Smckusick 	if (status & RMD_CRC)
463*53897Smckusick 		lance->lance_stats.ens_crc++;
464*53897Smckusick 	if (status & RMD_BUFF)
465*53897Smckusick 		printf("lance %d:recv error: buffer\n", chan);
466*53897Smckusick }
467*53897Smckusick 
468*53897Smckusick xmit_error(lance, tmd)
469*53897Smckusick 	register Lance_chan *lance;
470*53897Smckusick 	register xmit_msg_desc *tmd;
471*53897Smckusick {
472*53897Smckusick 	register int status = tmd->tmd_error;
473*53897Smckusick 	register int chan = lance - lancesw;
474*53897Smckusick 
475*53897Smckusick 	if (status & TMD_BUFF)
476*53897Smckusick 		printf("lance %d: xmit error: buffer\n", chan);
477*53897Smckusick 	if (status & TMD_UFLO)
478*53897Smckusick 		printf("lance %d: xmit error: underflow\n", chan);
479*53897Smckusick 	if (status & TMD_LCOL) {
480*53897Smckusick 		printf("lance %d: xmit error: late collision\n", chan);
481*53897Smckusick 		lance->lance_stats.ens_owcollis++;
482*53897Smckusick 	}
483*53897Smckusick 	if (status & TMD_LCAR)
484*53897Smckusick 		printf("lance %d: xmit error: loss of carrier\n", chan);
485*53897Smckusick 	if (status & TMD_RTRY) {
486*53897Smckusick 		printf("lance %d: xmit error: retry tdr=%d\n",
487*53897Smckusick 		    chan, status & TMD_TDR);
488*53897Smckusick 		lance->lance_stats.ens_xcollis++;
489*53897Smckusick 	}
490*53897Smckusick }
491*53897Smckusick 
492*53897Smckusick lance_write_reg(chan, reg, data)
493*53897Smckusick 	int chan, reg, data;
494*53897Smckusick {
495*53897Smckusick 	register Lance_reg *lance = lancesw[chan].lance_addr;
496*53897Smckusick 	register int s;
497*53897Smckusick 
498*53897Smckusick 	s = spl7();
499*53897Smckusick 	lance->rap = reg;
500*53897Smckusick 	lance->rdp = data;
501*53897Smckusick 	(void) splx(s);
502*53897Smckusick }
503*53897Smckusick 
504*53897Smckusick lance_read_reg(chan, reg)
505*53897Smckusick 	int chan, reg;
506*53897Smckusick {
507*53897Smckusick 	register Lance_reg *lance = lancesw[chan].lance_addr;
508*53897Smckusick 	register int s, d;
509*53897Smckusick 
510*53897Smckusick 	s = spl7();
511*53897Smckusick 	lance->rap = reg;
512*53897Smckusick 	d = lance->rdp;
513*53897Smckusick 	(void) splx(s);
514*53897Smckusick 
515*53897Smckusick 	return (d);
516*53897Smckusick }
517*53897Smckusick 
518*53897Smckusick get_hard_addr(chan, addr)
519*53897Smckusick 	int chan;
520*53897Smckusick 	u_short *addr;
521*53897Smckusick {
522*53897Smckusick 	register unsigned char *p, *q;
523*53897Smckusick 	register int i;
524*53897Smckusick 	register Lance_chan *lance = &lancesw[chan];
525*53897Smckusick 	unsigned char hard_addr[6];
526*53897Smckusick 
527*53897Smckusick 	p = (unsigned char *)lance->lance_rom + 16;
528*53897Smckusick 	q = hard_addr;
529*53897Smckusick 	for (i = 0; i < 6; i++) {
530*53897Smckusick 		*q = (*p++ & 0xf) << 4;
531*53897Smckusick 		*q++ |= *p++ & 0xf;
532*53897Smckusick 	}
533*53897Smckusick 
534*53897Smckusick 	bcopy(hard_addr, (char *)addr, 6);
535*53897Smckusick }
536*53897Smckusick 
537*53897Smckusick lance_led()
538*53897Smckusick {
539*53897Smckusick 
540*53897Smckusick #ifdef news700
541*53897Smckusick 	*(u_char *)ETHER_LED = 1;
542*53897Smckusick 	*(u_char *)ETHER_LED = 0;
543*53897Smckusick #endif /* news700 */
544*53897Smckusick }
545*53897Smckusick 
546*53897Smckusick #if defined(mips) && defined(CPU_SINGLE)
547*53897Smckusick bxcopy(s, d, n)
548*53897Smckusick 	caddr_t s, d;
549*53897Smckusick 	int n;
550*53897Smckusick {
551*53897Smckusick 
552*53897Smckusick 	if (n <= 0)
553*53897Smckusick 		return;
554*53897Smckusick 	switch ((((int)s & 03) << 2) + ((int)d & 03)) {
555*53897Smckusick 
556*53897Smckusick 	case 0x0:
557*53897Smckusick 		blcopy((long *)s, (long *)d, n);
558*53897Smckusick 		return;
559*53897Smckusick 
560*53897Smckusick 	case 0x5:
561*53897Smckusick 		*(char *)d = *(char *)s;
562*53897Smckusick 		blcopy((long *)(s + 1), (long *)(d + 1), n - 1);
563*53897Smckusick 		return;
564*53897Smckusick 
565*53897Smckusick 	case 0xa:
566*53897Smckusick 		switch (n) {
567*53897Smckusick 
568*53897Smckusick 		case 1:
569*53897Smckusick 			*(char *)d = *(char *)s;
570*53897Smckusick 			return;
571*53897Smckusick 
572*53897Smckusick 		case 2:
573*53897Smckusick 			*(short *)d = *(short *)s;
574*53897Smckusick 			return;
575*53897Smckusick 
576*53897Smckusick 		default:
577*53897Smckusick 			*(short *)d = *(short *)s;
578*53897Smckusick 			blcopy((long *)(s + 2), (long *)(d + 2), n - 2);
579*53897Smckusick 			return;
580*53897Smckusick 		}
581*53897Smckusick 
582*53897Smckusick 	case 0xf:
583*53897Smckusick 		switch (n) {
584*53897Smckusick 
585*53897Smckusick 		case 1:
586*53897Smckusick 			*(char *)d = *(char *)s;
587*53897Smckusick 			return;
588*53897Smckusick 
589*53897Smckusick 		case 2:
590*53897Smckusick 			*(char *)d = *(char *)s;
591*53897Smckusick 			*(char *)(d + 1) = *(char *)(s + 1);
592*53897Smckusick 			return;
593*53897Smckusick 
594*53897Smckusick 		case 3:
595*53897Smckusick 			*(char *)d = *(char *)s;
596*53897Smckusick 			*(short *)(d + 1) = *(short *)(s + 1);
597*53897Smckusick 			return;
598*53897Smckusick 
599*53897Smckusick 		default:
600*53897Smckusick 			*(char *)d = *(char *)s;
601*53897Smckusick 			*(short *)(d + 1) = *(short *)(s + 1);
602*53897Smckusick 			blcopy((long *)(s + 3), (long *)(d + 3), n - 3);
603*53897Smckusick 			return;
604*53897Smckusick 		}
605*53897Smckusick 
606*53897Smckusick 	case 0x7:
607*53897Smckusick 	case 0xd:
608*53897Smckusick 		switch (n) {
609*53897Smckusick 
610*53897Smckusick 		case 1:
611*53897Smckusick 			*(char *)d = *(char *)s;
612*53897Smckusick 			return;
613*53897Smckusick 
614*53897Smckusick 		case 2:
615*53897Smckusick 			*(char *)d = *(char *)s;
616*53897Smckusick 			*(char *)(d + 1) = *(char *)(s + 1);
617*53897Smckusick 			return;
618*53897Smckusick 
619*53897Smckusick 		default:
620*53897Smckusick 			*(char *)d = *(char *)s;
621*53897Smckusick 			bwcopy((short *)(s + 1), (short *)(d + 1), n);
622*53897Smckusick 			return;
623*53897Smckusick 		}
624*53897Smckusick 
625*53897Smckusick 	case 0x2:
626*53897Smckusick 	case 0x8:
627*53897Smckusick 		bwcopy((short *)s, (short *)d, n);
628*53897Smckusick 		return;
629*53897Smckusick 
630*53897Smckusick 	default:
631*53897Smckusick 		bbcopy((char *)s, (char *)d, n);
632*53897Smckusick 		return;
633*53897Smckusick 	}
634*53897Smckusick }
635*53897Smckusick 
636*53897Smckusick #define	COPY(s, d, n, t) \
637*53897Smckusick 	while ((n) >= 8 * sizeof (t)) { \
638*53897Smckusick 		int t0, t1, t2, t3, t4, t5, t6, t7; \
639*53897Smckusick 		t0 = (s)[0]; \
640*53897Smckusick 		t1 = (s)[1]; \
641*53897Smckusick 		t2 = (s)[2]; \
642*53897Smckusick 		t3 = (s)[3]; \
643*53897Smckusick 		t4 = (s)[4]; \
644*53897Smckusick 		t5 = (s)[5]; \
645*53897Smckusick 		t6 = (s)[6]; \
646*53897Smckusick 		t7 = (s)[7]; \
647*53897Smckusick 		(d)[0] = t0; \
648*53897Smckusick 		(d)[1] = t1; \
649*53897Smckusick 		(d)[2] = t2; \
650*53897Smckusick 		(d)[3] = t3; \
651*53897Smckusick 		(d)[4] = t4; \
652*53897Smckusick 		(d)[5] = t5; \
653*53897Smckusick 		(d)[6] = t6; \
654*53897Smckusick 		(d)[7] = t7; \
655*53897Smckusick 		(s) += 8; \
656*53897Smckusick 		(d) += 8; \
657*53897Smckusick 		(n) -= 8 * sizeof (t); \
658*53897Smckusick 	} \
659*53897Smckusick 	while ((n) >= sizeof (t)) { \
660*53897Smckusick 		(d)[0] = (s)[0]; \
661*53897Smckusick 		(s)++; \
662*53897Smckusick 		(d)++; \
663*53897Smckusick 		(n) -= sizeof (t); \
664*53897Smckusick 	}
665*53897Smckusick 
666*53897Smckusick blcopy(s, d, n)
667*53897Smckusick 	long *s, *d;
668*53897Smckusick 	int n;
669*53897Smckusick {
670*53897Smckusick 
671*53897Smckusick 	COPY(s, d, n, long);
672*53897Smckusick 	switch (n) {
673*53897Smckusick 
674*53897Smckusick 	case 0:
675*53897Smckusick 		return;
676*53897Smckusick 
677*53897Smckusick 	case 1:
678*53897Smckusick 		*(char *)d = *(char *)s;
679*53897Smckusick 		return;
680*53897Smckusick 
681*53897Smckusick 	case 2:
682*53897Smckusick 		*(short *)d = *(short *)s;
683*53897Smckusick 		return;
684*53897Smckusick 
685*53897Smckusick 	case 3:
686*53897Smckusick 		*(short *)d = *(short *)s;
687*53897Smckusick 		*((char *)d + 2) = *((char *)s + 2);
688*53897Smckusick 		return;
689*53897Smckusick 	}
690*53897Smckusick }
691*53897Smckusick 
692*53897Smckusick bwcopy(s, d, n)
693*53897Smckusick 	short *s, *d;
694*53897Smckusick 	int n;
695*53897Smckusick {
696*53897Smckusick 
697*53897Smckusick 	COPY(s, d, n, short);
698*53897Smckusick 	if (n == 1)
699*53897Smckusick 		*(char *)d = *(char *)s;
700*53897Smckusick }
701*53897Smckusick 
702*53897Smckusick bbcopy(s, d, n)
703*53897Smckusick 	char *s, *d;
704*53897Smckusick 	int n;
705*53897Smckusick {
706*53897Smckusick 
707*53897Smckusick 	COPY(s, d, n, char);
708*53897Smckusick }
709*53897Smckusick #endif /* defined(mips) && defined(CPU_SINGLE) */
710*53897Smckusick 
711*53897Smckusick #endif /* NEN > 0 */
712