|
|
1.1 ! root 1: /* @(#)if_hdh.c 7.1 (Berkeley) 6/5/86 */ ! 2: ! 3: ! 4: /************************************************************************\ ! 5: ! 6: ________________________________________________________ ! 7: / \ ! 8: | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | ! 9: | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | ! 10: | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | ! 11: | AAAA AAAA CCCC CCCC | ! 12: | AAAA AAAA CCCC CCCC | ! 13: | AAAA AAAA CCCC CCCC | ! 14: | AAAA AAAA CCCC CCCC | ! 15: | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | ! 16: | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | ! 17: | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | ! 18: \________________________________________________________/ ! 19: ! 20: Copyright (c) 1984 by Advanced Computer Communications ! 21: 720 Santa Barbara Street, Santa Barbara, California 93101 ! 22: (805) 963-9431 ! 23: ! 24: This software may be duplicated and used on systems ! 25: which are licensed to run U.C. Berkeley versions of ! 26: the UNIX operating system. Any duplication of any ! 27: part of this software must include a copy of ACC's ! 28: copyright notice. ! 29: ! 30: ! 31: File: ! 32: if_hdh.c ! 33: ! 34: Author: ! 35: Art Berggreen ! 36: ! 37: Project: ! 38: 4.2BSD HDH ! 39: ! 40: Function: ! 41: Device specific driver for IF-11/HDH under 4.2BSD ! 42: networking code. ! 43: ! 44: Revision History: ! 45: 31-Aug-1984: V1.0 - First Implementation. A.B. ! 46: 6-Nov-1984: V1.1 - Supress extra "LINE DOWN" msgs. A.B. ! 47: 13-Jan-1984: V1.2 - Add conditionals for TWG. A.B. ! 48: ! 49: \************************************************************************/ ! 50: ! 51: ! 52: ! 53: ! 54: /* $Header$ */ ! 55: ! 56: #include "hdh.h" ! 57: #ifdef NHDH > 0 ! 58: ! 59: /* ! 60: * ! 61: * ACC IF-11/HDH interface ! 62: * ! 63: */ ! 64: ! 65: #include "../machine/pte.h" ! 66: ! 67: #include "param.h" ! 68: #include "systm.h" ! 69: #include "mbuf.h" ! 70: #include "buf.h" ! 71: #include "protosw.h" ! 72: #include "socket.h" ! 73: #include "vmmac.h" ! 74: ! 75: #include "../net/if.h" ! 76: #include "../netimp/if_imp.h" ! 77: ! 78: #include "../vax/cpu.h" ! 79: #include "../vax/mtpr.h" ! 80: #include "../vaxuba/ubareg.h" ! 81: #include "../vaxuba/ubavar.h" ! 82: ! 83: #include "if_hdhreg.h" ! 84: #include "if_uba.h" ! 85: ! 86: int hdhprobe(), hdhattach(), hdhintr(); ! 87: struct uba_device *hdhinfo[NHDH]; ! 88: u_short hdhstd[] = { 0 }; ! 89: struct uba_driver hdhdriver = ! 90: { hdhprobe, 0, hdhattach, 0, hdhstd, "hdh", hdhinfo }; ! 91: ! 92: #define HDHUNIT(x) minor(x) ! 93: ! 94: int hdhinit(), hdhstart(), hdhreset(); ! 95: ! 96: /* ! 97: * "Lower half" of IMP interface driver. ! 98: * ! 99: * Each IMP interface is handled by a common module which handles ! 100: * the IMP-host protocol and a hardware driver which manages the ! 101: * hardware specific details of talking with the IMP. ! 102: * ! 103: * The hardware portion of the IMP driver handles DMA and related ! 104: * management of UNIBUS resources. The IMP protocol module interprets ! 105: * contents of these messages and "controls" the actions of the ! 106: * hardware module during IMP resets, but not, for instance, during ! 107: * UNIBUS resets. ! 108: * ! 109: * The two modules are coupled at "attach time", and ever after, ! 110: * through the imp interface structure. Higher level protocols, ! 111: * e.g. IP, interact with the IMP driver, rather than the HDH. ! 112: */ ! 113: ! 114: #define NHDHCH 2 /* no. of FDX channels for HDH */ ! 115: #define SUPR 0 /* supervisor channel */ ! 116: #define DATA 1 /* data channel */ ! 117: #define HDHSUPR 0 /* supervisor read */ ! 118: #define HDHSUPW 1 /* supervisor write */ ! 119: #define HDHDATR 2 /* data read */ ! 120: #define HDHDATW 3 /* data write */ ! 121: ! 122: #define HDH_UP 2 /* HDH protocol is up */ ! 123: #define HDH_STARTED 1 /* HDH has been initialized */ ! 124: ! 125: #define HCBUSY 1 /* HDH HDX channel busy flag */ ! 126: ! 127: /* ! 128: /* The IF-11/HDH has four independent dath flow channels between the ! 129: /* front-end and the host. Two are used for reading and writing ! 130: /* control messages and two are used for data flow. Each IF-11/HDH ! 131: /* has a device dependent data structure (hdh_softc) which contains ! 132: /* an array of four channel dependent structures (hdh_chan) to maintain ! 133: /* the context of each channel. Channel structures can be linked into ! 134: /* a queue of I/O requests pending for the hardware interface. ! 135: /* UNIBUS mapping resources are allocated for each channel pair. ! 136: */ ! 137: ! 138: struct hdh_chan { /* HDH HDX channel structure */ ! 139: struct hdh_chan *hc_next; /* link for Start I/O queuing */ ! 140: char hc_chan; /* HDX chan number */ ! 141: char hc_adx; /* extended UNIBUS address bits */ ! 142: short hc_addr; /* lower UNIBUS address bits */ ! 143: short hc_cnt; /* byte count */ ! 144: char hc_func; /* UMC I/O function */ ! 145: char hc_sbfc; /* UMC I/O subfunction */ ! 146: short hc_flags; /* status flags */ ! 147: }; ! 148: ! 149: struct hdh_sioq { /* Start I/O queue head structure */ ! 150: struct hdh_chan *sioq_head; /* pointer to queue head */ ! 151: struct hdh_chan *sioq_tail; /* pointer to queue tail */ ! 152: }; ! 153: ! 154: struct hdh_softc { /* HDH device dependent structure */ ! 155: struct ifnet *hdh_if; /* pointer to IMP's ifnet struct */ ! 156: struct impcb *hdh_ic; /* data structure shared with IMP */ ! 157: struct ifuba hdh_ifuba[NHDHCH]; /* UNIBUS resources */ ! 158: struct hdh_chan hdh_chan[2*NHDHCH]; /* HDX HDH channels */ ! 159: struct hdh_sioq hdh_sioq; /* start i/o queue */ ! 160: short hdh_flags; /* various status conditions */ ! 161: } hdh_softc[NHDH]; ! 162: ! 163: ! 164: /* ! 165: * Normally, code goes here to cause the device to interrupt to determine its ! 166: * interrupt vector. However, since the UMC must be told its vector in order ! 167: * to interrupt, we allocate and return an unused vector and initialize the ! 168: * UMC. ! 169: */ ! 170: hdhprobe(reg) ! 171: caddr_t reg; ! 172: { ! 173: register int br, cvec; ! 174: struct hdhregs *addr = (struct hdhregs *)reg; ! 175: #ifdef lint ! 176: br = 0; cvec = br; br = cvec; ! 177: hdhintr(0); ! 178: #endif ! 179: ! 180: br = 0x15; /* priority 21 (5 on UNIBUS) */ ! 181: ! 182: #ifdef HDHDEBUG ! 183: cvec = 0270; /* use constant for now ... */ ! 184: #else ! 185: ! 186: #ifdef VAXVMS /* if VMS */ ! 187: cvec = 0270; /* we can't allocate vectors */ ! 188: #else ! 189: cvec = (uba_hd[numuba].uh_lastiv -= 4); /* available vector */ ! 190: #endif VAXVMS ! 191: ! 192: #endif HDHDEBUG ! 193: ! 194: addr->ioini = (char) 0; /* init UMC regs */ ! 195: addr->staack = (char) 0; /* pass vector */ ! 196: addr->ionmi = (char) 0; /* and kick UMC */ ! 197: addr->iochn = (char) (cvec >> 2); ! 198: addr->csr = (short) HDH_RST; ! 199: addr->csr = (short) (HDH_IEN|HDH_DMA|HDH_WRT); /* set enables */ ! 200: DELAY(5000); /* give the UMC some time */ ! 201: return(1); ! 202: } ! 203: ! 204: /* ! 205: * Call the IMP module to allow it to set up its internal ! 206: * state, then tie the two modules together by setting up ! 207: * the back pointers to common data structures. ! 208: */ ! 209: hdhattach(ui) ! 210: struct uba_device *ui; ! 211: { ! 212: register struct hdh_softc *sc = &hdh_softc[ui->ui_unit]; ! 213: register struct impcb *ip; ! 214: struct ifimpcb { ! 215: struct ifnet ifimp_if; ! 216: struct impcb ifimp_impcb; ! 217: } *ifimp; ! 218: ! 219: if ((ifimp = (struct ifimpcb *)impattach(ui, hdhreset)) == 0) ! 220: return;; ! 221: sc->hdh_if = &ifimp->ifimp_if; ! 222: ip = &ifimp->ifimp_impcb; ! 223: sc->hdh_ic = ip; ! 224: ip->ic_init = hdhinit; ! 225: ip->ic_start = hdhstart; ! 226: sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT; ! 227: } ! 228: ! 229: /* ! 230: * Reset interface after UNIBUS reset. ! 231: */ ! 232: hdhreset(unit, uban) ! 233: int unit, uban; ! 234: { ! 235: register struct uba_device *ui = hdhinfo[unit]; ! 236: register struct hdh_softc *sc = &hdh_softc[unit]; ! 237: ! 238: #ifdef HDHDEBUG ! 239: printf("HDH RESET\n"); ! 240: #endif HDHDEBUG ! 241: ! 242: if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0) ! 243: || (ui->ui_ubanum != uban)) ! 244: return; ! 245: printf(" hdh%d", unit); ! 246: sc->hdh_if->if_flags &= ~IFF_RUNNING; ! 247: sc->hdh_flags = 0; ! 248: (*sc->hdh_if->if_init)(unit); ! 249: } ! 250: ! 251: /* ! 252: * Initialize the imp interface. ! 253: */ ! 254: ! 255: static char init_blk[] = ! 256: { ! 257: HDHINIT, /* SYSINIT opcode */ ! 258: HDHRQUP & 0xff, /* control code (LSB) */ ! 259: (HDHRQUP>>8) & 0xff, /* control code (MSB) */ ! 260: 10, /* command extension len */ ! 261: 0, /* loopback mode (off) */ ! 262: 3, /* our address (3=DTE) */ ! 263: 1, /* their address (1=DCE) */ ! 264: 3, /* frame ack t1 timeout */ ! 265: 3, /* poll ack timeout */ ! 266: 30, /* adm wait timeout */ ! 267: 3, /* rej wait timeout */ ! 268: 10, /* max retries */ ! 269: 3, /* watchdog timeout */ ! 270: 0xaa /* baud rate (0xaa=38.4KB) */ ! 271: /* (output on RS-232 pin 24, */ ! 272: /* send/receive timing is always */ ! 273: /* taken from pins 15/17) */ ! 274: }; ! 275: ! 276: hdhinit(unit) ! 277: int unit; ! 278: { ! 279: register struct hdh_softc *sc; ! 280: register struct uba_device *ui; ! 281: int i; ! 282: ! 283: #ifdef HDHDEBUG ! 284: printf("HDH INIT\n"); ! 285: #endif HDHDEBUG ! 286: ! 287: if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL ! 288: || ui->ui_alive == 0) { ! 289: printf("hdh%d: not alive\n", unit); ! 290: return(0); ! 291: } ! 292: sc = &hdh_softc[unit]; ! 293: ! 294: if (sc->hdh_flags & HDH_STARTED) ! 295: return(1); ! 296: ! 297: /* ! 298: * Alloc uba resources ! 299: */ ! 300: for(i=0;i<NHDHCH;i++) { ! 301: if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0, ! 302: (int)btoc(IMPMTU)) == 0) { ! 303: printf("hdh%d: cannot get chan %d uba resources\n", ! 304: unit, i); ! 305: ui->ui_alive = 0; ! 306: return(0); ! 307: } ! 308: } ! 309: ! 310: sc->hdh_if->if_flags |= IFF_RUNNING; ! 311: sc->hdh_flags = HDH_STARTED; ! 312: ! 313: /* ! 314: * hang a supervisor read (for line status) ! 315: */ ! 316: hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB); ! 317: ! 318: /* ! 319: * hang a data read ! 320: */ ! 321: hdh_iorq(unit, HDHDATR, IMPMTU, HDHRDB+HDHSTR); ! 322: ! 323: /* ! 324: * bring up line to IMP ! 325: */ ! 326: ! 327: snd_supr(unit, init_blk, sizeof(init_blk)); ! 328: ! 329: return(1); ! 330: } ! 331: ! 332: /* ! 333: * Start an output operation on an mbuf. ! 334: */ ! 335: hdhstart(dev) ! 336: dev_t dev; ! 337: { ! 338: int unit = HDHUNIT(dev); ! 339: register struct hdh_softc *sc = &hdh_softc[unit]; ! 340: register struct mbuf *m; ! 341: int len; ! 342: ! 343: /* ! 344: * If output isn't active, attempt to ! 345: * start sending a new packet. ! 346: */ ! 347: ! 348: if (sc->hdh_ic->ic_oactive) { ! 349: printf("hdh%d: start on active unit\n", unit); ! 350: return; ! 351: } ! 352: ! 353: if ((sc->hdh_flags & HDH_UP) == 0) { ! 354: sc->hdh_ic->ic_oactive = 0; /* Link not up, can't xmit */ ! 355: return; ! 356: } ! 357: ! 358: IF_DEQUEUE(&sc->hdh_if->if_snd, m); ! 359: if (m == 0) { ! 360: sc->hdh_ic->ic_oactive = 0; ! 361: return; ! 362: } ! 363: ! 364: len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ ! 365: sc->hdh_ic->ic_oactive = 1; ! 366: ! 367: hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); ! 368: } ! 369: ! 370: /* ! 371: * Start i/o operation on a UMC logical channel ! 372: */ ! 373: hdh_iorq(unit, lcn, len, func) ! 374: int unit, lcn, len, func; ! 375: { ! 376: register struct hdh_softc *sc = &hdh_softc[unit]; ! 377: register struct hdh_chan *hc = &sc->hdh_chan[lcn]; ! 378: register int info, s; ! 379: ! 380: /* ! 381: * If channel is busy (shouldn't be), drop. ! 382: */ ! 383: if (hc->hc_flags & HCBUSY) { ! 384: printf("hdh%d: channel busy lcn=%d\n", unit, lcn); ! 385: return; ! 386: } ! 387: ! 388: /* get appropriate UNIBUS mapping info */ ! 389: ! 390: if (lcn & 1) /* read or write? */ ! 391: info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; ! 392: else ! 393: info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; ! 394: ! 395: /* set channel info */ ! 396: ! 397: hc->hc_flags |= HCBUSY; ! 398: hc->hc_chan = lcn; ! 399: hc->hc_adx = (char)((info & 0x30000) >> 12); ! 400: hc->hc_addr = (unsigned short)(info & 0xffff); ! 401: hc->hc_cnt = len; ! 402: hc->hc_func = (char)func; ! 403: hc->hc_sbfc = 0; ! 404: ! 405: s = splimp(); ! 406: /* ! 407: * If UMC comm regs busy, queue start i/o for later. ! 408: */ ! 409: if (sc->hdh_sioq.sioq_head) { ! 410: (sc->hdh_sioq.sioq_tail)->hc_next = hc; ! 411: sc->hdh_sioq.sioq_tail = hc; ! 412: hc->hc_next = 0; ! 413: splx(s); ! 414: return; ! 415: } ! 416: ! 417: /* start i/o on channel now */ ! 418: ! 419: sc->hdh_sioq.sioq_head = hc; ! 420: sc->hdh_sioq.sioq_tail = hc; ! 421: hc->hc_next = 0; ! 422: start_chn(unit); ! 423: splx(s); ! 424: } ! 425: ! 426: start_chn(unit) ! 427: int unit; ! 428: { ! 429: register struct hdh_softc *sc = &hdh_softc[unit]; ! 430: register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; ! 431: register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; ! 432: ! 433: /* ! 434: * Set up comm regs. ! 435: */ ! 436: addr->iochn = hc->hc_chan; ! 437: addr->ioadx = hc->hc_adx; ! 438: addr->ioadl = hc->hc_addr; ! 439: addr->iocnt = hc->hc_cnt; ! 440: addr->iofcn = hc->hc_func; ! 441: addr->iosbf = hc->hc_sbfc; ! 442: addr->ioini = 1; ! 443: ! 444: /* signal UMC if necessary */ ! 445: ! 446: if (!(addr->ionmi)) { ! 447: addr->ionmi = 1; ! 448: addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; ! 449: } ! 450: } ! 451: ! 452: /* ! 453: * IF-11/HDH interrupt handler ! 454: */ ! 455: hdhintr(unit) ! 456: int unit; ! 457: { ! 458: register struct hdh_softc *sc = &hdh_softc[unit]; ! 459: register struct hdh_chan *hc; ! 460: register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; ! 461: int lcn, type, cc, cnt; ! 462: ! 463: /* ! 464: * Check for hardware errors. ! 465: */ ! 466: if (addr->csr & HDH_UER) { ! 467: printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); ! 468: addr->csr = 0; /* disable i/f */ ! 469: return; ! 470: } ! 471: /* ! 472: * Get logical channel info. ! 473: */ ! 474: if ((lcn = addr->stachn) >= (NHDHCH*2)) { ! 475: printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); ! 476: return; ! 477: } ! 478: ! 479: hc = &sc->hdh_chan[lcn]; ! 480: ! 481: type = addr->statyp; ! 482: cc = addr->stacc; ! 483: cnt = hc->hc_cnt - addr->stacnt; ! 484: ! 485: /* Figure out what kind of interrupt it was */ ! 486: ! 487: switch(type) { ! 488: ! 489: case HDHSACK: /* start i/o accepted */ ! 490: if (hc != sc->hdh_sioq.sioq_head) { ! 491: printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", ! 492: unit, lcn, hc, sc->hdh_sioq.sioq_head); ! 493: return; ! 494: } ! 495: ! 496: /* try to start any queued i/o request */ ! 497: ! 498: if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { ! 499: start_chn(unit); ! 500: } ! 501: break; ! 502: ! 503: case HDHDONE: /* i/o completion */ ! 504: switch (cc) { ! 505: ! 506: case HDHIOCABT: ! 507: printf("hdh%d: I/O abort ", unit); ! 508: goto daterr; ! 509: ! 510: case HDHIOCERR: ! 511: printf("hdh%d: program error ", unit); ! 512: goto daterr; ! 513: ! 514: case HDHIOCOVR: ! 515: printf("hdh%d: overrun error ", unit); ! 516: goto daterr; ! 517: ! 518: case HDHIOCUBE: ! 519: printf("hdh%d: NXM timeout or UB parity error ", unit); ! 520: ! 521: daterr: ! 522: printf("lcn=%d func=%x\n", lcn, hc->hc_func); ! 523: if (hc->hc_func & HDHRDB) ! 524: sc->hdh_if->if_ierrors++; ! 525: else ! 526: sc->hdh_if->if_oerrors++; ! 527: } ! 528: ! 529: hc->hc_flags &= ~HCBUSY; ! 530: ! 531: /* was it supervisor or data traffic? */ ! 532: ! 533: if (lcn > HDHSUPW) ! 534: hdh_data(unit, lcn, cc, cnt); ! 535: else ! 536: hdh_supr(unit, lcn, cc); ! 537: ! 538: } ! 539: ! 540: /* ! 541: * Ack the interrupt ! 542: */ ! 543: addr->staack = 1; ! 544: if (!(addr->ionmi)) { ! 545: addr->ionmi = 1; ! 546: addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; ! 547: } ! 548: } ! 549: ! 550: /* ! 551: * data channel interrupt completion handler ! 552: */ ! 553: hdh_data(unit, lcn, cc, rcnt) ! 554: int unit, lcn, cc, rcnt; ! 555: { ! 556: register struct hdh_softc *sc = &hdh_softc[unit]; ! 557: register struct hdh_chan *hc = &sc->hdh_chan[lcn]; ! 558: register struct mbuf *m; ! 559: ! 560: ! 561: /* was it read or write? */ ! 562: ! 563: if (hc->hc_func & HDHRDB) { ! 564: if (cc == HDHIOCOK) { ! 565: /* ! 566: * Queue good packet for input ! 567: */ ! 568: sc->hdh_if->if_ipackets++; ! 569: m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, ! 570: sc->hdh_if); ! 571: impinput(unit, m); ! 572: } ! 573: ! 574: /* hang a new data read */ ! 575: ! 576: hdh_iorq(unit, lcn, IMPMTU, HDHRDB+HDHSTR); ! 577: ! 578: } else { ! 579: /* ! 580: * fire up next output ! 581: */ ! 582: sc->hdh_if->if_opackets++; ! 583: sc->hdh_ic->ic_oactive = 0; ! 584: hdhstart(unit); ! 585: } ! 586: } ! 587: ! 588: /* ! 589: * supervisor channel interrupt completion handler ! 590: */ ! 591: hdh_supr(unit, lcn, cc) ! 592: int unit, lcn, cc; ! 593: { ! 594: register struct hdh_softc *sc = &hdh_softc[unit]; ! 595: register struct hdh_chan *hc = &sc->hdh_chan[lcn]; ! 596: short *p; ! 597: ! 598: ! 599: /* was it read or write? */ ! 600: ! 601: if (hc->hc_func & HDHRDB) { ! 602: if (cc == HDHIOCOK) { ! 603: p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); ! 604: ! 605: /* figure out what kind of supervisor message */ ! 606: ! 607: switch (*p) { ! 608: ! 609: case HDHIACK: ! 610: case HDHLNACK: ! 611: break; ! 612: ! 613: case HDHLNUP: ! 614: printf("hdh%d: LINE UP\n", unit); ! 615: sc->hdh_flags |= HDH_UP; ! 616: hdhstart(unit); ! 617: break; ! 618: ! 619: case HDHLNDN: ! 620: if (sc->hdh_flags & HDH_UP) ! 621: printf("hdh%d: LINE DOWN\n", unit); ! 622: sc->hdh_flags &= ~HDH_UP; ! 623: break; ! 624: ! 625: case HDHLOOP: ! 626: break; ! 627: ! 628: case HDHSQERR: ! 629: printf("hdh%d: HOST SEQUENCE ERROR\n", unit); ! 630: break; ! 631: ! 632: case HDHSQRCV: ! 633: printf("hdh%d: IMP SEQUENCE ERROR\n", unit); ! 634: break; ! 635: ! 636: case HDHDTERR: ! 637: printf("hdh%d: HOST DATA ERROR\n", unit); ! 638: break; ! 639: ! 640: case HDHTIMO: ! 641: printf("hdh%d: TIMEOUT\n", unit); ! 642: break; ! 643: ! 644: default: ! 645: printf("hdh%d: supervisor error, code=%x\n", ! 646: unit, *p); ! 647: } ! 648: } ! 649: ! 650: /* hang a new supr read */ ! 651: ! 652: hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB+HDHSTR); ! 653: } ! 654: } ! 655: ! 656: snd_supr(unit, msg, len) ! 657: int unit, len; ! 658: char *msg; ! 659: { ! 660: register struct hdh_softc *sc = &hdh_softc[unit]; ! 661: register struct mbuf *m; ! 662: register char *p; ! 663: register int cnt; ! 664: ! 665: if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { ! 666: printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); ! 667: return; ! 668: } ! 669: ! 670: cnt = len; ! 671: m->m_len = len; ! 672: p = mtod(m, char *); ! 673: ! 674: while(cnt--) *p++ = *msg++; ! 675: ! 676: cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); ! 677: ! 678: hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); ! 679: } ! 680: #endif NHDH
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.