1: /*
2: * @(#)if_hy.c 7.1 (Berkeley) 6/5/86
3: */
4:
5: /*
6: * 4.2 BSD Unix Kernel - Vax Network Interface Support
7: *
8: * $Header: if_hy.c,v 10.1 84/07/22 21:02:56 steveg Exp $
9: * $Locker: $
10: *
11: * Modifications from Berkeley 4.2 BSD
12: * Copyright (c) 1983, Tektronix Inc.
13: * All Rights Reserved
14: *
15: * $Log: if_hy.c,v $
16: * Revision 10.1 84/07/22 21:02:56 steveg
17: * define PI13 (moved from if_hyreg.h, somehow got dropped in the process)
18: * rework hywatch to check for power fails first
19: *
20: * Revision 10.0 84/06/30 19:54:27 steveg
21: * Big Build
22: *
23: * Revision 3.17 84/06/20 19:20:28 steveg
24: * increment hy_ntime in hywatch
25: * print out state name, csr, last command, and hy_flags when watchdog timer
26: * expires
27: *
28: * Revision 3.16 84/06/20 19:09:34 steveg
29: * turn on continuous logging by default
30: *
31: * Revision 3.15 84/05/30 22:19:09 steveg
32: * changes to reflect new layout ot statistics data
33: *
34: * Revision 3.14 84/05/30 19:25:15 steveg
35: * move driver states to if_hy.h so log printing programs can use them
36: *
37: * Revision 3.13 84/05/30 17:13:26 steveg
38: * make it compile
39: *
40: * Revision 3.12 84/05/30 13:46:16 steveg
41: * rework logging
42: *
43: * Revision 3.11 84/05/18 19:35:02 steveg
44: * clear IFF_RUNNING and IFF_UP on unibus reset to force resource allocation
45: * by the init routine
46: *
47: * Revision 3.10 84/05/04 12:14:44 steveg
48: * more rework to make it actually work under 4.2
49: *
50: * Revision 3.9 84/05/01 23:34:52 steveg
51: * fix typo so it compiles (unit -> ui->ui_unit)
52: *
53: * Revision 3.8 84/05/01 23:18:30 steveg
54: * changes after talking with rickk
55: * - check power off more closely
56: * - support remote loopback through A710 adapters
57: * - IMPLINK -> HYLINK
58: * - return EHOSTUNREACH on hyroute failure
59: * - bump if_collisions on abnormal interrupts that aren't input or output
60: *
61: *
62: */
63:
64:
65: #include "hy.h"
66: #if NHY > 0
67:
68: /*
69: * Network Systems Copropration Hyperchanel interface
70: */
71: #include "machine/pte.h"
72:
73: #include "param.h"
74: #include "systm.h"
75: #include "mbuf.h"
76: #include "buf.h"
77: #include "protosw.h"
78: #include "socket.h"
79: #include "vmmac.h"
80: #include "errno.h"
81: #include "time.h"
82: #include "kernel.h"
83: #include "ioctl.h"
84:
85: #include "../net/if.h"
86: #include "../net/netisr.h"
87: #include "../net/route.h"
88:
89: #ifdef INET
90: #include "../netinet/in.h"
91: #include "../netinet/in_systm.h"
92: #include "../netinet/in_var.h"
93: #include "../netinet/ip.h"
94: #endif
95:
96: #include "../vax/cpu.h"
97: #include "../vax/mtpr.h"
98: #include "../vaxuba/ubareg.h"
99: #include "../vaxuba/ubavar.h"
100:
101: /*
102: * configuration specific paramters
103: * - change as appropriate for particular installaions
104: */
105: #define HYROUTE
106: #define HYELOG
107: #define HYLOG
108: #define HYMTU 1100
109: #define PI13
110:
111: #ifdef DEBUG
112: #define HYLOG
113: #endif
114:
115: #include "if_hy.h"
116: #include "if_hyreg.h"
117: #include "if_uba.h"
118:
119: int hyprobe(), hyattach(), hyinit(), hyioctl();
120: int hyoutput(), hyreset(), hywatch();
121: struct uba_device *hyinfo[NHY];
122: u_short hystd[] = { 0772410, 0 };
123: struct uba_driver hydriver =
124: { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo };
125:
126: /*
127: * Hyperchannel software status per interface.
128: *
129: * Each interface is referenced by a network interface structure,
130: * hy_if, which the routing code uses to locate the interface.
131: * This structure contains the output queue for the interface, its address, ...
132: * We also have, for each interface, a UBA interface structure, which
133: * contains information about the UNIBUS resources held by the interface:
134: * map registers, buffered data paths, etc. Information is cached in this
135: * structure for use by the if_uba.c routines in running the interface
136: * efficiently.
137: */
138: struct hy_softc {
139: struct ifnet hy_if; /* network-visible interface */
140: struct ifuba hy_ifuba; /* UNIBUS resources */
141: short hy_flags; /* flags */
142: short hy_state; /* driver state */
143: u_short hy_host; /* local host number */
144: struct in_addr hy_addr; /* internet address */
145: int hy_olen; /* packet length on output */
146: int hy_lastwcr; /* last command's word count */
147: short hy_savedstate; /* saved for reissue after status */
148: short hy_savedcmd; /* saved command for reissue */
149: int hy_savedcount; /* saved byte count for reissue */
150: int hy_savedaddr; /* saved unibus address for reissue */
151: int hy_ntime; /* number of timeouts since last cmd */
152: int hy_retry; /* retry counter */
153: struct hy_stat hy_stat; /* statistics */
154: struct hy_status hy_status; /* status */
155: } hy_softc[NHY];
156:
157: #ifdef HYELOG
158: u_long hy_elog[HYE_SIZE];
159: #endif
160:
161: #ifdef HYLOG
162: struct hy_log hy_log;
163: #endif
164:
165: #ifdef HYROUTE
166: struct hy_route hy_route[NHY];
167: #endif
168:
169: #ifdef DEBUG
170: #define printL printf
171: #define printD if (hy_debug_flag) printf
172: int hy_debug_flag = 0;
173: /*
174: * hy_nodebug bit 0x01 set hy_debug_flag on hycancel
175: * hy_nodebug bit 0x02 set hy_debug_flag on command reissue
176: * hy_nodebug bit 0x04 set hy_debug_flag on abnormal interrupt
177: */
178: int hy_nodebug = 0x0;
179: #endif
180:
181: #define SCANINTERVAL 10 /* seconds */
182: #define MAXINTERVAL 20 /* seconds (max action) */
183:
184: /*
185: * Cause a device interrupt. This code uses a buffer starting at
186: * location zero on the unibus (which is already mapped by the
187: * autoconfigure code in the kernel).
188: */
189: hyprobe(reg)
190: caddr_t reg;
191: {
192: register int br, cvec; /* r11, r10 value-result */
193: register struct hydevice *addr = (struct hydevice *) reg;
194:
195: #ifdef lint
196: br = 0; cvec = br; br = cvec;
197: hyint(0);
198: #endif
199: /*
200: * request adapter status to a buffer starting at unibus location 0
201: */
202: addr->hyd_bar = 0;
203: addr->hyd_wcr = -((sizeof(struct hy_status) + 1) >> 1);
204: addr->hyd_dbuf = HYF_STATUS;
205: #ifdef PI13
206: addr->hyd_csr |= S_GO | S_IE | S_IATTN;
207: #else
208: addr->hyd_csr |= S_GO | S_IE;
209: #endif
210: DELAY(10000);
211: #ifdef PI13
212: addr->hyd_csr |= S_CLRINT; /* clear any stacked interrupts */
213: #endif
214: addr->hyd_csr &= ~(S_IE | S_CLRINT); /* disable further interrupts */
215: return(sizeof(struct hydevice));
216: }
217:
218: /*
219: * Interface exists: make available by filling in network interface
220: * record. System will initialize the interface when it is ready
221: * to accept packets.
222: */
223: hyattach(ui)
224: struct uba_device *ui;
225: {
226: register struct hy_softc *is = &hy_softc[ui->ui_unit];
227: register struct ifnet *ifp = &is->hy_if;
228:
229: ifp->if_unit = ui->ui_unit;
230: ifp->if_name = "hy";
231: ifp->if_mtu = HYMTU;
232: is->hy_state = STARTUP; /* don't allow state transitions yet */
233: ifp->if_init = hyinit;
234: ifp->if_ioctl = hyioctl;
235: ifp->if_output = hyoutput;
236: ifp->if_reset = hyreset;
237: ifp->if_watchdog = hywatch;
238: ifp->if_timer = SCANINTERVAL;
239: is->hy_ifuba.ifu_flags = UBA_CANTWAIT;
240: #ifdef notdef
241: is->hy_ifuba.ifu_flags |= UBA_NEEDBDP;
242: #endif
243: if_attach(ifp);
244: }
245:
246: /*
247: * Reset of interface after UNIBUS reset.
248: * If interface is on specified uba, reset its state.
249: */
250: hyreset(unit, uban)
251: int unit, uban;
252: {
253: register struct uba_device *ui;
254: register struct hy_softc *is;
255:
256: if (unit >= NHY || (ui = hyinfo[unit]) == 0 || ui->ui_alive == 0 ||
257: ui->ui_ubanum != uban)
258: return;
259: printf(" hy%d", unit);
260: is = &hy_softc[unit]; /* force unibus resource allocation */
261: is->hy_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
262: hyinit(unit);
263: }
264:
265: /*
266: * Initialization of interface; clear recorded pending
267: * operations, and reinitialize UNIBUS usage.
268: */
269: hyinit(unit)
270: int unit;
271: {
272: register struct hy_softc *is = &hy_softc[unit];
273: register struct uba_device *ui = hyinfo[unit];
274: register struct mbuf *m;
275: int s;
276:
277: if (is->hy_if.if_addrlist == 0) /* address still unknown */
278: return;
279: if (is->hy_if.if_flags & IFF_RUNNING) /* just reset the device */
280: goto justreset;
281: if (if_ubainit(&is->hy_ifuba, ui->ui_ubanum,
282: sizeof (struct hym_hdr), (int)btoc(HYMTU)) == 0) {
283: #ifdef DEBUG
284: if (hy_nodebug & 4)
285: hy_debug_flag = 1;
286: #endif
287: printf("hy%d: can't initialize\n", unit);
288: is->hy_if.if_flags &= ~IFF_UP;
289: return;
290: }
291: is->hy_if.if_flags |= IFF_RUNNING;
292:
293: justreset:
294: /*
295: * remove any left over outgoing messages, reset the hardware and
296: * start the state machine
297: */
298: s = splimp();
299: #ifdef HYLOG
300: hylog(HYL_RESET, 0, (char *)0);
301: #endif
302: is->hy_state = IDLE;
303: is->hy_flags = RQ_STATUS | RQ_STATISTICS | RQ_MARKUP;
304: is->hy_retry = 0;
305: for(;;) {
306: IF_DEQUEUE(&is->hy_if.if_snd, m);
307: if (m != NULL)
308: m_freem(m);
309: else
310: break;
311: }
312: hycancel(ui); /* also bumps the state machine */
313: splx(s);
314: }
315:
316: /*
317: * Issue a command to the adapter
318: */
319: hystart(ui, cmd, count, ubaddr)
320: struct uba_device *ui;
321: int cmd, count, ubaddr;
322: {
323: register struct hy_softc *is = &hy_softc[ui->ui_unit];
324: register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
325:
326: #ifdef DEBUG
327: printD("hy%d: hystart cmd = 0x%x count=%d ubaddr=0x%x\n",
328: ui->ui_unit, cmd, count, ubaddr);
329: printD("hy%d: - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
330: ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
331: addr->hyd_wcr);
332: #endif
333: if (((is->hy_flags & RQ_REISSUE) == 0) &&
334: (cmd != HYF_STATUS) && (cmd != HYF_END_OP) && (cmd != HYF_RSTATS)) {
335: is->hy_savedstate = is->hy_state;
336: is->hy_savedcmd = cmd;
337: is->hy_savedcount = count;
338: is->hy_savedaddr = ubaddr;
339: }
340: #ifdef PI13
341: if (addr->hyd_csr & S_POWEROFF) {
342: printf("hy%d: \"Soft\" Adapter Power Failure (hystart)\n", ui->ui_unit);
343: addr->hyd_csr |= S_POWEROFF;
344: DELAY(100);
345: if (addr->hyd_csr & S_POWEROFF) {
346: printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hystart)\n", ui->ui_unit);
347: if_down(&is->hy_if);
348: is->hy_if.if_flags &= ~IFF_UP;
349: is->hy_state = STARTUP;
350: } else {
351: printf("hy%d: Adapter Power Restored (hystart)\n", ui->ui_unit);
352: }
353: return;
354: }
355: #endif
356: addr->hyd_bar = ubaddr & 0xffff;
357: addr->hyd_wcr = is->hy_lastwcr = -((count+1) >> 1);
358: addr->hyd_dbuf = cmd;
359: #ifdef PI13
360: addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE | S_IATTN;
361: #else
362: addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE;
363: #endif
364: #ifdef DEBUG
365: printD("hy%d: exit hystart - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
366: ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
367: addr->hyd_wcr);
368: #endif
369: #ifdef HYLOG
370: {
371: struct {
372: u_char hcmd;
373: u_char hstate;
374: short hcount;
375: } hcl;
376:
377: hcl.hcmd = cmd;
378: hcl.hstate = is->hy_state;
379: hcl.hcount = count;
380: hylog(HYL_CMD, sizeof(hcl), (char *)&hcl);
381: }
382: #endif
383: is->hy_ntime = 0;
384: }
385:
386: int hyint_active = 0; /* set during hy interrupt */
387: /*
388: * Hyperchannel interface interrupt.
389: *
390: * An interrupt can occur for many reasons. Examine the status of
391: * the hyperchannel status bits to determine what to do next.
392: *
393: * If input error just drop packet.
394: * Otherwise purge input buffered data path and examine
395: * packet to determine type. Othewise decapsulate
396: * packet based on type and pass to type specific higher-level
397: * input routine.
398: */
399: hyint(unit)
400: int unit;
401: {
402: register struct hy_softc *is = &hy_softc[unit];
403: register struct uba_device *ui = hyinfo[unit];
404: register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
405:
406: if (hyint_active)
407: panic("RECURSIVE HYPERCHANNEL INTERRUPT");
408: hyint_active++;
409: #ifdef DEBUG
410: printD("hy%d: hyint enter - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
411: unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr);
412: #endif
413: #ifdef HYLOG
414: logit:
415: {
416: struct {
417: u_char hstate;
418: u_char hflags;
419: short hcsr;
420: short hwcr;
421: } hil;
422: hil.hstate = is->hy_state;
423: hil.hflags = is->hy_flags;
424: hil.hcsr = addr->hyd_csr;
425: hil.hwcr = addr->hyd_wcr;
426: hylog(HYL_INT, sizeof(hil), (char *)&hil);
427: }
428: #endif
429: if (HYS_ERROR(addr) && ((addr->hyd_csr & S_ATTN) == 0)) {
430: /*
431: * Error bit set, some sort of error in the interface.
432: *
433: * The adapter sets attn on command completion so that's not
434: * a real error even though the interface considers it one.
435: */
436: #ifdef DEBUG
437: if (hy_nodebug & 4)
438: hy_debug_flag = 1;
439: #endif
440: printf("csr = 0x%b\nbar = 0x%x\nwcr = 0x%x\n",
441: addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
442: addr->hyd_wcr);
443: if (addr->hyd_csr & S_NEX) {
444: printf("hy%d: NEX - Non Existant Memory\n", unit);
445: #ifdef PI13
446: addr->hyd_csr |= S_NEX; /* as per PI13 manual */
447: #else
448: addr->hyd_csr &= ~S_NEX;
449: #endif
450: hycancel(ui);
451: #ifdef PI13
452: } else if (addr->hyd_csr & S_POWEROFF) {
453: printf("hy%d: \"Soft\" Adapter Power Failure (hyint)\n", unit);
454: addr->hyd_csr |= S_POWEROFF;
455: DELAY(100);
456: if (addr->hyd_csr & S_POWEROFF) {
457: printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hyint)\n", unit);
458: if_down(&is->hy_if);
459: is->hy_if.if_flags &= ~IFF_UP;
460: is->hy_state = STARTUP;
461: } else {
462: printf("hy%d: Adapter Power Restored (hyint)\n", unit);
463: }
464: #endif
465: } else {
466: printf("hy%d: BAR overflow\n", unit);
467: hycancel(ui);
468: }
469: } else if (HYS_NORMAL(addr)) {
470: /*
471: * Normal interrupt, bump state machine unless in state
472: * waiting and no data present (assumed to be word count
473: * zero interrupt or other hardware botch).
474: */
475: if (is->hy_state != WAITING || HYS_RECVDATA(addr))
476: hyact(ui);
477: } else if (HYS_ABNORMAL(addr)) {
478: /*
479: * Abnormal termination.
480: * bump error counts, retry the last function
481: * 'MAXRETRY' times before kicking the bucket.
482: *
483: * Don't reissue the cmd if in certain states, abnormal
484: * on a reissued cmd or max retry exceeded.
485: */
486: #ifdef HYLOG
487: if (hy_log.hyl_enable != hy_log.hyl_onerr) {
488: hy_log.hyl_enable = hy_log.hyl_onerr;
489: goto logit;
490: }
491: #endif
492: #ifdef DEBUG
493: if (hy_nodebug & 4)
494: hy_debug_flag = 1;
495: printD("hy%d: abnormal interrupt, driver state \"%s\" (%d)\n",
496: unit, hy_state_names[is->hy_state], is->hy_state);
497: printD("\tflags 0x%x olen %d lastwcr %d retry %d\n",
498: is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry);
499: printD("\tsaved: state %d count %d cmd 0x%x ptr 0x%x\n",
500: is->hy_savedstate, is->hy_savedcount,
501: is->hy_savedaddr, is->hy_savedcmd);
502: #endif
503: #ifdef PI13
504: addr->hyd_csr &= ~S_C; /* clear the damned PI-13 */
505: #endif
506: if (is->hy_state == XMITSENT || is->hy_state == XMITDATASENT)
507: is->hy_if.if_oerrors++;
508: else if (is->hy_state == RECVSENT || is->hy_state == RECVDATASENT)
509: is->hy_if.if_ierrors++;
510: else
511: is->hy_if.if_collisions++; /* other errors */
512: if (is->hy_state == XMITDATASENT ||
513: is->hy_state == RECVSENT ||
514: is->hy_state == RECVDATASENT ||
515: (is->hy_flags & RQ_REISSUE) != 0 || is->hy_retry > MAXRETRY)
516: hycancel(ui);
517: else {
518: #ifdef DEBUG
519: if (hy_nodebug & 2)
520: hy_debug_flag = 1;
521: #endif
522: is->hy_retry++;
523: is->hy_flags |= RQ_ENDOP | RQ_STATUS | RQ_REISSUE;
524: is->hy_state = IDLE;
525: hyact(ui);
526: }
527: } else {
528: /*
529: * Interrupt is neither normal, abnormal, or interface error.
530: * Ignore it. It's either stacked or a word count 0.
531: */
532: #ifdef HYLOG
533: if (hy_log.hyl_enable != hy_log.hyl_onerr) {
534: hy_log.hyl_enable = hy_log.hyl_onerr;
535: goto logit;
536: }
537: #endif
538: #ifdef DEBUG
539: printD("hy%d: possible stacked interrupt ignored\n", unit);
540: #endif
541: }
542: #ifdef DEBUG
543: printD("hy%d: hyint exit\n\n", unit);
544: #endif
545: hyint_active = 0;
546:
547: }
548:
549: int hyoutprint = 0;
550:
551: /*
552: * Encapsulate a packet of type family for the local net.
553: */
554: hyoutput(ifp, m0, dst)
555: struct ifnet *ifp;
556: struct mbuf *m0;
557: struct sockaddr *dst;
558: {
559: register struct hym_hdr *hym;
560: register struct mbuf *m;
561: register char *mp;
562: int dlen; /* packet size, incl hardware header, but not sw header */
563: int error = 0;
564: int s;
565:
566: /*
567: * Calculate packet length for later deciding whether it will fit
568: * in a message proper or we also need associated data.
569: */
570: dlen = 0;
571: for (m = m0; m; m = m->m_next)
572: dlen += m->m_len;
573: m = m0;
574: if (dst->sa_family == AF_HYLINK) { /* don't add header */
575: dlen -= HYM_SWLEN;
576: goto headerexists;
577: }
578:
579: /*
580: * Add the software and hardware hyperchannel headers.
581: * If there's not enough space in the first mbuf, allocate another.
582: * If that should fail, drop this sucker.
583: * No extra space for headers is allocated.
584: */
585: mp = mtod(m, char *); /* save pointer to real message */
586: if (m->m_off > MMAXOFF ||
587: MMINOFF + sizeof(struct hym_hdr) > m->m_off) {
588: m = m_get(M_DONTWAIT, MT_HEADER);
589: if (m == 0) {
590: m = m0;
591: error = ENOBUFS;
592: goto drop;
593: }
594: m->m_next = m0;
595: m->m_off = MMINOFF;
596: m->m_len = sizeof(struct hym_hdr);
597: } else {
598: m->m_off -= sizeof(struct hym_hdr);
599: m->m_len += sizeof(struct hym_hdr);
600: }
601:
602: dlen += sizeof(struct hym_hdr) - HYM_SWLEN;
603:
604: hym = mtod(m, struct hym_hdr *);
605:
606: bzero((caddr_t)hym, sizeof(struct hym_hdr));
607:
608: switch(dst->sa_family) {
609:
610: #ifdef INET
611: case AF_INET: {
612: int i;
613:
614: /*
615: * if loopback address, swizzle ip header so when
616: * it comes back it looks like it was addressed to us
617: */
618: i = hyroute(ifp, (u_long)in_lnaof(((struct sockaddr_in *)dst)->sin_addr), hym);
619: if (i < 0)
620: goto notfound;
621: if (i > 0) {
622: struct in_addr temp;
623:
624: temp.s_addr = ((struct ip *)mp)->ip_dst.s_addr;
625: ((struct ip *)mp)->ip_dst.s_addr = ((struct ip *)mp)->ip_src.s_addr;
626: ((struct ip *)mp)->ip_src.s_addr = temp.s_addr;
627: }
628: /*
629: * If entire packet won't fit in message proper, just
630: * send hyperchannel hardware header and ip header in
631: * message proper.
632: *
633: * This insures that the associated data is at least a
634: * TCP/UDP header in length and thus prevents potential
635: * problems with very short word counts.
636: */
637: if (dlen > MPSIZE)
638: hym->hym_mplen = sizeof(struct hy_hdr) + (((struct ip *)mp)->ip_hl << 2);
639: hym->hym_type = HYLINK_IP;
640: break;
641: }
642: #endif
643:
644: default:
645: printf("hy%d: can't handle af%d\n", ifp->if_unit,
646: dst->sa_family);
647: error = EAFNOSUPPORT;
648: goto drop;
649: }
650:
651:
652: :
653:
654: /*
655: * insure message proper is below the maximum
656: */
657: if (hym->hym_mplen > MPSIZE || (dlen > MPSIZE && hym->hym_mplen == 0))
658: hym->hym_mplen = MPSIZE;
659:
660: hym->hym_from = htons(hy_softc[ifp->if_unit].hy_host);
661: if (hym->hym_mplen)
662: hym->hym_ctl |= H_ASSOC;
663: else
664: hym->hym_ctl &= ~H_ASSOC;
665: if (hyoutprint) printf("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n",
666: ifp->if_unit, hym->hym_mplen, hym->hym_ctl,
667: hym->hym_access, hym->hym_to, hym->hym_from,
668: hym->hym_param, hym->hym_type);
669: #ifdef DEBUG
670: printD("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n",
671: ifp->if_unit, hym->hym_mplen, hym->hym_ctl,
672: hym->hym_access, hym->hym_to, hym->hym_from,
673: hym->hym_param, hym->hym_type);
674: #endif
675: s = splimp();
676: if (IF_QFULL(&ifp->if_snd)) {
677: IF_DROP(&ifp->if_snd);
678: error = ENOBUFS;
679: splx(s);
680: goto drop;
681: }
682: IF_ENQUEUE(&ifp->if_snd, m);
683: if (hy_softc[ifp->if_unit].hy_state == WAITING)
684: hyact(hyinfo[ifp->if_unit]);
685: splx(s);
686: return (0);
687: notfound:
688: error = EHOSTUNREACH;
689: drop:
690: m_freem(m);
691: return (error);
692: }
693:
694: int
695: hyroute(ifp, dest, hym)
696: register struct ifnet *ifp;
697: u_long dest;
698: register struct hym_hdr *hym;
699: {
700: #ifdef HYROUTE
701: register struct hy_route *rt = &hy_route[ifp->if_unit];
702: register struct hyr_hash *rhash;
703: register int i;
704: #endif
705:
706: hym->hym_param = 0;
707: #ifdef HYROUTE
708: if (rt->hyr_lasttime != 0) {
709: i = HYRHASH(dest);
710: rhash = &rt->hyr_hash[i];
711: i = 0;
712: while (rhash->hyr_key != dest) {
713: if (rhash->hyr_flags == 0 || i > HYRSIZE)
714: return(-1);
715: rhash++; i++;
716: if (rhash >= &rt->hyr_hash[HYRSIZE])
717: rhash = &rt->hyr_hash[0];
718: }
719: if (rhash->hyr_flags & HYR_GATE) {
720: i = rhash->hyr_nextgate;
721: if (i >= rhash->hyr_egate)
722: rhash->hyr_nextgate = rhash->hyr_pgate;
723: else
724: rhash->hyr_nextgate++;
725: rhash = &rt->hyr_hash[rt->hyr_gateway[i]];
726: if ((rhash->hyr_flags & HYR_DIR) == 0)
727: return(-1);
728: } else if (rhash->hyr_flags & HYR_LOOP) {
729: hym->hym_param = H_LOOPBK; /* adapter loopback */
730: } else if (rhash->hyr_flags & HYR_RLOOP) {
731: hym->hym_param = H_RLOOPBK; /* A710 remote loopback */
732: }
733: hym->hym_ctl = rhash->hyr_ctl;
734: hym->hym_access = rhash->hyr_access;
735: hym->hym_to = rhash->hyr_dst;
736: } else {
737: #endif
738: hym->hym_ctl = H_XTRUNKS | H_RTRUNKS;
739: hym->hym_access = 0;
740: hym->hym_to = htons((u_short)dest);
741: if (dest & 0x010000)
742: hym->hym_param = H_LOOPBK; /* adapter loopback */
743: else if (dest & 0x020000)
744: hym->hym_param = H_RLOOPBK; /* A710 remote loopback */
745: #ifdef HYROUTE
746: }
747: #endif
748:
749: if (hym->hym_param == 0)
750: return(0);
751: else
752: return(1);
753: }
754:
755: hyact(ui)
756: register struct uba_device *ui;
757: {
758: register struct hy_softc *is = &hy_softc[ui->ui_unit];
759: register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
760:
761: actloop:
762: #ifdef DEBUG
763: printD("hy%d: hyact, enter state \"%s\"\n", ui->ui_unit,
764: hy_state_names[is->hy_state]);
765: #endif
766: switch (is->hy_state) {
767:
768: case STARTUP:
769: goto endintr;
770:
771: case IDLE: {
772: register rq = is->hy_flags;
773:
774: if (rq & RQ_STATUS) {
775: is->hy_flags &= ~RQ_STATUS;
776: is->hy_state = STATSENT;
777: hystart(ui, HYF_STATUS, sizeof (is->hy_status),
778: is->hy_ifuba.ifu_r.ifrw_info);
779: } else if (rq & RQ_ENDOP) {
780: is->hy_flags &= ~RQ_ENDOP;
781: is->hy_state = ENDOPSENT;
782: hystart(ui, HYF_END_OP, 0, 0);
783: } else if (rq & RQ_STATISTICS) {
784: is->hy_flags &= ~RQ_STATISTICS;
785: is->hy_state = RSTATSENT;
786: hystart(ui, HYF_RSTATS, sizeof (is->hy_stat),
787: is->hy_ifuba.ifu_r.ifrw_info);
788: } else if (HYS_RECVDATA(addr)) {
789: is->hy_state = RECVSENT;
790: is->hy_retry = 0;
791: hystart(ui, HYF_INPUTMSG, MPSIZE, is->hy_ifuba.ifu_r.ifrw_info + HYM_SWLEN);
792: } else if (rq & RQ_REISSUE) {
793: is->hy_flags &= ~RQ_REISSUE;
794: is->hy_state = is->hy_savedstate;
795: #ifdef DEBUG
796: printD("hy%d: reissue cmd=0x%x count=%d",
797: ui->ui_unit, is->hy_savedcmd, is->hy_savedcount);
798: printD(" ubaddr=0x%x retry=%d\n",
799: is->hy_savedaddr, is->hy_retry);
800: #endif
801: hystart(ui, is->hy_savedcmd, is->hy_savedcount,
802: is->hy_savedaddr);
803: } else {
804: register struct mbuf *m;
805:
806: IF_DEQUEUE(&is->hy_if.if_snd, m);
807: if (m != NULL) {
808: register struct hym_hdr *hym;
809: register int mplen;
810: register int cmd;
811:
812: is->hy_state = XMITSENT;
813: is->hy_retry = 0;
814: hym = mtod(m, struct hym_hdr *);
815: #ifdef HYLOG
816: hylog(HYL_XMIT, sizeof(struct hym_hdr),
817: (char *)hym);
818: #endif
819: mplen = hym->hym_mplen;
820: if (hym->hym_to_adapter == hym->hym_from_adapter)
821: cmd = HYF_XMITLOCMSG;
822: else
823: cmd = HYF_XMITMSG;
824: #ifdef DEBUG
825: printD("hy%d: hym_hdr = ", ui->ui_unit);
826: if (hy_debug_flag)
827: hyprintdata((char *)hym,
828: sizeof (struct hym_hdr));
829: #endif
830: is->hy_olen = if_wubaput(&is->hy_ifuba, m) - HYM_SWLEN;
831: if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
832: UBAPURGE(is->hy_ifuba.ifu_uba,
833: is->hy_ifuba.ifu_w.ifrw_bdp);
834: #ifdef DEBUG
835: printD(
836: "hy%d: sending packet (mplen = %d, hy_olen = %d) data = ",
837: ui->ui_unit, mplen, is->hy_olen);
838: if (hy_debug_flag)
839: hyprintdata(
840: is->hy_ifuba.ifu_w.ifrw_addr,
841: is->hy_olen + HYM_SWLEN);
842: #endif
843: if (mplen == 0) {
844: is->hy_flags &= ~RQ_XASSOC;
845: mplen = is->hy_olen;
846: } else {
847: is->hy_flags |= RQ_XASSOC;
848: }
849: hystart(ui, cmd, mplen, is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN);
850: } else if (rq & RQ_MARKDOWN) {
851: is->hy_flags &= ~(RQ_MARKUP | RQ_MARKDOWN);
852: is->hy_state = MARKPORT;
853: is->hy_retry = 0;
854: /*
855: * Port number is taken from status data
856: */
857: hystart(ui,
858: (int)(HYF_MARKP0|(PORTNUM(&is->hy_status)<<2)),
859: 0, 0);
860: } else if (rq & RQ_MARKUP) {
861: register struct ifnet *ifp = &is->hy_if;
862:
863: is->hy_flags &= ~RQ_MARKUP;
864: is->hy_retry = 0;
865: /*
866: * Fill in the host number
867: * from the status buffer
868: */
869: printf(
870: "hy%d: unit number 0x%x port %d type %x microcode level 0x%x\n",
871: ui->ui_unit,
872: is->hy_stat.hyc_uaddr,
873: PORTNUM(&is->hy_status),
874: (is->hy_stat.hyc_atype[0]<<8) |
875: is->hy_stat.hyc_atype[1],
876: is->hy_stat.hyc_atype[2]);
877:
878: is->hy_host =
879: (is->hy_stat.hyc_uaddr << 8) |
880: PORTNUM(&is->hy_status);
881: ifp->if_flags |= IFF_UP;
882: #ifdef HYLOG
883: hylog(HYL_UP, 0, (char *)0);
884: #endif
885: } else {
886: is->hy_state = WAITING;
887: is->hy_retry = 0;
888: hystart(ui, HYF_WAITFORMSG, 0, 0);
889: }
890: }
891: break;
892: }
893:
894: case STATSENT:
895: bcopy(is->hy_ifuba.ifu_r.ifrw_addr, (caddr_t)&is->hy_status,
896: sizeof (struct hy_status));
897: #ifdef DEBUG
898: printD("hy%d: status - %x %x %x %x %x %x %x %x\n",
899: ui->ui_unit, is->hy_status.hys_gen_status,
900: is->hy_status.hys_last_fcn,
901: is->hy_status.hys_resp_trunk,
902: is->hy_status.hys_status_trunk,
903: is->hy_status.hys_recd_resp,
904: is->hy_status.hys_error,
905: is->hy_status.hys_caddr,
906: is->hy_status.hys_pad);
907: #endif
908: is->hy_state = IDLE;
909: #ifdef HYLOG
910: hylog(HYL_STATUS, sizeof (struct hy_status),
911: (char *)&is->hy_status);
912: #endif
913: #ifdef HYELOG
914: {
915: register int i;
916:
917: i = is->hy_status.hys_error;
918: if (i > HYE_MAX)
919: i = HYE_MAX;
920: switch (is->hy_status.hys_last_fcn) {
921: case HYF_XMITLOCMSG:
922: i += HYE_MAX+1; /* fall through */
923: case HYF_XMITLSTDATA:
924: i += HYE_MAX+1; /* fall through */
925: case HYF_XMITMSG:
926: i += HYE_MAX+1;
927: }
928: hy_elog[i]++;
929: }
930: #endif
931: break;
932:
933: case RSTATSENT: {
934: register struct hy_stat *p =
935: (struct hy_stat *)is->hy_ifuba.ifu_r.ifrw_addr;
936:
937: bcopy((caddr_t)p, (caddr_t)&is->hy_stat, sizeof(struct hy_stat));
938: #ifdef DEBUG
939:
940: printD("hy%d: statistics - df0 %d df1 %d df2 %d df3 %d\n",
941: ui->ui_unit,
942: (is->hy_stat.hyc_df0[0]<<16) | (is->hy_stat.hyc_df0[1]<<8) | is->hy_stat.hyc_df0[2],
943: (is->hy_stat.hyc_df1[0]<<16) | (is->hy_stat.hyc_df1[1]<<8) | is->hy_stat.hyc_df1[2],
944: (is->hy_stat.hyc_df2[0]<<16) | (is->hy_stat.hyc_df2[1]<<8) | is->hy_stat.hyc_df2[2],
945: (is->hy_stat.hyc_df3[0]<<16) | (is->hy_stat.hyc_df3[1]<<8) | is->hy_stat.hyc_df3[2]);
946: printD(" ret0 %d ret1 %d ret2 %d ret3 %d\n",
947: (is->hy_stat.hyc_ret0[0]<<16) | (is->hy_stat.hyc_ret0[1]<<8) | is->hy_stat.hyc_ret0[2],
948: (is->hy_stat.hyc_ret1[0]<<16) | (is->hy_stat.hyc_ret1[1]<<8) | is->hy_stat.hyc_ret1[2],
949: (is->hy_stat.hyc_ret2[0]<<16) | (is->hy_stat.hyc_ret2[1]<<8) | is->hy_stat.hyc_ret2[2],
950: (is->hy_stat.hyc_ret3[0]<<16) | (is->hy_stat.hyc_ret3[1]<<8) | is->hy_stat.hyc_ret3[2]);
951: printD(" cancel %d abort %d atype %x %x %x uaddr %x\n",
952: (is->hy_stat.hyc_cancel[0]<<8) | is->hy_stat.hyc_cancel[1],
953: (is->hy_stat.hyc_abort[0]<<8) | is->hy_stat.hyc_abort[1],
954: is->hy_stat.hyc_atype[0], is->hy_stat.hyc_atype[1],
955: is->hy_stat.hyc_atype[2], is->hy_stat.hyc_uaddr);
956: #endif
957: is->hy_state = IDLE;
958: #ifdef HYLOG
959: hylog(HYL_STATISTICS, sizeof (struct hy_stat),
960: (char *)&is->hy_stat);
961: #endif
962: break;
963: }
964:
965: case CLEARSENT:
966: is->hy_state = IDLE;
967: break;
968:
969: case ENDOPSENT:
970: is->hy_state = IDLE;
971: break;
972:
973: case RECVSENT: {
974: register struct hym_hdr *hym;
975: register unsigned len;
976:
977: if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
978: UBAPURGE(is->hy_ifuba.ifu_uba,
979: is->hy_ifuba.ifu_r.ifrw_bdp);
980: hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr);
981: len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
982: if (len > MPSIZE) {
983: printf("hy%d: RECVD MP > MPSIZE (%d)\n",
984: ui->ui_unit, len);
985: is->hy_state = IDLE;
986: #ifdef DEBUG
987: hy_debug_flag = 1;
988: printD("hy%d: csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
989: ui->ui_unit, addr->hyd_csr, HY_CSR_BITS,
990: addr->hyd_bar, addr->hyd_wcr);
991: #endif
992: }
993: hym->hym_mplen = len;
994: #ifdef DEBUG
995: printD("hy%d: recvd mp, len = %d, data = ", ui->ui_unit, len);
996: if (hy_debug_flag)
997: hyprintdata((char *)hym, len + HYM_SWLEN);
998: #endif
999: if (hym->hym_ctl & H_ASSOC) {
1000: is->hy_state = RECVDATASENT;
1001: is->hy_retry = 0;
1002: hystart(ui, HYF_INPUTDATA,
1003: (int)(HYMTU + sizeof (struct hy_hdr) - len),
1004: (int)(HYM_SWLEN + is->hy_ifuba.ifu_r.ifrw_info + len));
1005: } else {
1006: hyrecvdata(ui, hym, (int)len + HYM_SWLEN);
1007: is->hy_state = IDLE;
1008: }
1009: break;
1010: }
1011:
1012: case RECVDATASENT: {
1013: register struct hym_hdr *hym;
1014: register unsigned len;
1015:
1016: if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
1017: UBAPURGE(is->hy_ifuba.ifu_uba,
1018: is->hy_ifuba.ifu_r.ifrw_bdp);
1019: hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr);
1020: len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
1021: #ifdef DEBUG
1022: printD("hy%d: recvd assoc data, len = %d, data = ",
1023: ui->ui_unit, len);
1024: if (hy_debug_flag)
1025: hyprintdata((char *)hym + hym->hym_mplen, len);
1026: #endif
1027: hyrecvdata(ui, hym, (int)(len + hym->hym_mplen + HYM_SWLEN));
1028: is->hy_state = IDLE;
1029: break;
1030: }
1031:
1032: case XMITSENT:
1033: if (is->hy_flags & RQ_XASSOC) {
1034: register int len;
1035:
1036: is->hy_flags &= ~RQ_XASSOC;
1037: is->hy_state = XMITDATASENT;
1038: is->hy_retry = 0;
1039: len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
1040: if (len > is->hy_olen) {
1041: printf(
1042: "hy%d: xmit error - len > hy_olen [%d > %d]\n",
1043: ui->ui_unit, len, is->hy_olen);
1044: #ifdef DEBUG
1045: hy_debug_flag = 1;
1046: #endif
1047: }
1048: hystart(ui, HYF_XMITLSTDATA, is->hy_olen - len,
1049: is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN + len);
1050: break;
1051: }
1052: /* fall through to ... */
1053:
1054: case XMITDATASENT:
1055: hyxmitdata(ui);
1056: is->hy_state = IDLE;
1057: break;
1058:
1059: case WAITING: /* wait for message complete or output requested */
1060: if (HYS_RECVDATA(addr))
1061: is->hy_state = IDLE;
1062: else {
1063: is->hy_state = CLEARSENT;
1064: is->hy_retry = 0;
1065: hystart(ui, HYF_CLRWFMSG, 0, 0);
1066: }
1067: break;
1068:
1069: case MARKPORT:
1070: is->hy_state = STARTUP;
1071: if_down(&is->hy_if);
1072: is->hy_if.if_flags &= ~IFF_UP;
1073: goto endintr;
1074:
1075: default:
1076: printf("hy%d: DRIVER BUG - INVALID STATE %d\n",
1077: ui->ui_unit, is->hy_state);
1078: panic("HYPERCHANNEL IN INVALID STATE");
1079: /*NOTREACHED*/
1080: }
1081: if (is->hy_state == IDLE)
1082: goto actloop;
1083: endintr:
1084: ;
1085: #ifdef DEBUG
1086: printD("hy%d: hyact, exit at \"%s\"\n", ui->ui_unit,
1087: hy_state_names[is->hy_state]);
1088: #endif
1089: }
1090:
1091: struct sockproto hypproto = { PF_HYLINK };
1092: struct sockaddr_in hypdst = { AF_HYLINK };
1093: struct sockaddr_in hypsrc = { AF_HYLINK };
1094:
1095: /*
1096: * Called from device interrupt when receiving data.
1097: * Examine packet to determine type. Decapsulate packet
1098: * based on type and pass to type specific higher-level
1099: * input routine.
1100: */
1101: hyrecvdata(ui, hym, len)
1102: struct uba_device *ui;
1103: register struct hym_hdr *hym;
1104: int len;
1105: {
1106: register struct hy_softc *is = &hy_softc[ui->ui_unit];
1107: struct mbuf *m;
1108: register struct ifqueue *inq;
1109:
1110: is->hy_if.if_ipackets++;
1111: #ifdef DEBUG
1112: printD("hy%d: recieved packet, len = %d\n", ui->ui_unit, len);
1113: #endif
1114: #ifdef HYLOG
1115: {
1116: struct {
1117: short hlen;
1118: struct hym_hdr hhdr;
1119: } hh;
1120: hh.hlen = len;
1121: hh.hhdr = *hym;
1122: hylog(HYL_RECV, sizeof(hh), (char *)&hh);
1123: }
1124: #endif
1125: if (len > HYMTU + MPSIZE || len == 0)
1126: return; /* sanity */
1127: /*
1128: * Pull packet off interface.
1129: */
1130: m = if_rubaget(&is->hy_ifuba, len, 0, &is->hy_if);
1131: if (m == NULL)
1132: return;
1133:
1134: /*
1135: * if normal or adapter loopback response packet believe hym_type,
1136: * otherwise, use the raw input queue cause it's a response from an
1137: * adapter command.
1138: */
1139: if (hym->hym_param != 0 && (u_short)hym->hym_param != 0x80ff)
1140: goto rawlinkin;
1141:
1142: switch (hym->hym_type) {
1143:
1144: #ifdef INET
1145: case HYLINK_IP:
1146: schednetisr(NETISR_IP);
1147: inq = &ipintrq;
1148: break;
1149: #endif
1150: default:
1151: rawlinkin:
1152: {
1153: struct mbuf *m0;
1154:
1155: MGET(m0, M_DONTWAIT, MT_DATA);
1156: if (m0 == 0) {
1157: m_freem(m);
1158: return;
1159: }
1160: m0->m_off = MMINOFF;
1161: m0->m_len = sizeof(struct hym_hdr);
1162: m0->m_next = m;
1163: bcopy((caddr_t)hym, mtod(m0, caddr_t), sizeof(struct hym_hdr));
1164: m = m0;
1165: hypproto.sp_protocol = 0;
1166: hypdst.sin_addr = is->hy_addr;
1167: hypsrc.sin_addr = is->hy_addr;
1168: raw_input(m, &hypproto, (struct sockaddr *)&hypsrc,
1169: (struct sockaddr *)&hypdst);
1170: return;
1171: }
1172: }
1173: if (IF_QFULL(inq)) {
1174: IF_DROP(inq);
1175: m_freem(m);
1176: } else
1177: IF_ENQUEUE(inq, m);
1178: }
1179:
1180: /*
1181: * Transmit done, release resources, bump counters.
1182: */
1183: hyxmitdata(ui)
1184: struct uba_device *ui;
1185: {
1186: register struct hy_softc *is = &hy_softc[ui->ui_unit];
1187:
1188: is->hy_if.if_opackets++;
1189: if (is->hy_ifuba.ifu_xtofree) {
1190: m_freem(is->hy_ifuba.ifu_xtofree);
1191: is->hy_ifuba.ifu_xtofree = 0;
1192: }
1193: }
1194:
1195: hycancel(ui)
1196: register struct uba_device *ui;
1197: {
1198: register struct hy_softc *is = &hy_softc[ui->ui_unit];
1199:
1200: if (is->hy_ifuba.ifu_xtofree) {
1201: m_freem(is->hy_ifuba.ifu_xtofree);
1202: is->hy_ifuba.ifu_xtofree = 0;
1203: }
1204: #ifdef HYLOG
1205: hylog(HYL_CANCEL, 0, (char *)0);
1206: #endif
1207: #ifdef DEBUG
1208: if (hy_nodebug & 1)
1209: hy_debug_flag = 1;
1210: #endif
1211: #ifdef DEBUG
1212: printD("hy%d: cancel from state \"%s\" cmd=0x%x count=%d ptr=0x%x\n",
1213: ui->ui_unit, hy_state_names[is->hy_state], is->hy_savedcmd,
1214: is->hy_savedcount, is->hy_savedaddr);
1215: printD("\tflags 0x%x olen %d lastwcr %d retry %d\n",
1216: is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry);
1217: printD("\tsaved: state %d count %d ptr 0x%x cmd 0x%x\n",
1218: is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr,
1219: is->hy_savedcmd);
1220: #endif
1221: is->hy_state = IDLE;
1222: is->hy_flags |= (RQ_ENDOP | RQ_STATUS);
1223: hyact(ui);
1224: }
1225:
1226: #ifdef DEBUG
1227: hyprintdata(cp, len)
1228: register char *cp;
1229: register int len;
1230: {
1231: register int count = 16;
1232: register char *fmt;
1233: static char regfmt[] = "\n\t %x";
1234:
1235: fmt = ®fmt[2];
1236: while (--len >= 0) {
1237: printL(fmt, *cp++ & 0xff);
1238: fmt = ®fmt[2];
1239: if (--count <= 0) {
1240: fmt = ®fmt[0];
1241: count = 16;
1242: }
1243: }
1244: printL("\n");
1245: }
1246: #endif
1247:
1248: hywatch(unit)
1249: int unit;
1250: {
1251: register struct hy_softc *is = &hy_softc[unit];
1252: register struct uba_device *ui = hyinfo[unit];
1253: register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
1254: int s;
1255:
1256: s = splimp();
1257: #ifdef PI13
1258: if ((addr->hyd_csr & S_POWEROFF) != 0) {
1259: addr->hyd_csr |= S_POWEROFF;
1260: DELAY(100);
1261: if ((addr->hyd_csr & S_POWEROFF) == 0) {
1262: printf("hy%d: Adapter Power Restored (hywatch)\n", unit);
1263: is->hy_state = IDLE;
1264: is->hy_flags |=
1265: (RQ_MARKUP | RQ_STATISTICS | RQ_ENDOP | RQ_STATUS);
1266: hyact(ui);
1267: }
1268: }
1269: #endif
1270: if (++is->hy_ntime >= 2 && is->hy_state != WAITING &&
1271: is->hy_state != STARTUP && is->hy_state != IDLE) {
1272: #ifdef HYLOG
1273: printf("hy%d: watchdog timer expired in state \"%s\"\n", unit,
1274: hy_state_names[is->hy_state]);
1275: #else
1276: printf("hy%d: watchdog timer expired in state %d\n", unit,
1277: is->hy_state);
1278: #endif
1279: printf("hy%d: last command 0x%x, flags 0x%x, csr 0x%b\n", unit,
1280: is->hy_savedcmd, is->hy_flags, addr->hyd_csr, HY_CSR_BITS);
1281: hycancel(ui);
1282: }
1283: splx(s);
1284: is->hy_if.if_timer = SCANINTERVAL;
1285: }
1286:
1287: #ifdef HYLOG
1288: hylog(code, len, ptr)
1289: int code, len;
1290: char *ptr;
1291: {
1292: register unsigned char *p;
1293: int s;
1294:
1295: s = splimp();
1296: if (hy_log.hyl_self != &hy_log) {
1297: hy_log.hyl_eptr = &hy_log.hyl_buf[HYL_SIZE];
1298: hy_log.hyl_ptr = &hy_log.hyl_buf[0];
1299: hy_log.hyl_self = &hy_log;
1300: hy_log.hyl_enable = HYL_CONTINUOUS;
1301: hy_log.hyl_onerr = HYL_CONTINUOUS;
1302: hy_log.hyl_count = 0;
1303: hy_log.hyl_icount = 16;
1304: hy_log.hyl_filter = 0xffff; /* enable all */
1305: }
1306: if (hy_log.hyl_enable == HYL_DISABLED || ((1 << code) & hy_log.hyl_filter) == 0)
1307: goto out;
1308: p = hy_log.hyl_ptr;
1309: if (p + len + 3 >= hy_log.hyl_eptr) {
1310: bzero((caddr_t)p, (unsigned)(hy_log.hyl_eptr - p));
1311: p = &hy_log.hyl_buf[0];
1312: if (hy_log.hyl_enable != HYL_CONTINUOUS) {
1313: hy_log.hyl_enable = HYL_DISABLED;
1314: goto out;
1315: }
1316: }
1317: *p++ = code;
1318: *p++ = len;
1319: bcopy((caddr_t)ptr, (caddr_t)p, (unsigned)len);
1320: if (hy_log.hyl_count != 0 && --hy_log.hyl_count == 0) {
1321: *p++ = '\0';
1322: hy_log.hyl_enable = HYL_DISABLED;
1323: hy_log.hyl_count = hy_log.hyl_icount;
1324: }
1325: p += len;
1326: if (hy_log.hyl_wait != 0) { /* wakeup HYGETLOG if wanted */
1327: if (hy_log.hyl_wait <= p - hy_log.hyl_ptr) {
1328: wakeup((caddr_t)&hy_log);
1329: hy_log.hyl_wait = 0;
1330: } else
1331: hy_log.hyl_wait -= p - hy_log.hyl_ptr;
1332: }
1333: hy_log.hyl_ptr = p;
1334: out:
1335: splx(s);
1336: }
1337: #endif
1338:
1339: /*ARGSUSED*/
1340: hyioctl(ifp, cmd, data)
1341: register struct ifnet *ifp;
1342: int cmd;
1343: caddr_t data;
1344: {
1345: struct ifaddr *ifa = (struct ifaddr *) data;
1346: struct hyrsetget *sg = (struct hyrsetget *)data;
1347: #if defined(HYLOG) || defined(HYELOG)
1348: struct hylsetget *sgl = (struct hylsetget *)data;
1349: #endif
1350: struct hy_route *r = (struct hy_route *)&hy_route[ifp->if_unit];
1351: int s = splimp(), error = 0;
1352: #ifdef HYLOG
1353: struct hy_softc *is = &hy_softc[ifp->if_unit];
1354: struct {
1355: u_char hstate;
1356: u_char hflags;
1357: u_short iflags;
1358: int hcmd;
1359: int herror;
1360: u_long haddr;
1361: u_long hmisc;
1362: } hil;
1363:
1364: hil.hmisc = -1;
1365: hil.hstate = is->hy_state;
1366: hil.hflags = is->hy_flags;
1367: hil.hcmd = cmd;
1368: #endif
1369:
1370: switch(cmd) {
1371:
1372: case SIOCSIFADDR:
1373: if (ifa->ifa_addr.sa_family != AF_INET)
1374: return(EINVAL);
1375: if ((ifp->if_flags & IFF_RUNNING) == 0)
1376: hyinit(ifp->if_unit);
1377: hy_softc[ifp->if_unit].hy_addr = IA_SIN(ifa)->sin_addr;
1378: #ifdef HYLOG
1379: hil.haddr = is->hy_addr.s_addr;
1380: #endif
1381: break;
1382:
1383: case HYSETROUTE:
1384: if (!suser()) {
1385: error = EPERM;
1386: goto out;
1387: }
1388:
1389: if (sg->hyrsg_len != sizeof(struct hy_route)) {
1390: error = EINVAL;
1391: goto out;
1392: }
1393: if (copyin((caddr_t)(sg->hyrsg_ptr), (caddr_t)r, sg->hyrsg_len)) {
1394: r->hyr_lasttime = 0; /* disable further routing if trouble */
1395: error = EFAULT;
1396: goto out;
1397: }
1398: r->hyr_lasttime = time.tv_sec;
1399: #ifdef HYLOG
1400: hil.hmisc = r->hyr_lasttime;
1401: #endif
1402: break;
1403:
1404: case HYGETROUTE:
1405: if (sg->hyrsg_len < sizeof(struct hy_route)) {
1406: error = EINVAL;
1407: goto out;
1408: }
1409: if (copyout((caddr_t)r, (caddr_t) (sg->hyrsg_ptr), sizeof(struct hy_route))) {
1410: error = EFAULT;
1411: goto out;
1412: }
1413: break;
1414:
1415: #ifdef HYELOG
1416: case HYGETELOG:
1417: if (sgl->hylsg_len < sizeof(hy_elog)) {
1418: error = EINVAL;
1419: goto out;
1420: }
1421: if (copyout((caddr_t)hy_elog, sgl->hylsg_ptr, sizeof(hy_elog))) {
1422: error = EFAULT;
1423: goto out;
1424: }
1425: if (sgl->hylsg_cmd) {
1426: if (!suser()) {
1427: error = EPERM;
1428: goto out;
1429: }
1430: bzero((caddr_t)hy_elog, sizeof(hy_elog));
1431: }
1432: break;
1433: #endif
1434:
1435: #ifdef HYLOG
1436: case HYSETLOG:
1437: if (!suser()) {
1438: error = EPERM;
1439: goto out;
1440: }
1441: hy_log.hyl_enable = HYL_DISABLED;
1442: hylog(HYL_NOP, 0, (char *)0); /* force log init */
1443: hy_log.hyl_enable = sgl->hylsg_cmd & 0x0f;
1444: hy_log.hyl_onerr = (sgl->hylsg_cmd >> 4) & 0x0f;
1445: hy_log.hyl_filter = (sgl->hylsg_cmd >> 8) & 0xffffff;
1446: hy_log.hyl_count = hy_log.hyl_icount = sgl->hylsg_len;
1447: wakeup((caddr_t)&hy_log); /* wakeup sleeping HYGETLOG */
1448: break;
1449:
1450: case HYGETLOG:
1451: if (sgl->hylsg_len < sizeof(hy_log)) {
1452: error = EINVAL;
1453: goto out;
1454: }
1455: if (sgl->hylsg_cmd != 0) {
1456: if (hy_log.hyl_wait) {
1457: error = EBUSY;
1458: goto out;
1459: }
1460: hy_log.hyl_wait = sgl->hylsg_cmd;
1461: sleep((caddr_t)&hy_log, PZERO - 1);
1462: }
1463:
1464: if (copyout((caddr_t)&hy_log, sgl->hylsg_ptr, sizeof(hy_log))) {
1465: error = EFAULT;
1466: goto out;
1467: }
1468: break;
1469: #endif
1470:
1471: default:
1472: error = EINVAL;
1473: break;
1474: }
1475: out:
1476: #ifdef HYLOG
1477: hil.herror = error;
1478: hil.iflags = ifp->if_flags;
1479: hil.haddr = is->hy_addr.s_addr;
1480: hylog(HYL_IOCTL, sizeof(hil), (char *)&hil);
1481: #endif
1482: splx(s);
1483: return (error);
1484: }
1485: #endif