|
|
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.