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