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