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