xref: /csrg-svn/sys/vax/if/if_de.c (revision 17110)
1 /*	if_de.c	6.7	84/08/29	*/
2 #include "de.h"
3 #if NDE > 0
4 
5 /*
6  * DEC DEUNA interface
7  *
8  *	Lou Salkind
9  *	New York University
10  *
11  * TODO:
12  *	timeout routine (get statistics)
13  */
14 #include "../machine/pte.h"
15 
16 #include "param.h"
17 #include "systm.h"
18 #include "mbuf.h"
19 #include "buf.h"
20 #include "protosw.h"
21 #include "socket.h"
22 #include "vmmac.h"
23 #include "ioctl.h"
24 #include "errno.h"
25 
26 #include "../net/if.h"
27 #include "../net/netisr.h"
28 #include "../net/route.h"
29 #include "../netinet/in.h"
30 #include "../netinet/in_systm.h"
31 #include "../netinet/ip.h"
32 #include "../netinet/ip_var.h"
33 #include "../netinet/if_ether.h"
34 #include "../netpup/pup.h"
35 
36 #include "../vax/cpu.h"
37 #include "../vax/mtpr.h"
38 #include "if_dereg.h"
39 #include "if_uba.h"
40 #include "../vaxuba/ubareg.h"
41 #include "../vaxuba/ubavar.h"
42 
43 #define	NXMT	2	/* number of transmit buffers */
44 #define	NRCV	4	/* number of receive buffers (must be > 1) */
45 #define	NTOT	(NXMT + NRCV)
46 
47 int	dedebug = 0;
48 
49 int	deprobe(), deattach(), deintr();
50 struct	uba_device *deinfo[NDE];
51 u_short destd[] = { 0 };
52 struct	uba_driver dedriver =
53 	{ deprobe, 0, deattach, 0, destd, "de", deinfo };
54 #define	DEUNIT(x)	minor(x)
55 int	deinit(),deoutput(),deioctl(),dereset();
56 struct	mbuf *deget();
57 
58 
59 /*
60  * The deuba structures generalizes the ifuba structure
61  * to an arbitrary number of receive and transmit buffers.
62  */
63 struct	ifxmt {
64 	struct	ifrw x_ifrw;			/* mapping information */
65 	struct	pte x_map[IF_MAXNUBAMR];	/* output base pages */
66 	short	x_xswapd;			/* mask of clusters swapped */
67 	struct	mbuf *x_xtofree;		/* pages being dma'ed out */
68 };
69 
70 struct	deuba {
71 	short	ifu_uban;		/* uba number */
72 	short	ifu_hlen;		/* local net header length */
73 	struct	uba_regs *ifu_uba;	/* uba regs, in vm */
74 	struct	ifrw ifu_r[NRCV];	/* receive information */
75 	struct	ifxmt ifu_w[NXMT];	/* transmit information */
76 	short	ifu_flags;		/* used during uballoc's */
77 };
78 
79 /*
80  * Ethernet software status per interface.
81  *
82  * Each interface is referenced by a network interface structure,
83  * ds_if, which the routing code uses to locate the interface.
84  * This structure contains the output queue for the interface, its address, ...
85  * We also have, for each interface, a UBA interface structure, which
86  * contains information about the UNIBUS resources held by the interface:
87  * map registers, buffered data paths, etc.  Information is cached in this
88  * structure for use by the if_uba.c routines in running the interface
89  * efficiently.
90  */
91 struct	de_softc {
92 	struct	arpcom ds_ac;		/* Ethernet common part */
93 #define	ds_if	ds_ac.ac_if		/* network-visible interface */
94 #define	ds_addr	ds_ac.ac_enaddr		/* hardware Ethernet address */
95 	int	ds_flags;
96 #define	DSF_LOCK	1		/* lock out destart */
97 #define	DSF_RUNNING	2
98 	int	ds_ubaddr;		/* map info for incore structs */
99 	struct	deuba ds_deuba;		/* unibus resource structure */
100 	/* the following structures are always mapped in */
101 	struct	de_pcbb ds_pcbb;	/* port control block */
102 	struct	de_ring ds_xrent[NXMT];	/* transmit ring entrys */
103 	struct	de_ring ds_rrent[NRCV];	/* receive ring entrys */
104 	struct	de_udbbuf ds_udbbuf;	/* UNIBUS data buffer */
105 	/* end mapped area */
106 #define	INCORE_BASE(p)	((char *)&(p)->ds_pcbb)
107 #define	RVAL_OFF(n)	((char *)&de_softc[0].n - INCORE_BASE(&de_softc[0]))
108 #define	LVAL_OFF(n)	((char *)de_softc[0].n - INCORE_BASE(&de_softc[0]))
109 #define	PCBB_OFFSET	RVAL_OFF(ds_pcbb)
110 #define	XRENT_OFFSET	LVAL_OFF(ds_xrent)
111 #define	RRENT_OFFSET	LVAL_OFF(ds_rrent)
112 #define	UDBBUF_OFFSET	RVAL_OFF(ds_udbbuf)
113 #define	INCORE_SIZE	RVAL_OFF(ds_xindex)
114 	int	ds_xindex;		/* UNA index into transmit chain */
115 	int	ds_rindex;		/* UNA index into receive chain */
116 	int	ds_xfree;		/* index for next transmit buffer */
117 	int	ds_nxmit;		/* # of transmits in progress */
118 } de_softc[NDE];
119 
120 deprobe(reg)
121 	caddr_t reg;
122 {
123 	register int br, cvec;		/* r11, r10 value-result */
124 	register struct dedevice *addr = (struct dedevice *)reg;
125 	register i;
126 
127 #ifdef lint
128 	br = 0; cvec = br; br = cvec;
129 	i = 0; derint(i); deintr(i);
130 #endif
131 
132 	addr->pcsr0 = PCSR0_RSET;
133 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
134 		;
135 	/* make board interrupt by executing a GETPCBB command */
136 	addr->pcsr0 = PCSR0_INTE;
137 	addr->pcsr2 = 0;
138 	addr->pcsr3 = 0;
139 	addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;
140 	DELAY(100000);
141 	return(1);
142 }
143 
144 /*
145  * Interface exists: make available by filling in network interface
146  * record.  System will initialize the interface when it is ready
147  * to accept packets.  We get the ethernet address here.
148  */
149 deattach(ui)
150 	struct uba_device *ui;
151 {
152 	register struct de_softc *ds = &de_softc[ui->ui_unit];
153 	register struct ifnet *ifp = &ds->ds_if;
154 	register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
155 	struct sockaddr_in *sin;
156 	int csr0;
157 
158 	ifp->if_unit = ui->ui_unit;
159 	ifp->if_name = "de";
160 	ifp->if_mtu = ETHERMTU;
161 
162 	/*
163 	 * Reset the board and temporarily map
164 	 * the pcbb buffer onto the Unibus.
165 	 */
166 	addr->pcsr0 = PCSR0_RSET;
167 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
168 		;
169 	csr0 = addr->pcsr0;
170 	addr->pchigh = csr0 >> 8;
171 	if (csr0 & PCSR0_PCEI)
172 		printf("de%d: reset failed, csr0=%b csr1=%b\n", ui->ui_unit,
173 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
174 	ds->ds_ubaddr = uballoc(ui->ui_ubanum, (char *)&ds->ds_pcbb,
175 		sizeof (struct de_pcbb), 0);
176 	addr->pcsr2 = ds->ds_ubaddr & 0xffff;
177 	addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;
178 	addr->pclow = CMD_GETPCBB;
179 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
180 		;
181 	csr0 = addr->pcsr0;
182 	addr->pchigh = csr0 >> 8;
183 	if (csr0 & PCSR0_PCEI)
184 		printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit,
185 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
186 	ds->ds_pcbb.pcbb0 = FC_RDPHYAD;
187 	addr->pclow = CMD_GETCMD;
188 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
189 		;
190 	csr0 = addr->pcsr0;
191 	addr->pchigh = csr0 >> 8;
192 	if (csr0 & PCSR0_PCEI)
193 		printf("de%d: rdphyad failed, csr0=%b csr1=%b\n", ui->ui_unit,
194 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
195 	ubarelse(ui->ui_ubanum, &ds->ds_ubaddr);
196 	if (dedebug)
197 		printf("de%d: addr=%d:%d:%d:%d:%d:%d\n", ui->ui_unit,
198 		    ds->ds_pcbb.pcbb2&0xff, (ds->ds_pcbb.pcbb2>>8)&0xff,
199 		    ds->ds_pcbb.pcbb4&0xff, (ds->ds_pcbb.pcbb4>>8)&0xff,
200 		    ds->ds_pcbb.pcbb6&0xff, (ds->ds_pcbb.pcbb6>>8)&0xff);
201 	bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)&ds->ds_addr,
202 	    sizeof (ds->ds_addr));
203 	sin = (struct sockaddr_in *)&ifp->if_addr;
204 	sin->sin_family = AF_INET;
205 	ifp->if_init = deinit;
206 	ifp->if_output = deoutput;
207 	ifp->if_ioctl = deioctl;
208 	ifp->if_reset = dereset;
209 	ds->ds_deuba.ifu_flags = UBA_CANTWAIT;
210 #ifdef notdef
211 	/* CAN WE USE BDP's ??? */
212 	ds->ds_deuba.ifu_flags |= UBA_NEEDBDP;
213 #endif
214 	if_attach(ifp);
215 }
216 
217 /*
218  * Reset of interface after UNIBUS reset.
219  * If interface is on specified uba, reset its state.
220  */
221 dereset(unit, uban)
222 	int unit, uban;
223 {
224 	register struct uba_device *ui;
225 
226 	if (unit >= NDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 ||
227 	    ui->ui_ubanum != uban)
228 		return;
229 	printf(" de%d", unit);
230 	deinit(unit);
231 }
232 
233 /*
234  * Initialization of interface; clear recorded pending
235  * operations, and reinitialize UNIBUS usage.
236  */
237 deinit(unit)
238 	int unit;
239 {
240 	register struct de_softc *ds = &de_softc[unit];
241 	register struct uba_device *ui = deinfo[unit];
242 	register struct dedevice *addr;
243 	register struct ifrw *ifrw;
244 	register struct ifxmt *ifxp;
245 	struct ifnet *ifp = &ds->ds_if;
246 	struct sockaddr_in *sin;
247 	int s;
248 	struct de_ring *rp;
249 	int incaddr;
250 	int csr0;
251 
252 	sin = (struct sockaddr_in *)&ifp->if_addr;
253 	if (sin->sin_addr.s_addr == 0)	/* if address still unknown */
254 		return;
255 
256 	if (ifp->if_flags & IFF_RUNNING)
257 		goto justarp;
258 	if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum,
259 	    sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) {
260 		printf("de%d: can't initialize\n", unit);
261 		ds->ds_if.if_flags &= ~IFF_UP;
262 		return;
263 	}
264 	ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds), INCORE_SIZE,0);
265 	addr = (struct dedevice *)ui->ui_addr;
266 
267 	/* set the pcbb block address */
268 	incaddr = ds->ds_ubaddr + PCBB_OFFSET;
269 	addr->pcsr2 = incaddr & 0xffff;
270 	addr->pcsr3 = (incaddr >> 16) & 0x3;
271 	addr->pclow = CMD_GETPCBB;
272 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
273 		;
274 	csr0 = addr->pcsr0;
275 	addr->pchigh = csr0 >> 8;
276 	if (csr0 & PCSR0_PCEI)
277 		printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit,
278 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
279 
280 	/* set the transmit and receive ring header addresses */
281 	incaddr = ds->ds_ubaddr + UDBBUF_OFFSET;
282 	ds->ds_pcbb.pcbb0 = FC_WTRING;
283 	ds->ds_pcbb.pcbb2 = incaddr & 0xffff;
284 	ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;
285 
286 	incaddr = ds->ds_ubaddr + XRENT_OFFSET;
287 	ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;
288 	ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;
289 	ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);
290 	ds->ds_udbbuf.b_trlen = NXMT;
291 	incaddr = ds->ds_ubaddr + RRENT_OFFSET;
292 	ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;
293 	ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;
294 	ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);
295 	ds->ds_udbbuf.b_rrlen = NRCV;
296 
297 	addr->pclow = CMD_GETCMD;
298 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
299 		;
300 	csr0 = addr->pcsr0;
301 	addr->pchigh = csr0 >> 8;
302 	if (csr0 & PCSR0_PCEI)
303 		printf("de%d: wtring failed, csr0=%b csr1=%b\n", ui->ui_unit,
304 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
305 
306 	/* initialize the mode - enable hardware padding */
307 	ds->ds_pcbb.pcbb0 = FC_WTMODE;
308 	/* let hardware do padding - set MTCH bit on broadcast */
309 	ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;
310 	addr->pclow = CMD_GETCMD;
311 	while ((addr->pcsr0 & PCSR0_INTR) == 0)
312 		;
313 	csr0 = addr->pcsr0;
314 	addr->pchigh = csr0 >> 8;
315 	if (csr0 & PCSR0_PCEI)
316 		printf("de%d: wtmode failed, csr0=%b csr1=%b\n", ui->ui_unit,
317 		    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
318 
319 	/* set up the receive and transmit ring entries */
320 	ifxp = &ds->ds_deuba.ifu_w[0];
321 	for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
322 		rp->r_segbl = ifxp->x_ifrw.ifrw_info & 0xffff;
323 		rp->r_segbh = (ifxp->x_ifrw.ifrw_info >> 16) & 0x3;
324 		rp->r_flags = 0;
325 		ifxp++;
326 	}
327 	ifrw = &ds->ds_deuba.ifu_r[0];
328 	for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
329 		rp->r_slen = sizeof (struct de_buf);
330 		rp->r_segbl = ifrw->ifrw_info & 0xffff;
331 		rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
332 		rp->r_flags = RFLG_OWN;		/* hang receive */
333 		ifrw++;
334 	}
335 
336 	/* start up the board (rah rah) */
337 	s = splimp();
338 	ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0;
339 	ds->ds_if.if_flags |= IFF_UP|IFF_RUNNING;
340 	destart(unit);				/* queue output packets */
341 	addr->pclow = PCSR0_INTE;		/* avoid interlock */
342 	addr->pclow = CMD_START | PCSR0_INTE;
343 	ds->ds_flags |= DSF_RUNNING;
344 	splx(s);
345 justarp:
346 	if_rtinit(&ds->ds_if, RTF_UP);
347 	arpwhohas(&ds->ds_ac, &sin->sin_addr);
348 }
349 
350 /*
351  * Setup output on interface.
352  * Get another datagram to send off of the interface queue,
353  * and map it to the interface before starting the output.
354  */
355 destart(unit)
356 	int unit;
357 {
358         int len;
359 	struct uba_device *ui = deinfo[unit];
360 	struct dedevice *addr = (struct dedevice *)ui->ui_addr;
361 	register struct de_softc *ds = &de_softc[unit];
362 	register struct de_ring *rp;
363 	struct mbuf *m;
364 	register int nxmit;
365 
366 	/*
367 	 * the following test is necessary, since
368 	 * the code is not reentrant and we have
369 	 * multiple transmission buffers.
370 	 */
371 	if (ds->ds_flags & DSF_LOCK)
372 		return;
373 	for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {
374 		IF_DEQUEUE(&ds->ds_if.if_snd, m);
375 		if (m == 0)
376 			break;
377 		rp = &ds->ds_xrent[ds->ds_xfree];
378 		if (rp->r_flags & XFLG_OWN)
379 			panic("deuna xmit in progress");
380 		len = deput(&ds->ds_deuba, ds->ds_xfree, m);
381 		if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)
382 			UBAPURGE(ds->ds_deuba.ifu_uba,
383 			ds->ds_deuba.ifu_w[ds->ds_xfree].x_ifrw.ifrw_bdp);
384 		rp->r_slen = len;
385 		rp->r_tdrerr = 0;
386 		rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
387 
388 		ds->ds_xfree++;
389 		if (ds->ds_xfree == NXMT)
390 			ds->ds_xfree = 0;
391 	}
392 	if (ds->ds_nxmit != nxmit) {
393 		ds->ds_nxmit = nxmit;
394 		if (ds->ds_flags & DSF_RUNNING)
395 			addr->pclow = PCSR0_INTE|CMD_PDMD;
396 	}
397 }
398 
399 /*
400  * Command done interrupt.
401  */
402 deintr(unit)
403 	int unit;
404 {
405 	struct uba_device *ui = deinfo[unit];
406 	register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
407 	register struct de_softc *ds = &de_softc[unit];
408 	register struct de_ring *rp;
409 	register struct ifxmt *ifxp;
410 	short csr0;
411 
412 	/* save flags right away - clear out interrupt bits */
413 	csr0 = addr->pcsr0;
414 	addr->pchigh = csr0 >> 8;
415 
416 
417 	ds->ds_flags |= DSF_LOCK;	/* prevent entering destart */
418 	/*
419 	 * if receive, put receive buffer on mbuf
420 	 * and hang the request again
421 	 */
422 	derecv(unit);
423 
424 	/*
425 	 * Poll transmit ring and check status.
426 	 * Be careful about loopback requests.
427 	 * Then free buffer space and check for
428 	 * more transmit requests.
429 	 */
430 	for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {
431 		rp = &ds->ds_xrent[ds->ds_xindex];
432 		if (rp->r_flags & XFLG_OWN)
433 			break;
434 		ds->ds_if.if_opackets++;
435 		ifxp = &ds->ds_deuba.ifu_w[ds->ds_xindex];
436 		/* check for unusual conditions */
437 		if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
438 			if (rp->r_flags & XFLG_ERRS) {
439 				/* output error */
440 				ds->ds_if.if_oerrors++;
441 				if (dedebug)
442 			printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",
443 				    unit, rp->r_flags, XFLG_BITS,
444 				    rp->r_tdrerr, XERR_BITS, rp->r_slen);
445 			} else if (rp->r_flags & XFLG_ONE) {
446 				/* one collision */
447 				ds->ds_if.if_collisions++;
448 			} else if (rp->r_flags & XFLG_MORE) {
449 				/* more than one collision */
450 				ds->ds_if.if_collisions += 2;	/* guess */
451 			} else if (rp->r_flags & XFLG_MTCH) {
452 				/* received our own packet */
453 				ds->ds_if.if_ipackets++;
454 				deread(ds, &ifxp->x_ifrw,
455 				    rp->r_slen - sizeof (struct ether_header));
456 			}
457 		}
458 		if (ifxp->x_xtofree) {
459 			m_freem(ifxp->x_xtofree);
460 			ifxp->x_xtofree = 0;
461 		}
462 		/* check if next transmit buffer also finished */
463 		ds->ds_xindex++;
464 		if (ds->ds_xindex == NXMT)
465 			ds->ds_xindex = 0;
466 	}
467 	ds->ds_flags &= ~DSF_LOCK;
468 	destart(unit);
469 
470 	if (csr0 & PCSR0_RCBI) {
471 		printf("de%d: buffer unavailable\n", unit);
472 		addr->pclow = PCSR0_INTE|CMD_PDMD;
473 	}
474 }
475 
476 /*
477  * Ethernet interface receiver interface.
478  * If input error just drop packet.
479  * Otherwise purge input buffered data path and examine
480  * packet to determine type.  If can't determine length
481  * from type, then have to drop packet.  Othewise decapsulate
482  * packet based on type and pass to type specific higher-level
483  * input routine.
484  */
485 derecv(unit)
486 	int unit;
487 {
488 	register struct de_softc *ds = &de_softc[unit];
489 	register struct de_ring *rp;
490 	int len;
491 
492 	rp = &ds->ds_rrent[ds->ds_rindex];
493 	while ((rp->r_flags & RFLG_OWN) == 0) {
494 		ds->ds_if.if_ipackets++;
495 		if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)
496 			UBAPURGE(ds->ds_deuba.ifu_uba,
497 			ds->ds_deuba.ifu_r[ds->ds_rindex].ifrw_bdp);
498 		len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)
499 			- 4;	/* don't forget checksum! */
500 		/* check for errors */
501 		if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
502 		    (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) ||
503 		    (rp->r_lenerr & (RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||
504 		    len < ETHERMIN || len > ETHERMTU) {
505 			ds->ds_if.if_ierrors++;
506 			if (dedebug)
507 			printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",
508 				unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,
509 				RERR_BITS, len);
510 		} else
511 			deread(ds, &ds->ds_deuba.ifu_r[ds->ds_rindex], len);
512 
513 		/* hang the receive buffer again */
514 		rp->r_lenerr = 0;
515 		rp->r_flags = RFLG_OWN;
516 
517 		/* check next receive buffer */
518 		ds->ds_rindex++;
519 		if (ds->ds_rindex == NRCV)
520 			ds->ds_rindex = 0;
521 		rp = &ds->ds_rrent[ds->ds_rindex];
522 	}
523 }
524 
525 /*
526  * Pass a packet to the higher levels.
527  * We deal with the trailer protocol here.
528  */
529 deread(ds, ifrw, len)
530 	register struct de_softc *ds;
531 	struct ifrw *ifrw;
532 	int len;
533 {
534 	struct ether_header *eh;
535     	struct mbuf *m;
536 	int off, resid;
537 	int s;
538 	register struct ifqueue *inq;
539 
540 	/*
541 	 * Deal with trailer protocol: if type is PUP trailer
542 	 * get true type from first 16-bit word past data.
543 	 * Remember that type was trailer by setting off.
544 	 */
545 	eh = (struct ether_header *)ifrw->ifrw_addr;
546 	eh->ether_type = ntohs((u_short)eh->ether_type);
547 #define	dedataaddr(eh, off, type)	((type)(((caddr_t)((eh)+1)+(off))))
548 	if (eh->ether_type >= ETHERPUP_TRAIL &&
549 	    eh->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
550 		off = (eh->ether_type - ETHERPUP_TRAIL) * 512;
551 		if (off >= ETHERMTU)
552 			return;		/* sanity */
553 		eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
554 		resid = ntohs(*(dedataaddr(eh, off+2, u_short *)));
555 		if (off + resid > len)
556 			return;		/* sanity */
557 		len = off + resid;
558 	} else
559 		off = 0;
560 	if (len == 0)
561 		return;
562 
563 	/*
564 	 * Pull packet off interface.  Off is nonzero if packet
565 	 * has trailing header; deget will then force this header
566 	 * information to be at the front, but we still have to drop
567 	 * the type and length which are at the front of any trailer data.
568 	 */
569 	m = deget(&ds->ds_deuba, ifrw, len, off);
570 	if (m == 0)
571 		return;
572 	if (off) {
573 		m->m_off += 2 * sizeof (u_short);
574 		m->m_len -= 2 * sizeof (u_short);
575 	}
576 	switch (eh->ether_type) {
577 
578 #ifdef INET
579 	case ETHERPUP_IPTYPE:
580 		schednetisr(NETISR_IP);
581 		inq = &ipintrq;
582 		break;
583 
584 	case ETHERPUP_ARPTYPE:
585 		arpinput(&ds->ds_ac, m);
586 		return;
587 #endif
588 	default:
589 		m_freem(m);
590 		return;
591 	}
592 
593 	s = splimp();
594 	if (IF_QFULL(inq)) {
595 		IF_DROP(inq);
596 		splx(s);
597 		m_freem(m);
598 		return;
599 	}
600 	IF_ENQUEUE(inq, m);
601 	splx(s);
602 }
603 
604 /*
605  * Ethernet output routine.
606  * Encapsulate a packet of type family for the local net.
607  * Use trailer local net encapsulation if enough data in first
608  * packet leaves a multiple of 512 bytes of data in remainder.
609  */
610 deoutput(ifp, m0, dst)
611 	struct ifnet *ifp;
612 	struct mbuf *m0;
613 	struct sockaddr *dst;
614 {
615 	int type, s, error;
616 	struct ether_addr edst;
617 	struct in_addr idst;
618 	register struct de_softc *ds = &de_softc[ifp->if_unit];
619 	register struct mbuf *m = m0;
620 	register struct ether_header *eh;
621 	register int off;
622 
623 	switch (dst->sa_family) {
624 
625 #ifdef INET
626 	case AF_INET:
627 		idst = ((struct sockaddr_in *)dst)->sin_addr;
628 		if (!arpresolve(&ds->ds_ac, m, &idst, &edst))
629 			return (0);	/* if not yet resolved */
630 		off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
631 		/* need per host negotiation */
632 		if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
633 		if (off > 0 && (off & 0x1ff) == 0 &&
634 		    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
635 			type = ETHERPUP_TRAIL + (off>>9);
636 			m->m_off -= 2 * sizeof (u_short);
637 			m->m_len += 2 * sizeof (u_short);
638 			*mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
639 			*(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
640 			goto gottrailertype;
641 		}
642 		type = ETHERPUP_IPTYPE;
643 		off = 0;
644 		goto gottype;
645 #endif
646 
647 	case AF_UNSPEC:
648 		eh = (struct ether_header *)dst->sa_data;
649 		edst = eh->ether_dhost;
650 		type = eh->ether_type;
651 		goto gottype;
652 
653 	default:
654 		printf("de%d: can't handle af%d\n", ifp->if_unit,
655 			dst->sa_family);
656 		error = EAFNOSUPPORT;
657 		goto bad;
658 	}
659 
660 gottrailertype:
661 	/*
662 	 * Packet to be sent as trailer: move first packet
663 	 * (control information) to end of chain.
664 	 */
665 	while (m->m_next)
666 		m = m->m_next;
667 	m->m_next = m0;
668 	m = m0->m_next;
669 	m0->m_next = 0;
670 	m0 = m;
671 
672 gottype:
673 	/*
674 	 * Add local net header.  If no space in first mbuf,
675 	 * allocate another.
676 	 */
677 	if (m->m_off > MMAXOFF ||
678 	    MMINOFF + sizeof (struct ether_header) > m->m_off) {
679 		m = m_get(M_DONTWAIT, MT_HEADER);
680 		if (m == 0) {
681 			error = ENOBUFS;
682 			goto bad;
683 		}
684 		m->m_next = m0;
685 		m->m_off = MMINOFF;
686 		m->m_len = sizeof (struct ether_header);
687 	} else {
688 		m->m_off -= sizeof (struct ether_header);
689 		m->m_len += sizeof (struct ether_header);
690 	}
691 	eh = mtod(m, struct ether_header *);
692 	eh->ether_type = htons((u_short)type);
693 	eh->ether_dhost = edst;
694 	/* DEUNA fills in source address */
695 
696 	/*
697 	 * Queue message on interface, and start output if interface
698 	 * not yet active.
699 	 */
700 	s = splimp();
701 	if (IF_QFULL(&ifp->if_snd)) {
702 		IF_DROP(&ifp->if_snd);
703 		splx(s);
704 		m_freem(m);
705 		return (ENOBUFS);
706 	}
707 	IF_ENQUEUE(&ifp->if_snd, m);
708 	destart(ifp->if_unit);
709 	splx(s);
710 	return (0);
711 
712 bad:
713 	m_freem(m0);
714 	return (error);
715 }
716 
717 /*
718  * Routines supporting UNIBUS network interfaces.
719  */
720 
721 /*
722  * Init UNIBUS for interface on uban whose headers of size hlen are to
723  * end on a page boundary.  We allocate a UNIBUS map register for the page
724  * with the header, and nmr more UNIBUS map registers for i/o on the adapter,
725  * doing this for each receive and transmit buffer.  We also
726  * allocate page frames in the mbuffer pool for these pages.
727  */
728 de_ubainit(ifu, uban, hlen, nmr)
729 	register struct deuba *ifu;
730 	int uban, hlen, nmr;
731 {
732 	register caddr_t cp, dp;
733 	register struct ifrw *ifrw;
734 	register struct ifxmt *ifxp;
735 	int i, ncl;
736 
737 	ncl = clrnd(nmr + CLSIZE) / CLSIZE;
738 	if (ifu->ifu_r[0].ifrw_addr)
739 		/*
740 		 * If the first read buffer has a non-zero
741 		 * address, it means we have already allocated core
742 		 */
743 		cp = ifu->ifu_r[0].ifrw_addr - (CLBYTES - hlen);
744 	else {
745 		cp = m_clalloc(NTOT * ncl, MPG_SPACE);
746 		if (cp == 0)
747 			return (0);
748 		ifu->ifu_hlen = hlen;
749 		ifu->ifu_uban = uban;
750 		ifu->ifu_uba = uba_hd[uban].uh_uba;
751 		dp = cp + CLBYTES - hlen;
752 		for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {
753 			ifrw->ifrw_addr = dp;
754 			dp += ncl * CLBYTES;
755 		}
756 		for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {
757 			ifxp->x_ifrw.ifrw_addr = dp;
758 			dp += ncl * CLBYTES;
759 		}
760 	}
761 	/* allocate for receive ring */
762 	for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {
763 		if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
764 			struct ifrw *rw;
765 
766 			for (rw = ifu->ifu_r; rw < ifrw; rw++)
767 				ubarelse(ifu->ifu_uban, &rw->ifrw_info);
768 			goto bad;
769 		}
770 	}
771 	/* and now transmit ring */
772 	for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {
773 		ifrw = &ifxp->x_ifrw;
774 		if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
775 			struct ifxmt *xp;
776 
777 			for (xp = ifu->ifu_w; xp < ifxp; xp++)
778 				ubarelse(ifu->ifu_uban, &xp->x_ifrw.ifrw_info);
779 			for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++)
780 				ubarelse(ifu->ifu_uban, &ifrw->ifrw_info);
781 			goto bad;
782 		}
783 		for (i = 0; i < nmr; i++)
784 			ifxp->x_map[i] = ifrw->ifrw_mr[i];
785 		ifxp->x_xswapd = 0;
786 	}
787 	return (1);
788 bad:
789 	m_pgfree(cp, NTOT * ncl);
790 	ifu->ifu_r[0].ifrw_addr = 0;
791 	return(0);
792 }
793 
794 /*
795  * Setup either a ifrw structure by allocating UNIBUS map registers,
796  * possibly a buffered data path, and initializing the fields of
797  * the ifrw structure to minimize run-time overhead.
798  */
799 static
800 de_ubaalloc(ifu, ifrw, nmr)
801 	struct deuba *ifu;
802 	register struct ifrw *ifrw;
803 	int nmr;
804 {
805 	register int info;
806 
807 	info =
808 	    uballoc(ifu->ifu_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->ifu_hlen,
809 	        ifu->ifu_flags);
810 	if (info == 0)
811 		return (0);
812 	ifrw->ifrw_info = info;
813 	ifrw->ifrw_bdp = UBAI_BDP(info);
814 	ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT);
815 	ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1];
816 	return (1);
817 }
818 
819 /*
820  * Pull read data off a interface.
821  * Len is length of data, with local net header stripped.
822  * Off is non-zero if a trailer protocol was used, and
823  * gives the offset of the trailer information.
824  * We copy the trailer information and then all the normal
825  * data into mbufs.  When full cluster sized units are present
826  * on the interface on cluster boundaries we can get them more
827  * easily by remapping, and take advantage of this here.
828  */
829 struct mbuf *
830 deget(ifu, ifrw, totlen, off0)
831 	register struct deuba *ifu;
832 	register struct ifrw *ifrw;
833 	int totlen, off0;
834 {
835 	struct mbuf *top, **mp, *m;
836 	int off = off0, len;
837 	register caddr_t cp = ifrw->ifrw_addr + ifu->ifu_hlen;
838 
839 	top = 0;
840 	mp = &top;
841 	while (totlen > 0) {
842 		MGET(m, M_DONTWAIT, MT_DATA);
843 		if (m == 0)
844 			goto bad;
845 		if (off) {
846 			len = totlen - off;
847 			cp = ifrw->ifrw_addr + ifu->ifu_hlen + off;
848 		} else
849 			len = totlen;
850 		if (len >= CLBYTES) {
851 			struct mbuf *p;
852 			struct pte *cpte, *ppte;
853 			int x, *ip, i;
854 
855 			MCLGET(p, 1);
856 			if (p == 0)
857 				goto nopage;
858 			len = m->m_len = CLBYTES;
859 			m->m_off = (int)p - (int)m;
860 			if (!claligned(cp))
861 				goto copy;
862 
863 			/*
864 			 * Switch pages mapped to UNIBUS with new page p,
865 			 * as quick form of copy.  Remap UNIBUS and invalidate.
866 			 */
867 			cpte = &Mbmap[mtocl(cp)*CLSIZE];
868 			ppte = &Mbmap[mtocl(p)*CLSIZE];
869 			x = btop(cp - ifrw->ifrw_addr);
870 			ip = (int *)&ifrw->ifrw_mr[x];
871 			for (i = 0; i < CLSIZE; i++) {
872 				struct pte t;
873 				t = *ppte; *ppte++ = *cpte; *cpte = t;
874 				*ip++ =
875 				    cpte++->pg_pfnum|ifrw->ifrw_proto;
876 				mtpr(TBIS, cp);
877 				cp += NBPG;
878 				mtpr(TBIS, (caddr_t)p);
879 				p += NBPG / sizeof (*p);
880 			}
881 			goto nocopy;
882 		}
883 nopage:
884 		m->m_len = MIN(MLEN, len);
885 		m->m_off = MMINOFF;
886 copy:
887 		bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);
888 		cp += m->m_len;
889 nocopy:
890 		*mp = m;
891 		mp = &m->m_next;
892 		if (off) {
893 			/* sort of an ALGOL-W style for statement... */
894 			off += m->m_len;
895 			if (off == totlen) {
896 				cp = ifrw->ifrw_addr + ifu->ifu_hlen;
897 				off = 0;
898 				totlen = off0;
899 			}
900 		} else
901 			totlen -= m->m_len;
902 	}
903 	return (top);
904 bad:
905 	m_freem(top);
906 	return (0);
907 }
908 
909 /*
910  * Map a chain of mbufs onto a network interface
911  * in preparation for an i/o operation.
912  * The argument chain of mbufs includes the local network
913  * header which is copied to be in the mapped, aligned
914  * i/o space.
915  */
916 deput(ifu, n, m)
917 	struct deuba *ifu;
918 	int n;
919 	register struct mbuf *m;
920 {
921 	register struct mbuf *mp;
922 	register caddr_t cp;
923 	register struct ifxmt *ifxp;
924 	register struct ifrw *ifrw;
925 	register int i;
926 	int xswapd = 0;
927 	int x, cc, t;
928 	caddr_t dp;
929 
930 	ifxp = &ifu->ifu_w[n];
931 	ifrw = &ifxp->x_ifrw;
932 	cp = ifrw->ifrw_addr;
933 	while (m) {
934 		dp = mtod(m, char *);
935 		if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) {
936 			struct pte *pte; int *ip;
937 			pte = &Mbmap[mtocl(dp)*CLSIZE];
938 			x = btop(cp - ifrw->ifrw_addr);
939 			ip = (int *)&ifrw->ifrw_mr[x];
940 			for (i = 0; i < CLSIZE; i++)
941 				*ip++ =
942 				    ifrw->ifrw_proto | pte++->pg_pfnum;
943 			xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT));
944 			mp = m->m_next;
945 			m->m_next = ifxp->x_xtofree;
946 			ifxp->x_xtofree = m;
947 			cp += m->m_len;
948 		} else {
949 			bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
950 			cp += m->m_len;
951 			MFREE(m, mp);
952 		}
953 		m = mp;
954 	}
955 
956 	/*
957 	 * Xswapd is the set of clusters we just mapped out.  Ifxp->x_xswapd
958 	 * is the set of clusters mapped out from before.  We compute
959 	 * the number of clusters involved in this operation in x.
960 	 * Clusters mapped out before and involved in this operation
961 	 * should be unmapped so original pages will be accessed by the device.
962 	 */
963 	cc = cp - ifrw->ifrw_addr;
964 	x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT;
965 	ifxp->x_xswapd &= ~xswapd;
966 	while (i = ffs(ifxp->x_xswapd)) {
967 		i--;
968 		if (i >= x)
969 			break;
970 		ifxp->x_xswapd &= ~(1<<i);
971 		i *= CLSIZE;
972 		for (t = 0; t < CLSIZE; t++) {
973 			ifrw->ifrw_mr[i] = ifxp->x_map[i];
974 			i++;
975 		}
976 	}
977 	ifxp->x_xswapd |= xswapd;
978 	return (cc);
979 }
980 
981 /*
982  * Process an ioctl request.
983  */
984 deioctl(ifp, cmd, data)
985 	register struct ifnet *ifp;
986 	int cmd;
987 	caddr_t data;
988 {
989 	register struct ifreq *ifr = (struct ifreq *)data;
990 	int s = splimp(), error = 0;
991 
992 	switch (cmd) {
993 
994 	case SIOCSIFADDR:
995 		if (ifp->if_flags & IFF_RUNNING)
996 			if_rtinit(ifp, -1);	/* delete previous route */
997 		desetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
998 		deinit(ifp->if_unit);
999 		break;
1000 
1001 	default:
1002 		error = EINVAL;
1003 	}
1004 	splx(s);
1005 	return (error);
1006 }
1007 
1008 desetaddr(ifp, sin)
1009 	register struct ifnet *ifp;
1010 	register struct sockaddr_in *sin;
1011 {
1012 
1013 	ifp->if_addr = *(struct sockaddr *)sin;
1014 	ifp->if_net = in_netof(sin->sin_addr);
1015 	ifp->if_host[0] = in_lnaof(sin->sin_addr);
1016 	sin = (struct sockaddr_in *)&ifp->if_broadaddr;
1017 	sin->sin_family = AF_INET;
1018 	sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
1019 	ifp->if_flags |= IFF_BROADCAST;
1020 }
1021 #endif
1022