Removed definition "LIB= rpc". We want libc.a to contain librpc.a, not
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / sys / vax / if / if_ix.c
CommitLineData
49ff8a6a
KS
1/*
2 * Copyright (c) 1986 Regents of the University of California.
5f9369d6 3 * All rights reserved.
49ff8a6a 4 *
5f9369d6
KB
5 * This code is derived from software contributed to Berkeley by
6 * Micom-Interlan Inc.
7 *
af359dea
C
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
5f9369d6 23 *
af359dea
C
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)if_ix.c 7.8 (Berkeley) 12/16/90
49ff8a6a
KS
37 */
38
39#include "np.h"
40#if NNP > 0
41
42/*
43 * Interlan NP100 Ethernet Communications Controller interface
44 */
b28b3a13 45#include "../include/pte.h"
49ff8a6a 46
b28b3a13
KB
47#include "sys/param.h"
48#include "sys/systm.h"
49#include "sys/mbuf.h"
50#include "sys/buf.h"
51#include "sys/protosw.h"
52#include "sys/socket.h"
53#include "sys/vmmac.h"
54#include "sys/ioctl.h"
55#include "sys/errno.h"
49ff8a6a 56
b28b3a13
KB
57#include "net/if.h"
58#include "net/netisr.h"
59#include "net/route.h"
49ff8a6a
KS
60
61#ifdef INET
b28b3a13
KB
62#include "netinet/in.h"
63#include "netinet/in_systm.h"
64#include "netinet/in_var.h"
65#include "netinet/ip.h"
66#include "netinet/if_ether.h"
49ff8a6a
KS
67#endif
68
69#ifdef NS
b28b3a13
KB
70#include "netns/ns.h"
71#include "netns/ns_if.h"
49ff8a6a
KS
72#endif
73
b28b3a13
KB
74#include "../include/cpu.h"
75#include "../include/mtpr.h"
76#include "../if/if_uba.h"
77#include "../uba/ubareg.h"
78#include "../uba/ubavar.h"
79#include "../uba/npreg.h"
80#include "../if/if_ix.h"
49ff8a6a
KS
81
82int ixattach(), ixrint(), ixcint();
83#define ILUNIT(x) minor(x)
4f02060d 84int ixinit(), ixioctl(), ixreset(), ixwatch(), ixstart();
49ff8a6a
KS
85int (*IxAttach)() = ixattach;
86int (*IxReset)() = ixreset;
87
88/*
89 * Ethernet software status per interface.
90 *
91 * Each interface is referenced by a network interface structure,
92 * ix_if, which the routing code uses to locate the interface.
93 * This structure contains the output queue for the interface, its address, ...
94 * We also have, for each interface, a UBA interface structure, which
95 * contains information about the UNIBUS resources held by the interface:
96 * map registers, buffered data paths, etc. Information is cached in this
97 * structure for use by the if_uba.c routines in running the interface
98 * efficiently.
99 */
100struct ix_softc {
101 struct arpcom ix_ac; /* Ethernet common part */
102#define ix_if ix_ac.ac_if /* network-visible interface */
103#define ix_addr ix_ac.ac_enaddr /* hardware Ethernet address */
104 int ix_flags;
105#define IXF_OACTIVE 0x1 /* output is active */
106#define IXF_RCVPENDING 0x2 /* start rcv in ilcint */
107#define IXF_GOTUBA 0x4 /* unibus resources mapped */
108#define IXF_RUNNING 0x8 /* board is running */
109#define IXF_SETADDR 0x10 /* physical address is changed */
110#define IXF_STATPENDING 0x20 /* stat cmd pending */
111#define IXF_GOTCQE 0x40 /* np resources available */
785d9ccc
MK
112#define IXF_OWATCH 0x80 /* is output hung? */
113#define IXF_RWATCH 0x100 /* is input hung? */
49ff8a6a
KS
114 struct ifuba ix_ifuba; /* unibus resources */
115 u_short ix_aid; /* Access Id returned by open DDL */
116 u_short ix_badcqe;
117 struct npmaster *ix_mp; /* Board physio request header */
118 struct npreq *ix_rrp; /* Cached npreq for recv */
119 struct npreq *ix_wrp; /* Cached npreq for xmit */
120 short ix_scaninterval; /* interval of stat collection */
121#define IXWATCHINTERVAL 60 /* once every 60 seconds */
122 union ix_stats ix_stats; /* holds on-board statistics */
123 int ix_ubaddr; /* mapping registers of ix_stats */
124} ix_softc[NNP];
125extern struct uba_device *npdinfo[];
126
127/*
128 * Interface exists: make available by filling in network interface
129 * record. System will initialize the interface when it is ready
130 * to accept packets. We can't even get the ethernet address
131 * or other interesting data until the board has been downloaded.
132 * running ifconfig will attempt to start unit.
133 */
134ixattach(ui)
135 struct uba_device *ui;
136{
137 register struct ix_softc *ix = &ix_softc[ui->ui_unit];
138 register struct ifnet *ifp = &ix->ix_if;
139 extern struct npmaster npmasters[];
140
141 ifp->if_unit = ui->ui_unit;
142 ifp->if_name = "ix";
143 ifp->if_mtu = ETHERMTU;
144 ifp->if_flags = IFF_BROADCAST;
145
146 ifp->if_init = ixinit;
4f02060d
KS
147 ifp->if_output = ether_output;
148 ifp->if_start = ixstart;
49ff8a6a
KS
149 ifp->if_ioctl = ixioctl;
150 ifp->if_reset = ixreset;
151
152 ix->ix_mp = npmasters + ui->ui_unit;
153 ix->ix_ifuba.ifu_flags = UBA_CANTWAIT;
154
155 if_attach(ifp);
156}
157
158struct npreq *
159ix_GetReq(mp, addr, len)
160 struct npmaster *mp;
161 caddr_t addr;
162{
163 int unit = mp->unit;
164 register struct npreq *rp;
165 register struct CQE *ep;
166 struct ix_softc *ix = ix_softc + unit;
167 extern struct npreq *NpGetReq();
168
169 while ((rp = NpGetReq(mp->reqtab)) == NULL) {
170 mp->reqtab->flags |= WANTREQ;
171 sleep((caddr_t)(mp->reqtab), PZERO - 1);
172 }
173 rp->flags = KERNREQ; /* Clear flags */
174
175 ep = rp->element; /* Associated CQE */
176 ep->cqe_famid = (unsign32)ix; /* Process ID */
177 ep->cqe_wind = 0; /* Amount of buffer mapped */
178 ep->cqe_nbuf = 1; /* Must be 1, no buffer chain */
179 ep->cqe_char = 1; /* Driver owns this CQE */
180 ep->cqe_prot = NPDLA; /* Data Link Access protocol */
181 ep->cqe_bcnt = len; /* Byte count */
182 rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */
183 ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr);
184 ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr);
185 return (rp);
186}
187
188ix_DoReq(mp, rp, cmd, addr, len, rpb, routine)
189 struct npmaster *mp;
190 register struct npreq *rp;
191 u_short cmd;
192 caddr_t addr;
193 int len;
194 register u_short *rpb;
195 int (*routine)();
196{
197 register struct CQE *ep = rp->element;
198 register u_short *p = &ep->rpb1;
199 u_short cnt = *rpb++;
200 extern long NpDebug;
201 int pri;
785d9ccc 202 int result = 0;
49ff8a6a
KS
203
204 ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */
205 ep->cqe_bcnt = len; /* Byte count */
785d9ccc 206 rp->flags = KERNREQ | REQALOC; /* Clear flags */
49ff8a6a
KS
207 rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */
208 rp->intr = routine;
209 rp->user = (caddr_t) (ep->cqe_func = cmd);/* In case pissed on in CQE */
210 ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr);
211 ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr);
212 ep->cqe_lenrpb = cnt + cnt;
213 for (; cnt > 0; cnt--) *p++ = *rpb++;
214
215 if (NpDebug & DEBCQE)
216 printf("Function is %x ep %x reqid %x\n", ep->cqe_func, ep, ep->cqe_reqid);
217 if (NpDebug & DEBCQE)
218 printf("irp len = %x rp = %x\n", ep->cqe_lenrpb, rp);
219 if (routine == 0) {
220 NpAddReq(mp->reqtab, rp); /* Queue onto active list */
221 while (!(rp->flags & REQDONE)) {
c4054532 222 pri = spl5();
49ff8a6a
KS
223 NpAddCQE(ep, &mp->shmemp->devcq, mp);
224 sleep((caddr_t)rp, PZERO - 1);
225 splx(pri);
226 }
227 if (rp->flags & IOABORT || ep->cqe_sts != NPDONE
228 || ep->cqe_ust0 != NPDONE
229 || ep->cqe_ust1 != NPOK) {
230 struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid;
785d9ccc
MK
231 printf("ix%d: Req failed, cmd %x, stat %x, flags %x, ",
232 ix->ix_if.if_unit, rp->user,
233 ep->cqe_sts, rp->flags);
49ff8a6a 234 printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);
785d9ccc 235 result = 1;
49ff8a6a
KS
236 }
237 NpRemReq(rp); /* Clear request */
238 } else {
c4054532 239 pri = spl5();
49ff8a6a
KS
240 NpAddCQE(ep, &mp->shmemp->devcq, mp);
241 splx(pri);
242 }
785d9ccc 243 return(result);
49ff8a6a 244}
49ff8a6a
KS
245/*
246 * Reset of interface after UNIBUS reset.
247 * If interface is on specified uba, reset its state.
248 */
249ixreset(unit, uban, softp)
250 int unit, uban;
251 caddr_t softp;
252{
253 register struct uba_device *ui;
254 int mask = IXF_SETADDR; /* Only remember new physaddr */
255
256 if (unit >= NNP || (ui = npdinfo[unit]) == 0 || ui->ui_alive == 0 ||
257 ui->ui_ubanum != uban)
258 return;
259 printf(" ix%d reset", unit);
260 if (softp)
261 mask |= IXF_GOTUBA; /* UBA mapping regs still valid; */
262 ix_softc[unit].ix_if.if_flags &= ~IFF_RUNNING;
263 ix_softc[unit].ix_flags &= mask;
264}
265
c4054532 266int ix_MacLoop = 0;
49ff8a6a
KS
267
268/*
269 * Initialization of interface; clear recorded pending
270 * operations, and reinitialize UNIBUS usage.
271 */
272ixinit(unit)
273 int unit;
274{
275 register struct ix_softc *ix = &ix_softc[unit];
276 struct uba_device *ui = npdinfo[unit];
277 register struct ifnet *ifp = &ix->ix_if;
278 register struct CQE *ep;
279 struct npreq *rp;
280 struct npmaster *mp = ix->ix_mp;
281 register u_short *dpmp = & mp->shmemp->statblock.sb_dpm;
282 u_short rpb[7];
283 int s;
284
285 /* not yet, if address still unknown */
785d9ccc
MK
286 if ((ifp->if_addrlist == (struct ifaddr *)0) ||
287 (ix->ix_flags & IXF_RUNNING))
49ff8a6a
KS
288 return;
289 if ((mp->flags & AVAILABLE) == 0 || (*dpmp & PROTOMASK(NPDLA)) == 0) {
290 ifp->if_flags &= ~IFF_UP;
291 return;
292 }
293 if ((ix->ix_flags & IXF_GOTUBA) == 0) {
294 ix->ix_ifuba.ifu_flags = UBA_CANTWAIT;
295 if (if_ubainit(&ix->ix_ifuba, ui->ui_ubanum,
296 sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) {
297 printf("ix%d: can't initialize\n", unit);
298 ix->ix_if.if_flags &= ~IFF_UP;
299 return;
300 }
301 ix->ix_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ix->ix_stats,
302 sizeof (union ix_stats), 0);
303 ix->ix_flags |= IXF_GOTUBA;
304 }
305 if ((ix->ix_flags & IXF_GOTCQE) == 0) {
306 ix->ix_rrp = ix_GetReq(mp, ix->ix_ifuba.ifu_r.ifrw_info,
307 ETHERMTU);
308 ix->ix_wrp = ix_GetReq(mp, 0, 0);
309 ix->ix_flags |= IXF_GOTCQE;
310 }
311
312 rp = ix->ix_wrp;
313 ep = rp->element;
314
315 /* Changing the ethernet address resets the dla module,
316 so must do it before opening the channel */
317 if (ix->ix_flags & IXF_SETADDR) {
318 register char *cp = (char *) &ix->ix_stats;
319 int spincount;
320 int x;
785d9ccc
MK
321 /* Try Issuing an open channel request before reprogramming
322 the physical address */
323 rpb[0] = 6; /* RPB length */
324 rpb[2] = 0x10; /* Share with any smart users */
325 rpb[3] = 0; /* Take (a copy of) all frames */
326 rpb[5] = 8; /* On board rcv queue length */
327 rpb[6] = 0; /* XMT packets as is */
328 if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0))
329 return;
330 /* Proceed with LDPA */
49ff8a6a
KS
331 *cp++ = 1;
332 bcopy(ix->ix_addr, (caddr_t)cp, 6);
333 rpb[0] = 1; /* RPB length */
785d9ccc
MK
334 if (ix_DoReq(mp, rp, IXC_LDPA, ix->ix_ubaddr, 7, rpb, 0))
335 return;
49ff8a6a
KS
336#ifndef TheyFinallyFixedTheBoard
337 /* Board requires some time to reinitialize its protocols */
338 x = spl1();
339 spincount = 2000000;
340 while (((*dpmp & PROTOMASK(NPDLA))==0) && spincount > 0)
341 spincount--;
342 if (spincount==0) {
343 printf("ix%d: failed to reinitialize DLA module\n",
344 unit);
345 splx(x);
346 }
347 splx(x);
348#endif
349 }
350 rpb[0] = 6; /* RPB length */
351 rpb[2] = 0x10; /* Share with any smart users */
785d9ccc
MK
352 if (ix_MacLoop) rpb[2] |= 0x8;
353 /* Enable software loopback on board */
49ff8a6a
KS
354 rpb[3] = 0; /* Take (a copy of) all frames */
355 rpb[5] = 8; /* On board rcv queue length */
356 rpb[6] = 0; /* XMT packets as is */
785d9ccc
MK
357 if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0))
358 return;
49ff8a6a
KS
359
360 ix->ix_aid = ep->rpb1;
361
362 /* Here we request our ethernet address, if we didn't reset it*/
363 if ((ix->ix_flags & IXF_SETADDR)==0) {
364 rpb[0] = 2;
365 rpb[1] = ix->ix_aid;
366 rpb[2] = 0; /* get all stats */
785d9ccc 367 if (ix_DoReq(mp, rp, IXC_GSTAT, /* Get Stats */
49ff8a6a 368 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8,
785d9ccc
MK
369 rpb, 0))
370 return;
49ff8a6a
KS
371 bcopy((caddr_t) &ix->ix_stats, (caddr_t) ix->ix_addr, 6);
372 }
373 ix->ix_if.if_flags |= IFF_RUNNING;
374 ix->ix_flags |= IXF_RUNNING;
375 ifp->if_watchdog = ixwatch;
376 ifp->if_timer = ix->ix_scaninterval = IXWATCHINTERVAL;
377 ixrint(mp, 0);
378}
379
380/*
381 * Start output on interface.
382 * Get another datagram to send off of the interface queue,
383 * and map it to the interface before starting the output.
384 */
4f02060d
KS
385ixstart(ifp)
386struct ifnet *ifp;
49ff8a6a
KS
387{
388 int len = 0;
4f02060d 389 int unit = ifp->if_unit;
49ff8a6a
KS
390 register struct ix_softc *ix = &ix_softc[unit];
391 register struct mbuf *n;
392 struct mbuf *m;
393 int s, error = 0;
394 struct npmaster *mp = ix->ix_mp;
395 struct npreq *rp = ix->ix_wrp;
396 struct CQE *ep;
397 u_short rpb[8];
398
399 IF_DEQUEUE(&ix->ix_if.if_snd, m);
400 if (m == 0) {
401 if (ix->ix_flags & IXF_STATPENDING) {
c4054532 402 ix->ix_flags &= ~IXF_STATPENDING;
4f02060d 403 ix->ix_if.if_flags |= IFF_OACTIVE;
49ff8a6a
KS
404 rpb[0] = 2;
405 rpb[1] = ix->ix_aid;
406 rpb[2] = 0; /* get all stats */
407 ix_DoReq(mp, rp, IXC_GSTAT, /* general Stats */
408 (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8,
409 rpb, ixcint);
410 }
4f02060d 411 return (0);
49ff8a6a
KS
412 }
413 /*
414 * Ensure minimum packet length.
415 * This makes the safe assumtion that there are no virtual holes
416 * after the data.
417 * For security, it might be wise to zero out the added bytes,
418 * but we're mainly interested in speed at the moment.
419 */
420 len = if_wubaput(&ix->ix_ifuba, m);
421 if (len - sizeof(struct ether_header) < ETHERMIN)
422 len = ETHERMIN + sizeof(struct ether_header);
423
4f02060d 424 ix->ix_if.if_flags |= IFF_OACTIVE;
49ff8a6a
KS
425
426 /* Now setup to call np driver */
427 rpb[0] = 8;
428 rpb[1] = ix->ix_aid;
429 ix_DoReq(mp, rp, IXC_XMIT, /* send frame */
430 ix->ix_ifuba.ifu_w.ifrw_info, len, rpb, ixcint);
4f02060d 431 return (0);
49ff8a6a
KS
432}
433
434/*
435 * Command done interrupt. (almost)
436 */
437ixcint(mp, rp)
438 struct npmaster *mp;
439 struct npreq *rp;
440{
441 struct CQE *ep;
442 register struct ix_softc *ix;
443 int s = splimp();
444
445 ep = rp->element;
446 ix = (struct ix_softc *)ep->cqe_famid;
785d9ccc 447 ix->ix_flags &= ~IXF_OWATCH;
4f02060d 448 if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) {
49ff8a6a
KS
449 printf("ix%d: stray xmit interrupt, npreq=%x\n",
450 ix->ix_if.if_unit, rp);
451 }
4f02060d 452 ix->ix_if.if_flags &= ~IFF_OACTIVE;
785d9ccc
MK
453 if (rp->flags & IOABORT || ep->cqe_sts != NPDONE
454 || ep->cqe_ust0 != NPDONE || ep->cqe_ust1 != NPOK) {
455 if (ep->cqe_ust1 == 0x48)
456 ix->ix_if.if_oerrors++;
457 else {
458 struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid;
459 printf(
460 "ix%d: ixcint failed, cmd %x, stat %x, flags %x, ",
461 ix->ix_if.if_unit, rp->user,
462 ep->cqe_sts, rp->flags);
463 printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);
464 if (++ix->ix_badcqe > 65) {
465 ix->ix_badcqe = 0;
466 printf("ixcint: shutting down unix dla\n");
467 ix->ix_if.if_flags &= ~IFF_UP;
468 }
469 }
470 }
471 else switch (ep->cqe_func) {
49ff8a6a
KS
472
473 case IXC_XMIT:
785d9ccc 474 ix->ix_if.if_opackets++;
49ff8a6a
KS
475 break;
476
477 case IXC_GSTAT:
785d9ccc 478 ix->ix_if.if_collisions += ix->ix_stats.ixg.macg_xrty;
49ff8a6a 479 }
785d9ccc 480done:
49ff8a6a
KS
481 if (ix->ix_ifuba.ifu_xtofree) {
482 m_freem(ix->ix_ifuba.ifu_xtofree);
483 ix->ix_ifuba.ifu_xtofree = 0;
484 }
785d9ccc 485 if ((ix->ix_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING))
4f02060d 486 (void) ixstart(&ix->ix_if);
49ff8a6a
KS
487 splx(s);
488}
489
490/*
491 * Ethernet interface receiver interrupt.
492 * If input error just drop packet.
493 * Otherwise purge input buffered data path and examine
494 * packet to determine type. If can't determine length
495 * from type, then have to drop packet. Othewise decapsulate
496 * packet based on type and pass to type specific higher-level
497 * input routine.
498 */
499ixrint(mp, rp)
500 struct npmaster *mp;
501 struct npreq *rp;
502{
503 struct CQE *ep;
504 register struct ix_softc *ix = ix_softc + mp->unit;
505 register struct ether_header *il;
506 struct mbuf *m;
507 int len, off, resid, s;
508 register struct ifqueue *inq;
509
510 if ((ix->ix_flags & IXF_RUNNING) == 0)
511 return;
512 if (rp == 0)
513 goto setup;
785d9ccc 514 ix->ix_flags &= ~(IXF_RCVPENDING|IXF_RWATCH);
49ff8a6a
KS
515 ep = rp->element;
516 ix->ix_if.if_ipackets++;
517 if (ix->ix_ifuba.ifu_flags & UBA_NEEDBDP)
518 UBAPURGE(ix->ix_ifuba.ifu_uba, ix->ix_ifuba.ifu_r.ifrw_bdp);
519 il = (struct ether_header *)(ix->ix_ifuba.ifu_r.ifrw_addr);
520 len = ep->cqe_bcnt - sizeof (struct ether_header);
785d9ccc 521 if (ep->cqe_sts != NPDONE || rp->flags & IOABORT
49ff8a6a
KS
522 || ep->cqe_ust0 != NPDONE
523 || ep->cqe_ust1 != NPOK) {
785d9ccc
MK
524 printf("ix%drint: cqe error, cmd %x, stat %x, flags %x, ",
525 ix->ix_if.if_unit, rp->user, ep->cqe_sts, rp->flags);
526 printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);
527 if (++ix->ix_badcqe > 50) {
49ff8a6a
KS
528 ix->ix_badcqe = 0;
529 printf("ixrint: shutting down unix dla\n");
530 ix->ix_if.if_flags &= ~IFF_UP;
531 return;
532 }
533 goto setup;
534 }
535
536 if ( len < 46 || len > ETHERMTU) {
537 ix->ix_if.if_ierrors++;
538#ifdef notdef
539 if (ix->ix_if.if_ierrors % 100 == 0)
540 printf("ix%d: += 100 input errors\n", unit);
541#endif
542 goto setup;
543 }
544
545 /*
546 * Deal with trailer protocol: if type is trailer type
547 * get true type from first 16-bit word past data.
548 * Remember that type was trailer by setting off.
549 */
550 il->ether_type = ntohs((u_short)il->ether_type);
551#define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off))))
552 if (il->ether_type >= ETHERTYPE_TRAIL &&
553 il->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
554 off = (il->ether_type - ETHERTYPE_TRAIL) * 512;
555 if (off >= ETHERMTU)
556 goto setup; /* sanity */
557 il->ether_type = ntohs(*ildataaddr(il, off, u_short *));
558 resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
559 if (off + resid > len)
560 goto setup; /* sanity */
561 len = off + resid;
562 } else
563 off = 0;
564 if (len == 0)
565 goto setup;
566
567 /*
568 * Pull packet off interface. Off is nonzero if packet
569 * has trailing header; ilget will then force this header
570 * information to be at the front, but we still have to drop
571 * the type and length which are at the front of any trailer data.
572 */
573 m = if_rubaget(&ix->ix_ifuba, len, off, &ix->ix_if);
4f02060d
KS
574 if (m)
575 ether_input(&ix->ix_if, il, m);
49ff8a6a
KS
576
577setup:
578 /*
579 * Reset for next packet if possible.
580 * If waiting for transmit command completion, set flag
581 * and wait until command completes.
582 */
583 if (rp == 0) {
584 rp = ix->ix_rrp;
585 rp->intr = ixrint;
586 ep = rp->element;
587 }
588 len = ETHERMTU + sizeof(struct ether_header);
589
590 /* Now setup to call np driver */
591 /* Initializations of request structure */
592
593 ep->cqe_func = IXC_RECV; /* get frame */
594 ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */
595 ep->cqe_bcnt = len; /* Byte count */
596 ep->cqe_lenrpb = 10; /* RPB length */
597 ep->rpb1 = ix->ix_aid; /* which channel */
598 ep->rpb2 = 65535; /* Timeout */
599
600 ix->ix_flags |= IXF_RCVPENDING;
601
c4054532 602 s = spl5();
49ff8a6a
KS
603 NpAddCQE(ep, &mp->shmemp->devcq, mp); /* Add CQE to device's queue */
604 splx(s);
605}
606
607
785d9ccc 608long ixwatchcount;
49ff8a6a
KS
609/*
610 * Watchdog routine, request statistics from board.
611 */
612ixwatch(unit)
613 int unit;
614{
615 register struct ix_softc *ix = &ix_softc[unit];
616 register struct ifnet *ifp = &ix->ix_if;
617 int s;
618
785d9ccc
MK
619 ixwatchcount++;
620 if (ix->ix_badcqe > 1) {
621 ix->ix_badcqe--; /* If errors aren't happening too fast,
622 give the board a reprieve */
623 }
624 s = splimp();
49ff8a6a
KS
625 if (ix->ix_flags & IXF_STATPENDING) {
626 ifp->if_timer = ix->ix_scaninterval;
785d9ccc
MK
627 ix->ix_flags |= IXF_OWATCH;
628 splx(s);
49ff8a6a
KS
629 return;
630 }
49ff8a6a 631 ix->ix_flags |= IXF_STATPENDING;
4f02060d
KS
632 if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0)
633 (void) ixstart(ifp);
785d9ccc
MK
634 else
635 ix->ix_flags |= IXF_OWATCH;
636 if (ix->ix_flags & IXF_RCVPENDING)
637 ix->ix_flags |= IXF_RWATCH;
49ff8a6a
KS
638 splx(s);
639 ifp->if_timer = ix->ix_scaninterval;
640}
641/*
642 * Process an ioctl request.
643 */
644ixioctl(ifp, cmd, data)
645 register struct ifnet *ifp;
646 int cmd;
647 caddr_t data;
648{
649 register struct ifaddr *ifa = (struct ifaddr *)data;
650 register struct ix_softc *ix = &ix_softc[ifp->if_unit];
651 int s = splimp(), error = 0;
652
653 switch (cmd) {
654
655 case SIOCSIFADDR:
656 ifp->if_flags |= IFF_UP;
657 ixinit(ifp->if_unit);
658 if ((ifp->if_flags & IFF_UP) == 0)
659 return (EBUSY);
660
4f02060d 661 switch (ifa->ifa_addr->sa_family) {
49ff8a6a
KS
662#ifdef INET
663 case AF_INET:
664 ((struct arpcom *)ifp)->ac_ipaddr =
665 IA_SIN(ifa)->sin_addr;
666 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
667 break;
668#endif
669#ifdef NS
670 case AF_NS:
671 {
672 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
673
674 if (ns_nullhost(*ina)) {
675 ina->x_host = * (union ns_host *)
676 (ix_softc[ifp->if_unit].ix_addr);
677 } else {
678 return
679 ix_setaddr(ina->x_host.c_host, ifp->if_unit);
680 }
681 break;
682 }
683#endif
684 }
685 break;
686
687 case SIOCSIFFLAGS:
688 if ((ifp->if_flags & IFF_UP) == 0 &&
689 ix->ix_flags & IXF_RUNNING) {
690 ix->ix_flags &= ~IXF_RUNNING;
691 NpReset(ix->ix_mp, 0);
692 } else if (ifp->if_flags & IFF_UP &&
693 (ix->ix_flags & IXF_RUNNING) == 0)
694 ixinit(ifp->if_unit);
695 break;
696
697 default:
698 error = EINVAL;
699 }
700 splx(s);
701 return (error);
702}
703
704/*
705 * set ethernet address for unit
706 */
707ix_setaddr(physaddr, unit)
708u_char *physaddr;
709int unit;
710{
711 register struct ix_softc *ix = &ix_softc[unit];
712
713 if (! (ix->ix_flags & IXF_RUNNING))
714 return (EBUSY);
715
716 /* The following is a big cop out due to the fact that
717 Changing the ethernet address resets the dla module,
718 so must re-open the channel, anyway. */
719
720
721 bcopy((caddr_t)physaddr, (caddr_t)ix->ix_addr, sizeof ix->ix_addr);
722 ix->ix_flags &= ~IXF_RUNNING;
723 ix->ix_flags |= IXF_SETADDR;
724 ixinit(unit);
725 NpKill(ix->ix_mp, ix->ix_rrp);
726}
785d9ccc
MK
727static showme() {
728 return ((int) &(ix_softc->ix_badcqe));
729}
49ff8a6a 730#endif