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