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