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