xref: /csrg-svn/sys/news3400/if/if_lance.c (revision 57180)
153897Smckusick /*
253897Smckusick  * Copyright (c) 1992 The Regents of the University of California.
353897Smckusick  * All rights reserved.
453897Smckusick  *
553897Smckusick  * This code is derived from software contributed to Berkeley by
653897Smckusick  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
753897Smckusick  *
853897Smckusick  * %sccs.include.redist.c%
953897Smckusick  *
1053897Smckusick  * from: $Hdr: if_lance.c,v 4.300 91/06/09 06:25:58 root Rel41 $ SONY
1153897Smckusick  *
12*57180Sutashiro  *	@(#)if_lance.c	7.3 (Berkeley) 12/17/92
1353897Smckusick  */
1453897Smckusick 
1553897Smckusick /*
1653897Smckusick  * if_lance: Am7990 LANCE driver
1753897Smckusick  *
1853897Smckusick  * This driver is available only for single CPU machine.
1953897Smckusick  */
2053897Smckusick 
2153897Smckusick #define	LANCE_LED
2253897Smckusick 
2353897Smckusick #include "en.h"
2453897Smckusick 
2553897Smckusick #if NEN > 0
2653897Smckusick 
27*57180Sutashiro #include <machine/fix_machine_type.h>
28*57180Sutashiro #include <machine/adrsmap.h>
2953897Smckusick 
30*57180Sutashiro #include <sys/param.h>
3153897Smckusick 
32*57180Sutashiro #include <news3400/if/lancereg.h>
33*57180Sutashiro #include <news3400/if/if_lance.h>
3453897Smckusick 
3553897Smckusick #ifdef mips
3653897Smckusick #define	VOLATILE	volatile
3753897Smckusick #else
3853897Smckusick #define	VOLATILE
3953897Smckusick #endif
4053897Smckusick 
4153897Smckusick #ifdef LANCE_LED
4253897Smckusick #ifdef news3400
4353897Smckusick #define	LED_ON	{ \
4453897Smckusick 	VOLATILE u_char *p = (u_char *)DEBUG_PORT; \
4553897Smckusick 	*p = DP_WRITE | (*p & ~DP_LED2); \
4653897Smckusick }
4753897Smckusick #define	LED_OFF	{ \
4853897Smckusick 	VOLATILE u_char *p = (u_char *)DEBUG_PORT; \
4953897Smckusick 	*p = DP_WRITE | (*p | DP_LED2); \
5053897Smckusick }
5153897Smckusick #else /* news3400 */
5253897Smckusick #define	LED_ON
5353897Smckusick #define	LED_OFF
5453897Smckusick #endif /* news3400 */
5553897Smckusick #else /* LANCE_LED */
5653897Smckusick #define	LED_ON
5753897Smckusick #define	LED_OFF
5853897Smckusick #endif /* LANCE_LED */
5953897Smckusick 
6053897Smckusick /*
6153897Smckusick  *	LANCE memory configuration
6253897Smckusick  */
6353897Smckusick #define	INIT_BLOCK		0x000000
6453897Smckusick #define	RECV_MSG_DESC		0x000100
6553897Smckusick #define	XMIT_MSG_DESC		0x000200
6653897Smckusick #ifdef mips
6753897Smckusick #define	RECV_BUFFER		(0x000300 + 2)
6853897Smckusick 				/* for data alignment to long word */
6953897Smckusick #else /* mips */
7053897Smckusick #define	RECV_BUFFER		0x000300
7153897Smckusick #endif /* mips */
7253897Smckusick #define	XMIT_BUFFER		(RECV_BUFFER+(RECV_BUFFER_SIZE*RECV_BUFFERS))
7353897Smckusick 
7453897Smckusick #define	RECV_RING_LEN		3	/* log2(8) */
7553897Smckusick #define	XMIT_RING_LEN		1	/* log2(2) */
7653897Smckusick 
7753897Smckusick #define	RECV_BUFFER_SIZE	0x600
7853897Smckusick #define	XMIT_BUFFER_SIZE	0x600
7953897Smckusick 
8053897Smckusick #define	RECV_BUFFERS		(1 << RECV_RING_LEN)
8153897Smckusick #define	XMIT_BUFFERS		(1 << XMIT_RING_LEN)
8253897Smckusick 
8353897Smckusick /*
8453897Smckusick  *	Initialization block
8553897Smckusick  */
8653897Smckusick struct init_block init_block = {
8753897Smckusick 	0,
8853897Smckusick 	0, 0, 0, 0, 0, 0,
8953897Smckusick 	0, 0, 0, 0, 0, 0, 0, 0,
9053897Smckusick 	RECV_MSG_DESC & 0xffff,
9153897Smckusick 	(RECV_RING_LEN << 13) | (RECV_MSG_DESC >> 16),
9253897Smckusick 	XMIT_MSG_DESC & 0xffff,
9353897Smckusick 	(XMIT_RING_LEN << 13) | (XMIT_MSG_DESC >> 16)
9453897Smckusick };
9553897Smckusick 
9653897Smckusick /*
9753897Smckusick  *	LANCE control block
9853897Smckusick  */
9953897Smckusick Lance_chan lancesw[NEN] = {
10053897Smckusick       {	(Lance_reg *)LANCE_PORT,
10153897Smckusick 	(caddr_t)LANCE_MEMORY,
10253897Smckusick 	(caddr_t)ETHER_ID },
10353897Smckusick #if NEN > 1
10453897Smckusick       {	(Lance_reg *)LANCE_PORT1,
10553897Smckusick 	(caddr_t)LANCE_MEMORY1,
10653897Smckusick 	(caddr_t)ETHER_ID1 },
10754474Sutashiro #endif
10853897Smckusick #if NEN > 2
10953897Smckusick       {	(Lance_reg *)LANCE_PORT2,
11053897Smckusick 	(caddr_t)LANCE_MEMORY2,
11153897Smckusick 	(caddr_t)ETHER_ID2 },
11254474Sutashiro #endif
11353897Smckusick };
11453897Smckusick 
11553897Smckusick lance_probe(chan)
11653897Smckusick 	int chan;
11753897Smckusick {
11853897Smckusick 	register Lance_chan *lance = &lancesw[chan];
11953897Smckusick 	VOLATILE int *p = (VOLATILE int *)lance->lance_memory;
12053897Smckusick 
12153897Smckusick 	if (badaddr(lance->lance_addr, 1))
12253897Smckusick 		return (0);
12353897Smckusick 
12453897Smckusick 	*p = 0x12345678;
12553897Smckusick 
12653897Smckusick 	return (*p == 0x12345678);
12753897Smckusick }
12853897Smckusick 
12953897Smckusick lance_open(chan)
13053897Smckusick 	int chan;
13153897Smckusick {
13253897Smckusick 	register Lance_chan *lance = &lancesw[chan];
13353897Smckusick 	register recv_msg_desc *rmd;
13453897Smckusick 	register xmit_msg_desc *tmd;
13553897Smckusick 	register struct init_block *ib;
13653897Smckusick 	register int buffer, i;
13753897Smckusick 
13853897Smckusick 	if ((lance->lance_flags & LANCE_ACTIVE) == 0) {
13953897Smckusick 		if (lance->lance_addr == (Lance_reg *)0)
14053897Smckusick 			return (-1);
14153897Smckusick 
14253897Smckusick 		lance_write_reg(chan, CSR0, CSR_STOP);
14353897Smckusick 
14453897Smckusick 		rmd = (recv_msg_desc *)
14553897Smckusick 		    (RECV_MSG_DESC + lance->lance_memory);
14653897Smckusick 		lance->lance_last_rmd =
14753897Smckusick 		    (lance->lance_rmd = rmd) + RECV_BUFFERS - 1;
14853897Smckusick 		buffer = RECV_BUFFER;
14953897Smckusick 		for (i = 0; i < RECV_BUFFERS; i++) {
15053897Smckusick 			rmd->rmd_ladr = buffer & 0xffff;
15153897Smckusick 			rmd->rmd_stat = RMD_OWN | (buffer >> 16);
15253897Smckusick 			rmd->rmd_bcnt = -RECV_BUFFER_SIZE;
15353897Smckusick 			rmd->rmd_mcnt = 0;
15453897Smckusick 			rmd++;
15553897Smckusick 			buffer += RECV_BUFFER_SIZE;
15653897Smckusick 		}
15753897Smckusick 
15853897Smckusick 		tmd = (xmit_msg_desc *)
15953897Smckusick 		    (XMIT_MSG_DESC + lance->lance_memory);
16053897Smckusick 		lance->lance_last_tmd =
16153897Smckusick 			(lance->lance_tmd = tmd) + XMIT_BUFFERS - 1;
16253897Smckusick 		buffer = XMIT_BUFFER;
16353897Smckusick 		for (i = 0; i < XMIT_BUFFERS; i++) {
16453897Smckusick 			tmd->tmd_ladr = buffer & 0xffff;
16553897Smckusick 			tmd->tmd_stat = buffer >> 16;
16653897Smckusick 			tmd->tmd_bcnt = 0;
16753897Smckusick 			tmd++;
16853897Smckusick 			buffer += XMIT_BUFFER_SIZE;
16953897Smckusick 		}
17053897Smckusick 		get_hard_addr(chan, lance->lance_stats.ens_addr);
17153897Smckusick 
17253897Smckusick 		ib = (struct init_block *)(INIT_BLOCK + lance->lance_memory);
17353897Smckusick 		lance->lance_ib = ib;
17453897Smckusick 		*ib = init_block;
17553897Smckusick 		ib->ib_padr[0] = lance->lance_stats.ens_addr[1];
17653897Smckusick 		ib->ib_padr[1] = lance->lance_stats.ens_addr[0];
17753897Smckusick 		ib->ib_padr[2] = lance->lance_stats.ens_addr[3];
17853897Smckusick 		ib->ib_padr[3] = lance->lance_stats.ens_addr[2];
17953897Smckusick 		ib->ib_padr[4] = lance->lance_stats.ens_addr[5];
18053897Smckusick 		ib->ib_padr[5] = lance->lance_stats.ens_addr[4];
18153897Smckusick 
18253897Smckusick 		if (lance->lance_flags & LANCE_PROM)
18353897Smckusick 			ib->ib_mode |= IB_PROM;
18453897Smckusick 
18553897Smckusick 		lance->lance_flags |= LANCE_ACTIVE;
18653897Smckusick 		lance_init(chan);
18753897Smckusick 
18853897Smckusick 		if (lance_read_reg(chan, CSR0) !=
18953897Smckusick 		    (CSR_INEA|CSR_RXON|CSR_TXON|CSR_STRT|CSR_INIT)) {
19053897Smckusick 			lance->lance_flags &= ~LANCE_ACTIVE;
19153897Smckusick 			return (-1);
19253897Smckusick 		}
19353897Smckusick 
19453897Smckusick 	}
19553897Smckusick 
19653897Smckusick 	return (0);
19753897Smckusick }
19853897Smckusick 
19953897Smckusick lance_close(chan)
20053897Smckusick 	int chan;
20153897Smckusick {
20253897Smckusick 	register Lance_chan *lance = &lancesw[chan];
20353897Smckusick 
20453897Smckusick 	lance_write_reg(chan, CSR0, CSR_STOP);
20553897Smckusick 	lance->lance_flags &= ~LANCE_ACTIVE;
20653897Smckusick 
20753897Smckusick }
20853897Smckusick 
20953897Smckusick #define	RECEIVE(lance, rmd)	{ \
21053897Smckusick 	register int i; \
21153897Smckusick 	(rmd) = (lance)->lance_last_rmd + 1; \
21253897Smckusick 	if ((rmd) >= (lance)->lance_rmd + RECV_BUFFERS) \
21353897Smckusick 		(rmd) = (lance)->lance_rmd; \
21453897Smckusick 	if (((rmd)->rmd_stat & RMD_OWN) == 0) \
21553897Smckusick 		(lance)->lance_last_rmd = (rmd); \
21653897Smckusick 	else \
21753897Smckusick 		(rmd) = NULL; \
21853897Smckusick }
21953897Smckusick #define	RECV_BUF(lance, rmd)	(char *)((rmd)->rmd_ladr \
22053897Smckusick 					+ (((rmd)->rmd_stat & RMD_HADR) << 16) \
22153897Smckusick 					+ (lance)->lance_memory)
22253897Smckusick #define	RECV_CNT(rmd)		((rmd)->rmd_mcnt - 4)
22353897Smckusick #define	RECV_ERR(rmd)		((rmd)->rmd_stat & RMD_ERR)
22453897Smckusick #define	RELEASE_RECV_BUF(rmd)	{ \
22553897Smckusick 	(rmd)->rmd_mcnt = 0; \
22653897Smckusick 	(rmd)->rmd_stat = ((rmd)->rmd_stat & RMD_HADR) | RMD_OWN; \
22753897Smckusick }
22853897Smckusick 
22953897Smckusick 
23053897Smckusick caddr_t
23153897Smckusick get_recv_buffer(chan)
23253897Smckusick 	int chan;
23353897Smckusick {
23453897Smckusick 	register Lance_chan *lance = &lancesw[chan];
23553897Smckusick 	register recv_msg_desc *rmd;
23653897Smckusick 
23753897Smckusick next:
23853897Smckusick 	RECEIVE(lance, rmd);
23953897Smckusick 	if (rmd == NULL)
24053897Smckusick 		return (NULL);
24153897Smckusick 
24253897Smckusick 	if (RECV_ERR(rmd)) {
24353897Smckusick 		recv_error(lance, rmd);
24453897Smckusick 		RELEASE_RECV_BUF(rmd);
24553897Smckusick 		goto next;
24653897Smckusick 	}
24753897Smckusick 
24853897Smckusick 	return (RECV_BUF(lance, rmd));
24953897Smckusick }
25053897Smckusick 
25153897Smckusick get_recv_length(chan)
25253897Smckusick 	int chan;
25353897Smckusick {
25453897Smckusick 
25553897Smckusick 	return (RECV_CNT(lancesw[chan].lance_last_rmd));
25653897Smckusick }
25753897Smckusick 
25853897Smckusick free_recv_buffer(chan)
25953897Smckusick 	int chan;
26053897Smckusick {
26153897Smckusick 	register recv_msg_desc *rmd = lancesw[chan].lance_last_rmd;
26253897Smckusick 
26353897Smckusick 	RELEASE_RECV_BUF(rmd);
26453897Smckusick }
26553897Smckusick 
26653897Smckusick #define	GET_XMIT_BUF(lance, tmd)	{ \
26753897Smckusick 	(tmd) = (lance)->lance_last_tmd + 1; \
26853897Smckusick 	if ((tmd) >= (lance)->lance_tmd + XMIT_BUFFERS) \
26953897Smckusick 		(tmd) = (lance)->lance_tmd; \
27053897Smckusick 	if ((tmd)->tmd_stat & TMD_OWN) \
27153897Smckusick 		(tmd) = NULL; \
27253897Smckusick 	else \
27353897Smckusick 		(lance)->lance_last_tmd = (tmd); \
27453897Smckusick }
27553897Smckusick #define	XMIT_BUF(lance, tmd)	(char *)((tmd)->tmd_ladr \
27653897Smckusick 					+ (((tmd)->tmd_stat & TMD_HADR) << 16) \
27753897Smckusick 					+ (lance)->lance_memory)
27853897Smckusick #define	XMIT_ERR(tmd)		((tmd)->tmd_stat & TMD_ERR)
27953897Smckusick #define	TRANSMIT(lance, tmd, count)	{ \
28053897Smckusick 	(tmd)->tmd_bcnt = -(count); \
28153897Smckusick 	(tmd)->tmd_error = 0; \
28253897Smckusick 	(tmd)->tmd_stat = ((tmd)->tmd_stat & TMD_HADR) | (TMD_OWN|TMD_STP|TMD_ENP); \
28353897Smckusick 	(lance)->lance_addr->rap = CSR0; \
28453897Smckusick 	(lance)->lance_addr->rdp = (CSR_INEA|CSR_TDMD); \
28553897Smckusick }
28653897Smckusick 
28753897Smckusick caddr_t
28853897Smckusick get_xmit_buffer(chan)
28953897Smckusick 	int chan;
29053897Smckusick {
29153897Smckusick 	register Lance_chan *lance = &lancesw[chan];
29253897Smckusick 	register xmit_msg_desc *tmd;
29353897Smckusick 
29453897Smckusick 	GET_XMIT_BUF(lance, tmd);
29553897Smckusick 	if (tmd == NULL)
29653897Smckusick 		return (NULL);
29753897Smckusick 	return (XMIT_BUF(lance, tmd));
29853897Smckusick }
29953897Smckusick 
30053897Smckusick lance_transmit(chan, count)
30153897Smckusick 	int chan;
30253897Smckusick 	int count;
30353897Smckusick {
30453897Smckusick 	register Lance_chan *lance = &lancesw[chan];
30553897Smckusick 	register xmit_msg_desc *tmd;
30653897Smckusick 
30753897Smckusick 	tmd = lance->lance_last_tmd;
30853897Smckusick 	TRANSMIT(lance, tmd, count);
30953897Smckusick }
31053897Smckusick 
31153897Smckusick lance_xmit_error(chan)
31253897Smckusick 	int chan;
31353897Smckusick {
31453897Smckusick 	register Lance_chan *lance = &lancesw[chan];
31553897Smckusick 	register xmit_msg_desc *tmd;
31653897Smckusick 
31753897Smckusick 	tmd = lance->lance_last_tmd;
31853897Smckusick 	if (XMIT_ERR(tmd)) {
31953897Smckusick 		xmit_error(lance, tmd);
32053897Smckusick 		return (1);
32153897Smckusick 	}
32253897Smckusick 
32353897Smckusick 	return (0);
32453897Smckusick }
32553897Smckusick 
32653897Smckusick lance_collision(chan)
32753897Smckusick 	int chan;
32853897Smckusick {
32953897Smckusick 	register Lance_chan *lance = &lancesw[chan];
33053897Smckusick 
33153897Smckusick 	if (lance->lance_last_tmd->tmd_stat & (TMD_MORE|TMD_ONE)) {
33253897Smckusick 		lance->lance_stats.ens_collis++;
33353897Smckusick 		return (1);
33453897Smckusick 	}
33553897Smckusick 
33653897Smckusick 	return (0);
33753897Smckusick }
33853897Smckusick 
33953897Smckusick lance_get_addr(chan, addr)
34053897Smckusick 	int chan;
34153897Smckusick 	caddr_t addr;
34253897Smckusick {
34353897Smckusick 	register Lance_chan *lance = &lancesw[chan];
34453897Smckusick 
34553897Smckusick 	bcopy(lance->lance_stats.ens_addr, addr,
34653897Smckusick 		sizeof(lance->lance_stats.ens_addr));
34753897Smckusick }
34853897Smckusick 
34953897Smckusick lance_prom_mode(chan, cmd)
35053897Smckusick 	int chan;
35153897Smckusick {
35253897Smckusick 	register Lance_chan *lance = &lancesw[chan];
35353897Smckusick 
35453897Smckusick 	lance_close(chan);
35553897Smckusick 	if (cmd)
35653897Smckusick 		lance->lance_flags |= LANCE_PROM;
35753897Smckusick 	else
35853897Smckusick 		lance->lance_flags &= ~LANCE_PROM;
35953897Smckusick 	lance_open(chan);
36053897Smckusick }
36153897Smckusick 
36253897Smckusick lance_get_status(chan, addr)
36353897Smckusick 	int chan;
36453897Smckusick 	caddr_t addr;
36553897Smckusick {
36653897Smckusick 	register Lance_chan *lance = &lancesw[chan];
36753897Smckusick 	register int s;
36853897Smckusick 
36953897Smckusick 	s = splimp();
37053897Smckusick 	bcopy(&lance->lance_stats.ens_frames, addr,
37153897Smckusick 	    sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr));
37253897Smckusick 	bzero(&lance->lance_stats.ens_frames,
37353897Smckusick 	    sizeof(lance->lance_stats) - sizeof (lance->lance_stats.ens_addr));
37453897Smckusick 	(void) splx(s);
37553897Smckusick }
37653897Smckusick 
37753897Smckusick lance_intr()
37853897Smckusick {
37953897Smckusick 	register Lance_chan *lance;
38053897Smckusick 	register Lance_reg *reg;
38153897Smckusick 	register int stat, chan;
38253897Smckusick 	int retval = 0;
38353897Smckusick 
38453897Smckusick 	LED_ON;
38553897Smckusick 
38653897Smckusick 	for (chan = 0, lance = lancesw; chan < NEN ; lance++, chan++) {
38753897Smckusick 		if ((lance->lance_flags & LANCE_ACTIVE) == 0)
38853897Smckusick 			continue;
38953897Smckusick 
39053897Smckusick 		reg = lance->lance_addr;
39153897Smckusick 		reg->rap = CSR0;
39253897Smckusick 		stat = reg->rdp & ~CSR_INEA;
39353897Smckusick 		if ((stat & CSR_INTR) == 0)
39453897Smckusick 			continue;
39553897Smckusick 
39653897Smckusick 		retval = 1;
39753897Smckusick 		reg->rdp = stat;
39853897Smckusick 		reg->rdp = CSR_INEA;
39953897Smckusick 
40053897Smckusick 		if (stat & CSR_ERR) {
40153897Smckusick 			if (stat & CSR_BABL)
40253897Smckusick 				printf("lance %d error: babl\n", chan);
40353897Smckusick 			if (stat & CSR_MISS)
40453897Smckusick 				lance->lance_stats.ens_lost++;
40553897Smckusick 			if (stat & CSR_MERR)
40653897Smckusick 				printf("lance %d error: merr\n", chan);
40753897Smckusick 		}
40853897Smckusick 		if (stat & CSR_RINT) {
40953897Smckusick 			lance->lance_stats.ens_frames++;
41053897Smckusick 			enrint(chan);
41153897Smckusick 		}
41253897Smckusick 		if (stat & CSR_TINT) {
41353897Smckusick 			lance->lance_stats.ens_xmit++;
41453897Smckusick 			enxint(chan);
41553897Smckusick 		}
41653897Smckusick 		if (stat & CSR_IDON)
41753897Smckusick 			lance->lance_flags |= LANCE_IDON;
41853897Smckusick 	}
41953897Smckusick 
42053897Smckusick 	LED_OFF;
42153897Smckusick 
42253897Smckusick 	return (retval);
42353897Smckusick }
42453897Smckusick 
42553897Smckusick lance_init(chan)
42653897Smckusick 	int chan;
42753897Smckusick {
42853897Smckusick 	register Lance_chan *lance = &lancesw[chan];
42953897Smckusick 	register int s;
43053897Smckusick 
43153897Smckusick 	s = splimp();
43253897Smckusick 	lance_write_reg(chan, CSR1, INIT_BLOCK & 0xffff);
43353897Smckusick 	lance_write_reg(chan, CSR2, INIT_BLOCK >> 16);
43453897Smckusick 	lance_write_reg(chan, CSR3, CSR_BSWP|CSR_BCON);
43553897Smckusick 
43653897Smckusick 	lance_write_reg(chan, CSR0, CSR_INEA|CSR_STRT|CSR_INIT);
43753897Smckusick 	(void) splx(s);
43853897Smckusick 
43953897Smckusick 	while ((lance->lance_flags & LANCE_IDON) == 0)
44053897Smckusick 		;
44153897Smckusick }
44253897Smckusick 
44353897Smckusick recv_error(lance, rmd)
44453897Smckusick 	register Lance_chan *lance;
44553897Smckusick 	register recv_msg_desc *rmd;
44653897Smckusick {
44753897Smckusick 	register int status = rmd->rmd_stat;
44853897Smckusick 	register int chan = lance - lancesw;
44953897Smckusick 
45053897Smckusick 	if (status & RMD_FRAM)
45153897Smckusick 		lance->lance_stats.ens_align++;
45253897Smckusick 	if (status & RMD_OFLO)
45353897Smckusick 		printf("lance %d recv error: overflow\n", chan);
45453897Smckusick 	if (status & RMD_CRC)
45553897Smckusick 		lance->lance_stats.ens_crc++;
45653897Smckusick 	if (status & RMD_BUFF)
45753897Smckusick 		printf("lance %d:recv error: buffer\n", chan);
45853897Smckusick }
45953897Smckusick 
46053897Smckusick xmit_error(lance, tmd)
46153897Smckusick 	register Lance_chan *lance;
46253897Smckusick 	register xmit_msg_desc *tmd;
46353897Smckusick {
46453897Smckusick 	register int status = tmd->tmd_error;
46553897Smckusick 	register int chan = lance - lancesw;
46653897Smckusick 
46753897Smckusick 	if (status & TMD_BUFF)
46853897Smckusick 		printf("lance %d: xmit error: buffer\n", chan);
46953897Smckusick 	if (status & TMD_UFLO)
47053897Smckusick 		printf("lance %d: xmit error: underflow\n", chan);
47153897Smckusick 	if (status & TMD_LCOL) {
47253897Smckusick 		printf("lance %d: xmit error: late collision\n", chan);
47353897Smckusick 		lance->lance_stats.ens_owcollis++;
47453897Smckusick 	}
47553897Smckusick 	if (status & TMD_LCAR)
47653897Smckusick 		printf("lance %d: xmit error: loss of carrier\n", chan);
47753897Smckusick 	if (status & TMD_RTRY) {
47853897Smckusick 		printf("lance %d: xmit error: retry tdr=%d\n",
47953897Smckusick 		    chan, status & TMD_TDR);
48053897Smckusick 		lance->lance_stats.ens_xcollis++;
48153897Smckusick 	}
48253897Smckusick }
48353897Smckusick 
48453897Smckusick lance_write_reg(chan, reg, data)
48553897Smckusick 	int chan, reg, data;
48653897Smckusick {
48753897Smckusick 	register Lance_reg *lance = lancesw[chan].lance_addr;
48853897Smckusick 	register int s;
48953897Smckusick 
49053897Smckusick 	s = spl7();
49153897Smckusick 	lance->rap = reg;
49253897Smckusick 	lance->rdp = data;
49353897Smckusick 	(void) splx(s);
49453897Smckusick }
49553897Smckusick 
49653897Smckusick lance_read_reg(chan, reg)
49753897Smckusick 	int chan, reg;
49853897Smckusick {
49953897Smckusick 	register Lance_reg *lance = lancesw[chan].lance_addr;
50053897Smckusick 	register int s, d;
50153897Smckusick 
50253897Smckusick 	s = spl7();
50353897Smckusick 	lance->rap = reg;
50453897Smckusick 	d = lance->rdp;
50553897Smckusick 	(void) splx(s);
50653897Smckusick 
50753897Smckusick 	return (d);
50853897Smckusick }
50953897Smckusick 
51053897Smckusick get_hard_addr(chan, addr)
51153897Smckusick 	int chan;
51253897Smckusick 	u_short *addr;
51353897Smckusick {
51453897Smckusick 	register unsigned char *p, *q;
51553897Smckusick 	register int i;
51653897Smckusick 	register Lance_chan *lance = &lancesw[chan];
51753897Smckusick 	unsigned char hard_addr[6];
51853897Smckusick 
51953897Smckusick 	p = (unsigned char *)lance->lance_rom + 16;
52053897Smckusick 	q = hard_addr;
52153897Smckusick 	for (i = 0; i < 6; i++) {
52253897Smckusick 		*q = (*p++ & 0xf) << 4;
52353897Smckusick 		*q++ |= *p++ & 0xf;
52453897Smckusick 	}
52553897Smckusick 
52653897Smckusick 	bcopy(hard_addr, (char *)addr, 6);
52753897Smckusick }
52853897Smckusick 
52953897Smckusick #if defined(mips) && defined(CPU_SINGLE)
53053897Smckusick bxcopy(s, d, n)
53153897Smckusick 	caddr_t s, d;
53253897Smckusick 	int n;
53353897Smckusick {
53453897Smckusick 
53553897Smckusick 	if (n <= 0)
53653897Smckusick 		return;
53753897Smckusick 	switch ((((int)s & 03) << 2) + ((int)d & 03)) {
53853897Smckusick 
53953897Smckusick 	case 0x0:
54053897Smckusick 		blcopy((long *)s, (long *)d, n);
54153897Smckusick 		return;
54253897Smckusick 
54353897Smckusick 	case 0x5:
54453897Smckusick 		*(char *)d = *(char *)s;
54553897Smckusick 		blcopy((long *)(s + 1), (long *)(d + 1), n - 1);
54653897Smckusick 		return;
54753897Smckusick 
54853897Smckusick 	case 0xa:
54953897Smckusick 		switch (n) {
55053897Smckusick 
55153897Smckusick 		case 1:
55253897Smckusick 			*(char *)d = *(char *)s;
55353897Smckusick 			return;
55453897Smckusick 
55553897Smckusick 		case 2:
55653897Smckusick 			*(short *)d = *(short *)s;
55753897Smckusick 			return;
55853897Smckusick 
55953897Smckusick 		default:
56053897Smckusick 			*(short *)d = *(short *)s;
56153897Smckusick 			blcopy((long *)(s + 2), (long *)(d + 2), n - 2);
56253897Smckusick 			return;
56353897Smckusick 		}
56453897Smckusick 
56553897Smckusick 	case 0xf:
56653897Smckusick 		switch (n) {
56753897Smckusick 
56853897Smckusick 		case 1:
56953897Smckusick 			*(char *)d = *(char *)s;
57053897Smckusick 			return;
57153897Smckusick 
57253897Smckusick 		case 2:
57353897Smckusick 			*(char *)d = *(char *)s;
57453897Smckusick 			*(char *)(d + 1) = *(char *)(s + 1);
57553897Smckusick 			return;
57653897Smckusick 
57753897Smckusick 		case 3:
57853897Smckusick 			*(char *)d = *(char *)s;
57953897Smckusick 			*(short *)(d + 1) = *(short *)(s + 1);
58053897Smckusick 			return;
58153897Smckusick 
58253897Smckusick 		default:
58353897Smckusick 			*(char *)d = *(char *)s;
58453897Smckusick 			*(short *)(d + 1) = *(short *)(s + 1);
58553897Smckusick 			blcopy((long *)(s + 3), (long *)(d + 3), n - 3);
58653897Smckusick 			return;
58753897Smckusick 		}
58853897Smckusick 
58953897Smckusick 	case 0x7:
59053897Smckusick 	case 0xd:
59153897Smckusick 		switch (n) {
59253897Smckusick 
59353897Smckusick 		case 1:
59453897Smckusick 			*(char *)d = *(char *)s;
59553897Smckusick 			return;
59653897Smckusick 
59753897Smckusick 		case 2:
59853897Smckusick 			*(char *)d = *(char *)s;
59953897Smckusick 			*(char *)(d + 1) = *(char *)(s + 1);
60053897Smckusick 			return;
60153897Smckusick 
60253897Smckusick 		default:
60353897Smckusick 			*(char *)d = *(char *)s;
60453897Smckusick 			bwcopy((short *)(s + 1), (short *)(d + 1), n);
60553897Smckusick 			return;
60653897Smckusick 		}
60753897Smckusick 
60853897Smckusick 	case 0x2:
60953897Smckusick 	case 0x8:
61053897Smckusick 		bwcopy((short *)s, (short *)d, n);
61153897Smckusick 		return;
61253897Smckusick 
61353897Smckusick 	default:
61453897Smckusick 		bbcopy((char *)s, (char *)d, n);
61553897Smckusick 		return;
61653897Smckusick 	}
61753897Smckusick }
61853897Smckusick 
61953897Smckusick #define	COPY(s, d, n, t) \
62053897Smckusick 	while ((n) >= 8 * sizeof (t)) { \
62153897Smckusick 		int t0, t1, t2, t3, t4, t5, t6, t7; \
62253897Smckusick 		t0 = (s)[0]; \
62353897Smckusick 		t1 = (s)[1]; \
62453897Smckusick 		t2 = (s)[2]; \
62553897Smckusick 		t3 = (s)[3]; \
62653897Smckusick 		t4 = (s)[4]; \
62753897Smckusick 		t5 = (s)[5]; \
62853897Smckusick 		t6 = (s)[6]; \
62953897Smckusick 		t7 = (s)[7]; \
63053897Smckusick 		(d)[0] = t0; \
63153897Smckusick 		(d)[1] = t1; \
63253897Smckusick 		(d)[2] = t2; \
63353897Smckusick 		(d)[3] = t3; \
63453897Smckusick 		(d)[4] = t4; \
63553897Smckusick 		(d)[5] = t5; \
63653897Smckusick 		(d)[6] = t6; \
63753897Smckusick 		(d)[7] = t7; \
63853897Smckusick 		(s) += 8; \
63953897Smckusick 		(d) += 8; \
64053897Smckusick 		(n) -= 8 * sizeof (t); \
64153897Smckusick 	} \
64253897Smckusick 	while ((n) >= sizeof (t)) { \
64353897Smckusick 		(d)[0] = (s)[0]; \
64453897Smckusick 		(s)++; \
64553897Smckusick 		(d)++; \
64653897Smckusick 		(n) -= sizeof (t); \
64753897Smckusick 	}
64853897Smckusick 
64953897Smckusick blcopy(s, d, n)
65053897Smckusick 	long *s, *d;
65153897Smckusick 	int n;
65253897Smckusick {
65353897Smckusick 
65453897Smckusick 	COPY(s, d, n, long);
65553897Smckusick 	switch (n) {
65653897Smckusick 
65753897Smckusick 	case 0:
65853897Smckusick 		return;
65953897Smckusick 
66053897Smckusick 	case 1:
66153897Smckusick 		*(char *)d = *(char *)s;
66253897Smckusick 		return;
66353897Smckusick 
66453897Smckusick 	case 2:
66553897Smckusick 		*(short *)d = *(short *)s;
66653897Smckusick 		return;
66753897Smckusick 
66853897Smckusick 	case 3:
66953897Smckusick 		*(short *)d = *(short *)s;
67053897Smckusick 		*((char *)d + 2) = *((char *)s + 2);
67153897Smckusick 		return;
67253897Smckusick 	}
67353897Smckusick }
67453897Smckusick 
67553897Smckusick bwcopy(s, d, n)
67653897Smckusick 	short *s, *d;
67753897Smckusick 	int n;
67853897Smckusick {
67953897Smckusick 
68053897Smckusick 	COPY(s, d, n, short);
68153897Smckusick 	if (n == 1)
68253897Smckusick 		*(char *)d = *(char *)s;
68353897Smckusick }
68453897Smckusick 
68553897Smckusick bbcopy(s, d, n)
68653897Smckusick 	char *s, *d;
68753897Smckusick 	int n;
68853897Smckusick {
68953897Smckusick 
69053897Smckusick 	COPY(s, d, n, char);
69153897Smckusick }
69253897Smckusick #endif /* defined(mips) && defined(CPU_SINGLE) */
69353897Smckusick 
69453897Smckusick #endif /* NEN > 0 */
695