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