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

Defined functions

hdh_data defined in line 553; used 1 times
hdh_iorq defined in line 373; used 6 times
hdh_supr defined in line 591; used 1 times
hdhattach defined in line 209; used 2 times
hdhinit defined in line 276; used 2 times
hdhintr defined in line 455; used 2 times
hdhprobe defined in line 170; used 2 times
hdhreset defined in line 232; used 2 times
hdhstart defined in line 335; used 4 times
snd_supr defined in line 656; used 1 times
start_chn defined in line 426; used 2 times

Defined variables

hdh_softc defined in line 161; used 10 times
hdhdriver defined in line 89; never used
hdhinfo defined in line 87; used 5 times
hdhstd defined in line 88; used 1 times
  • in line 90
init_blk defined in line 255; used 2 times
  • in line 327(2)

Defined struct's

hdh_chan defined in line 138; used 18 times
hdh_sioq defined in line 149; used 2 times
  • in line 159(2)
hdh_softc defined in line 154; used 20 times
ifimpcb defined in line 214; used 2 times
  • in line 219(2)

Defined macros

DATA defined in line 116; used 1 times
HCBUSY defined in line 125; used 3 times
HDHDATR defined in line 119; used 1 times
HDHDATW defined in line 120; used 1 times
HDHSUPR defined in line 117; used 2 times
HDHSUPW defined in line 118; used 2 times
HDHUNIT defined in line 92; used 1 times
HDH_STARTED defined in line 123; used 2 times
HDH_UP defined in line 122; used 4 times
NHDHCH defined in line 114; used 4 times
SUPR defined in line 115; used 1 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2197
Valid CSS Valid XHTML 1.0 Strict