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