1*26310Skarels /* @(#)if_hdh.c 6.5 (Berkeley) 02/21/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 8624888Skarels int hdhprobe(), hdhattach(), hdhrint(), hdhxint(); 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; 17724888Skarels #endif 17824888Skarels 17924888Skarels br = 0x15; /* priority 21 (5 on UNIBUS) */ 18024888Skarels 18124888Skarels #ifdef HDHDEBUG 18224888Skarels cvec = 0270; /* use constant for now ... */ 18324888Skarels #else 18424888Skarels 18524888Skarels #ifdef VAXVMS /* if VMS */ 18624888Skarels cvec = 0270; /* we can't allocate vectors */ 18724888Skarels #else 18824888Skarels cvec = (uba_hd[numuba].uh_lastiv -= 4); /* available vector */ 18924888Skarels #endif VAXVMS 19024888Skarels 19124888Skarels #endif HDHDEBUG 19224888Skarels 19324888Skarels addr->ioini = (char) 0; /* init UMC regs */ 19424888Skarels addr->staack = (char) 0; /* pass vector */ 19524888Skarels addr->ionmi = (char) 0; /* and kick UMC */ 19624888Skarels addr->iochn = (char) (cvec >> 2); 19724888Skarels addr->csr = (short) HDH_RST; 19824888Skarels addr->csr = (short) (HDH_IEN|HDH_DMA|HDH_WRT); /* set enables */ 19924888Skarels DELAY(5000); /* give the UMC some time */ 20024888Skarels return(1); 20124888Skarels } 20224888Skarels 20324888Skarels /* 20424888Skarels * Call the IMP module to allow it to set up its internal 20524888Skarels * state, then tie the two modules together by setting up 20624888Skarels * the back pointers to common data structures. 20724888Skarels */ 20824888Skarels hdhattach(ui) 20924888Skarels struct uba_device *ui; 21024888Skarels { 21124888Skarels register struct hdh_softc *sc = &hdh_softc[ui->ui_unit]; 21224888Skarels register struct impcb *ip; 21324888Skarels struct ifimpcb { 21424888Skarels struct ifnet ifimp_if; 21524888Skarels struct impcb ifimp_impcb; 21624888Skarels } *ifimp; 21724888Skarels 21824888Skarels if ((ifimp = (struct ifimpcb *)impattach(ui, hdhreset)) == 0) 21925461Skarels return;; 22024888Skarels sc->hdh_if = &ifimp->ifimp_if; 22124888Skarels ip = &ifimp->ifimp_impcb; 22224888Skarels sc->hdh_ic = ip; 22324888Skarels ip->ic_init = hdhinit; 22424888Skarels ip->ic_start = hdhstart; 22524888Skarels sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT; 22624888Skarels } 22724888Skarels 22824888Skarels /* 22924888Skarels * Reset interface after UNIBUS reset. 23024888Skarels */ 23124888Skarels hdhreset(unit, uban) 23224888Skarels int unit, uban; 23324888Skarels { 23424888Skarels register struct uba_device *ui = hdhinfo[unit]; 23524888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 23624888Skarels 23724888Skarels #ifdef HDHDEBUG 23824888Skarels printf("HDH RESET\n"); 23924888Skarels #endif HDHDEBUG 24024888Skarels 24124888Skarels if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0) 24224888Skarels || (ui->ui_ubanum != uban)) 24324888Skarels return; 24424888Skarels printf(" hdh%d", unit); 24525461Skarels sc->hdh_if->if_flags &= ~IFF_RUNNING; 24625461Skarels sc->hdh_flags = 0; 24724888Skarels (*sc->hdh_if->if_init)(unit); 24824888Skarels } 24924888Skarels 25024888Skarels /* 25124888Skarels * Initialize the imp interface. 25224888Skarels */ 25324888Skarels 25424888Skarels static char init_blk[] = 25524888Skarels { 25624888Skarels HDHINIT, /* SYSINIT opcode */ 25724888Skarels HDHRQUP & 0xff, /* control code (LSB) */ 25824888Skarels (HDHRQUP>>8) & 0xff, /* control code (MSB) */ 25924888Skarels 10, /* command extension len */ 26024888Skarels 0, /* loopback mode (off) */ 26124888Skarels 3, /* our address (3=DTE) */ 26224888Skarels 1, /* their address (1=DCE) */ 26324888Skarels 3, /* frame ack t1 timeout */ 26424888Skarels 3, /* poll ack timeout */ 26524888Skarels 30, /* adm wait timeout */ 26624888Skarels 3, /* rej wait timeout */ 26724888Skarels 10, /* max retries */ 26824888Skarels 3, /* watchdog timeout */ 26924888Skarels 0xaa /* baud rate (0xaa=38.4KB) */ 27024888Skarels /* (output on RS-232 pin 24, */ 27124888Skarels /* send/receive timing is always */ 27224888Skarels /* taken from pins 15/17) */ 27324888Skarels }; 27424888Skarels 27524888Skarels hdhinit(unit) 27624888Skarels int unit; 27724888Skarels { 27824888Skarels register struct hdh_softc *sc; 27924888Skarels register struct uba_device *ui; 28026283Skarels int i; 28124888Skarels 28224888Skarels #ifdef HDHDEBUG 28324888Skarels printf("HDH INIT\n"); 28424888Skarels #endif HDHDEBUG 28524888Skarels 28624888Skarels if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL 28724888Skarels || ui->ui_alive == 0) { 28824888Skarels printf("hdh%d: not alive\n", unit); 28924888Skarels return(0); 29024888Skarels } 29124888Skarels sc = &hdh_softc[unit]; 29224888Skarels 29325461Skarels if (sc->hdh_flags & HDH_STARTED) 29424888Skarels return(1); 29524888Skarels 29624888Skarels /* 29724888Skarels * Alloc uba resources 29824888Skarels */ 29924888Skarels for(i=0;i<NHDHCH;i++) { 30024888Skarels if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0, 30124888Skarels (int)btoc(IMPMTU)) == 0) { 30224888Skarels printf("hdh%d: cannot get chan %d uba resources\n", 30324888Skarels unit, i); 30424888Skarels ui->ui_alive = 0; 30524888Skarels return(0); 30624888Skarels } 30724888Skarels } 30824888Skarels 30925461Skarels sc->hdh_if->if_flags |= IFF_RUNNING; 31024888Skarels sc->hdh_flags = HDH_STARTED; 31124888Skarels 31224888Skarels /* 31324888Skarels * hang a supervisor read (for line status) 31424888Skarels */ 31524888Skarels hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB); 31624888Skarels 31724888Skarels /* 31824888Skarels * hang a data read 31924888Skarels */ 32024888Skarels hdh_iorq(unit, HDHDATR, IMPMTU, HDHRDB+HDHSTR); 32124888Skarels 32224888Skarels /* 32324888Skarels * bring up line to IMP 32424888Skarels */ 32524888Skarels 32624888Skarels snd_supr(unit, init_blk, sizeof(init_blk)); 32724888Skarels 32824888Skarels return(1); 32924888Skarels } 33024888Skarels 33124888Skarels /* 33224888Skarels * Start an output operation on an mbuf. 33324888Skarels */ 33424888Skarels hdhstart(dev) 33524888Skarels dev_t dev; 33624888Skarels { 33724888Skarels int unit = HDHUNIT(dev); 33824888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 33924888Skarels register struct mbuf *m; 34024888Skarels int len; 34124888Skarels 34224888Skarels /* 34324888Skarels * If output isn't active, attempt to 34424888Skarels * start sending a new packet. 34524888Skarels */ 34624888Skarels 34724888Skarels if (sc->hdh_ic->ic_oactive) { 34824888Skarels printf("hdh%d: start on active unit\n", unit); 34924888Skarels return; 35024888Skarels } 35124888Skarels 35224888Skarels if ((sc->hdh_flags & HDH_UP) == 0) { 35324888Skarels sc->hdh_ic->ic_oactive = 0; /* Link not up, can't xmit */ 35424888Skarels return; 35524888Skarels } 35624888Skarels 35724888Skarels IF_DEQUEUE(&sc->hdh_if->if_snd, m); 35824888Skarels if (m == 0) { 35924888Skarels sc->hdh_ic->ic_oactive = 0; 36024888Skarels return; 36124888Skarels } 36224888Skarels 36324888Skarels len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ 36424888Skarels sc->hdh_ic->ic_oactive = 1; 36524888Skarels 36624888Skarels hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); 36724888Skarels } 36824888Skarels 36924888Skarels /* 37024888Skarels * Start i/o operation on a UMC logical channel 37124888Skarels */ 37224888Skarels hdh_iorq(unit, lcn, len, func) 37324888Skarels int unit, lcn, len, func; 37424888Skarels { 37524888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 37624888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 37724888Skarels register int info, s; 37824888Skarels 37924888Skarels /* 38024888Skarels * If channel is busy (shouldn't be), drop. 38124888Skarels */ 38224888Skarels if (hc->hc_flags & HCBUSY) { 38324888Skarels printf("hdh%d: channel busy lcn=%d\n", unit, lcn); 38424888Skarels return; 38524888Skarels } 38624888Skarels 38724888Skarels /* get appropriate UNIBUS mapping info */ 38824888Skarels 38924888Skarels if (lcn & 1) /* read or write? */ 39024888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; 39124888Skarels else 39224888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; 39324888Skarels 39424888Skarels /* set channel info */ 39524888Skarels 39624888Skarels hc->hc_flags |= HCBUSY; 39724888Skarels hc->hc_chan = lcn; 39824888Skarels hc->hc_adx = (char)((info & 0x30000) >> 12); 39924888Skarels hc->hc_addr = (unsigned short)(info & 0xffff); 40024888Skarels hc->hc_cnt = len; 40124888Skarels hc->hc_func = (char)func; 40224888Skarels hc->hc_sbfc = 0; 40324888Skarels 40424888Skarels s = splimp(); 40524888Skarels /* 40624888Skarels * If UMC comm regs busy, queue start i/o for later. 40724888Skarels */ 40824888Skarels if (sc->hdh_sioq.sioq_head) { 40924888Skarels (sc->hdh_sioq.sioq_tail)->hc_next = hc; 41024888Skarels sc->hdh_sioq.sioq_tail = hc; 41124888Skarels hc->hc_next = 0; 41224888Skarels splx(s); 41324888Skarels return; 41424888Skarels } 41524888Skarels 41624888Skarels /* start i/o on channel now */ 41724888Skarels 41824888Skarels sc->hdh_sioq.sioq_head = hc; 41924888Skarels sc->hdh_sioq.sioq_tail = hc; 42024888Skarels hc->hc_next = 0; 42124888Skarels start_chn(unit); 42224888Skarels splx(s); 42324888Skarels } 42424888Skarels 42524888Skarels start_chn(unit) 42624888Skarels int unit; 42724888Skarels { 42824888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 42924888Skarels register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; 43024888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 43124888Skarels 43224888Skarels /* 43324888Skarels * Set up comm regs. 43424888Skarels */ 43524888Skarels addr->iochn = hc->hc_chan; 43624888Skarels addr->ioadx = hc->hc_adx; 43724888Skarels addr->ioadl = hc->hc_addr; 43824888Skarels addr->iocnt = hc->hc_cnt; 43924888Skarels addr->iofcn = hc->hc_func; 44024888Skarels addr->iosbf = hc->hc_sbfc; 44124888Skarels addr->ioini = 1; 44224888Skarels 44324888Skarels /* signal UMC if necessary */ 44424888Skarels 44524888Skarels if (!(addr->ionmi)) { 44624888Skarels addr->ionmi = 1; 44724888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 44824888Skarels } 44924888Skarels } 45024888Skarels 45124888Skarels /* 45224888Skarels * IF-11/HDH interrupt handler 45324888Skarels */ 45424888Skarels hdhintr(unit) 45524888Skarels int unit; 45624888Skarels { 45724888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 45824888Skarels register struct hdh_chan *hc; 45924888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 46026283Skarels int lcn, type, cc, cnt; 46124888Skarels 46224888Skarels /* 46324888Skarels * Check for hardware errors. 46424888Skarels */ 46524888Skarels if (addr->csr & HDH_UER) { 46624888Skarels printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); 46724888Skarels addr->csr = 0; /* disable i/f */ 46824888Skarels return; 46924888Skarels } 47024888Skarels /* 47124888Skarels * Get logical channel info. 47224888Skarels */ 47324888Skarels if ((lcn = addr->stachn) >= (NHDHCH*2)) { 47424888Skarels printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); 47524888Skarels return; 47624888Skarels } 47724888Skarels 47824888Skarels hc = &sc->hdh_chan[lcn]; 47924888Skarels 48024888Skarels type = addr->statyp; 48124888Skarels cc = addr->stacc; 48224888Skarels cnt = hc->hc_cnt - addr->stacnt; 48324888Skarels 48424888Skarels /* Figure out what kind of interrupt it was */ 48524888Skarels 48624888Skarels switch(type) { 48724888Skarels 48824888Skarels case HDHSACK: /* start i/o accepted */ 48924888Skarels if (hc != sc->hdh_sioq.sioq_head) { 49024888Skarels printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", 49124888Skarels unit, lcn, hc, sc->hdh_sioq.sioq_head); 49224888Skarels return; 49324888Skarels } 49424888Skarels 49524888Skarels /* try to start any queued i/o request */ 49624888Skarels 49724888Skarels if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { 49824888Skarels start_chn(unit); 49924888Skarels } 50024888Skarels break; 50124888Skarels 50224888Skarels case HDHDONE: /* i/o completion */ 50324888Skarels switch (cc) { 50424888Skarels 50524888Skarels case HDHIOCABT: 50624888Skarels printf("hdh%d: I/O abort ", unit); 50724888Skarels goto daterr; 50824888Skarels 50924888Skarels case HDHIOCERR: 51024888Skarels printf("hdh%d: program error ", unit); 51124888Skarels goto daterr; 51224888Skarels 51324888Skarels case HDHIOCOVR: 51424888Skarels printf("hdh%d: overrun error ", unit); 51524888Skarels goto daterr; 51624888Skarels 51724888Skarels case HDHIOCUBE: 51824888Skarels printf("hdh%d: NXM timeout or UB parity error ", unit); 51924888Skarels 52024888Skarels daterr: 52124888Skarels printf("lcn=%d func=%x\n", lcn, hc->hc_func); 52224888Skarels if (hc->hc_func & HDHRDB) 52324888Skarels sc->hdh_if->if_ierrors++; 52424888Skarels else 52524888Skarels sc->hdh_if->if_oerrors++; 52624888Skarels } 52724888Skarels 52824888Skarels hc->hc_flags &= ~HCBUSY; 52924888Skarels 53024888Skarels /* was it supervisor or data traffic? */ 53124888Skarels 53224888Skarels if (lcn > HDHSUPW) 53324888Skarels hdh_data(unit, lcn, cc, cnt); 53424888Skarels else 535*26310Skarels hdh_supr(unit, lcn, cc); 53624888Skarels 53724888Skarels } 53824888Skarels 53924888Skarels /* 54024888Skarels * Ack the interrupt 54124888Skarels */ 54224888Skarels addr->staack = 1; 54324888Skarels if (!(addr->ionmi)) { 54424888Skarels addr->ionmi = 1; 54524888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 54624888Skarels } 54724888Skarels } 54824888Skarels 54924888Skarels /* 55024888Skarels * data channel interrupt completion handler 55124888Skarels */ 55224888Skarels hdh_data(unit, lcn, cc, rcnt) 55324888Skarels int unit, lcn, cc, rcnt; 55424888Skarels { 55524888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 55624888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 55724888Skarels register struct mbuf *m; 55824888Skarels 55924888Skarels 56024888Skarels /* was it read or write? */ 56124888Skarels 56224888Skarels if (hc->hc_func & HDHRDB) { 56324888Skarels if (cc == HDHIOCOK) { 56424888Skarels /* 56524888Skarels * Queue good packet for input 56624888Skarels */ 56724888Skarels sc->hdh_if->if_ipackets++; 56825461Skarels m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, 56925461Skarels sc->hdh_if); 57024888Skarels impinput(unit, m); 57124888Skarels } 57224888Skarels 57324888Skarels /* hang a new data read */ 57424888Skarels 57524888Skarels hdh_iorq(unit, lcn, IMPMTU, HDHRDB+HDHSTR); 57624888Skarels 57724888Skarels } else { 57824888Skarels /* 57924888Skarels * fire up next output 58024888Skarels */ 58124888Skarels sc->hdh_if->if_opackets++; 58224888Skarels sc->hdh_ic->ic_oactive = 0; 58324888Skarels hdhstart(unit); 58424888Skarels } 58524888Skarels } 58624888Skarels 58724888Skarels /* 58824888Skarels * supervisor channel interrupt completion handler 58924888Skarels */ 590*26310Skarels hdh_supr(unit, lcn, cc) 591*26310Skarels int unit, lcn, cc; 59224888Skarels { 59324888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 59424888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 59524888Skarels short *p; 59624888Skarels 59724888Skarels 59824888Skarels /* was it read or write? */ 59924888Skarels 60024888Skarels if (hc->hc_func & HDHRDB) { 60124888Skarels if (cc == HDHIOCOK) { 60224888Skarels p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); 60324888Skarels 60424888Skarels /* figure out what kind of supervisor message */ 60524888Skarels 60624888Skarels switch (*p) { 60724888Skarels 60824888Skarels case HDHIACK: 60924888Skarels case HDHLNACK: 61024888Skarels break; 61124888Skarels 61224888Skarels case HDHLNUP: 61324888Skarels printf("hdh%d: LINE UP\n", unit); 61424888Skarels sc->hdh_flags |= HDH_UP; 61524888Skarels hdhstart(unit); 61624888Skarels break; 61724888Skarels 61824888Skarels case HDHLNDN: 61924888Skarels if (sc->hdh_flags & HDH_UP) 62024888Skarels printf("hdh%d: LINE DOWN\n", unit); 62124888Skarels sc->hdh_flags &= ~HDH_UP; 62224888Skarels break; 62324888Skarels 62424888Skarels case HDHLOOP: 62524888Skarels break; 62624888Skarels 62724888Skarels case HDHSQERR: 62824888Skarels printf("hdh%d: HOST SEQUENCE ERROR\n", unit); 62924888Skarels break; 63024888Skarels 63124888Skarels case HDHSQRCV: 63224888Skarels printf("hdh%d: IMP SEQUENCE ERROR\n", unit); 63324888Skarels break; 63424888Skarels 63524888Skarels case HDHDTERR: 63624888Skarels printf("hdh%d: HOST DATA ERROR\n", unit); 63724888Skarels break; 63824888Skarels 63924888Skarels case HDHTIMO: 64024888Skarels printf("hdh%d: TIMEOUT\n", unit); 64124888Skarels break; 64224888Skarels 64324888Skarels default: 64424888Skarels printf("hdh%d: supervisor error, code=%x\n", 64524888Skarels unit, *p); 64624888Skarels } 64724888Skarels } 64824888Skarels 64924888Skarels /* hang a new supr read */ 65024888Skarels 65124888Skarels hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB+HDHSTR); 65224888Skarels } 65324888Skarels } 65424888Skarels 65524888Skarels snd_supr(unit, msg, len) 65624888Skarels int unit, len; 65724888Skarels char *msg; 65824888Skarels { 65924888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 66024888Skarels register struct mbuf *m; 66124888Skarels register char *p; 66224888Skarels register int cnt; 66324888Skarels 66424888Skarels if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { 66524888Skarels printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); 66624888Skarels return(0); 66724888Skarels } 66824888Skarels 66924888Skarels cnt = len; 67024888Skarels m->m_len = len; 67124888Skarels p = mtod(m, char *); 67224888Skarels 67324888Skarels while(cnt--) *p++ = *msg++; 67424888Skarels 67524888Skarels cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); 67624888Skarels 67724888Skarels hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); 67824888Skarels 67924888Skarels return(1); 68024888Skarels } 68124888Skarels #endif NHDH 682