1*26392Skarels /* @(#)if_hdh.c 6.6 (Berkeley) 02/23/86 */ 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: 4524888Skarels 31-Aug-1984: V1.0 - First Implementation. A.B. 4624888Skarels 6-Nov-1984: V1.1 - Supress extra "LINE DOWN" msgs. A.B. 4724888Skarels 13-Jan-1984: V1.2 - Add conditionals for TWG. A.B. 4824888Skarels 4924888Skarels \************************************************************************/ 5024888Skarels 5124888Skarels 5224888Skarels 5324888Skarels 5424888Skarels /* $Header$ */ 5524888Skarels 5624888Skarels #include "hdh.h" 5724888Skarels #ifdef NHDH > 0 5824888Skarels 5924888Skarels /* 6024888Skarels * 6124888Skarels * ACC IF-11/HDH interface 6224888Skarels * 6324888Skarels */ 6424888Skarels 6524888Skarels #include "../machine/pte.h" 6624888Skarels 6725461Skarels #include "param.h" 6825461Skarels #include "systm.h" 6925461Skarels #include "mbuf.h" 7025461Skarels #include "buf.h" 7125461Skarels #include "protosw.h" 7225461Skarels #include "socket.h" 7325461Skarels #include "vmmac.h" 7424888Skarels 7524888Skarels #include "../net/if.h" 7624888Skarels #include "../netimp/if_imp.h" 7724888Skarels 7824888Skarels #include "../vax/cpu.h" 7924888Skarels #include "../vax/mtpr.h" 8024888Skarels #include "../vaxuba/ubareg.h" 8124888Skarels #include "../vaxuba/ubavar.h" 8224888Skarels 8325461Skarels #include "if_hdhreg.h" 8425461Skarels #include "if_uba.h" 8525461Skarels 86*26392Skarels int hdhprobe(), hdhattach(), hdhintr(); 8724888Skarels struct uba_device *hdhinfo[NHDH]; 8824888Skarels u_short hdhstd[] = { 0 }; 8924888Skarels struct uba_driver hdhdriver = 9024888Skarels { hdhprobe, 0, hdhattach, 0, hdhstd, "hdh", hdhinfo }; 9124888Skarels 9224888Skarels #define HDHUNIT(x) minor(x) 9324888Skarels 9424888Skarels int hdhinit(), hdhstart(), hdhreset(); 9524888Skarels 9624888Skarels /* 9724888Skarels * "Lower half" of IMP interface driver. 9824888Skarels * 9924888Skarels * Each IMP interface is handled by a common module which handles 10024888Skarels * the IMP-host protocol and a hardware driver which manages the 10124888Skarels * hardware specific details of talking with the IMP. 10224888Skarels * 10324888Skarels * The hardware portion of the IMP driver handles DMA and related 10424888Skarels * management of UNIBUS resources. The IMP protocol module interprets 10524888Skarels * contents of these messages and "controls" the actions of the 10624888Skarels * hardware module during IMP resets, but not, for instance, during 10724888Skarels * UNIBUS resets. 10824888Skarels * 10924888Skarels * The two modules are coupled at "attach time", and ever after, 11024888Skarels * through the imp interface structure. Higher level protocols, 11124888Skarels * e.g. IP, interact with the IMP driver, rather than the HDH. 11224888Skarels */ 11324888Skarels 11424888Skarels #define NHDHCH 2 /* no. of FDX channels for HDH */ 11524888Skarels #define SUPR 0 /* supervisor channel */ 11624888Skarels #define DATA 1 /* data channel */ 11724888Skarels #define HDHSUPR 0 /* supervisor read */ 11824888Skarels #define HDHSUPW 1 /* supervisor write */ 11924888Skarels #define HDHDATR 2 /* data read */ 12024888Skarels #define HDHDATW 3 /* data write */ 12124888Skarels 12224888Skarels #define HDH_UP 2 /* HDH protocol is up */ 12324888Skarels #define HDH_STARTED 1 /* HDH has been initialized */ 12424888Skarels 12524888Skarels #define HCBUSY 1 /* HDH HDX channel busy flag */ 12624888Skarels 12724888Skarels /* 12824888Skarels /* The IF-11/HDH has four independent dath flow channels between the 12924888Skarels /* front-end and the host. Two are used for reading and writing 13024888Skarels /* control messages and two are used for data flow. Each IF-11/HDH 13124888Skarels /* has a device dependent data structure (hdh_softc) which contains 13224888Skarels /* an array of four channel dependent structures (hdh_chan) to maintain 13324888Skarels /* the context of each channel. Channel structures can be linked into 13424888Skarels /* a queue of I/O requests pending for the hardware interface. 13524888Skarels /* UNIBUS mapping resources are allocated for each channel pair. 13624888Skarels */ 13724888Skarels 13824888Skarels struct hdh_chan { /* HDH HDX channel structure */ 13924888Skarels struct hdh_chan *hc_next; /* link for Start I/O queuing */ 14024888Skarels char hc_chan; /* HDX chan number */ 14124888Skarels char hc_adx; /* extended UNIBUS address bits */ 14224888Skarels short hc_addr; /* lower UNIBUS address bits */ 14324888Skarels short hc_cnt; /* byte count */ 14424888Skarels char hc_func; /* UMC I/O function */ 14524888Skarels char hc_sbfc; /* UMC I/O subfunction */ 14624888Skarels short hc_flags; /* status flags */ 14724888Skarels }; 14824888Skarels 14924888Skarels struct hdh_sioq { /* Start I/O queue head structure */ 15024888Skarels struct hdh_chan *sioq_head; /* pointer to queue head */ 15124888Skarels struct hdh_chan *sioq_tail; /* pointer to queue tail */ 15224888Skarels }; 15324888Skarels 15424888Skarels struct hdh_softc { /* HDH device dependent structure */ 15524888Skarels struct ifnet *hdh_if; /* pointer to IMP's ifnet struct */ 15624888Skarels struct impcb *hdh_ic; /* data structure shared with IMP */ 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; 177*26392Skarels 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) 21024888Skarels struct uba_device *ui; 21124888Skarels { 21224888Skarels register struct hdh_softc *sc = &hdh_softc[ui->ui_unit]; 21324888Skarels register struct impcb *ip; 21424888Skarels struct ifimpcb { 21524888Skarels struct ifnet ifimp_if; 21624888Skarels struct impcb ifimp_impcb; 21724888Skarels } *ifimp; 21824888Skarels 21924888Skarels if ((ifimp = (struct ifimpcb *)impattach(ui, hdhreset)) == 0) 22025461Skarels return;; 22124888Skarels sc->hdh_if = &ifimp->ifimp_if; 22224888Skarels ip = &ifimp->ifimp_impcb; 22324888Skarels sc->hdh_ic = ip; 22424888Skarels ip->ic_init = hdhinit; 22524888Skarels ip->ic_start = hdhstart; 22624888Skarels sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT; 22724888Skarels } 22824888Skarels 22924888Skarels /* 23024888Skarels * Reset interface after UNIBUS reset. 23124888Skarels */ 23224888Skarels hdhreset(unit, uban) 23324888Skarels int unit, uban; 23424888Skarels { 23524888Skarels register struct uba_device *ui = hdhinfo[unit]; 23624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 23724888Skarels 23824888Skarels #ifdef HDHDEBUG 23924888Skarels printf("HDH RESET\n"); 24024888Skarels #endif HDHDEBUG 24124888Skarels 24224888Skarels if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0) 24324888Skarels || (ui->ui_ubanum != uban)) 24424888Skarels return; 24524888Skarels printf(" hdh%d", unit); 24625461Skarels sc->hdh_if->if_flags &= ~IFF_RUNNING; 24725461Skarels sc->hdh_flags = 0; 24824888Skarels (*sc->hdh_if->if_init)(unit); 24924888Skarels } 25024888Skarels 25124888Skarels /* 25224888Skarels * Initialize the imp interface. 25324888Skarels */ 25424888Skarels 25524888Skarels static char init_blk[] = 25624888Skarels { 25724888Skarels HDHINIT, /* SYSINIT opcode */ 25824888Skarels HDHRQUP & 0xff, /* control code (LSB) */ 25924888Skarels (HDHRQUP>>8) & 0xff, /* control code (MSB) */ 26024888Skarels 10, /* command extension len */ 26124888Skarels 0, /* loopback mode (off) */ 26224888Skarels 3, /* our address (3=DTE) */ 26324888Skarels 1, /* their address (1=DCE) */ 26424888Skarels 3, /* frame ack t1 timeout */ 26524888Skarels 3, /* poll ack timeout */ 26624888Skarels 30, /* adm wait timeout */ 26724888Skarels 3, /* rej wait timeout */ 26824888Skarels 10, /* max retries */ 26924888Skarels 3, /* watchdog timeout */ 27024888Skarels 0xaa /* baud rate (0xaa=38.4KB) */ 27124888Skarels /* (output on RS-232 pin 24, */ 27224888Skarels /* send/receive timing is always */ 27324888Skarels /* taken from pins 15/17) */ 27424888Skarels }; 27524888Skarels 27624888Skarels hdhinit(unit) 27724888Skarels int unit; 27824888Skarels { 27924888Skarels register struct hdh_softc *sc; 28024888Skarels register struct uba_device *ui; 28126283Skarels int i; 28224888Skarels 28324888Skarels #ifdef HDHDEBUG 28424888Skarels printf("HDH INIT\n"); 28524888Skarels #endif HDHDEBUG 28624888Skarels 28724888Skarels if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL 28824888Skarels || ui->ui_alive == 0) { 28924888Skarels printf("hdh%d: not alive\n", unit); 29024888Skarels return(0); 29124888Skarels } 29224888Skarels sc = &hdh_softc[unit]; 29324888Skarels 29425461Skarels if (sc->hdh_flags & HDH_STARTED) 29524888Skarels return(1); 29624888Skarels 29724888Skarels /* 29824888Skarels * Alloc uba resources 29924888Skarels */ 30024888Skarels for(i=0;i<NHDHCH;i++) { 30124888Skarels if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0, 30224888Skarels (int)btoc(IMPMTU)) == 0) { 30324888Skarels printf("hdh%d: cannot get chan %d uba resources\n", 30424888Skarels unit, i); 30524888Skarels ui->ui_alive = 0; 30624888Skarels return(0); 30724888Skarels } 30824888Skarels } 30924888Skarels 31025461Skarels sc->hdh_if->if_flags |= IFF_RUNNING; 31124888Skarels sc->hdh_flags = HDH_STARTED; 31224888Skarels 31324888Skarels /* 31424888Skarels * hang a supervisor read (for line status) 31524888Skarels */ 31624888Skarels hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB); 31724888Skarels 31824888Skarels /* 31924888Skarels * hang a data read 32024888Skarels */ 32124888Skarels hdh_iorq(unit, HDHDATR, IMPMTU, HDHRDB+HDHSTR); 32224888Skarels 32324888Skarels /* 32424888Skarels * bring up line to IMP 32524888Skarels */ 32624888Skarels 32724888Skarels snd_supr(unit, init_blk, sizeof(init_blk)); 32824888Skarels 32924888Skarels return(1); 33024888Skarels } 33124888Skarels 33224888Skarels /* 33324888Skarels * Start an output operation on an mbuf. 33424888Skarels */ 33524888Skarels hdhstart(dev) 33624888Skarels dev_t dev; 33724888Skarels { 33824888Skarels int unit = HDHUNIT(dev); 33924888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 34024888Skarels register struct mbuf *m; 34124888Skarels int len; 34224888Skarels 34324888Skarels /* 34424888Skarels * If output isn't active, attempt to 34524888Skarels * start sending a new packet. 34624888Skarels */ 34724888Skarels 34824888Skarels if (sc->hdh_ic->ic_oactive) { 34924888Skarels printf("hdh%d: start on active unit\n", unit); 35024888Skarels return; 35124888Skarels } 35224888Skarels 35324888Skarels if ((sc->hdh_flags & HDH_UP) == 0) { 35424888Skarels sc->hdh_ic->ic_oactive = 0; /* Link not up, can't xmit */ 35524888Skarels return; 35624888Skarels } 35724888Skarels 35824888Skarels IF_DEQUEUE(&sc->hdh_if->if_snd, m); 35924888Skarels if (m == 0) { 36024888Skarels sc->hdh_ic->ic_oactive = 0; 36124888Skarels return; 36224888Skarels } 36324888Skarels 36424888Skarels len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ 36524888Skarels sc->hdh_ic->ic_oactive = 1; 36624888Skarels 36724888Skarels hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); 36824888Skarels } 36924888Skarels 37024888Skarels /* 37124888Skarels * Start i/o operation on a UMC logical channel 37224888Skarels */ 37324888Skarels hdh_iorq(unit, lcn, len, func) 37424888Skarels int unit, lcn, len, func; 37524888Skarels { 37624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 37724888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 37824888Skarels register int info, s; 37924888Skarels 38024888Skarels /* 38124888Skarels * If channel is busy (shouldn't be), drop. 38224888Skarels */ 38324888Skarels if (hc->hc_flags & HCBUSY) { 38424888Skarels printf("hdh%d: channel busy lcn=%d\n", unit, lcn); 38524888Skarels return; 38624888Skarels } 38724888Skarels 38824888Skarels /* get appropriate UNIBUS mapping info */ 38924888Skarels 39024888Skarels if (lcn & 1) /* read or write? */ 39124888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; 39224888Skarels else 39324888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; 39424888Skarels 39524888Skarels /* set channel info */ 39624888Skarels 39724888Skarels hc->hc_flags |= HCBUSY; 39824888Skarels hc->hc_chan = lcn; 39924888Skarels hc->hc_adx = (char)((info & 0x30000) >> 12); 40024888Skarels hc->hc_addr = (unsigned short)(info & 0xffff); 40124888Skarels hc->hc_cnt = len; 40224888Skarels hc->hc_func = (char)func; 40324888Skarels hc->hc_sbfc = 0; 40424888Skarels 40524888Skarels s = splimp(); 40624888Skarels /* 40724888Skarels * If UMC comm regs busy, queue start i/o for later. 40824888Skarels */ 40924888Skarels if (sc->hdh_sioq.sioq_head) { 41024888Skarels (sc->hdh_sioq.sioq_tail)->hc_next = hc; 41124888Skarels sc->hdh_sioq.sioq_tail = hc; 41224888Skarels hc->hc_next = 0; 41324888Skarels splx(s); 41424888Skarels return; 41524888Skarels } 41624888Skarels 41724888Skarels /* start i/o on channel now */ 41824888Skarels 41924888Skarels sc->hdh_sioq.sioq_head = hc; 42024888Skarels sc->hdh_sioq.sioq_tail = hc; 42124888Skarels hc->hc_next = 0; 42224888Skarels start_chn(unit); 42324888Skarels splx(s); 42424888Skarels } 42524888Skarels 42624888Skarels start_chn(unit) 42724888Skarels int unit; 42824888Skarels { 42924888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 43024888Skarels register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; 43124888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 43224888Skarels 43324888Skarels /* 43424888Skarels * Set up comm regs. 43524888Skarels */ 43624888Skarels addr->iochn = hc->hc_chan; 43724888Skarels addr->ioadx = hc->hc_adx; 43824888Skarels addr->ioadl = hc->hc_addr; 43924888Skarels addr->iocnt = hc->hc_cnt; 44024888Skarels addr->iofcn = hc->hc_func; 44124888Skarels addr->iosbf = hc->hc_sbfc; 44224888Skarels addr->ioini = 1; 44324888Skarels 44424888Skarels /* signal UMC if necessary */ 44524888Skarels 44624888Skarels if (!(addr->ionmi)) { 44724888Skarels addr->ionmi = 1; 44824888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 44924888Skarels } 45024888Skarels } 45124888Skarels 45224888Skarels /* 45324888Skarels * IF-11/HDH interrupt handler 45424888Skarels */ 45524888Skarels hdhintr(unit) 45624888Skarels int unit; 45724888Skarels { 45824888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 45924888Skarels register struct hdh_chan *hc; 46024888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 46126283Skarels int lcn, type, cc, cnt; 46224888Skarels 46324888Skarels /* 46424888Skarels * Check for hardware errors. 46524888Skarels */ 46624888Skarels if (addr->csr & HDH_UER) { 46724888Skarels printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); 46824888Skarels addr->csr = 0; /* disable i/f */ 46924888Skarels return; 47024888Skarels } 47124888Skarels /* 47224888Skarels * Get logical channel info. 47324888Skarels */ 47424888Skarels if ((lcn = addr->stachn) >= (NHDHCH*2)) { 47524888Skarels printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); 47624888Skarels return; 47724888Skarels } 47824888Skarels 47924888Skarels hc = &sc->hdh_chan[lcn]; 48024888Skarels 48124888Skarels type = addr->statyp; 48224888Skarels cc = addr->stacc; 48324888Skarels cnt = hc->hc_cnt - addr->stacnt; 48424888Skarels 48524888Skarels /* Figure out what kind of interrupt it was */ 48624888Skarels 48724888Skarels switch(type) { 48824888Skarels 48924888Skarels case HDHSACK: /* start i/o accepted */ 49024888Skarels if (hc != sc->hdh_sioq.sioq_head) { 49124888Skarels printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", 49224888Skarels unit, lcn, hc, sc->hdh_sioq.sioq_head); 49324888Skarels return; 49424888Skarels } 49524888Skarels 49624888Skarels /* try to start any queued i/o request */ 49724888Skarels 49824888Skarels if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { 49924888Skarels start_chn(unit); 50024888Skarels } 50124888Skarels break; 50224888Skarels 50324888Skarels case HDHDONE: /* i/o completion */ 50424888Skarels switch (cc) { 50524888Skarels 50624888Skarels case HDHIOCABT: 50724888Skarels printf("hdh%d: I/O abort ", unit); 50824888Skarels goto daterr; 50924888Skarels 51024888Skarels case HDHIOCERR: 51124888Skarels printf("hdh%d: program error ", unit); 51224888Skarels goto daterr; 51324888Skarels 51424888Skarels case HDHIOCOVR: 51524888Skarels printf("hdh%d: overrun error ", unit); 51624888Skarels goto daterr; 51724888Skarels 51824888Skarels case HDHIOCUBE: 51924888Skarels printf("hdh%d: NXM timeout or UB parity error ", unit); 52024888Skarels 52124888Skarels daterr: 52224888Skarels printf("lcn=%d func=%x\n", lcn, hc->hc_func); 52324888Skarels if (hc->hc_func & HDHRDB) 52424888Skarels sc->hdh_if->if_ierrors++; 52524888Skarels else 52624888Skarels sc->hdh_if->if_oerrors++; 52724888Skarels } 52824888Skarels 52924888Skarels hc->hc_flags &= ~HCBUSY; 53024888Skarels 53124888Skarels /* was it supervisor or data traffic? */ 53224888Skarels 53324888Skarels if (lcn > HDHSUPW) 53424888Skarels hdh_data(unit, lcn, cc, cnt); 53524888Skarels else 53626310Skarels hdh_supr(unit, lcn, cc); 53724888Skarels 53824888Skarels } 53924888Skarels 54024888Skarels /* 54124888Skarels * Ack the interrupt 54224888Skarels */ 54324888Skarels addr->staack = 1; 54424888Skarels if (!(addr->ionmi)) { 54524888Skarels addr->ionmi = 1; 54624888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 54724888Skarels } 54824888Skarels } 54924888Skarels 55024888Skarels /* 55124888Skarels * data channel interrupt completion handler 55224888Skarels */ 55324888Skarels hdh_data(unit, lcn, cc, rcnt) 55424888Skarels int unit, lcn, cc, rcnt; 55524888Skarels { 55624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 55724888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 55824888Skarels register struct mbuf *m; 55924888Skarels 56024888Skarels 56124888Skarels /* was it read or write? */ 56224888Skarels 56324888Skarels if (hc->hc_func & HDHRDB) { 56424888Skarels if (cc == HDHIOCOK) { 56524888Skarels /* 56624888Skarels * Queue good packet for input 56724888Skarels */ 56824888Skarels sc->hdh_if->if_ipackets++; 56925461Skarels m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, 57025461Skarels sc->hdh_if); 57124888Skarels impinput(unit, m); 57224888Skarels } 57324888Skarels 57424888Skarels /* hang a new data read */ 57524888Skarels 57624888Skarels hdh_iorq(unit, lcn, IMPMTU, HDHRDB+HDHSTR); 57724888Skarels 57824888Skarels } else { 57924888Skarels /* 58024888Skarels * fire up next output 58124888Skarels */ 58224888Skarels sc->hdh_if->if_opackets++; 58324888Skarels sc->hdh_ic->ic_oactive = 0; 58424888Skarels hdhstart(unit); 58524888Skarels } 58624888Skarels } 58724888Skarels 58824888Skarels /* 58924888Skarels * supervisor channel interrupt completion handler 59024888Skarels */ 59126310Skarels hdh_supr(unit, lcn, cc) 59226310Skarels int unit, lcn, cc; 59324888Skarels { 59424888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 59524888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 59624888Skarels short *p; 59724888Skarels 59824888Skarels 59924888Skarels /* was it read or write? */ 60024888Skarels 60124888Skarels if (hc->hc_func & HDHRDB) { 60224888Skarels if (cc == HDHIOCOK) { 60324888Skarels p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); 60424888Skarels 60524888Skarels /* figure out what kind of supervisor message */ 60624888Skarels 60724888Skarels switch (*p) { 60824888Skarels 60924888Skarels case HDHIACK: 61024888Skarels case HDHLNACK: 61124888Skarels break; 61224888Skarels 61324888Skarels case HDHLNUP: 61424888Skarels printf("hdh%d: LINE UP\n", unit); 61524888Skarels sc->hdh_flags |= HDH_UP; 61624888Skarels hdhstart(unit); 61724888Skarels break; 61824888Skarels 61924888Skarels case HDHLNDN: 62024888Skarels if (sc->hdh_flags & HDH_UP) 62124888Skarels printf("hdh%d: LINE DOWN\n", unit); 62224888Skarels sc->hdh_flags &= ~HDH_UP; 62324888Skarels break; 62424888Skarels 62524888Skarels case HDHLOOP: 62624888Skarels break; 62724888Skarels 62824888Skarels case HDHSQERR: 62924888Skarels printf("hdh%d: HOST SEQUENCE ERROR\n", unit); 63024888Skarels break; 63124888Skarels 63224888Skarels case HDHSQRCV: 63324888Skarels printf("hdh%d: IMP SEQUENCE ERROR\n", unit); 63424888Skarels break; 63524888Skarels 63624888Skarels case HDHDTERR: 63724888Skarels printf("hdh%d: HOST DATA ERROR\n", unit); 63824888Skarels break; 63924888Skarels 64024888Skarels case HDHTIMO: 64124888Skarels printf("hdh%d: TIMEOUT\n", unit); 64224888Skarels break; 64324888Skarels 64424888Skarels default: 64524888Skarels printf("hdh%d: supervisor error, code=%x\n", 64624888Skarels unit, *p); 64724888Skarels } 64824888Skarels } 64924888Skarels 65024888Skarels /* hang a new supr read */ 65124888Skarels 65224888Skarels hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB+HDHSTR); 65324888Skarels } 65424888Skarels } 65524888Skarels 65624888Skarels snd_supr(unit, msg, len) 65724888Skarels int unit, len; 65824888Skarels char *msg; 65924888Skarels { 66024888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 66124888Skarels register struct mbuf *m; 66224888Skarels register char *p; 66324888Skarels register int cnt; 66424888Skarels 66524888Skarels if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { 66624888Skarels printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); 66724888Skarels return(0); 66824888Skarels } 66924888Skarels 67024888Skarels cnt = len; 67124888Skarels m->m_len = len; 67224888Skarels p = mtod(m, char *); 67324888Skarels 67424888Skarels while(cnt--) *p++ = *msg++; 67524888Skarels 67624888Skarels cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); 67724888Skarels 67824888Skarels hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); 67924888Skarels 68024888Skarels return(1); 68124888Skarels } 68224888Skarels #endif NHDH 683