xref: /csrg-svn/sys/vax/if/if_de.c (revision 19861)
1*19861Skarels /*	if_de.c	6.8	85/05/01	*/
215357Skarels #include "de.h"
315357Skarels #if NDE > 0
415357Skarels 
515357Skarels /*
615357Skarels  * DEC DEUNA interface
715357Skarels  *
815357Skarels  *	Lou Salkind
915357Skarels  *	New York University
1015357Skarels  *
1115357Skarels  * TODO:
1215357Skarels  *	timeout routine (get statistics)
1315357Skarels  */
1415357Skarels #include "../machine/pte.h"
1515357Skarels 
1617110Sbloom #include "param.h"
1717110Sbloom #include "systm.h"
1817110Sbloom #include "mbuf.h"
1917110Sbloom #include "buf.h"
2017110Sbloom #include "protosw.h"
2117110Sbloom #include "socket.h"
2217110Sbloom #include "vmmac.h"
2317110Sbloom #include "ioctl.h"
2417110Sbloom #include "errno.h"
2515357Skarels 
2615357Skarels #include "../net/if.h"
2715357Skarels #include "../net/netisr.h"
2815357Skarels #include "../net/route.h"
2915357Skarels #include "../netinet/in.h"
3015357Skarels #include "../netinet/in_systm.h"
31*19861Skarels #include "../netinet/in_var.h"
3215357Skarels #include "../netinet/ip.h"
3315357Skarels #include "../netinet/ip_var.h"
3415357Skarels #include "../netinet/if_ether.h"
3515357Skarels #include "../netpup/pup.h"
3615357Skarels 
3715357Skarels #include "../vax/cpu.h"
3815357Skarels #include "../vax/mtpr.h"
3917110Sbloom #include "if_dereg.h"
4017110Sbloom #include "if_uba.h"
4115357Skarels #include "../vaxuba/ubareg.h"
4215357Skarels #include "../vaxuba/ubavar.h"
4315357Skarels 
4415357Skarels #define	NXMT	2	/* number of transmit buffers */
4515357Skarels #define	NRCV	4	/* number of receive buffers (must be > 1) */
4615357Skarels #define	NTOT	(NXMT + NRCV)
4715357Skarels 
4816279Skarels int	dedebug = 0;
4915916Skarels 
5015357Skarels int	deprobe(), deattach(), deintr();
5115357Skarels struct	uba_device *deinfo[NDE];
5215357Skarels u_short destd[] = { 0 };
5315357Skarels struct	uba_driver dedriver =
5415357Skarels 	{ deprobe, 0, deattach, 0, destd, "de", deinfo };
5515357Skarels int	deinit(),deoutput(),deioctl(),dereset();
5615357Skarels struct	mbuf *deget();
5715357Skarels 
5815357Skarels 
5915357Skarels /*
6016208Skarels  * The deuba structures generalizes the ifuba structure
6116208Skarels  * to an arbitrary number of receive and transmit buffers.
6215357Skarels  */
6316208Skarels struct	ifxmt {
6416208Skarels 	struct	ifrw x_ifrw;			/* mapping information */
6516208Skarels 	struct	pte x_map[IF_MAXNUBAMR];	/* output base pages */
6616208Skarels 	short	x_xswapd;			/* mask of clusters swapped */
6716208Skarels 	struct	mbuf *x_xtofree;		/* pages being dma'ed out */
6816208Skarels };
6916208Skarels 
7015357Skarels struct	deuba {
7115357Skarels 	short	ifu_uban;		/* uba number */
7215357Skarels 	short	ifu_hlen;		/* local net header length */
7315357Skarels 	struct	uba_regs *ifu_uba;	/* uba regs, in vm */
7415357Skarels 	struct	ifrw ifu_r[NRCV];	/* receive information */
7516208Skarels 	struct	ifxmt ifu_w[NXMT];	/* transmit information */
7615357Skarels 	short	ifu_flags;		/* used during uballoc's */
7715357Skarels };
7815357Skarels 
7915357Skarels /*
8015357Skarels  * Ethernet software status per interface.
8115357Skarels  *
8215357Skarels  * Each interface is referenced by a network interface structure,
8315357Skarels  * ds_if, which the routing code uses to locate the interface.
8415357Skarels  * This structure contains the output queue for the interface, its address, ...
8515357Skarels  * We also have, for each interface, a UBA interface structure, which
8615357Skarels  * contains information about the UNIBUS resources held by the interface:
8715357Skarels  * map registers, buffered data paths, etc.  Information is cached in this
8815357Skarels  * structure for use by the if_uba.c routines in running the interface
8915357Skarels  * efficiently.
9015357Skarels  */
9115357Skarels struct	de_softc {
9215357Skarels 	struct	arpcom ds_ac;		/* Ethernet common part */
9315357Skarels #define	ds_if	ds_ac.ac_if		/* network-visible interface */
9415357Skarels #define	ds_addr	ds_ac.ac_enaddr		/* hardware Ethernet address */
9515357Skarels 	int	ds_flags;
9615357Skarels #define	DSF_LOCK	1		/* lock out destart */
9715916Skarels #define	DSF_RUNNING	2
9815357Skarels 	int	ds_ubaddr;		/* map info for incore structs */
9915357Skarels 	struct	deuba ds_deuba;		/* unibus resource structure */
10015357Skarels 	/* the following structures are always mapped in */
10115357Skarels 	struct	de_pcbb ds_pcbb;	/* port control block */
10215357Skarels 	struct	de_ring ds_xrent[NXMT];	/* transmit ring entrys */
10315357Skarels 	struct	de_ring ds_rrent[NRCV];	/* receive ring entrys */
10415357Skarels 	struct	de_udbbuf ds_udbbuf;	/* UNIBUS data buffer */
10515357Skarels 	/* end mapped area */
10615357Skarels #define	INCORE_BASE(p)	((char *)&(p)->ds_pcbb)
10715357Skarels #define	RVAL_OFF(n)	((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0]))
10815357Skarels #define	LVAL_OFF(n)	((char *)de_softc[0].n - INCORE_BASE(&de_softc[0]))
10915357Skarels #define	PCBB_OFFSET	RVAL_OFF(ds_pcbb)
11015357Skarels #define	XRENT_OFFSET	LVAL_OFF(ds_xrent)
11115357Skarels #define	RRENT_OFFSET	LVAL_OFF(ds_rrent)
11215357Skarels #define	UDBBUF_OFFSET	RVAL_OFF(ds_udbbuf)
11315357Skarels #define	INCORE_SIZE	RVAL_OFF(ds_xindex)
11415357Skarels 	int	ds_xindex;		/* UNA index into transmit chain */
11515357Skarels 	int	ds_rindex;		/* UNA index into receive chain */
11615357Skarels 	int	ds_xfree;		/* index for next transmit buffer */
11715357Skarels 	int	ds_nxmit;		/* # of transmits in progress */
11815357Skarels } de_softc[NDE];
11915357Skarels 
12015357Skarels deprobe(reg)
12115357Skarels 	caddr_t reg;
12215357Skarels {
12315357Skarels 	register int br, cvec;		/* r11, r10 value-result */
12415357Skarels 	register struct dedevice *addr = (struct dedevice *)reg;
12515357Skarels 	register i;
12615357Skarels 
12715357Skarels #ifdef lint
12815357Skarels 	br = 0; cvec = br; br = cvec;
12915357Skarels 	i = 0; derint(i); deintr(i);
13015357Skarels #endif
13115357Skarels 
13215357Skarels 	addr->pcsr0 = PCSR0_RSET;
13315357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
13415357Skarels 		;
13515357Skarels 	/* make board interrupt by executing a GETPCBB command */
13615357Skarels 	addr->pcsr0 = PCSR0_INTE;
13715357Skarels 	addr->pcsr2 = 0;
13815357Skarels 	addr->pcsr3 = 0;
13915357Skarels 	addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;
14015357Skarels 	DELAY(100000);
14115357Skarels 	return(1);
14215357Skarels }
14315357Skarels 
14415357Skarels /*
14515357Skarels  * Interface exists: make available by filling in network interface
14615357Skarels  * record.  System will initialize the interface when it is ready
14715357Skarels  * to accept packets.  We get the ethernet address here.
14815357Skarels  */
14915357Skarels deattach(ui)
15015357Skarels 	struct uba_device *ui;
15115357Skarels {
15215357Skarels 	register struct de_softc *ds = &de_softc[ui->ui_unit];
15315357Skarels 	register struct ifnet *ifp = &ds->ds_if;
15415357Skarels 	register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
15515357Skarels 	int csr0;
15615357Skarels 
15715357Skarels 	ifp->if_unit = ui->ui_unit;
15815357Skarels 	ifp->if_name = "de";
15915357Skarels 	ifp->if_mtu = ETHERMTU;
160*19861Skarels 	ifp->if_flags = IFF_BROADCAST;
16115357Skarels 
16215357Skarels 	/*
16315357Skarels 	 * Reset the board and temporarily map
16415357Skarels 	 * the pcbb buffer onto the Unibus.
16515357Skarels 	 */
16615357Skarels 	addr->pcsr0 = PCSR0_RSET;
16715357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
16815357Skarels 		;
16915357Skarels 	csr0 = addr->pcsr0;
17015357Skarels 	addr->pchigh = csr0 >> 8;
17115357Skarels 	if (csr0 & PCSR0_PCEI)
17215357Skarels 		printf("de%d: reset failed, csr0=%b csr1=%b\n", ui->ui_unit,
17315357Skarels 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
17415357Skarels 	ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb,
17515357Skarels 		sizeof (struct de_pcbb), 0);
17615357Skarels 	addr->pcsr2 = ds->ds_ubaddr & 0xffff;
17715357Skarels 	addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
17815357Skarels 	addr->pclow = CMD_GETPCBB;
17915357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
18015357Skarels 		;
18115357Skarels 	csr0 = addr->pcsr0;
18215357Skarels 	addr->pchigh = csr0 >> 8;
18315357Skarels 	if (csr0 & PCSR0_PCEI)
18415357Skarels 		printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit,
18515357Skarels 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
18615357Skarels 	ds->ds_pcbb.pcbb0 = FC_RDPHYAD;
18715357Skarels 	addr->pclow = CMD_GETCMD;
18815357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
18915357Skarels 		;
19015357Skarels 	csr0 = addr->pcsr0;
19115357Skarels 	addr->pchigh = csr0 >> 8;
19215357Skarels 	if (csr0 & PCSR0_PCEI)
19315357Skarels 		printf("de%d: rdphyad failed, csr0=%b csr1=%b\n", ui->ui_unit,
19415357Skarels 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
19515357Skarels 	ubarelse(ui->ui_ubanum, &ds->ds_ubaddr);
19615916Skarels 	if (dedebug)
19715916Skarels 		printf("de%d: addr=%d:%d:%d:%d:%d:%d\n", ui->ui_unit,
19815916Skarels 		    ds->ds_pcbb.pcbb2&0xff, (ds->ds_pcbb.pcbb2>>8)&0xff,
19915916Skarels 		    ds->ds_pcbb.pcbb4&0xff, (ds->ds_pcbb.pcbb4>>8)&0xff,
20015916Skarels 		    ds->ds_pcbb.pcbb6&0xff, (ds->ds_pcbb.pcbb6>>8)&0xff);
201*19861Skarels  	bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
20215357Skarels 	    sizeof (ds->ds_addr));
20315357Skarels 	ifp->if_init = deinit;
20415357Skarels 	ifp->if_output = deoutput;
20515357Skarels 	ifp->if_ioctl = deioctl;
20615357Skarels 	ifp->if_reset = dereset;
20715357Skarels 	ds->ds_deuba.ifu_flags = UBA_CANTWAIT;
20815357Skarels #ifdef notdef
20915357Skarels 	/* CAN WE USE BDP's ??? */
21015357Skarels 	ds->ds_deuba.ifu_flags |= UBA_NEEDBDP;
21115357Skarels #endif
21215357Skarels 	if_attach(ifp);
21315357Skarels }
21415357Skarels 
21515357Skarels /*
21615357Skarels  * Reset of interface after UNIBUS reset.
21715357Skarels  * If interface is on specified uba, reset its state.
21815357Skarels  */
21915357Skarels dereset(unit, uban)
22015357Skarels 	int unit, uban;
22115357Skarels {
22215357Skarels 	register struct uba_device *ui;
22315357Skarels 
22415357Skarels 	if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 ||
22515357Skarels 	    ui->ui_ubanum != uban)
22615357Skarels 		return;
22715357Skarels 	printf(" de%d", unit);
228*19861Skarels 	de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
22915357Skarels 	deinit(unit);
23015357Skarels }
23115357Skarels 
23215357Skarels /*
23315357Skarels  * Initialization of interface; clear recorded pending
23415357Skarels  * operations, and reinitialize UNIBUS usage.
23515357Skarels  */
23615357Skarels deinit(unit)
23715357Skarels 	int unit;
23815357Skarels {
23915357Skarels 	register struct de_softc *ds = &de_softc[unit];
24015357Skarels 	register struct uba_device *ui = deinfo[unit];
24115357Skarels 	register struct dedevice *addr;
24215357Skarels 	register struct ifrw *ifrw;
24316208Skarels 	register struct ifxmt *ifxp;
24416208Skarels 	struct ifnet *ifp = &ds->ds_if;
24515357Skarels 	int s;
24615357Skarels 	struct de_ring *rp;
24715357Skarels 	int incaddr;
24815357Skarels 	int csr0;
24915357Skarels 
250*19861Skarels 	/* not yet, if address still unknown */
251*19861Skarels 	if (ifp->if_addrlist == (struct ifaddr *)0)
25215357Skarels 		return;
25315357Skarels 
25415357Skarels 	if (ifp->if_flags & IFF_RUNNING)
255*19861Skarels 		return;
25615357Skarels 	if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum,
25715357Skarels 	    sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) {
25815357Skarels 		printf("de%d: can't initialize\n", unit);
25915357Skarels 		ds->ds_if.if_flags &= ~IFF_UP;
26015357Skarels 		return;
26115357Skarels 	}
26215357Skarels 	ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), INCORE_SIZE,0);
26315357Skarels 	addr = (struct dedevice *)ui->ui_addr;
26415357Skarels 
26515357Skarels 	/* set the pcbb block address */
26615357Skarels 	incaddr = ds->ds_ubaddr + PCBB_OFFSET;
26715357Skarels 	addr->pcsr2 = incaddr & 0xffff;
26815357Skarels 	addr->pcsr3 = (incaddr >> 16) & 0x3;
26915357Skarels 	addr->pclow = CMD_GETPCBB;
27015357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
27115357Skarels 		;
27215357Skarels 	csr0 = addr->pcsr0;
27315357Skarels 	addr->pchigh = csr0 >> 8;
27415357Skarels 	if (csr0 & PCSR0_PCEI)
27515357Skarels 		printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit,
27615357Skarels 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
27715357Skarels 
27815357Skarels 	/* set the transmit and receive ring header addresses */
27915357Skarels 	incaddr = ds->ds_ubaddr + UDBBUF_OFFSET;
28015357Skarels 	ds->ds_pcbb.pcbb0 = FC_WTRING;
28115357Skarels 	ds->ds_pcbb.pcbb2 = incaddr & 0xffff;
28215357Skarels 	ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;
28315357Skarels 
28415357Skarels 	incaddr = ds->ds_ubaddr + XRENT_OFFSET;
28515357Skarels 	ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;
28615357Skarels 	ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;
28715357Skarels 	ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);
28815357Skarels 	ds->ds_udbbuf.b_trlen = NXMT;
28915357Skarels 	incaddr = ds->ds_ubaddr + RRENT_OFFSET;
29015357Skarels 	ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;
29115357Skarels 	ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;
29215357Skarels 	ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);
29315357Skarels 	ds->ds_udbbuf.b_rrlen = NRCV;
29415357Skarels 
29515357Skarels 	addr->pclow = CMD_GETCMD;
29615357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
29715357Skarels 		;
29815357Skarels 	csr0 = addr->pcsr0;
29915357Skarels 	addr->pchigh = csr0 >> 8;
30015357Skarels 	if (csr0 & PCSR0_PCEI)
30115357Skarels 		printf("de%d: wtring failed, csr0=%b csr1=%b\n", ui->ui_unit,
30215357Skarels 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
30315357Skarels 
30415357Skarels 	/* initialize the mode - enable hardware padding */
30515357Skarels 	ds->ds_pcbb.pcbb0 = FC_WTMODE;
30615357Skarels 	/* let hardware do padding - set MTCH bit on broadcast */
30715357Skarels 	ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;
30815357Skarels 	addr->pclow = CMD_GETCMD;
30915357Skarels 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
31015357Skarels 		;
31115357Skarels 	csr0 = addr->pcsr0;
31215357Skarels 	addr->pchigh = csr0 >> 8;
31315357Skarels 	if (csr0 & PCSR0_PCEI)
31415357Skarels 		printf("de%d: wtmode failed, csr0=%b csr1=%b\n", ui->ui_unit,
31515357Skarels 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
31615357Skarels 
31715357Skarels 	/* set up the receive and transmit ring entries */
31816208Skarels 	ifxp = &ds->ds_deuba.ifu_w[0];
31915357Skarels 	for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
32016208Skarels 		rp->r_segbl = ifxp->x_ifrw.ifrw_info & 0xffff;
32116208Skarels 		rp->r_segbh = (ifxp->x_ifrw.ifrw_info >> 16) & 0x3;
32215357Skarels 		rp->r_flags = 0;
32316208Skarels 		ifxp++;
32415357Skarels 	}
32515357Skarels 	ifrw = &ds->ds_deuba.ifu_r[0];
32615357Skarels 	for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
32715357Skarels 		rp->r_slen = sizeof (struct de_buf);
32815357Skarels 		rp->r_segbl = ifrw->ifrw_info & 0xffff;
32915357Skarels 		rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
33015357Skarels 		rp->r_flags = RFLG_OWN;		/* hang receive */
33115357Skarels 		ifrw++;
33215357Skarels 	}
33315357Skarels 
33415357Skarels 	/* start up the board (rah rah) */
33515357Skarels 	s = splimp();
33615357Skarels 	ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0;
337*19861Skarels 	ds->ds_if.if_flags |= IFF_RUNNING;
33815916Skarels 	destart(unit);				/* queue output packets */
33915357Skarels 	addr->pclow = PCSR0_INTE;		/* avoid interlock */
34015357Skarels 	addr->pclow = CMD_START | PCSR0_INTE;
34115916Skarels 	ds->ds_flags |= DSF_RUNNING;
34215357Skarels 	splx(s);
34315357Skarels }
34415357Skarels 
34515357Skarels /*
34615357Skarels  * Setup output on interface.
34715357Skarels  * Get another datagram to send off of the interface queue,
34815357Skarels  * and map it to the interface before starting the output.
34915357Skarels  */
35015357Skarels destart(unit)
35115357Skarels 	int unit;
35215357Skarels {
35315357Skarels         int len;
35415357Skarels 	struct uba_device *ui = deinfo[unit];
35515357Skarels 	struct dedevice *addr = (struct dedevice *)ui->ui_addr;
35615357Skarels 	register struct de_softc *ds = &de_softc[unit];
35715357Skarels 	register struct de_ring *rp;
35815357Skarels 	struct mbuf *m;
35915357Skarels 	register int nxmit;
36015357Skarels 
36115357Skarels 	/*
36215357Skarels 	 * the following test is necessary, since
36315357Skarels 	 * the code is not reentrant and we have
36415357Skarels 	 * multiple transmission buffers.
36515357Skarels 	 */
36615357Skarels 	if (ds->ds_flags & DSF_LOCK)
36715357Skarels 		return;
36815357Skarels 	for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {
36915357Skarels 		IF_DEQUEUE(&ds->ds_if.if_snd, m);
37015357Skarels 		if (m == 0)
37115357Skarels 			break;
37215357Skarels 		rp = &ds->ds_xrent[ds->ds_xfree];
37315357Skarels 		if (rp->r_flags & XFLG_OWN)
37415357Skarels 			panic("deuna xmit in progress");
37516208Skarels 		len = deput(&ds->ds_deuba, ds->ds_xfree, m);
37615357Skarels 		if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)
37715357Skarels 			UBAPURGE(ds->ds_deuba.ifu_uba,
37816208Skarels 			ds->ds_deuba.ifu_w[ds->ds_xfree].x_ifrw.ifrw_bdp);
37915357Skarels 		rp->r_slen = len;
38015357Skarels 		rp->r_tdrerr = 0;
38115357Skarels 		rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
38215357Skarels 
38315357Skarels 		ds->ds_xfree++;
38415357Skarels 		if (ds->ds_xfree == NXMT)
38515357Skarels 			ds->ds_xfree = 0;
38615357Skarels 	}
38715357Skarels 	if (ds->ds_nxmit != nxmit) {
38815357Skarels 		ds->ds_nxmit = nxmit;
38915916Skarels 		if (ds->ds_flags & DSF_RUNNING)
39015357Skarels 			addr->pclow = PCSR0_INTE|CMD_PDMD;
39115357Skarels 	}
39215357Skarels }
39315357Skarels 
39415357Skarels /*
39515357Skarels  * Command done interrupt.
39615357Skarels  */
39715357Skarels deintr(unit)
39815357Skarels 	int unit;
39915357Skarels {
40015357Skarels 	struct uba_device *ui = deinfo[unit];
40115357Skarels 	register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
40215357Skarels 	register struct de_softc *ds = &de_softc[unit];
40315357Skarels 	register struct de_ring *rp;
40416208Skarels 	register struct ifxmt *ifxp;
40515357Skarels 	short csr0;
40615357Skarels 
40715357Skarels 	/* save flags right away - clear out interrupt bits */
40815357Skarels 	csr0 = addr->pcsr0;
40915357Skarels 	addr->pchigh = csr0 >> 8;
41015357Skarels 
41115357Skarels 
41215357Skarels 	ds->ds_flags |= DSF_LOCK;	/* prevent entering destart */
41315357Skarels 	/*
41415357Skarels 	 * if receive, put receive buffer on mbuf
41515357Skarels 	 * and hang the request again
41615357Skarels 	 */
41715357Skarels 	derecv(unit);
41815357Skarels 
41915357Skarels 	/*
42015357Skarels 	 * Poll transmit ring and check status.
42115357Skarels 	 * Be careful about loopback requests.
42215357Skarels 	 * Then free buffer space and check for
42315357Skarels 	 * more transmit requests.
42415357Skarels 	 */
42515357Skarels 	for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {
42615357Skarels 		rp = &ds->ds_xrent[ds->ds_xindex];
42715357Skarels 		if (rp->r_flags & XFLG_OWN)
42815357Skarels 			break;
42915357Skarels 		ds->ds_if.if_opackets++;
43016208Skarels 		ifxp = &ds->ds_deuba.ifu_w[ds->ds_xindex];
43115357Skarels 		/* check for unusual conditions */
43215357Skarels 		if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
43315357Skarels 			if (rp->r_flags & XFLG_ERRS) {
43415357Skarels 				/* output error */
43515357Skarels 				ds->ds_if.if_oerrors++;
43615916Skarels 				if (dedebug)
43715357Skarels 			printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",
43815357Skarels 				    unit, rp->r_flags, XFLG_BITS,
43915357Skarels 				    rp->r_tdrerr, XERR_BITS, rp->r_slen);
44015357Skarels 			} else if (rp->r_flags & XFLG_ONE) {
44115357Skarels 				/* one collision */
44215357Skarels 				ds->ds_if.if_collisions++;
44315357Skarels 			} else if (rp->r_flags & XFLG_MORE) {
44415357Skarels 				/* more than one collision */
44515357Skarels 				ds->ds_if.if_collisions += 2;	/* guess */
44615357Skarels 			} else if (rp->r_flags & XFLG_MTCH) {
44715357Skarels 				/* received our own packet */
44815357Skarels 				ds->ds_if.if_ipackets++;
44916208Skarels 				deread(ds, &ifxp->x_ifrw,
45015357Skarels 				    rp->r_slen - sizeof (struct ether_header));
45115357Skarels 			}
45215357Skarels 		}
45316208Skarels 		if (ifxp->x_xtofree) {
45416208Skarels 			m_freem(ifxp->x_xtofree);
45516208Skarels 			ifxp->x_xtofree = 0;
45616208Skarels 		}
45715357Skarels 		/* check if next transmit buffer also finished */
45815357Skarels 		ds->ds_xindex++;
45915357Skarels 		if (ds->ds_xindex == NXMT)
46015357Skarels 			ds->ds_xindex = 0;
46115357Skarels 	}
46215357Skarels 	ds->ds_flags &= ~DSF_LOCK;
46315357Skarels 	destart(unit);
46415357Skarels 
46515357Skarels 	if (csr0 & PCSR0_RCBI) {
46615357Skarels 		printf("de%d: buffer unavailable\n", unit);
46715357Skarels 		addr->pclow = PCSR0_INTE|CMD_PDMD;
46815357Skarels 	}
46915357Skarels }
47015357Skarels 
47115357Skarels /*
47215357Skarels  * Ethernet interface receiver interface.
47315357Skarels  * If input error just drop packet.
47415357Skarels  * Otherwise purge input buffered data path and examine
47515357Skarels  * packet to determine type.  If can't determine length
47615357Skarels  * from type, then have to drop packet.  Othewise decapsulate
47715357Skarels  * packet based on type and pass to type specific higher-level
47815357Skarels  * input routine.
47915357Skarels  */
48015357Skarels derecv(unit)
48115357Skarels 	int unit;
48215357Skarels {
48315357Skarels 	register struct de_softc *ds = &de_softc[unit];
48415357Skarels 	register struct de_ring *rp;
48515357Skarels 	int len;
48615357Skarels 
48715357Skarels 	rp = &ds->ds_rrent[ds->ds_rindex];
48815357Skarels 	while ((rp->r_flags & RFLG_OWN) == 0) {
48915357Skarels 		ds->ds_if.if_ipackets++;
49015357Skarels 		if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)
49115357Skarels 			UBAPURGE(ds->ds_deuba.ifu_uba,
49215357Skarels 			ds->ds_deuba.ifu_r[ds->ds_rindex].ifrw_bdp);
49315357Skarels 		len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
49415357Skarels 			- 4;	/* don't forget checksum! */
49515357Skarels 		/* check for errors */
49615357Skarels 		if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
49715357Skarels 		    (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
49815357Skarels 		    (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
49915357Skarels 		    len < ETHERMIN || len > ETHERMTU) {
50015357Skarels 			ds->ds_if.if_ierrors++;
50115916Skarels 			if (dedebug)
50215357Skarels 			printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",
50315357Skarels 				unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,
50415357Skarels 				RERR_BITS, len);
50515357Skarels 		} else
50615357Skarels 			deread(ds, &ds->ds_deuba.ifu_r[ds->ds_rindex], len);
50715357Skarels 
50815357Skarels 		/* hang the receive buffer again */
50915357Skarels 		rp->r_lenerr = 0;
51015357Skarels 		rp->r_flags = RFLG_OWN;
51115357Skarels 
51215357Skarels 		/* check next receive buffer */
51315357Skarels 		ds->ds_rindex++;
51415357Skarels 		if (ds->ds_rindex == NRCV)
51515357Skarels 			ds->ds_rindex = 0;
51615357Skarels 		rp = &ds->ds_rrent[ds->ds_rindex];
51715357Skarels 	}
51815357Skarels }
51915357Skarels 
52015357Skarels /*
52115357Skarels  * Pass a packet to the higher levels.
52215357Skarels  * We deal with the trailer protocol here.
52315357Skarels  */
52415357Skarels deread(ds, ifrw, len)
52515357Skarels 	register struct de_softc *ds;
52615357Skarels 	struct ifrw *ifrw;
52715357Skarels 	int len;
52815357Skarels {
52915357Skarels 	struct ether_header *eh;
53015357Skarels     	struct mbuf *m;
53115357Skarels 	int off, resid;
53216722Sbloom 	int s;
53315357Skarels 	register struct ifqueue *inq;
53415357Skarels 
53515357Skarels 	/*
536*19861Skarels 	 * Deal with trailer protocol: if type is trailer type
53715357Skarels 	 * get true type from first 16-bit word past data.
53815357Skarels 	 * Remember that type was trailer by setting off.
53915357Skarels 	 */
54015357Skarels 	eh = (struct ether_header *)ifrw->ifrw_addr;
54115357Skarels 	eh->ether_type = ntohs((u_short)eh->ether_type);
54215357Skarels #define	dedataaddr(eh, off, type)	((type)(((caddr_t)((eh)+1)+(off))))
543*19861Skarels 	if (eh->ether_type >= ETHERTYPE_TRAIL &&
544*19861Skarels 	    eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
545*19861Skarels 		off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
54615357Skarels 		if (off >= ETHERMTU)
54715357Skarels 			return;		/* sanity */
54815357Skarels 		eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
54915357Skarels 		resid = ntohs(*(dedataaddr(eh, off+2, u_short *)));
55015357Skarels 		if (off + resid > len)
55115357Skarels 			return;		/* sanity */
55215357Skarels 		len = off + resid;
55315357Skarels 	} else
55415357Skarels 		off = 0;
55515357Skarels 	if (len == 0)
55615357Skarels 		return;
55715357Skarels 
55815357Skarels 	/*
55915357Skarels 	 * Pull packet off interface.  Off is nonzero if packet
56015357Skarels 	 * has trailing header; deget will then force this header
56115357Skarels 	 * information to be at the front, but we still have to drop
56215357Skarels 	 * the type and length which are at the front of any trailer data.
56315357Skarels 	 */
56415357Skarels 	m = deget(&ds->ds_deuba, ifrw, len, off);
56515357Skarels 	if (m == 0)
56615357Skarels 		return;
56715357Skarels 	if (off) {
56815357Skarels 		m->m_off += 2 * sizeof (u_short);
56915357Skarels 		m->m_len -= 2 * sizeof (u_short);
57015357Skarels 	}
57115357Skarels 	switch (eh->ether_type) {
57215357Skarels 
57315357Skarels #ifdef INET
574*19861Skarels 	case ETHERTYPE_IP:
57515357Skarels 		schednetisr(NETISR_IP);
57615357Skarels 		inq = &ipintrq;
57715357Skarels 		break;
57815357Skarels 
579*19861Skarels 	case ETHERTYPE_ARP:
58015357Skarels 		arpinput(&ds->ds_ac, m);
58115357Skarels 		return;
58215357Skarels #endif
58315357Skarels 	default:
58415357Skarels 		m_freem(m);
58515357Skarels 		return;
58615357Skarels 	}
58715357Skarels 
58816722Sbloom 	s = splimp();
58915357Skarels 	if (IF_QFULL(inq)) {
59015357Skarels 		IF_DROP(inq);
59116722Sbloom 		splx(s);
59215357Skarels 		m_freem(m);
59315357Skarels 		return;
59415357Skarels 	}
59515357Skarels 	IF_ENQUEUE(inq, m);
59616722Sbloom 	splx(s);
59715357Skarels }
59815357Skarels 
59915357Skarels /*
60015357Skarels  * Ethernet output routine.
60115357Skarels  * Encapsulate a packet of type family for the local net.
60215357Skarels  * Use trailer local net encapsulation if enough data in first
60315357Skarels  * packet leaves a multiple of 512 bytes of data in remainder.
60415357Skarels  */
60515357Skarels deoutput(ifp, m0, dst)
60615357Skarels 	struct ifnet *ifp;
60715357Skarels 	struct mbuf *m0;
60815357Skarels 	struct sockaddr *dst;
60915357Skarels {
61015357Skarels 	int type, s, error;
611*19861Skarels  	u_char edst[6];
61215357Skarels 	struct in_addr idst;
61315357Skarels 	register struct de_softc *ds = &de_softc[ifp->if_unit];
61415357Skarels 	register struct mbuf *m = m0;
61515357Skarels 	register struct ether_header *eh;
61615357Skarels 	register int off;
61715357Skarels 
61815357Skarels 	switch (dst->sa_family) {
61915357Skarels 
62015357Skarels #ifdef INET
62115357Skarels 	case AF_INET:
62215357Skarels 		idst = ((struct sockaddr_in *)dst)->sin_addr;
623*19861Skarels  		if (!arpresolve(&ds->ds_ac, m, &idst, edst))
62415357Skarels 			return (0);	/* if not yet resolved */
62515357Skarels 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
62615357Skarels 		/* need per host negotiation */
62715357Skarels 		if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
62815357Skarels 		if (off > 0 && (off & 0x1ff) == 0 &&
62915357Skarels 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
630*19861Skarels 			type = ETHERTYPE_TRAIL + (off>>9);
63115357Skarels 			m->m_off -= 2 * sizeof (u_short);
63215357Skarels 			m->m_len += 2 * sizeof (u_short);
633*19861Skarels 			*mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
63415357Skarels 			*(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
63515357Skarels 			goto gottrailertype;
63615357Skarels 		}
637*19861Skarels 		type = ETHERTYPE_IP;
63815357Skarels 		off = 0;
63915357Skarels 		goto gottype;
64015357Skarels #endif
64115357Skarels 
64215357Skarels 	case AF_UNSPEC:
64315357Skarels 		eh = (struct ether_header *)dst->sa_data;
644*19861Skarels  		bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
64515357Skarels 		type = eh->ether_type;
64615357Skarels 		goto gottype;
64715357Skarels 
64815357Skarels 	default:
64915357Skarels 		printf("de%d: can't handle af%d\n", ifp->if_unit,
65015357Skarels 			dst->sa_family);
65115357Skarels 		error = EAFNOSUPPORT;
65215357Skarels 		goto bad;
65315357Skarels 	}
65415357Skarels 
65515357Skarels gottrailertype:
65615357Skarels 	/*
65715357Skarels 	 * Packet to be sent as trailer: move first packet
65815357Skarels 	 * (control information) to end of chain.
65915357Skarels 	 */
66015357Skarels 	while (m->m_next)
66115357Skarels 		m = m->m_next;
66215357Skarels 	m->m_next = m0;
66315357Skarels 	m = m0->m_next;
66415357Skarels 	m0->m_next = 0;
66515357Skarels 	m0 = m;
66615357Skarels 
66715357Skarels gottype:
66815357Skarels 	/*
66915357Skarels 	 * Add local net header.  If no space in first mbuf,
67015357Skarels 	 * allocate another.
67115357Skarels 	 */
67215357Skarels 	if (m->m_off > MMAXOFF ||
67315357Skarels 	    MMINOFF + sizeof (struct ether_header) > m->m_off) {
67415357Skarels 		m = m_get(M_DONTWAIT, MT_HEADER);
67515357Skarels 		if (m == 0) {
67615357Skarels 			error = ENOBUFS;
67715357Skarels 			goto bad;
67815357Skarels 		}
67915357Skarels 		m->m_next = m0;
68015357Skarels 		m->m_off = MMINOFF;
68115357Skarels 		m->m_len = sizeof (struct ether_header);
68215357Skarels 	} else {
68315357Skarels 		m->m_off -= sizeof (struct ether_header);
68415357Skarels 		m->m_len += sizeof (struct ether_header);
68515357Skarels 	}
68615357Skarels 	eh = mtod(m, struct ether_header *);
68715357Skarels 	eh->ether_type = htons((u_short)type);
688*19861Skarels  	bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
68915357Skarels 	/* DEUNA fills in source address */
69015357Skarels 
69115357Skarels 	/*
69215357Skarels 	 * Queue message on interface, and start output if interface
69315357Skarels 	 * not yet active.
69415357Skarels 	 */
69515357Skarels 	s = splimp();
69615357Skarels 	if (IF_QFULL(&ifp->if_snd)) {
69715357Skarels 		IF_DROP(&ifp->if_snd);
69815357Skarels 		splx(s);
69915357Skarels 		m_freem(m);
70015357Skarels 		return (ENOBUFS);
70115357Skarels 	}
70215357Skarels 	IF_ENQUEUE(&ifp->if_snd, m);
70315357Skarels 	destart(ifp->if_unit);
70415357Skarels 	splx(s);
70515357Skarels 	return (0);
70615357Skarels 
70715357Skarels bad:
70815357Skarels 	m_freem(m0);
70915357Skarels 	return (error);
71015357Skarels }
71115357Skarels 
71215357Skarels /*
71315357Skarels  * Routines supporting UNIBUS network interfaces.
71415357Skarels  */
71515357Skarels 
71615357Skarels /*
71715357Skarels  * Init UNIBUS for interface on uban whose headers of size hlen are to
71815357Skarels  * end on a page boundary.  We allocate a UNIBUS map register for the page
71915357Skarels  * with the header, and nmr more UNIBUS map registers for i/o on the adapter,
72015357Skarels  * doing this for each receive and transmit buffer.  We also
72115357Skarels  * allocate page frames in the mbuffer pool for these pages.
72215357Skarels  */
72315357Skarels de_ubainit(ifu, uban, hlen, nmr)
72415357Skarels 	register struct deuba *ifu;
72515357Skarels 	int uban, hlen, nmr;
72615357Skarels {
72715357Skarels 	register caddr_t cp, dp;
72815357Skarels 	register struct ifrw *ifrw;
72916208Skarels 	register struct ifxmt *ifxp;
73016208Skarels 	int i, ncl;
73115357Skarels 
73215357Skarels 	ncl = clrnd(nmr + CLSIZE) / CLSIZE;
73315357Skarels 	if (ifu->ifu_r[0].ifrw_addr)
73415357Skarels 		/*
73515357Skarels 		 * If the first read buffer has a non-zero
73615357Skarels 		 * address, it means we have already allocated core
73715357Skarels 		 */
73815357Skarels 		cp = ifu->ifu_r[0].ifrw_addr - (CLBYTES - hlen);
73915357Skarels 	else {
74015357Skarels 		cp = m_clalloc(NTOT * ncl, MPG_SPACE);
74115357Skarels 		if (cp == 0)
74215357Skarels 			return (0);
74315357Skarels 		ifu->ifu_hlen = hlen;
74415357Skarels 		ifu->ifu_uban = uban;
74515357Skarels 		ifu->ifu_uba = uba_hd[uban].uh_uba;
74615357Skarels 		dp = cp + CLBYTES - hlen;
74715357Skarels 		for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {
74815357Skarels 			ifrw->ifrw_addr = dp;
74915357Skarels 			dp += ncl * CLBYTES;
75015357Skarels 		}
75116208Skarels 		for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {
75216208Skarels 			ifxp->x_ifrw.ifrw_addr = dp;
75315357Skarels 			dp += ncl * CLBYTES;
75415357Skarels 		}
75515357Skarels 	}
75615357Skarels 	/* allocate for receive ring */
75715357Skarels 	for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {
75815357Skarels 		if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
75916208Skarels 			struct ifrw *rw;
76015357Skarels 
76116208Skarels 			for (rw = ifu->ifu_r; rw < ifrw; rw++)
76216208Skarels 				ubarelse(ifu->ifu_uban, &rw->ifrw_info);
76315357Skarels 			goto bad;
76415357Skarels 		}
76515357Skarels 	}
76615357Skarels 	/* and now transmit ring */
76716208Skarels 	for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {
76816208Skarels 		ifrw = &ifxp->x_ifrw;
76915357Skarels 		if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
77016208Skarels 			struct ifxmt *xp;
77115357Skarels 
77216208Skarels 			for (xp = ifu->ifu_w; xp < ifxp; xp++)
77316208Skarels 				ubarelse(ifu->ifu_uban, &xp->x_ifrw.ifrw_info);
77416208Skarels 			for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++)
77516208Skarels 				ubarelse(ifu->ifu_uban, &ifrw->ifrw_info);
77615357Skarels 			goto bad;
77715357Skarels 		}
77816208Skarels 		for (i = 0; i < nmr; i++)
77916208Skarels 			ifxp->x_map[i] = ifrw->ifrw_mr[i];
78016208Skarels 		ifxp->x_xswapd = 0;
78115357Skarels 	}
78215357Skarels 	return (1);
78315357Skarels bad:
78415357Skarels 	m_pgfree(cp, NTOT * ncl);
78515357Skarels 	ifu->ifu_r[0].ifrw_addr = 0;
78615357Skarels 	return(0);
78715357Skarels }
78815357Skarels 
78915357Skarels /*
79015357Skarels  * Setup either a ifrw structure by allocating UNIBUS map registers,
79115357Skarels  * possibly a buffered data path, and initializing the fields of
79215357Skarels  * the ifrw structure to minimize run-time overhead.
79315357Skarels  */
79415357Skarels static
79515357Skarels de_ubaalloc(ifu, ifrw, nmr)
79615357Skarels 	struct deuba *ifu;
79715357Skarels 	register struct ifrw *ifrw;
79815357Skarels 	int nmr;
79915357Skarels {
80015357Skarels 	register int info;
80115357Skarels 
80215357Skarels 	info =
80315357Skarels 	    uballoc(ifu->ifu_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->ifu_hlen,
80415357Skarels 	        ifu->ifu_flags);
80515357Skarels 	if (info == 0)
80615357Skarels 		return (0);
80715357Skarels 	ifrw->ifrw_info = info;
80815357Skarels 	ifrw->ifrw_bdp = UBAI_BDP(info);
80915357Skarels 	ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT);
81015357Skarels 	ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1];
81115357Skarels 	return (1);
81215357Skarels }
81315357Skarels 
81415357Skarels /*
81515357Skarels  * Pull read data off a interface.
81615357Skarels  * Len is length of data, with local net header stripped.
81715357Skarels  * Off is non-zero if a trailer protocol was used, and
81815357Skarels  * gives the offset of the trailer information.
81915357Skarels  * We copy the trailer information and then all the normal
82015357Skarels  * data into mbufs.  When full cluster sized units are present
82115357Skarels  * on the interface on cluster boundaries we can get them more
82215357Skarels  * easily by remapping, and take advantage of this here.
82315357Skarels  */
82415357Skarels struct mbuf *
82515357Skarels deget(ifu, ifrw, totlen, off0)
82615357Skarels 	register struct deuba *ifu;
82715357Skarels 	register struct ifrw *ifrw;
82815357Skarels 	int totlen, off0;
82915357Skarels {
83015357Skarels 	struct mbuf *top, **mp, *m;
83115357Skarels 	int off = off0, len;
83215357Skarels 	register caddr_t cp = ifrw->ifrw_addr + ifu->ifu_hlen;
83315357Skarels 
83415357Skarels 	top = 0;
83515357Skarels 	mp = &top;
83615357Skarels 	while (totlen > 0) {
83715357Skarels 		MGET(m, M_DONTWAIT, MT_DATA);
83815357Skarels 		if (m == 0)
83915357Skarels 			goto bad;
84015357Skarels 		if (off) {
84115357Skarels 			len = totlen - off;
84215357Skarels 			cp = ifrw->ifrw_addr + ifu->ifu_hlen + off;
84315357Skarels 		} else
84415357Skarels 			len = totlen;
84515357Skarels 		if (len >= CLBYTES) {
84615357Skarels 			struct mbuf *p;
84715357Skarels 			struct pte *cpte, *ppte;
84815357Skarels 			int x, *ip, i;
84915357Skarels 
85015357Skarels 			MCLGET(p, 1);
85115357Skarels 			if (p == 0)
85215357Skarels 				goto nopage;
85315357Skarels 			len = m->m_len = CLBYTES;
85415357Skarels 			m->m_off = (int)p - (int)m;
85515357Skarels 			if (!claligned(cp))
85615357Skarels 				goto copy;
85715357Skarels 
85815357Skarels 			/*
85915357Skarels 			 * Switch pages mapped to UNIBUS with new page p,
86015357Skarels 			 * as quick form of copy.  Remap UNIBUS and invalidate.
86115357Skarels 			 */
86215357Skarels 			cpte = &Mbmap[mtocl(cp)*CLSIZE];
86315357Skarels 			ppte = &Mbmap[mtocl(p)*CLSIZE];
86415357Skarels 			x = btop(cp - ifrw->ifrw_addr);
86515357Skarels 			ip = (int *)&ifrw->ifrw_mr[x];
86615357Skarels 			for (i = 0; i < CLSIZE; i++) {
86715357Skarels 				struct pte t;
86815357Skarels 				t = *ppte; *ppte++ = *cpte; *cpte = t;
86915357Skarels 				*ip++ =
87015357Skarels 				    cpte++->pg_pfnum|ifrw->ifrw_proto;
87115357Skarels 				mtpr(TBIS, cp);
87215357Skarels 				cp += NBPG;
87315357Skarels 				mtpr(TBIS, (caddr_t)p);
87415357Skarels 				p += NBPG / sizeof (*p);
87515357Skarels 			}
87615357Skarels 			goto nocopy;
87715357Skarels 		}
87815357Skarels nopage:
87915357Skarels 		m->m_len = MIN(MLEN, len);
88015357Skarels 		m->m_off = MMINOFF;
88115357Skarels copy:
88215357Skarels 		bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
88315357Skarels 		cp += m->m_len;
88415357Skarels nocopy:
88515357Skarels 		*mp = m;
88615357Skarels 		mp = &m->m_next;
88715357Skarels 		if (off) {
88815357Skarels 			/* sort of an ALGOL-W style for statement... */
88915357Skarels 			off += m->m_len;
89015357Skarels 			if (off == totlen) {
89115357Skarels 				cp = ifrw->ifrw_addr + ifu->ifu_hlen;
89215357Skarels 				off = 0;
89315357Skarels 				totlen = off0;
89415357Skarels 			}
89515357Skarels 		} else
89615357Skarels 			totlen -= m->m_len;
89715357Skarels 	}
89815357Skarels 	return (top);
89915357Skarels bad:
90015357Skarels 	m_freem(top);
90115357Skarels 	return (0);
90215357Skarels }
90315357Skarels 
90415357Skarels /*
90515357Skarels  * Map a chain of mbufs onto a network interface
90615357Skarels  * in preparation for an i/o operation.
90715357Skarels  * The argument chain of mbufs includes the local network
90815357Skarels  * header which is copied to be in the mapped, aligned
90915357Skarels  * i/o space.
91015357Skarels  */
91116208Skarels deput(ifu, n, m)
91216208Skarels 	struct deuba *ifu;
91316208Skarels 	int n;
91415357Skarels 	register struct mbuf *m;
91515357Skarels {
91615357Skarels 	register struct mbuf *mp;
91715357Skarels 	register caddr_t cp;
91816208Skarels 	register struct ifxmt *ifxp;
91916208Skarels 	register struct ifrw *ifrw;
92015357Skarels 	register int i;
92116208Skarels 	int xswapd = 0;
92216208Skarels 	int x, cc, t;
92316208Skarels 	caddr_t dp;
92415357Skarels 
92516208Skarels 	ifxp = &ifu->ifu_w[n];
92616208Skarels 	ifrw = &ifxp->x_ifrw;
92715357Skarels 	cp = ifrw->ifrw_addr;
92815357Skarels 	while (m) {
92915357Skarels 		dp = mtod(m, char *);
93015357Skarels 		if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) {
93116208Skarels 			struct pte *pte; int *ip;
93216208Skarels 			pte = &Mbmap[mtocl(dp)*CLSIZE];
93315357Skarels 			x = btop(cp - ifrw->ifrw_addr);
93415357Skarels 			ip = (int *)&ifrw->ifrw_mr[x];
93516208Skarels 			for (i = 0; i < CLSIZE; i++)
93615357Skarels 				*ip++ =
93716208Skarels 				    ifrw->ifrw_proto | pte++->pg_pfnum;
93816208Skarels 			xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT));
93916208Skarels 			mp = m->m_next;
94016208Skarels 			m->m_next = ifxp->x_xtofree;
94116208Skarels 			ifxp->x_xtofree = m;
94216208Skarels 			cp += m->m_len;
94315357Skarels 		} else {
94415357Skarels 			bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
94515357Skarels 			cp += m->m_len;
94616208Skarels 			MFREE(m, mp);
94715357Skarels 		}
94815357Skarels 		m = mp;
94915357Skarels 	}
95015357Skarels 
95116208Skarels 	/*
95216208Skarels 	 * Xswapd is the set of clusters we just mapped out.  Ifxp->x_xswapd
95316208Skarels 	 * is the set of clusters mapped out from before.  We compute
95416208Skarels 	 * the number of clusters involved in this operation in x.
95516208Skarels 	 * Clusters mapped out before and involved in this operation
95616208Skarels 	 * should be unmapped so original pages will be accessed by the device.
95716208Skarels 	 */
95815357Skarels 	cc = cp - ifrw->ifrw_addr;
95916208Skarels 	x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT;
96016208Skarels 	ifxp->x_xswapd &= ~xswapd;
96116208Skarels 	while (i = ffs(ifxp->x_xswapd)) {
96216208Skarels 		i--;
96316208Skarels 		if (i >= x)
96416208Skarels 			break;
96516208Skarels 		ifxp->x_xswapd &= ~(1<<i);
96616208Skarels 		i *= CLSIZE;
96716208Skarels 		for (t = 0; t < CLSIZE; t++) {
96816208Skarels 			ifrw->ifrw_mr[i] = ifxp->x_map[i];
96916208Skarels 			i++;
97016208Skarels 		}
97116208Skarels 	}
97216208Skarels 	ifxp->x_xswapd |= xswapd;
97315357Skarels 	return (cc);
97415357Skarels }
97515357Skarels 
97615357Skarels /*
97715357Skarels  * Process an ioctl request.
97815357Skarels  */
97915357Skarels deioctl(ifp, cmd, data)
98015357Skarels 	register struct ifnet *ifp;
98115357Skarels 	int cmd;
98215357Skarels 	caddr_t data;
98315357Skarels {
984*19861Skarels 	register struct ifaddr *ifa = (struct ifaddr *)data;
98515357Skarels 	int s = splimp(), error = 0;
98615357Skarels 
98715357Skarels 	switch (cmd) {
98815357Skarels 
98915357Skarels 	case SIOCSIFADDR:
990*19861Skarels 		ifp->if_flags |= IFF_UP;
99115357Skarels 		deinit(ifp->if_unit);
992*19861Skarels 
993*19861Skarels 		switch (ifa->ifa_addr.sa_family) {
994*19861Skarels 		case AF_INET:
995*19861Skarels 			((struct arpcom *)ifp)->ac_ipaddr =
996*19861Skarels 				IA_SIN(ifa)->sin_addr;
997*19861Skarels 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
998*19861Skarels 			break;
999*19861Skarels 		}
100015357Skarels 		break;
100115357Skarels 
100215357Skarels 	default:
100315357Skarels 		error = EINVAL;
100415357Skarels 	}
100515357Skarels 	splx(s);
100615357Skarels 	return (error);
100715357Skarels }
100816208Skarels #endif
1009