1*34503Skarels /* @(#)if_hdh.c 7.5 (Berkeley) 05/26/88 */ 224888Skarels 324888Skarels 424888Skarels /************************************************************************\ 524888Skarels 624888Skarels ________________________________________________________ 724888Skarels / \ 824888Skarels | AAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | 924888Skarels | AAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | 1024888Skarels | AAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | 1124888Skarels | AAAA AAAA CCCC CCCC | 1224888Skarels | AAAA AAAA CCCC CCCC | 1324888Skarels | AAAA AAAA CCCC CCCC | 1424888Skarels | AAAA AAAA CCCC CCCC | 1524888Skarels | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC | 1624888Skarels | AAAA AAAAAAAAAAA CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC | 1724888Skarels | AAAA AAAAAAAAA CCCCCCCCCCCCCC CCCCCCCCCCCCCC | 1824888Skarels \________________________________________________________/ 1924888Skarels 2024888Skarels Copyright (c) 1984 by Advanced Computer Communications 2124888Skarels 720 Santa Barbara Street, Santa Barbara, California 93101 2224888Skarels (805) 963-9431 2324888Skarels 2424888Skarels This software may be duplicated and used on systems 2524888Skarels which are licensed to run U.C. Berkeley versions of 2624888Skarels the UNIX operating system. Any duplication of any 2724888Skarels part of this software must include a copy of ACC's 2824888Skarels copyright notice. 2924888Skarels 3024888Skarels 3124888Skarels File: 3224888Skarels if_hdh.c 3324888Skarels 3424888Skarels Author: 3524888Skarels Art Berggreen 3624888Skarels 3724888Skarels Project: 3824888Skarels 4.2BSD HDH 3924888Skarels 4024888Skarels Function: 4124888Skarels Device specific driver for IF-11/HDH under 4.2BSD 4224888Skarels networking code. 4324888Skarels 4424888Skarels Revision History: 4533452Skarels Converted to 4.3, updated, UCB. 4624888Skarels 31-Aug-1984: V1.0 - First Implementation. A.B. 4724888Skarels 6-Nov-1984: V1.1 - Supress extra "LINE DOWN" msgs. A.B. 4824888Skarels 13-Jan-1984: V1.2 - Add conditionals for TWG. A.B. 4924888Skarels 5024888Skarels \************************************************************************/ 5124888Skarels 5224888Skarels 5324888Skarels 5424888Skarels 5524888Skarels /* $Header$ */ 5624888Skarels 5724888Skarels #include "hdh.h" 5824888Skarels #ifdef NHDH > 0 5924888Skarels 6024888Skarels /* 6124888Skarels * 6224888Skarels * ACC IF-11/HDH interface 6324888Skarels * 6424888Skarels */ 6524888Skarels 6625461Skarels #include "param.h" 6725461Skarels #include "systm.h" 6825461Skarels #include "mbuf.h" 6925461Skarels #include "buf.h" 7025461Skarels #include "protosw.h" 7125461Skarels #include "socket.h" 7225461Skarels #include "vmmac.h" 7324888Skarels 7433452Skarels #include "../machine/pte.h" 7533452Skarels 7624888Skarels #include "../net/if.h" 7724888Skarels #include "../netimp/if_imp.h" 7824888Skarels 7924888Skarels #include "../vax/cpu.h" 8024888Skarels #include "../vax/mtpr.h" 8124888Skarels #include "../vaxuba/ubareg.h" 8224888Skarels #include "../vaxuba/ubavar.h" 8324888Skarels 8425461Skarels #include "if_hdhreg.h" 8525461Skarels #include "if_uba.h" 8625461Skarels 8726392Skarels int hdhprobe(), hdhattach(), hdhintr(); 8824888Skarels struct uba_device *hdhinfo[NHDH]; 8924888Skarels u_short hdhstd[] = { 0 }; 9024888Skarels struct uba_driver hdhdriver = 9124888Skarels { hdhprobe, 0, hdhattach, 0, hdhstd, "hdh", hdhinfo }; 9224888Skarels 9324888Skarels #define HDHUNIT(x) minor(x) 9424888Skarels 9533452Skarels int hdhinit(), hdhoutput(), hdhreset(); 9624888Skarels 9724888Skarels /* 9824888Skarels * "Lower half" of IMP interface driver. 9924888Skarels * 10024888Skarels * Each IMP interface is handled by a common module which handles 10124888Skarels * the IMP-host protocol and a hardware driver which manages the 10224888Skarels * hardware specific details of talking with the IMP. 10324888Skarels * 10424888Skarels * The hardware portion of the IMP driver handles DMA and related 10524888Skarels * management of UNIBUS resources. The IMP protocol module interprets 10624888Skarels * contents of these messages and "controls" the actions of the 10724888Skarels * hardware module during IMP resets, but not, for instance, during 10824888Skarels * UNIBUS resets. 10924888Skarels * 11024888Skarels * The two modules are coupled at "attach time", and ever after, 11124888Skarels * through the imp interface structure. Higher level protocols, 11224888Skarels * e.g. IP, interact with the IMP driver, rather than the HDH. 11324888Skarels */ 11424888Skarels 11524888Skarels #define NHDHCH 2 /* no. of FDX channels for HDH */ 11624888Skarels #define SUPR 0 /* supervisor channel */ 11724888Skarels #define DATA 1 /* data channel */ 11824888Skarels #define HDHSUPR 0 /* supervisor read */ 11924888Skarels #define HDHSUPW 1 /* supervisor write */ 12024888Skarels #define HDHDATR 2 /* data read */ 12124888Skarels #define HDHDATW 3 /* data write */ 12224888Skarels 12324888Skarels #define HDH_UP 2 /* HDH protocol is up */ 12424888Skarels #define HDH_STARTED 1 /* HDH has been initialized */ 12524888Skarels 12624888Skarels #define HCBUSY 1 /* HDH HDX channel busy flag */ 12724888Skarels 12824888Skarels /* 12924888Skarels /* The IF-11/HDH has four independent dath flow channels between the 13024888Skarels /* front-end and the host. Two are used for reading and writing 13124888Skarels /* control messages and two are used for data flow. Each IF-11/HDH 13224888Skarels /* has a device dependent data structure (hdh_softc) which contains 13324888Skarels /* an array of four channel dependent structures (hdh_chan) to maintain 13424888Skarels /* the context of each channel. Channel structures can be linked into 13524888Skarels /* a queue of I/O requests pending for the hardware interface. 13624888Skarels /* UNIBUS mapping resources are allocated for each channel pair. 13724888Skarels */ 13824888Skarels 13924888Skarels struct hdh_chan { /* HDH HDX channel structure */ 14024888Skarels struct hdh_chan *hc_next; /* link for Start I/O queuing */ 14124888Skarels char hc_chan; /* HDX chan number */ 14224888Skarels char hc_adx; /* extended UNIBUS address bits */ 14324888Skarels short hc_addr; /* lower UNIBUS address bits */ 14424888Skarels short hc_cnt; /* byte count */ 14524888Skarels char hc_func; /* UMC I/O function */ 14624888Skarels char hc_sbfc; /* UMC I/O subfunction */ 14724888Skarels short hc_flags; /* status flags */ 14824888Skarels }; 14924888Skarels 15024888Skarels struct hdh_sioq { /* Start I/O queue head structure */ 15124888Skarels struct hdh_chan *sioq_head; /* pointer to queue head */ 15224888Skarels struct hdh_chan *sioq_tail; /* pointer to queue tail */ 15324888Skarels }; 15424888Skarels 15524888Skarels struct hdh_softc { /* HDH device dependent structure */ 15633452Skarels struct imp_softc *hdh_imp; /* pointer to IMP's imp_softc struct */ 15724888Skarels struct ifuba hdh_ifuba[NHDHCH]; /* UNIBUS resources */ 15824888Skarels struct hdh_chan hdh_chan[2*NHDHCH]; /* HDX HDH channels */ 15924888Skarels struct hdh_sioq hdh_sioq; /* start i/o queue */ 16024888Skarels short hdh_flags; /* various status conditions */ 16124888Skarels } hdh_softc[NHDH]; 16224888Skarels 16324888Skarels 16424888Skarels /* 16524888Skarels * Normally, code goes here to cause the device to interrupt to determine its 16624888Skarels * interrupt vector. However, since the UMC must be told its vector in order 16724888Skarels * to interrupt, we allocate and return an unused vector and initialize the 16824888Skarels * UMC. 16924888Skarels */ 17024888Skarels hdhprobe(reg) 17124888Skarels caddr_t reg; 17224888Skarels { 17324888Skarels register int br, cvec; 17424888Skarels struct hdhregs *addr = (struct hdhregs *)reg; 17524888Skarels #ifdef lint 17624888Skarels br = 0; cvec = br; br = cvec; 17726392Skarels hdhintr(0); 17824888Skarels #endif 17924888Skarels 18024888Skarels br = 0x15; /* priority 21 (5 on UNIBUS) */ 18124888Skarels 18224888Skarels #ifdef HDHDEBUG 18324888Skarels cvec = 0270; /* use constant for now ... */ 18424888Skarels #else 18524888Skarels 18624888Skarels #ifdef VAXVMS /* if VMS */ 18724888Skarels cvec = 0270; /* we can't allocate vectors */ 18824888Skarels #else 18924888Skarels cvec = (uba_hd[numuba].uh_lastiv -= 4); /* available vector */ 19024888Skarels #endif VAXVMS 19124888Skarels 19224888Skarels #endif HDHDEBUG 19324888Skarels 19424888Skarels addr->ioini = (char) 0; /* init UMC regs */ 19524888Skarels addr->staack = (char) 0; /* pass vector */ 19624888Skarels addr->ionmi = (char) 0; /* and kick UMC */ 19724888Skarels addr->iochn = (char) (cvec >> 2); 19824888Skarels addr->csr = (short) HDH_RST; 19924888Skarels addr->csr = (short) (HDH_IEN|HDH_DMA|HDH_WRT); /* set enables */ 20024888Skarels DELAY(5000); /* give the UMC some time */ 20124888Skarels return(1); 20224888Skarels } 20324888Skarels 20424888Skarels /* 20524888Skarels * Call the IMP module to allow it to set up its internal 20624888Skarels * state, then tie the two modules together by setting up 20724888Skarels * the back pointers to common data structures. 20824888Skarels */ 20924888Skarels hdhattach(ui) 21034273Skarels register struct uba_device *ui; 21124888Skarels { 21224888Skarels register struct hdh_softc *sc = &hdh_softc[ui->ui_unit]; 21324888Skarels register struct impcb *ip; 21424888Skarels 21534273Skarels if ((sc->hdh_imp = impattach(ui->ui_driver->ud_dname, ui->ui_unit, 21634273Skarels hdhreset)) == 0) 21734273Skarels return; 21833452Skarels ip = &sc->hdh_imp->imp_cb; 21924888Skarels ip->ic_init = hdhinit; 22033452Skarels ip->ic_output = hdhoutput; 22124888Skarels sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT; 22224888Skarels } 22324888Skarels 22424888Skarels /* 22524888Skarels * Reset interface after UNIBUS reset. 22624888Skarels */ 22724888Skarels hdhreset(unit, uban) 22824888Skarels int unit, uban; 22924888Skarels { 23024888Skarels register struct uba_device *ui = hdhinfo[unit]; 23124888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 23224888Skarels 23324888Skarels #ifdef HDHDEBUG 23424888Skarels printf("HDH RESET\n"); 23524888Skarels #endif HDHDEBUG 23624888Skarels 23724888Skarels if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0) 23824888Skarels || (ui->ui_ubanum != uban)) 23924888Skarels return; 24024888Skarels printf(" hdh%d", unit); 24133452Skarels sc->hdh_imp->imp_if.if_flags &= ~IFF_RUNNING; 24234273Skarels sc->hdh_imp->imp_cb.ic_oactive = 0; 24325461Skarels sc->hdh_flags = 0; 24433452Skarels (*sc->hdh_imp->imp_if.if_init)(sc->hdh_imp->imp_if.if_unit); 24524888Skarels } 24624888Skarels 24724888Skarels /* 24824888Skarels * Initialize the imp interface. 24924888Skarels */ 25024888Skarels 25124888Skarels static char init_blk[] = 25224888Skarels { 25324888Skarels HDHINIT, /* SYSINIT opcode */ 25424888Skarels HDHRQUP & 0xff, /* control code (LSB) */ 25524888Skarels (HDHRQUP>>8) & 0xff, /* control code (MSB) */ 25624888Skarels 10, /* command extension len */ 25724888Skarels 0, /* loopback mode (off) */ 25824888Skarels 3, /* our address (3=DTE) */ 25924888Skarels 1, /* their address (1=DCE) */ 26024888Skarels 3, /* frame ack t1 timeout */ 26124888Skarels 3, /* poll ack timeout */ 26224888Skarels 30, /* adm wait timeout */ 26324888Skarels 3, /* rej wait timeout */ 26424888Skarels 10, /* max retries */ 26524888Skarels 3, /* watchdog timeout */ 26624888Skarels 0xaa /* baud rate (0xaa=38.4KB) */ 26724888Skarels /* (output on RS-232 pin 24, */ 26824888Skarels /* send/receive timing is always */ 26924888Skarels /* taken from pins 15/17) */ 27024888Skarels }; 27124888Skarels 27224888Skarels hdhinit(unit) 27324888Skarels int unit; 27424888Skarels { 27524888Skarels register struct hdh_softc *sc; 27624888Skarels register struct uba_device *ui; 27726283Skarels int i; 27824888Skarels 27924888Skarels #ifdef HDHDEBUG 28024888Skarels printf("HDH INIT\n"); 28124888Skarels #endif HDHDEBUG 28224888Skarels 28324888Skarels if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL 28424888Skarels || ui->ui_alive == 0) { 28524888Skarels printf("hdh%d: not alive\n", unit); 28624888Skarels return(0); 28724888Skarels } 28824888Skarels sc = &hdh_softc[unit]; 28924888Skarels 29025461Skarels if (sc->hdh_flags & HDH_STARTED) 29124888Skarels return(1); 29224888Skarels 29324888Skarels /* 29424888Skarels * Alloc uba resources 29524888Skarels */ 29633452Skarels if ((sc->hdh_imp->imp_if.if_flags & IFF_RUNNING) == 0) 29733452Skarels for(i=0;i<NHDHCH;i++) { 29824888Skarels if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0, 29933452Skarels (int)btoc(IMP_RCVBUF)) == 0) { 30024888Skarels printf("hdh%d: cannot get chan %d uba resources\n", 30124888Skarels unit, i); 30224888Skarels ui->ui_alive = 0; 30324888Skarels return(0); 30424888Skarels } 30524888Skarels } 30624888Skarels 30733452Skarels sc->hdh_imp->imp_if.if_flags |= IFF_RUNNING; 30824888Skarels sc->hdh_flags = HDH_STARTED; 30924888Skarels 31024888Skarels /* 31124888Skarels * hang a supervisor read (for line status) 31224888Skarels */ 31333452Skarels hdh_iorq(unit, HDHSUPR, IMP_RCVBUF, HDHRDB); 31424888Skarels 31524888Skarels /* 31624888Skarels * hang a data read 31724888Skarels */ 31833452Skarels hdh_iorq(unit, HDHDATR, IMP_RCVBUF, HDHRDB+HDHSTR); 31924888Skarels 32024888Skarels /* 32124888Skarels * bring up line to IMP 32224888Skarels */ 32324888Skarels 32424888Skarels snd_supr(unit, init_blk, sizeof(init_blk)); 32524888Skarels 32624888Skarels return(1); 32724888Skarels } 32824888Skarels 32924888Skarels /* 33024888Skarels * Start an output operation on an mbuf. 33124888Skarels */ 33233452Skarels hdhoutput(unit, m) 33333452Skarels int unit; 33433452Skarels struct mbuf *m; 33524888Skarels { 33624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 33724888Skarels int len; 33824888Skarels 33924888Skarels /* 34024888Skarels * If output isn't active, attempt to 34124888Skarels * start sending a new packet. 34224888Skarels */ 34324888Skarels 34433452Skarels if (sc->hdh_imp->imp_cb.ic_oactive) { 34524888Skarels printf("hdh%d: start on active unit\n", unit); 34624888Skarels return; 34724888Skarels } 34824888Skarels 34924888Skarels if ((sc->hdh_flags & HDH_UP) == 0) { 35033452Skarels /* Link not up, can't xmit */ 35124888Skarels return; 35224888Skarels } 35324888Skarels 35424888Skarels len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ 35533452Skarels sc->hdh_imp->imp_cb.ic_oactive = 1; 35624888Skarels 35724888Skarels hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); 35824888Skarels } 35924888Skarels 36024888Skarels /* 36124888Skarels * Start i/o operation on a UMC logical channel 36224888Skarels */ 36324888Skarels hdh_iorq(unit, lcn, len, func) 36424888Skarels int unit, lcn, len, func; 36524888Skarels { 36624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 36724888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 36824888Skarels register int info, s; 36924888Skarels 37024888Skarels /* 37124888Skarels * If channel is busy (shouldn't be), drop. 37224888Skarels */ 37324888Skarels if (hc->hc_flags & HCBUSY) { 37424888Skarels printf("hdh%d: channel busy lcn=%d\n", unit, lcn); 37524888Skarels return; 37624888Skarels } 37724888Skarels 37824888Skarels /* get appropriate UNIBUS mapping info */ 37924888Skarels 38024888Skarels if (lcn & 1) /* read or write? */ 38124888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; 38224888Skarels else 38324888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; 38424888Skarels 38524888Skarels /* set channel info */ 38624888Skarels 38724888Skarels hc->hc_flags |= HCBUSY; 38824888Skarels hc->hc_chan = lcn; 38924888Skarels hc->hc_adx = (char)((info & 0x30000) >> 12); 39024888Skarels hc->hc_addr = (unsigned short)(info & 0xffff); 39124888Skarels hc->hc_cnt = len; 39224888Skarels hc->hc_func = (char)func; 39324888Skarels hc->hc_sbfc = 0; 39424888Skarels 39524888Skarels s = splimp(); 39624888Skarels /* 39724888Skarels * If UMC comm regs busy, queue start i/o for later. 39824888Skarels */ 39924888Skarels if (sc->hdh_sioq.sioq_head) { 40024888Skarels (sc->hdh_sioq.sioq_tail)->hc_next = hc; 40124888Skarels sc->hdh_sioq.sioq_tail = hc; 40224888Skarels hc->hc_next = 0; 40324888Skarels splx(s); 40424888Skarels return; 40524888Skarels } 40624888Skarels 40724888Skarels /* start i/o on channel now */ 40824888Skarels 40924888Skarels sc->hdh_sioq.sioq_head = hc; 41024888Skarels sc->hdh_sioq.sioq_tail = hc; 41124888Skarels hc->hc_next = 0; 41224888Skarels start_chn(unit); 41324888Skarels splx(s); 41424888Skarels } 41524888Skarels 41624888Skarels start_chn(unit) 41724888Skarels int unit; 41824888Skarels { 41924888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 42024888Skarels register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; 42124888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 42224888Skarels 42324888Skarels /* 42424888Skarels * Set up comm regs. 42524888Skarels */ 42624888Skarels addr->iochn = hc->hc_chan; 42724888Skarels addr->ioadx = hc->hc_adx; 42824888Skarels addr->ioadl = hc->hc_addr; 42924888Skarels addr->iocnt = hc->hc_cnt; 43024888Skarels addr->iofcn = hc->hc_func; 43124888Skarels addr->iosbf = hc->hc_sbfc; 43224888Skarels addr->ioini = 1; 43324888Skarels 43424888Skarels /* signal UMC if necessary */ 43524888Skarels 43624888Skarels if (!(addr->ionmi)) { 43724888Skarels addr->ionmi = 1; 43824888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 43924888Skarels } 44024888Skarels } 44124888Skarels 44224888Skarels /* 44324888Skarels * IF-11/HDH interrupt handler 44424888Skarels */ 44524888Skarels hdhintr(unit) 44624888Skarels int unit; 44724888Skarels { 44824888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 44924888Skarels register struct hdh_chan *hc; 45024888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 45126283Skarels int lcn, type, cc, cnt; 45224888Skarels 45324888Skarels /* 45424888Skarels * Check for hardware errors. 45524888Skarels */ 45624888Skarels if (addr->csr & HDH_UER) { 45724888Skarels printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); 45824888Skarels addr->csr = 0; /* disable i/f */ 45924888Skarels return; 46024888Skarels } 46124888Skarels /* 46224888Skarels * Get logical channel info. 46324888Skarels */ 46424888Skarels if ((lcn = addr->stachn) >= (NHDHCH*2)) { 46524888Skarels printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); 46624888Skarels return; 46724888Skarels } 46824888Skarels 46924888Skarels hc = &sc->hdh_chan[lcn]; 47024888Skarels 47124888Skarels type = addr->statyp; 47224888Skarels cc = addr->stacc; 47324888Skarels cnt = hc->hc_cnt - addr->stacnt; 47424888Skarels 47524888Skarels /* Figure out what kind of interrupt it was */ 47624888Skarels 47724888Skarels switch(type) { 47824888Skarels 47924888Skarels case HDHSACK: /* start i/o accepted */ 48024888Skarels if (hc != sc->hdh_sioq.sioq_head) { 48124888Skarels printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", 48224888Skarels unit, lcn, hc, sc->hdh_sioq.sioq_head); 48324888Skarels return; 48424888Skarels } 48524888Skarels 48624888Skarels /* try to start any queued i/o request */ 48724888Skarels 48824888Skarels if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { 48924888Skarels start_chn(unit); 49024888Skarels } 49124888Skarels break; 49224888Skarels 49324888Skarels case HDHDONE: /* i/o completion */ 49424888Skarels switch (cc) { 49524888Skarels 49624888Skarels case HDHIOCABT: 49724888Skarels printf("hdh%d: I/O abort ", unit); 49824888Skarels goto daterr; 49924888Skarels 50024888Skarels case HDHIOCERR: 50124888Skarels printf("hdh%d: program error ", unit); 50224888Skarels goto daterr; 50324888Skarels 50424888Skarels case HDHIOCOVR: 50524888Skarels printf("hdh%d: overrun error ", unit); 50624888Skarels goto daterr; 50724888Skarels 50824888Skarels case HDHIOCUBE: 50924888Skarels printf("hdh%d: NXM timeout or UB parity error ", unit); 51024888Skarels 51124888Skarels daterr: 51224888Skarels printf("lcn=%d func=%x\n", lcn, hc->hc_func); 51324888Skarels if (hc->hc_func & HDHRDB) 51433452Skarels sc->hdh_imp->imp_if.if_ierrors++; 51524888Skarels else 51633452Skarels sc->hdh_imp->imp_if.if_oerrors++; 51724888Skarels } 51824888Skarels 51924888Skarels hc->hc_flags &= ~HCBUSY; 52024888Skarels 52124888Skarels /* was it supervisor or data traffic? */ 52224888Skarels 52324888Skarels if (lcn > HDHSUPW) 52424888Skarels hdh_data(unit, lcn, cc, cnt); 52524888Skarels else 52626310Skarels hdh_supr(unit, lcn, cc); 52724888Skarels 52824888Skarels } 52924888Skarels 53024888Skarels /* 53124888Skarels * Ack the interrupt 53224888Skarels */ 53324888Skarels addr->staack = 1; 53424888Skarels if (!(addr->ionmi)) { 53524888Skarels addr->ionmi = 1; 53624888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 53724888Skarels } 53824888Skarels } 53924888Skarels 54024888Skarels /* 54124888Skarels * data channel interrupt completion handler 54224888Skarels */ 54324888Skarels hdh_data(unit, lcn, cc, rcnt) 54424888Skarels int unit, lcn, cc, rcnt; 54524888Skarels { 54624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 54724888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 54824888Skarels register struct mbuf *m; 54924888Skarels 55024888Skarels 55124888Skarels /* was it read or write? */ 55224888Skarels 55324888Skarels if (hc->hc_func & HDHRDB) { 55424888Skarels if (cc == HDHIOCOK) { 55524888Skarels /* 55624888Skarels * Queue good packet for input 55724888Skarels */ 55833452Skarels sc->hdh_imp->imp_if.if_ipackets++; 55925461Skarels m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, 56033452Skarels &sc->hdh_imp->imp_if); 56124888Skarels impinput(unit, m); 56224888Skarels } 56324888Skarels 56424888Skarels /* hang a new data read */ 56524888Skarels 56633452Skarels hdh_iorq(unit, lcn, IMP_RCVBUF, HDHRDB+HDHSTR); 56724888Skarels 56824888Skarels } else { 56924888Skarels /* 57024888Skarels * fire up next output 57124888Skarels */ 57233452Skarels sc->hdh_imp->imp_if.if_opackets++; 57333452Skarels sc->hdh_imp->imp_cb.ic_oactive = 0; 574*34503Skarels impstart(sc->hdh_imp); 57524888Skarels } 57624888Skarels } 57724888Skarels 57824888Skarels /* 57924888Skarels * supervisor channel interrupt completion handler 58024888Skarels */ 58126310Skarels hdh_supr(unit, lcn, cc) 58226310Skarels int unit, lcn, cc; 58324888Skarels { 58424888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 58524888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 58624888Skarels short *p; 58724888Skarels 58824888Skarels 58924888Skarels /* was it read or write? */ 59024888Skarels 59124888Skarels if (hc->hc_func & HDHRDB) { 59224888Skarels if (cc == HDHIOCOK) { 59324888Skarels p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); 59424888Skarels 59524888Skarels /* figure out what kind of supervisor message */ 59624888Skarels 59724888Skarels switch (*p) { 59824888Skarels 59924888Skarels case HDHIACK: 60024888Skarels case HDHLNACK: 60124888Skarels break; 60224888Skarels 60324888Skarels case HDHLNUP: 60424888Skarels printf("hdh%d: LINE UP\n", unit); 60524888Skarels sc->hdh_flags |= HDH_UP; 606*34503Skarels impstart(sc->hdh_imp); 60724888Skarels break; 60824888Skarels 60924888Skarels case HDHLNDN: 61024888Skarels if (sc->hdh_flags & HDH_UP) 61124888Skarels printf("hdh%d: LINE DOWN\n", unit); 61224888Skarels sc->hdh_flags &= ~HDH_UP; 61324888Skarels break; 61424888Skarels 61524888Skarels case HDHLOOP: 61624888Skarels break; 61724888Skarels 61824888Skarels case HDHSQERR: 61924888Skarels printf("hdh%d: HOST SEQUENCE ERROR\n", unit); 62024888Skarels break; 62124888Skarels 62224888Skarels case HDHSQRCV: 62324888Skarels printf("hdh%d: IMP SEQUENCE ERROR\n", unit); 62424888Skarels break; 62524888Skarels 62624888Skarels case HDHDTERR: 62724888Skarels printf("hdh%d: HOST DATA ERROR\n", unit); 62824888Skarels break; 62924888Skarels 63024888Skarels case HDHTIMO: 63124888Skarels printf("hdh%d: TIMEOUT\n", unit); 63224888Skarels break; 63324888Skarels 63424888Skarels default: 63524888Skarels printf("hdh%d: supervisor error, code=%x\n", 63624888Skarels unit, *p); 63724888Skarels } 63824888Skarels } 63924888Skarels 64024888Skarels /* hang a new supr read */ 64124888Skarels 64233452Skarels hdh_iorq(unit, HDHSUPR, IMP_RCVBUF, HDHRDB+HDHSTR); 64324888Skarels } 64424888Skarels } 64524888Skarels 64624888Skarels snd_supr(unit, msg, len) 64724888Skarels int unit, len; 64824888Skarels char *msg; 64924888Skarels { 65024888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 65124888Skarels register struct mbuf *m; 65224888Skarels register char *p; 65324888Skarels register int cnt; 65424888Skarels 65524888Skarels if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { 65624888Skarels printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); 65728951Skarels return; 65824888Skarels } 65924888Skarels 66024888Skarels cnt = len; 66124888Skarels m->m_len = len; 66224888Skarels p = mtod(m, char *); 66324888Skarels 66424888Skarels while(cnt--) *p++ = *msg++; 66524888Skarels 66624888Skarels cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); 66724888Skarels 66824888Skarels hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); 66924888Skarels } 67024888Skarels #endif NHDH 671