|
|
1.1 ! root 1: /* if_hy.c 6.1 83/07/29 */ ! 2: ! 3: #include "hy.h" ! 4: #if NHY > 0 ! 5: ! 6: /* ! 7: * Network Systems Copropration Hyperchanel interface ! 8: * ! 9: * UNTESTED WITH 4.2 ! 10: */ ! 11: #include "../machine/pte.h" ! 12: ! 13: #include "../h/param.h" ! 14: #include "../h/systm.h" ! 15: #include "../h/mbuf.h" ! 16: #include "../h/buf.h" ! 17: #include "../h/protosw.h" ! 18: #include "../h/socket.h" ! 19: #include "../h/vmmac.h" ! 20: #include "../h/errno.h" ! 21: #include "../h/time.h" ! 22: #include "../h/kernel.h" ! 23: #include "../h/ioctl.h" ! 24: ! 25: #include "../net/if.h" ! 26: #include "../net/netisr.h" ! 27: #include "../net/route.h" ! 28: #include "../netinet/in.h" ! 29: #include "../netinet/in_systm.h" ! 30: #include "../netinet/ip.h" ! 31: #include "../netinet/ip_var.h" ! 32: ! 33: #include "../vax/cpu.h" ! 34: #include "../vax/mtpr.h" ! 35: #include "../vaxuba/ubareg.h" ! 36: #include "../vaxuba/ubavar.h" ! 37: #include "../vaxif/if_hy.h" ! 38: #include "../vaxif/if_hyreg.h" ! 39: #include "../vaxif/if_uba.h" ! 40: ! 41: #define HYROUTE ! 42: #define HYELOG ! 43: #define HYMTU 576 ! 44: ! 45: int hyprobe(), hyattach(), hyinit(), hyioctl(); ! 46: int hyoutput(), hyreset(), hywatch(); ! 47: struct uba_device *hyinfo[NHY]; ! 48: u_short hystd[] = { 0772410, 0 }; ! 49: struct uba_driver hydriver = ! 50: { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo }; ! 51: ! 52: /* ! 53: * Hyperchannel software status per interface. ! 54: * ! 55: * Each interface is referenced by a network interface structure, ! 56: * hy_if, which the routing code uses to locate the interface. ! 57: * This structure contains the output queue for the interface, its address, ... ! 58: * We also have, for each interface, a UBA interface structure, which ! 59: * contains information about the UNIBUS resources held by the interface: ! 60: * map registers, buffered data paths, etc. Information is cached in this ! 61: * structure for use by the if_uba.c routines in running the interface ! 62: * efficiently. ! 63: */ ! 64: struct hy_softc { ! 65: struct ifnet hy_if; /* network-visible interface */ ! 66: struct ifuba hy_ifuba; /* UNIBUS resources */ ! 67: short hy_flags; /* flags */ ! 68: short hy_state; /* driver state */ ! 69: int hy_ilen; /* mp length on input */ ! 70: int hy_olen; /* packet length on output */ ! 71: int hy_lastwcr; /* last command's word count */ ! 72: short hy_savedstate; /* saved for reissue after status */ ! 73: short hy_savedcmd; /* saved command for reissue */ ! 74: int hy_savedcount; /* saved byte count for reissue */ ! 75: int hy_savedaddr; /* saved unibus address for reissue */ ! 76: int hy_ntime; /* number of timeouts since last cmd */ ! 77: int hy_retry; /* retry counter */ ! 78: struct hy_stat hy_stat; /* statistics */ ! 79: struct hy_status hy_status; /* status */ ! 80: } hy_softc[NHY]; ! 81: ! 82: #ifdef HYELOG ! 83: #define HYE_MAX 0x18 ! 84: u_long hy_elog[(HYE_MAX+1)*4]; ! 85: #endif ! 86: ! 87: #ifdef DEBUG ! 88: #define printL lprintf ! 89: #define printD if (hy_debug_flag) lprintf ! 90: int hy_debug_flag = 0; ! 91: /* ! 92: * hy_nodebug bit 0x01 set hy_debug_flag on hycancel ! 93: * hy_nodebug bit 0x02 set hy_debug_flag on command reissue ! 94: * hy_nodebug bit 0x04 set hy_debug_flag on abnormal interrupt ! 95: * hy_nodebug bit 0x08 set hy_debug_flag on hyouput ! 96: * hy_nodebug bit 0x10 set hy_debug_flag on hyouput with associated data ! 97: */ ! 98: int hy_nodebug = 0x0; ! 99: #else ! 100: #define printD hyvoid ! 101: #endif ! 102: ! 103: /* ! 104: * Requests for service (in order by descending priority). ! 105: */ ! 106: #define RQ_ENDOP 001 /* end the last adapter function */ ! 107: #define RQ_REISSUE 002 /* reissue previous cmd after status */ ! 108: #define RQ_STATUS 004 /* get the status of the adapter */ ! 109: #define RQ_STATISTICS 010 /* get the statistics of the adapter */ ! 110: #define RQ_MARKDOWN 020 /* mark this adapter port down */ ! 111: #define RQ_MARKUP 040 /* mark this interface up */ ! 112: ! 113: #define RQ_XASSOC 0100 /* associated data to transmit */ ! 114: ! 115: /* ! 116: * Driver states. ! 117: */ ! 118: #define STARTUP 0 /* initial state (before fully there) */ ! 119: #define IDLE 1 /* idle state */ ! 120: #define STATSENT 2 /* status cmd sent to adapter */ ! 121: #define ENDOPSENT 3 /* end operation cmd sent */ ! 122: #define RECVSENT 4 /* input message cmd sent */ ! 123: #define RECVDATASENT 5 /* input data cmd sent */ ! 124: #define XMITSENT 6 /* transmit message cmd sent */ ! 125: #define XMITDATASENT 7 /* transmit data cmd sent */ ! 126: #define WAITING 8 /* waiting for messages */ ! 127: #define CLEARSENT 9 /* clear wait for message cmd sent */ ! 128: #define MARKPORT 10 /* mark this host's adapter port down issued */ ! 129: #define RSTATSENT 11 /* read statistics cmd sent to adapter */ ! 130: ! 131: #ifdef DEBUG ! 132: char *hy_state_names[] = { ! 133: "Startup", ! 134: "Idle", ! 135: "Status Sent", ! 136: "End op Sent", ! 137: "Recieve Message Proper Sent", ! 138: "Recieve Data Sent", ! 139: "Transmit Message Proper Sent", ! 140: "Transmit Data Sent", ! 141: "Wait for Message Sent", ! 142: "Clear Wait for Message Sent", ! 143: "Mark Port Down Sent", ! 144: "Read Statistics Sent" ! 145: }; ! 146: #endif ! 147: ! 148: #define SCANINTERVAL 10 /* seconds */ ! 149: #define MAXINTERVAL 20 /* seconds (max action) */ ! 150: ! 151: /* ! 152: * Cause a device interrupt. This code uses a buffer starting at ! 153: * location zero on the unibus (which is already mapped by the ! 154: * autoconfigure code in the kernel). ! 155: */ ! 156: hyprobe(reg) ! 157: caddr_t reg; ! 158: { ! 159: register int br, cvec; /* r11, r10 value-result */ ! 160: register struct hydevice *addr = (struct hydevice *) reg; ! 161: ! 162: #ifdef lint ! 163: br = 0; cvec = br; br = cvec; ! 164: hyint(0); ! 165: #endif ! 166: /* ! 167: * request adapter status to a buffer starting at unibus location 0 ! 168: */ ! 169: addr->hyd_bar = 0; ! 170: addr->hyd_wcr = -((sizeof(struct hy_status) + 1) >> 1); ! 171: addr->hyd_dbuf = HYF_STATUS; ! 172: #ifdef PI13 ! 173: addr->hyd_csr |= S_GO | S_IE | S_IATTN; ! 174: #else ! 175: addr->hyd_csr |= S_GO | S_IE; ! 176: #endif ! 177: DELAY(10000); ! 178: #ifdef PI13 ! 179: addr->hyd_csr |= S_CLRINT; /* clear any stacked interrupts */ ! 180: #endif ! 181: addr->hyd_csr &= ~(S_IE | S_CLRINT); /* disable further interrupts */ ! 182: return(1); ! 183: } ! 184: ! 185: /* ! 186: * Interface exists: make available by filling in network interface ! 187: * record. System will initialize the interface when it is ready ! 188: * to accept packets. ! 189: */ ! 190: hyattach(ui) ! 191: struct uba_device *ui; ! 192: { ! 193: register struct hy_softc *is = &hy_softc[ui->ui_unit]; ! 194: register struct ifnet *ifp = &is->hy_if; ! 195: ! 196: ifp->if_unit = ui->ui_unit; ! 197: ifp->if_name = "hy"; ! 198: ifp->if_mtu = HYMTU; ! 199: is->hy_state = STARTUP; /* don't allow state transitions yet */ ! 200: ifp->if_init = hyinit; ! 201: ifp->if_ioctl = hyioctl; ! 202: ifp->if_output = hyoutput; ! 203: ifp->if_reset = hyreset; ! 204: ifp->if_watchdog = hywatch; ! 205: ifp->if_timer = SCANINTERVAL; ! 206: is->hy_ifuba.ifu_flags = UBA_CANTWAIT; ! 207: #ifdef notdef ! 208: is->hy_ifuba.ifu_flags |= UBA_NEEDBDP; ! 209: #endif ! 210: if_attach(ifp); ! 211: } ! 212: ! 213: /* ! 214: * Reset of interface after UNIBUS reset. ! 215: * If interface is on specified uba, reset its state. ! 216: */ ! 217: hyreset(unit, uban) ! 218: int unit, uban; ! 219: { ! 220: register struct uba_device *ui = hyinfo[unit]; ! 221: ! 222: if (unit >= NHY || ui == 0 || ui->ui_alive == 0 || ! 223: ui->ui_ubanum != uban) ! 224: return; ! 225: printf(" hy%d", unit); ! 226: hyinit(unit); ! 227: } ! 228: ! 229: /* ! 230: * Initialization of interface; clear recorded pending ! 231: * operations, and reinitialize UNIBUS usage. ! 232: */ ! 233: hyinit(unit) ! 234: int unit; ! 235: { ! 236: register struct hy_softc *is = &hy_softc[unit]; ! 237: register struct uba_device *ui = hyinfo[unit]; ! 238: struct sockaddr_in *sin; ! 239: int s; ! 240: ! 241: sin = (struct sockaddr_in *)&is->hy_if.if_addr; ! 242: if (in_netof(sin->sin_addr) == 0) ! 243: return; ! 244: if (if_ubainit(&is->hy_ifuba, ui->ui_ubanum, ! 245: sizeof (struct hy_hdr), (int)btoc(HYMTU)) == 0) { ! 246: #ifdef DEBUG ! 247: if (hy_nodebug & 4) ! 248: hy_debug_flag = 1; ! 249: #endif ! 250: printf("hy%d: can't initialize\n", unit); ! 251: is->hy_if.if_flags &= ~IFF_UP; ! 252: return; ! 253: } ! 254: is->hy_if.if_flags |= IFF_RUNNING; ! 255: /* ! 256: * Issue wait for message and start the state machine ! 257: */ ! 258: s = splimp(); ! 259: is->hy_state = IDLE; ! 260: is->hy_flags = RQ_STATUS | RQ_STATISTICS | RQ_MARKUP; ! 261: is->hy_retry = 0; ! 262: hyact(ui); ! 263: splx(s); ! 264: } ! 265: ! 266: /* ! 267: * Issue a command to the adapter ! 268: */ ! 269: hystart(ui, cmd, count, ubaddr) ! 270: struct uba_device *ui; ! 271: int cmd, count, ubaddr; ! 272: { ! 273: register struct hy_softc *is = &hy_softc[ui->ui_unit]; ! 274: register struct hydevice *addr = (struct hydevice *)ui->ui_addr; ! 275: ! 276: #ifdef DEBUG ! 277: printD("hy%d: hystart cmd = 0x%x count=%d ubaddr=0x%x\n", ! 278: ui->ui_unit, cmd, count, ubaddr); ! 279: printD("hy%d: - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ! 280: ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, ! 281: addr->hyd_wcr); ! 282: #endif ! 283: if (((is->hy_flags & RQ_REISSUE) == 0) && ! 284: (cmd != HYF_STATUS) && (cmd != HYF_END_OP) && (cmd != HYF_RSTATS)) { ! 285: is->hy_savedstate = is->hy_state; ! 286: is->hy_savedcmd = cmd; ! 287: is->hy_savedcount = count; ! 288: is->hy_savedaddr = ubaddr; ! 289: } ! 290: addr->hyd_bar = ubaddr & 0xffff; ! 291: addr->hyd_wcr = is->hy_lastwcr = -((count+1) >> 1); ! 292: addr->hyd_dbuf = cmd; ! 293: #ifdef PI13 ! 294: addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE | S_IATTN; ! 295: #else ! 296: addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE; ! 297: #endif ! 298: #ifdef DEBUG ! 299: printD("hy%d: exit hystart - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ! 300: ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, ! 301: addr->hyd_wcr); ! 302: #endif ! 303: #ifdef HYLOG ! 304: { ! 305: struct { ! 306: u_char hcmd; ! 307: u_char hstate; ! 308: short hcount; ! 309: } hcl; ! 310: ! 311: hcl.hcmd = cmd; ! 312: hcl.hstate = is->hy_state; ! 313: hcl.hcount = count; ! 314: hylog(HYL_CMD, sizeof(hcl), (char *)&hcl); ! 315: } ! 316: #endif ! 317: is->hy_ntime = 0; ! 318: } ! 319: ! 320: int hyint_active = 0; /* set during hy interrupt */ ! 321: /* ! 322: * Hyperchannel interface interrupt. ! 323: * ! 324: * An interrupt can occur for many reasons. Examine the status of ! 325: * the hyperchannel status bits to determine what to do next. ! 326: * ! 327: * If input error just drop packet. ! 328: * Otherwise purge input buffered data path and examine ! 329: * packet to determine type. Othewise decapsulate ! 330: * packet based on type and pass to type specific higher-level ! 331: * input routine. ! 332: */ ! 333: hyint(unit) ! 334: int unit; ! 335: { ! 336: register struct hy_softc *is = &hy_softc[unit]; ! 337: register struct uba_device *ui = hyinfo[unit]; ! 338: register struct hydevice *addr = (struct hydevice *)ui->ui_addr; ! 339: ! 340: if (hyint_active) ! 341: panic("RECURSIVE HYPERCHANNEL INTERRUPT"); ! 342: hyint_active++; ! 343: #ifdef DEBUG ! 344: printD("hy%d: hyint enter - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ! 345: unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr); ! 346: #endif ! 347: #ifdef HYLOG ! 348: logit: ! 349: { ! 350: struct { ! 351: u_char hstate; ! 352: u_char hflags; ! 353: short hcsr; ! 354: short hwcr; ! 355: } hil; ! 356: hil.hstate = is->hy_state; ! 357: hil.hflags = is->hy_flags; ! 358: hil.hcsr = addr->hyd_csr; ! 359: hil.hwcr = addr->hyd_wcr; ! 360: hylog(HYL_INT, sizeof(hil), (char *)&hil); ! 361: } ! 362: #endif ! 363: if (HYS_ERROR(addr) && ((addr->hyd_csr & S_ATTN) == 0)) { ! 364: /* ! 365: * Error bit set, some sort of error in the interface. ! 366: * ! 367: * The adapter sets attn on command completion so that's not ! 368: * a real error even though the interface considers it one. ! 369: */ ! 370: #ifdef DEBUG ! 371: if (hy_nodebug & 4) ! 372: hy_debug_flag = 1; ! 373: #endif ! 374: printf("csr = 0x%b\nbar = 0x%x\nwcr = 0x%x\n", ! 375: addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, ! 376: addr->hyd_wcr); ! 377: if (addr->hyd_csr & S_NEX) { ! 378: printf("hy%d: NEX - Non Existant Memory\n", unit); ! 379: #ifdef PI13 ! 380: addr->hyd_csr |= S_NEX; /* as per PI13 manual */ ! 381: #else ! 382: addr->hyd_csr &= ~S_NEX; ! 383: #endif ! 384: hycancel(ui); ! 385: #ifdef PI13 ! 386: } else if (addr->hyd_csr & S_POWEROFF) { ! 387: printf("hy%d: Power Off bit set, trying to reset\n", ! 388: unit); ! 389: addr->hyd_csr |= S_POWEROFF; ! 390: DELAY(100); ! 391: if (addr->hyd_csr & S_POWEROFF) { ! 392: if_down(&is->hy_if); ! 393: is->hy_state = STARTUP; ! 394: printf( ! 395: "hy%d: Power Off Error, network shutdown\n", ! 396: unit); ! 397: } ! 398: #endif ! 399: } else { ! 400: printf("hy%d: BAR overflow\n", unit); ! 401: hycancel(ui); ! 402: } ! 403: } else if (HYS_NORMAL(addr)) { ! 404: /* ! 405: * Normal interrupt, bump state machine unless in state ! 406: * waiting and no data present (assumed to be word count ! 407: * zero interrupt or other hardware botch). ! 408: */ ! 409: if (is->hy_state != WAITING || HYS_RECVDATA(addr)) ! 410: hyact(ui); ! 411: } else if (HYS_ABNORMAL(addr)) { ! 412: /* ! 413: * Abnormal termination. ! 414: * bump error counts, retry the last function ! 415: * 'MAXRETRY' times before kicking the bucket. ! 416: * ! 417: * Don't reissue the cmd if in certain states, abnormal ! 418: * on a reissued cmd or max retry exceeded. ! 419: */ ! 420: #ifdef HYLOG ! 421: if (hy_log.hyl_enable != hy_log.hyl_onerr) { ! 422: hy_log.hyl_enable = hy_log.hyl_onerr; ! 423: goto logit; ! 424: } ! 425: #endif ! 426: #ifdef DEBUG ! 427: if (hy_nodebug & 4) ! 428: hy_debug_flag = 1; ! 429: printD("hy%d: abnormal interrupt, driver state \"%s\" (%d)\n", ! 430: unit, hy_state_names[is->hy_state], is->hy_state); ! 431: printD("\tflags 0x%x ilen %d olen %d lastwcr %d retry %d\n", ! 432: is->hy_flags, is->hy_ilen, is->hy_olen, ! 433: is->hy_lastwcr, is->hy_retry); ! 434: printD("\tsaved: state %d count %d cmd 0x%x ptr 0x%x\n", ! 435: is->hy_savedstate, is->hy_savedcount, ! 436: is->hy_savedaddr, is->hy_savedcmd); ! 437: #endif ! 438: #ifdef PI13 ! 439: addr->hyd_csr &= ~S_C; /* clear the damned PI-13 */ ! 440: #endif ! 441: if (is->hy_state == XMITSENT || is->hy_state == XMITDATASENT) ! 442: is->hy_if.if_oerrors++; ! 443: if (is->hy_state == RECVSENT || is->hy_state == RECVDATASENT) ! 444: is->hy_if.if_ierrors++; ! 445: if (is->hy_state == XMITDATASENT || ! 446: is->hy_state == RECVSENT || ! 447: is->hy_state == RECVDATASENT || ! 448: (is->hy_flags & RQ_REISSUE) != 0 || is->hy_retry > MAXRETRY) ! 449: hycancel(ui); ! 450: else { ! 451: #ifdef DEBUG ! 452: if (hy_nodebug & 2) ! 453: hy_debug_flag = 1; ! 454: #endif ! 455: is->hy_retry++; ! 456: is->hy_flags |= RQ_ENDOP | RQ_STATUS | RQ_REISSUE; ! 457: is->hy_state = IDLE; ! 458: hyact(ui); ! 459: } ! 460: } else { ! 461: /* ! 462: * Interrupt is neither normal, abnormal, or interface error. ! 463: * Ignore it. It's either stacked or a word count 0. ! 464: */ ! 465: #ifdef HYLOG ! 466: if (hy_log.hyl_enable != hy_log.hyl_onerr) { ! 467: hy_log.hyl_enable = hy_log.hyl_onerr; ! 468: goto logit; ! 469: } ! 470: #endif ! 471: #ifdef DEBUG ! 472: printD("hy%d: possible stacked interrupt ignored\n", unit); ! 473: #endif ! 474: } ! 475: #ifdef DEBUG ! 476: printD("hy%d: hyint exit\n\n", unit); ! 477: #endif ! 478: hyint_active = 0; ! 479: ! 480: } ! 481: ! 482: /* ! 483: * Encapsulate a packet of type family for the local net. ! 484: */ ! 485: hyoutput(ifp, m0, dst) ! 486: struct ifnet *ifp; ! 487: struct mbuf *m0; ! 488: struct sockaddr *dst; ! 489: { ! 490: register struct hym_hdr *hym; ! 491: register struct mbuf *m; ! 492: #ifdef HYROUTE ! 493: register struct hyroute *r = &hy_route[ifp->if_unit]; ! 494: #endif ! 495: short dtype; /* packet type */ ! 496: int dhost; /* destination adapter address */ ! 497: int dlen; ! 498: int mplen = 0; /* message proper length */ ! 499: short loopback = 0; /* hardware loopback requested */ ! 500: int error = 0; ! 501: int s; ! 502: ! 503: #ifdef DEBUG ! 504: if (hy_nodebug & 8) ! 505: hy_debug_flag = 1; ! 506: #endif ! 507: dlen = 0; ! 508: for (m = m0; m; m = m->m_next) ! 509: dlen += m->m_len; ! 510: m = m0; ! 511: switch(dst->sa_family) { ! 512: ! 513: #ifdef INET ! 514: case AF_INET: { ! 515: register struct ip *ip = mtod(m, struct ip *); ! 516: register struct sockaddr_in *sin = (struct sockaddr_in *)dst; ! 517: register long hostaddr = in_lnaof(sin->sin_addr); ! 518: ! 519: dhost = hostaddr & 0xffff; ! 520: dtype = HYLINK_IP; ! 521: #ifdef DEBUG ! 522: printD("hy%d: output to host %x, dhost %x\n", ! 523: ifp->if_unit, sin->sin_addr.s_addr, dhost); ! 524: #endif ! 525: /* ! 526: * Debugging loopback support: ! 527: * upper byte of 24 bit host number interpreted as follows ! 528: * 0x00 --> no loopback ! 529: * 0x01 --> hardware loop through remote adapter ! 530: * other --> software loop through remote ip layer ! 531: */ ! 532: if (hostaddr & 0xff0000) { ! 533: struct in_addr temp; ! 534: ! 535: temp = ip->ip_dst; ! 536: ip->ip_dst = ip->ip_src; ! 537: ip->ip_src = temp; ! 538: if ((hostaddr & 0xff0000) == 0x10000) ! 539: loopback = H_LOOPBK; ! 540: } ! 541: /* ! 542: * If entire packet won't fit in message proper, just ! 543: * send hyperchannel hardware header and ip header in ! 544: * message proper. If that won't fit either, just send ! 545: * the maximum message proper. ! 546: * ! 547: * This insures that the associated data is at least a ! 548: * TCP/UDP header in length and thus prevents potential ! 549: * problems with very short word counts. ! 550: */ ! 551: if (dlen > MPSIZE - sizeof (struct hy_hdr)) { ! 552: mplen = sizeof(struct hy_hdr) + (ip->ip_hl << 2); ! 553: if (mplen > MPSIZE) ! 554: mplen = MPSIZE; ! 555: } ! 556: break; ! 557: } ! 558: #endif ! 559: ! 560: default: ! 561: printf("hy%d: can't handle af%d\n", ifp->if_unit, ! 562: dst->sa_family); ! 563: #ifdef DEBUG ! 564: if (hy_nodebug & 4) ! 565: hy_debug_flag = 1; ! 566: #endif ! 567: error = EAFNOSUPPORT; ! 568: goto drop; ! 569: } ! 570: ! 571: /* ! 572: * Add the software and hardware hyperchannel headers. ! 573: * If there's not enough space in the first mbuf, allocate another. ! 574: * If that should fail, drop this sucker. ! 575: * No extra space for headers is allocated. ! 576: */ ! 577: if (m->m_off > MMAXOFF || ! 578: MMINOFF + sizeof(struct hym_hdr) > m->m_off) { ! 579: m = m_get(M_DONTWAIT, MT_HEADER); ! 580: if (m == 0) { ! 581: m = m0; ! 582: error = ENOBUFS; ! 583: goto drop; ! 584: } ! 585: m->m_next = m0; ! 586: m->m_off = MMINOFF; ! 587: m->m_len = sizeof(struct hym_hdr); ! 588: } else { ! 589: m->m_off -= sizeof(struct hym_hdr); ! 590: m->m_len += sizeof(struct hym_hdr); ! 591: } ! 592: hym = mtod(m, struct hym_hdr *); ! 593: hym->hym_mplen = mplen; ! 594: hym->hym_hdr.hyh_type = dtype; ! 595: hym->hym_hdr.hyh_off = 0; ! 596: hym->hym_hdr.hyh_from = htons((u_short)ifp->if_host[0]); ! 597: hym->hym_hdr.hyh_param = loopback; ! 598: #ifdef HYROUTE ! 599: if (r->hyr_lasttime.tv_sec != 0) { ! 600: register struct hy_hash *rh; ! 601: register int i; ! 602: ! 603: i = HYRHASH(dhost); ! 604: rh = &r->hyr_hash[i]; ! 605: i = 0; ! 606: while (rh->hyr_key != dhost) { ! 607: rh++; i++; ! 608: if (rh > &r->hyr_hash[HYRSIZE]) ! 609: rh = &r->hyr_hash[0]; ! 610: if (rh->hyr_flags == 0 || i > HYRSIZE) ! 611: goto notfound; ! 612: } ! 613: if (rh->hyr_flags & HYR_GATE) { ! 614: loopback = 0; /* no hardware loopback on gateways */ ! 615: i = rh->hyr_nextgate; ! 616: if (i >= rh->hyr_egate) ! 617: rh->hyr_nextgate = rh->hyr_pgate; ! 618: else ! 619: rh->hyr_nextgate++; ! 620: rh = &r->hyr_hash[r->hyr_gateway[i]]; ! 621: if ((rh->hyr_flags & HYR_DIR) == 0) ! 622: goto notfound; ! 623: } ! 624: hym->hym_hdr.hyh_ctl = rh->hyr_ctl; ! 625: hym->hym_hdr.hyh_access = rh->hyr_access; ! 626: hym->hym_hdr.hyh_to = rh->hyr_dst; ! 627: } else { ! 628: hym->hym_hdr.hyh_ctl = H_XTRUNKS | H_RTRUNKS; ! 629: hym->hym_hdr.hyh_access = 0; ! 630: hym->hym_hdr.hyh_to = htons((u_short)dhost); ! 631: } ! 632: #else ! 633: hym->hym_hdr.hyh_ctl = H_XTRUNKS | H_RTRUNKS; ! 634: hym->hym_hdr.hyh_access = 0; ! 635: hym->hym_hdr.hyh_to = htons(dhost); ! 636: #endif ! 637: ! 638: if (hym->hym_mplen) { ! 639: hym->hym_hdr.hyh_ctl |= H_ASSOC; ! 640: #ifdef DEBUG ! 641: if (hy_nodebug & 16) ! 642: hy_debug_flag = 1; ! 643: #endif ! 644: } else ! 645: hym->hym_hdr.hyh_ctl &= ~H_ASSOC; ! 646: #ifdef DEBUG ! 647: printD("hy%d: output mplen=%x ctl=%x access=%x to=%x", ! 648: ifp->if_unit, hym->hym_mplen, hym->hym_hdr.hyh_ctl, ! 649: hym->hym_hdr.hyh_access, hym->hym_hdr.hyh_to); ! 650: printD(" (adapter %x) from=%x param=%x type=%x off=%x\n", ! 651: hym->hym_hdr.hyh_to_adapter, ! 652: hym->hym_hdr.hyh_from, hym->hym_hdr.hyh_param, ! 653: hym->hym_hdr.hyh_type, hym->hym_hdr.hyh_off); ! 654: #endif ! 655: s = splimp(); ! 656: if (IF_QFULL(&ifp->if_snd)) { ! 657: IF_DROP(&ifp->if_snd); ! 658: error = ENOBUFS; ! 659: splx(s); ! 660: goto drop; ! 661: } ! 662: IF_ENQUEUE(&ifp->if_snd, m); ! 663: if (hy_softc[ifp->if_unit].hy_state == WAITING) ! 664: hyact(hyinfo[ifp->if_unit]); ! 665: splx(s); ! 666: return (0); ! 667: notfound: ! 668: error = ENETUNREACH; /* XXX */ ! 669: drop: ! 670: m_freem(m); ! 671: return (error); ! 672: } ! 673: ! 674: hyact(ui) ! 675: register struct uba_device *ui; ! 676: { ! 677: register struct hy_softc *is = &hy_softc[ui->ui_unit]; ! 678: register struct hydevice *addr = (struct hydevice *)ui->ui_addr; ! 679: ! 680: actloop: ! 681: #ifdef DEBUG ! 682: printD("hy%d: hyact, enter state \"%s\"\n", ui->ui_unit, ! 683: hy_state_names[is->hy_state]); ! 684: #endif ! 685: switch (is->hy_state) { ! 686: ! 687: case STARTUP: ! 688: goto endintr; ! 689: ! 690: case IDLE: { ! 691: register rq = is->hy_flags; ! 692: ! 693: if (rq & RQ_STATUS) { ! 694: is->hy_flags &= ~RQ_STATUS; ! 695: is->hy_state = STATSENT; ! 696: hystart(ui, HYF_STATUS, sizeof (is->hy_status), ! 697: is->hy_ifuba.ifu_r.ifrw_info); ! 698: } else if (rq & RQ_ENDOP) { ! 699: is->hy_flags &= ~RQ_ENDOP; ! 700: is->hy_state = ENDOPSENT; ! 701: hystart(ui, HYF_END_OP, 0, 0); ! 702: } else if (rq & RQ_STATISTICS) { ! 703: is->hy_flags &= ~RQ_STATISTICS; ! 704: is->hy_state = RSTATSENT; ! 705: hystart(ui, HYF_RSTATS, sizeof (is->hy_stat), ! 706: is->hy_ifuba.ifu_r.ifrw_info); ! 707: } else if (HYS_RECVDATA(addr)) { ! 708: is->hy_state = RECVSENT; ! 709: is->hy_retry = 0; ! 710: hystart(ui, HYF_INPUTMSG, MPSIZE, ! 711: is->hy_ifuba.ifu_r.ifrw_info); ! 712: } else if (rq & RQ_REISSUE) { ! 713: is->hy_flags &= ~RQ_REISSUE; ! 714: is->hy_state = is->hy_savedstate; ! 715: #ifdef DEBUG ! 716: printD("hy%d: reissue cmd=0x%x count=%d", ! 717: ui->ui_unit, is->hy_savedcmd, is->hy_savedcount); ! 718: printD(" ubaddr=0x%x retry=%d\n", ! 719: is->hy_savedaddr, is->hy_retry); ! 720: #endif ! 721: hystart(ui, is->hy_savedcmd, is->hy_savedcount, ! 722: is->hy_savedaddr); ! 723: } else { ! 724: register struct mbuf *m; ! 725: ! 726: IF_DEQUEUE(&is->hy_if.if_snd, m); ! 727: if (m != NULL) { ! 728: register struct hym_hdr *hym; ! 729: register int mplen; ! 730: register int cmd; ! 731: ! 732: is->hy_state = XMITSENT; ! 733: is->hy_retry = 0; ! 734: hym = mtod(m, struct hym_hdr *); ! 735: #ifdef HYLOG ! 736: hylog(HYL_XMIT, sizeof(struct hym_hdr), ! 737: (char *)hym); ! 738: #endif ! 739: mplen = hym->hym_mplen; ! 740: if (hym->hym_hdr.hyh_to_adapter == ! 741: hym->hym_hdr.hyh_from_adapter) ! 742: cmd = HYF_XMITLOCMSG; ! 743: else ! 744: cmd = HYF_XMITMSG; ! 745: #ifdef DEBUG ! 746: printD("hy%d: hym_hdr = ", ui->ui_unit); ! 747: if (hy_debug_flag) ! 748: hyprintdata((char *)hym, ! 749: sizeof (struct hym_hdr)); ! 750: #endif ! 751: /* ! 752: * Strip off the software part of ! 753: * the hyperchannel header ! 754: */ ! 755: m->m_off += sizeof(struct hym_data); ! 756: m->m_len -= sizeof(struct hym_data); ! 757: is->hy_olen = if_wubaput(&is->hy_ifuba, m); ! 758: if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) ! 759: UBAPURGE(is->hy_ifuba.ifu_uba, ! 760: is->hy_ifuba.ifu_w.ifrw_bdp); ! 761: #ifdef DEBUG ! 762: printD( ! 763: "hy%d: sending packet (mplen = %d, hy_olen = %d) data = ", ! 764: ui->ui_unit, mplen, is->hy_olen); ! 765: if (hy_debug_flag) ! 766: hyprintdata( ! 767: is->hy_ifuba.ifu_w.ifrw_addr, ! 768: is->hy_olen); ! 769: #endif ! 770: hystart(ui, cmd, ! 771: (mplen == 0) ? is->hy_olen : mplen, ! 772: is->hy_ifuba.ifu_w.ifrw_info); ! 773: if (mplen != 0) ! 774: is->hy_flags |= RQ_XASSOC; ! 775: } else if (rq & RQ_MARKDOWN) { ! 776: is->hy_flags &= ~(RQ_MARKUP | RQ_MARKDOWN); ! 777: is->hy_state = MARKPORT; ! 778: is->hy_retry = 0; ! 779: /* ! 780: * Port number is taken from status data ! 781: */ ! 782: hystart(ui, ! 783: (int)(HYF_MARKP0|(PORTNUM(&is->hy_status)<<2)), ! 784: 0, 0); ! 785: } else if (rq & RQ_MARKUP) { ! 786: register struct ifnet *ifp = &is->hy_if; ! 787: register struct sockaddr_in *sin = ! 788: (struct sockaddr_in *)&ifp->if_addr; ! 789: ! 790: is->hy_flags &= ~RQ_MARKUP; ! 791: is->hy_retry = 0; ! 792: /* ! 793: * Fill in the host number ! 794: * from the status buffer ! 795: */ ! 796: printf( ! 797: "hy%d: unit number 0x%x port %d type %x microcode level 0x%x\n", ! 798: ui->ui_unit, ! 799: is->hy_stat.hyc_uaddr, ! 800: PORTNUM(&is->hy_status), ! 801: (is->hy_stat.hyc_atype[0]<<8) | ! 802: is->hy_stat.hyc_atype[1], ! 803: is->hy_stat.hyc_atype[2]); ! 804: ! 805: ifp->if_host[0] = ! 806: (is->hy_stat.hyc_uaddr << 8) | ! 807: PORTNUM(&is->hy_status); ! 808: sin->sin_addr = ! 809: if_makeaddr(ifp->if_net, ifp->if_host[0]); ! 810: ifp->if_flags |= IFF_UP; ! 811: if_rtinit(ifp, RTF_UP); ! 812: #ifdef HYLOG ! 813: hylog(HYL_UP, 0, (char *)0); ! 814: #endif ! 815: } else { ! 816: is->hy_state = WAITING; ! 817: is->hy_retry = 0; ! 818: hystart(ui, HYF_WAITFORMSG, 0, 0); ! 819: } ! 820: } ! 821: break; ! 822: } ! 823: ! 824: case STATSENT: ! 825: bcopy(is->hy_ifuba.ifu_r.ifrw_addr, (caddr_t)&is->hy_status, ! 826: sizeof (struct hy_status)); ! 827: #ifdef DEBUG ! 828: printD("hy%d: status - %x %x %x %x %x %x %x %x\n", ! 829: ui->ui_unit, is->hy_status.hys_gen_status, ! 830: is->hy_status.hys_last_fcn, ! 831: is->hy_status.hys_resp_trunk, ! 832: is->hy_status.hys_status_trunk, ! 833: is->hy_status.hys_recd_resp, ! 834: is->hy_status.hys_error, ! 835: is->hy_status.hys_caddr, ! 836: is->hy_status.hys_pad); ! 837: #endif ! 838: is->hy_state = IDLE; ! 839: #ifdef HYLOG ! 840: hylog(HYL_STATUS, sizeof (struct hy_status), ! 841: (char *)&is->hy_status); ! 842: #endif ! 843: #ifdef HYELOG ! 844: { ! 845: register int i; ! 846: ! 847: i = is->hy_status.hys_error; ! 848: if (i < HYE_MAX) ! 849: i = HYE_MAX; ! 850: switch (is->hy_status.hys_last_fcn) { ! 851: case HYF_XMITLOCMSG: ! 852: i += HYE_MAX+1; /* fall through */ ! 853: case HYF_XMITLSTDATA: ! 854: i += HYE_MAX+1; /* fall through */ ! 855: case HYF_XMITMSG: ! 856: i += HYE_MAX+1; ! 857: } ! 858: hy_elog[i]++; ! 859: } ! 860: #endif ! 861: break; ! 862: ! 863: case RSTATSENT: { ! 864: register struct hy_stat *p = ! 865: (struct hy_stat *)is->hy_ifuba.ifu_r.ifrw_addr; ! 866: ! 867: is->hy_stat.hyc_msgcnt = ntohl(p->hyc_msgcnt); ! 868: is->hy_stat.hyc_dbcnt = ntohl(p->hyc_dbcnt); ! 869: is->hy_stat.hyc_tbusy = ntohl(p->hyc_tbusy); ! 870: is->hy_stat.hyc_hwret = ntohl(p->hyc_hwret); ! 871: is->hy_stat.hyc_crcbad = ntohl(p->hyc_crcbad); ! 872: is->hy_stat.hyc_mcret = ntohl(p->hyc_mcret); ! 873: is->hy_stat.hyc_tdabort = ntohl(p->hyc_tdabort); ! 874: is->hy_stat.hyc_atype[0] = p->hyc_atype[0]; ! 875: is->hy_stat.hyc_atype[1] = p->hyc_atype[1]; ! 876: is->hy_stat.hyc_atype[2] = p->hyc_atype[2]; ! 877: is->hy_stat.hyc_uaddr = p->hyc_uaddr; ! 878: #ifdef DEBUG ! 879: printD( ! 880: "hy%d: statistics - msgcnt %d dbcnt %d hwret %d tbusy %d crcbad %d\n", ! 881: ui->ui_unit, ! 882: is->hy_stat.hyc_msgcnt, is->hy_stat.hyc_dbcnt, ! 883: is->hy_stat.hyc_tbusy, is->hy_stat.hyc_hwret, ! 884: is->hy_stat.hyc_crcbad); ! 885: printD(" mcret %d tdabort %d atype %x %x %x uaddr %x\n", ! 886: is->hy_stat.hyc_mcret, is->hy_stat.hyc_tdabort, ! 887: is->hy_stat.hyc_atype[0], is->hy_stat.hyc_atype[1], ! 888: is->hy_stat.hyc_atype[2], is->hy_stat.hyc_uaddr); ! 889: #endif ! 890: is->hy_state = IDLE; ! 891: #ifdef HYLOG ! 892: hylog(HYL_STATISTICS, sizeof (struct hy_stat), ! 893: (char *)&is->hy_stat); ! 894: #endif ! 895: break; ! 896: } ! 897: ! 898: case CLEARSENT: ! 899: is->hy_state = IDLE; ! 900: break; ! 901: ! 902: case ENDOPSENT: ! 903: is->hy_state = IDLE; ! 904: break; ! 905: ! 906: case RECVSENT: { ! 907: register struct hy_hdr *hyh; ! 908: register unsigned len; ! 909: ! 910: if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) ! 911: UBAPURGE(is->hy_ifuba.ifu_uba, ! 912: is->hy_ifuba.ifu_r.ifrw_bdp); ! 913: hyh = (struct hy_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr); ! 914: len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; ! 915: if (len > MPSIZE) { ! 916: printf("hy%d: RECVD MP > MPSIZE (%d)\n", ! 917: ui->ui_unit, len); ! 918: #ifdef DEBUG ! 919: hy_debug_flag = 1; ! 920: printD("hy%d: csr = 0x%b, bar = 0x%x, wcr = 0x%x\n", ! 921: ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, ! 922: addr->hyd_bar, addr->hyd_wcr); ! 923: #endif ! 924: } ! 925: #ifdef DEBUG ! 926: printD("hy%d: recvd mp, len = %d, data = ", ui->ui_unit, len); ! 927: if (hy_debug_flag) ! 928: hyprintdata((char *)hyh, len); ! 929: #endif ! 930: if (hyh->hyh_ctl & H_ASSOC) { ! 931: is->hy_state = RECVDATASENT; ! 932: is->hy_ilen = len; ! 933: is->hy_retry = 0; ! 934: hystart(ui, HYF_INPUTDATA, ! 935: (int)(HYMTU-len+sizeof (struct hy_hdr)), ! 936: (int)(is->hy_ifuba.ifu_r.ifrw_info + len)); ! 937: } else { ! 938: hyrecvdata(ui, hyh, (int)len); ! 939: is->hy_state = IDLE; ! 940: } ! 941: break; ! 942: } ! 943: ! 944: case RECVDATASENT: { ! 945: register struct hy_hdr *hyh; ! 946: register unsigned len; ! 947: ! 948: if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP) ! 949: UBAPURGE(is->hy_ifuba.ifu_uba, ! 950: is->hy_ifuba.ifu_r.ifrw_bdp); ! 951: hyh = (struct hy_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr); ! 952: len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; ! 953: #ifdef DEBUG ! 954: printD("hy%d: recvd assoc data, len = %d, data = ", ! 955: ui->ui_unit, len); ! 956: if (hy_debug_flag) ! 957: hyprintdata((char *)hyh + is->hy_ilen, len); ! 958: #endif ! 959: hyrecvdata(ui, hyh, (int)(len + is->hy_ilen)); ! 960: is->hy_state = IDLE; ! 961: break; ! 962: } ! 963: ! 964: case XMITSENT: ! 965: if (is->hy_flags & RQ_XASSOC) { ! 966: register int len; ! 967: ! 968: is->hy_flags &= ~RQ_XASSOC; ! 969: is->hy_state = XMITDATASENT; ! 970: is->hy_retry = 0; ! 971: len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1; ! 972: if (len > is->hy_olen) { ! 973: printf( ! 974: "hy%d: xmit error - len > hy_olen [%d > %d]\n", ! 975: ui->ui_unit, len, is->hy_olen); ! 976: #ifdef DEBUG ! 977: hy_debug_flag = 1; ! 978: #endif ! 979: } ! 980: hystart(ui, HYF_XMITLSTDATA, is->hy_olen - len, ! 981: is->hy_ifuba.ifu_w.ifrw_info + len); ! 982: break; ! 983: } ! 984: /* fall through to ... */ ! 985: ! 986: case XMITDATASENT: ! 987: hyxmitdata(ui); ! 988: is->hy_state = IDLE; ! 989: break; ! 990: ! 991: case WAITING: /* wait for message complete or output requested */ ! 992: if (HYS_RECVDATA(addr)) ! 993: is->hy_state = IDLE; ! 994: else { ! 995: is->hy_state = CLEARSENT; ! 996: is->hy_retry = 0; ! 997: hystart(ui, HYF_CLRWFMSG, 0, 0); ! 998: } ! 999: break; ! 1000: ! 1001: case MARKPORT: ! 1002: is->hy_state = STARTUP; ! 1003: is->hy_if.if_flags &= ~IFF_UP; ! 1004: goto endintr; ! 1005: ! 1006: default: ! 1007: printf("hy%d: DRIVER BUG - INVALID STATE %d\n", ! 1008: ui->ui_unit, is->hy_state); ! 1009: panic("HYPERCHANNEL IN INVALID STATE"); ! 1010: /*NOTREACHED*/ ! 1011: } ! 1012: if (is->hy_state == IDLE) ! 1013: goto actloop; ! 1014: endintr: ! 1015: ; ! 1016: #ifdef DEBUG ! 1017: printD("hy%d: hyact, exit at \"%s\"\n", ui->ui_unit, ! 1018: hy_state_names[is->hy_state]); ! 1019: #endif ! 1020: } ! 1021: ! 1022: /* ! 1023: * Called from device interrupt when receiving data. ! 1024: * Examine packet to determine type. Decapsulate packet ! 1025: * based on type and pass to type specific higher-level ! 1026: * input routine. ! 1027: */ ! 1028: hyrecvdata(ui, hyh, len) ! 1029: struct uba_device *ui; ! 1030: register struct hy_hdr *hyh; ! 1031: int len; ! 1032: { ! 1033: register struct hy_softc *is = &hy_softc[ui->ui_unit]; ! 1034: struct mbuf *m; ! 1035: register struct ifqueue *inq; ! 1036: ! 1037: is->hy_if.if_ipackets++; ! 1038: #ifdef DEBUG ! 1039: printD("hy%d: recieved packet, len = %d (actual %d)\n", ! 1040: ui->ui_unit, len, ! 1041: len - (hyh->hyh_off + sizeof (struct hy_hdr))); ! 1042: #endif ! 1043: #ifdef HYLOG ! 1044: { ! 1045: struct { ! 1046: short hlen; ! 1047: struct hy_hdr hhdr; ! 1048: } hh; ! 1049: hh.hlen = len; ! 1050: hh.hhdr = *hyh; ! 1051: hylog(HYL_RECV, sizeof(hh), (char *)&hh); ! 1052: } ! 1053: #endif ! 1054: if (len > HYMTU + MPSIZE || len == 0) ! 1055: return; /* sanity */ ! 1056: /* ! 1057: * Pull packet off interface. ! 1058: */ ! 1059: m = if_rubaget(&is->hy_ifuba, len, 0); ! 1060: if (m == NULL) ! 1061: return; ! 1062: switch (hyh->hyh_type) { ! 1063: ! 1064: #ifdef INET ! 1065: case HYLINK_IP: ! 1066: /* ! 1067: * Strip the variable portion of the hyperchannel header ! 1068: * (fixed portion stripped in if_rubaget). ! 1069: */ ! 1070: m->m_len -= hyh->hyh_off; ! 1071: m->m_off += hyh->hyh_off; ! 1072: schednetisr(NETISR_IP); ! 1073: inq = &ipintrq; ! 1074: break; ! 1075: #endif ! 1076: default: ! 1077: m_freem(m); ! 1078: return; ! 1079: } ! 1080: if (IF_QFULL(inq)) { ! 1081: IF_DROP(inq); ! 1082: m_freem(m); ! 1083: } else ! 1084: IF_ENQUEUE(inq, m); ! 1085: } ! 1086: ! 1087: /* ! 1088: * Transmit done, release resources, bump counters. ! 1089: */ ! 1090: hyxmitdata(ui) ! 1091: struct uba_device *ui; ! 1092: { ! 1093: register struct hy_softc *is = &hy_softc[ui->ui_unit]; ! 1094: ! 1095: is->hy_if.if_opackets++; ! 1096: if (is->hy_ifuba.ifu_xtofree) { ! 1097: m_freem(is->hy_ifuba.ifu_xtofree); ! 1098: is->hy_ifuba.ifu_xtofree = 0; ! 1099: } ! 1100: } ! 1101: ! 1102: hycancel(ui) ! 1103: register struct uba_device *ui; ! 1104: { ! 1105: register struct hy_softc *is = &hy_softc[ui->ui_unit]; ! 1106: ! 1107: if (is->hy_ifuba.ifu_xtofree) { ! 1108: m_freem(is->hy_ifuba.ifu_xtofree); ! 1109: is->hy_ifuba.ifu_xtofree = 0; ! 1110: } ! 1111: #ifdef DEBUG ! 1112: if (hy_nodebug & 1) ! 1113: hy_debug_flag = 1; ! 1114: #endif ! 1115: #ifdef DEBUG ! 1116: printD("hy%d: cancel from state \"%s\" cmd=0x%x count=%d ptr=0x%x\n", ! 1117: ui->ui_unit, hy_state_names[is->hy_state], is->hy_savedcmd, ! 1118: is->hy_savedcount, is->hy_savedaddr); ! 1119: printD("\tflags 0x%x ilen %d olen %d lastwcr %d retry %d\n", ! 1120: is->hy_flags, is->hy_ilen, is->hy_olen, is->hy_lastwcr, ! 1121: is->hy_retry); ! 1122: printD("\tsaved: state %d count %d ptr 0x%x cmd 0x%x\n", ! 1123: is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr, ! 1124: is->hy_savedcmd); ! 1125: #endif ! 1126: is->hy_state = IDLE; ! 1127: is->hy_flags |= (RQ_ENDOP | RQ_STATUS); ! 1128: hyact(ui); ! 1129: } ! 1130: ! 1131: #ifdef DEBUG ! 1132: hyprintdata(cp, len) ! 1133: register char *cp; ! 1134: register int len; ! 1135: { ! 1136: register int count = 16; ! 1137: register char *fmt; ! 1138: static char regfmt[] = "\n\t %x"; ! 1139: ! 1140: fmt = ®fmt[2]; ! 1141: while (--len >= 0) { ! 1142: printL(fmt, *cp++ & 0xff); ! 1143: fmt = ®fmt[2]; ! 1144: if (--count <= 0) { ! 1145: fmt = ®fmt[0]; ! 1146: count = 16; ! 1147: } ! 1148: } ! 1149: printL("\n"); ! 1150: } ! 1151: #endif ! 1152: ! 1153: hywatch(unit) ! 1154: int unit; ! 1155: { ! 1156: register struct hy_softc *is = &hy_softc[unit]; ! 1157: register struct uba_device *ui = hyinfo[unit]; ! 1158: register struct hydevice *addr = (struct hydevice *)ui->ui_addr; ! 1159: int s; ! 1160: ! 1161: s = splimp(); ! 1162: is->hy_if.if_timer = SCANINTERVAL; ! 1163: if (is->hy_ntime > 2 && is->hy_state != WAITING && ! 1164: is->hy_state != STARTUP && is->hy_state != IDLE) { ! 1165: printf("hy%d: watchdog timer expired\n", unit); ! 1166: hycancel(ui); ! 1167: } ! 1168: #ifdef PI13 ! 1169: if ((addr->hyd_csr & S_POWEROFF) != 0) { ! 1170: addr->hyd_csr |= S_POWEROFF; ! 1171: DELAY(100); ! 1172: if ((addr->hyd_csr & S_POWEROFF) == 0) { ! 1173: printf("hy%d: adapter power restored\n", unit); ! 1174: is->hy_state = IDLE; ! 1175: is->hy_flags |= ! 1176: (RQ_MARKUP | RQ_STATISTICS | RQ_ENDOP | RQ_STATUS); ! 1177: hyact(ui); ! 1178: } ! 1179: } ! 1180: #endif ! 1181: splx(s); ! 1182: } ! 1183: ! 1184: #ifdef HYLOG ! 1185: hylog(code, len, ptr) ! 1186: int code, len; ! 1187: char *ptr; ! 1188: { ! 1189: register unsigned char *p; ! 1190: int s; ! 1191: ! 1192: s = splimp(); ! 1193: if (hy_log.hyl_self != &hy_log) { ! 1194: hy_log.hyl_eptr = &hy_log.hyl_buf[HYL_SIZE]; ! 1195: hy_log.hyl_ptr = &hy_log.hyl_buf[0]; ! 1196: hy_log.hyl_self = &hy_log; ! 1197: hy_log.hyl_enable = HYL_DISABLED; ! 1198: hy_log.hyl_onerr = HYL_CATCH1; ! 1199: } ! 1200: if (hy_log.hyl_enable == HYL_DISABLED || ! 1201: hy_log.hyl_enable == HYL_CAUGHT1 || ! 1202: hy_log.hyl_enable == HYL_CAUGHTSTATUS || ! 1203: (hy_log.hyl_enable == HYL_CATCHSTATUS && code != HYL_STATUS)) ! 1204: goto out; ! 1205: p = hy_log.hyl_ptr; ! 1206: if (p + len + 2 >= hy_log.hyl_eptr) { ! 1207: bzero((caddr_t)p, (unsigned)(hy_log.hyl_eptr - p)); ! 1208: p = &hy_log.hyl_buf[0]; ! 1209: if (hy_log.hyl_enable == HYL_CATCH1) { ! 1210: hy_log.hyl_enable = hy_log.hyl_onerr = HYL_CAUGHT1; ! 1211: goto out; ! 1212: } ! 1213: if (hy_log.hyl_enable == HYL_CATCHSTATUS) { ! 1214: hy_log.hyl_enable = hy_log.hyl_onerr = HYL_CAUGHTSTATUS; ! 1215: goto out; ! 1216: } ! 1217: } ! 1218: *p++ = code; ! 1219: *p++ = len; ! 1220: bcopy((caddr_t)ptr, (caddr_t)p, (unsigned)len); ! 1221: hy_log.hyl_ptr = p + len; ! 1222: out: ! 1223: splx(s); ! 1224: } ! 1225: #endif ! 1226: ! 1227: /*ARGSUSED*/ ! 1228: hyioctl(ifp, cmd, data) ! 1229: register struct ifnet *ifp; ! 1230: int cmd; ! 1231: caddr_t data; ! 1232: { ! 1233: struct sockaddr_in *sin; ! 1234: struct ifreq *ifr = (struct ifreq *)data; ! 1235: int s = splimp(), error = 0; ! 1236: ! 1237: switch(cmd) { ! 1238: ! 1239: case SIOCSIFADDR: ! 1240: if (ifp->if_flags & IFF_RUNNING) ! 1241: if_rtinit(ifp, -1); ! 1242: sin = (struct sockaddr_in *)&ifr->ifr_addr; ! 1243: ifp->if_net = in_netof(sin->sin_addr); ! 1244: sin = (struct sockaddr_in *)&ifp->if_addr; ! 1245: sin->sin_family = AF_INET; ! 1246: sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]); ! 1247: if (ifp->if_flags & IFF_RUNNING) ! 1248: if_rtinit(ifp, RTF_UP); ! 1249: else ! 1250: hyinit(ifp->if_unit); ! 1251: break; ! 1252: ! 1253: case HYSETROUTE: ! 1254: if (!suser()) { ! 1255: error = EPERM; ! 1256: goto bad; ! 1257: } ! 1258: hy_route[ifp->if_unit] = *(struct hyroute *)ifr->ifr_data; ! 1259: hy_route[ifp->if_unit].hyr_lasttime = time; ! 1260: break; ! 1261: ! 1262: case HYGETROUTE: ! 1263: *(struct hyroute *)ifr->ifr_data = hy_route[ifp->if_unit]; ! 1264: break; ! 1265: ! 1266: default: ! 1267: error = EINVAL; ! 1268: break; ! 1269: } ! 1270: bad: ! 1271: splx(s); ! 1272: return (error); ! 1273: } ! 1274: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.