1*25461Skarels /* @(#)if_hdh.c 6.2 (Berkeley) 11/11/85 */ 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 67*25461Skarels #include "param.h" 68*25461Skarels #include "systm.h" 69*25461Skarels #include "mbuf.h" 70*25461Skarels #include "buf.h" 71*25461Skarels #include "protosw.h" 72*25461Skarels #include "socket.h" 73*25461Skarels #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 83*25461Skarels #include "if_hdhreg.h" 84*25461Skarels #include "if_uba.h" 85*25461Skarels 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) 219*25461Skarels 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); 245*25461Skarels sc->hdh_if->if_flags &= ~IFF_RUNNING; 246*25461Skarels 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 hdhregs *addr; 28024888Skarels register struct uba_device *ui; 28124888Skarels register struct umc_chan *up; 28224888Skarels register struct mbuf *m, *n; 28324888Skarels int i, s, ubano; 28424888Skarels 28524888Skarels #ifdef HDHDEBUG 28624888Skarels printf("HDH INIT\n"); 28724888Skarels #endif HDHDEBUG 28824888Skarels 28924888Skarels if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL 29024888Skarels || ui->ui_alive == 0) { 29124888Skarels printf("hdh%d: not alive\n", unit); 29224888Skarels return(0); 29324888Skarels } 29424888Skarels addr = (struct hdhregs *)ui->ui_addr; 29524888Skarels sc = &hdh_softc[unit]; 29624888Skarels 297*25461Skarels if (sc->hdh_flags & HDH_STARTED) 29824888Skarels return(1); 29924888Skarels 30024888Skarels /* 30124888Skarels * Alloc uba resources 30224888Skarels */ 30324888Skarels for(i=0;i<NHDHCH;i++) { 30424888Skarels if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0, 30524888Skarels (int)btoc(IMPMTU)) == 0) { 30624888Skarels printf("hdh%d: cannot get chan %d uba resources\n", 30724888Skarels unit, i); 30824888Skarels ui->ui_alive = 0; 30924888Skarels return(0); 31024888Skarels } 31124888Skarels } 31224888Skarels 313*25461Skarels sc->hdh_if->if_flags |= IFF_RUNNING; 31424888Skarels sc->hdh_flags = HDH_STARTED; 31524888Skarels 31624888Skarels /* 31724888Skarels * hang a supervisor read (for line status) 31824888Skarels */ 31924888Skarels hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB); 32024888Skarels 32124888Skarels /* 32224888Skarels * hang a data read 32324888Skarels */ 32424888Skarels hdh_iorq(unit, HDHDATR, IMPMTU, HDHRDB+HDHSTR); 32524888Skarels 32624888Skarels /* 32724888Skarels * bring up line to IMP 32824888Skarels */ 32924888Skarels 33024888Skarels snd_supr(unit, init_blk, sizeof(init_blk)); 33124888Skarels 33224888Skarels return(1); 33324888Skarels } 33424888Skarels 33524888Skarels /* 33624888Skarels * Start an output operation on an mbuf. 33724888Skarels */ 33824888Skarels hdhstart(dev) 33924888Skarels dev_t dev; 34024888Skarels { 34124888Skarels int unit = HDHUNIT(dev); 34224888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 34324888Skarels register struct mbuf *m; 34424888Skarels int len; 34524888Skarels 34624888Skarels /* 34724888Skarels * If output isn't active, attempt to 34824888Skarels * start sending a new packet. 34924888Skarels */ 35024888Skarels 35124888Skarels if (sc->hdh_ic->ic_oactive) { 35224888Skarels printf("hdh%d: start on active unit\n", unit); 35324888Skarels return; 35424888Skarels } 35524888Skarels 35624888Skarels if ((sc->hdh_flags & HDH_UP) == 0) { 35724888Skarels sc->hdh_ic->ic_oactive = 0; /* Link not up, can't xmit */ 35824888Skarels return; 35924888Skarels } 36024888Skarels 36124888Skarels IF_DEQUEUE(&sc->hdh_if->if_snd, m); 36224888Skarels if (m == 0) { 36324888Skarels sc->hdh_ic->ic_oactive = 0; 36424888Skarels return; 36524888Skarels } 36624888Skarels 36724888Skarels len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ 36824888Skarels sc->hdh_ic->ic_oactive = 1; 36924888Skarels 37024888Skarels hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); 37124888Skarels } 37224888Skarels 37324888Skarels /* 37424888Skarels * Start i/o operation on a UMC logical channel 37524888Skarels */ 37624888Skarels hdh_iorq(unit, lcn, len, func) 37724888Skarels int unit, lcn, len, func; 37824888Skarels { 37924888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 38024888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 38124888Skarels register int info, s; 38224888Skarels 38324888Skarels /* 38424888Skarels * If channel is busy (shouldn't be), drop. 38524888Skarels */ 38624888Skarels if (hc->hc_flags & HCBUSY) { 38724888Skarels printf("hdh%d: channel busy lcn=%d\n", unit, lcn); 38824888Skarels return; 38924888Skarels } 39024888Skarels 39124888Skarels /* get appropriate UNIBUS mapping info */ 39224888Skarels 39324888Skarels if (lcn & 1) /* read or write? */ 39424888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; 39524888Skarels else 39624888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; 39724888Skarels 39824888Skarels /* set channel info */ 39924888Skarels 40024888Skarels hc->hc_flags |= HCBUSY; 40124888Skarels hc->hc_chan = lcn; 40224888Skarels hc->hc_adx = (char)((info & 0x30000) >> 12); 40324888Skarels hc->hc_addr = (unsigned short)(info & 0xffff); 40424888Skarels hc->hc_cnt = len; 40524888Skarels hc->hc_func = (char)func; 40624888Skarels hc->hc_sbfc = 0; 40724888Skarels 40824888Skarels s = splimp(); 40924888Skarels /* 41024888Skarels * If UMC comm regs busy, queue start i/o for later. 41124888Skarels */ 41224888Skarels if (sc->hdh_sioq.sioq_head) { 41324888Skarels (sc->hdh_sioq.sioq_tail)->hc_next = hc; 41424888Skarels sc->hdh_sioq.sioq_tail = hc; 41524888Skarels hc->hc_next = 0; 41624888Skarels splx(s); 41724888Skarels return; 41824888Skarels } 41924888Skarels 42024888Skarels /* start i/o on channel now */ 42124888Skarels 42224888Skarels sc->hdh_sioq.sioq_head = hc; 42324888Skarels sc->hdh_sioq.sioq_tail = hc; 42424888Skarels hc->hc_next = 0; 42524888Skarels start_chn(unit); 42624888Skarels splx(s); 42724888Skarels } 42824888Skarels 42924888Skarels start_chn(unit) 43024888Skarels int unit; 43124888Skarels { 43224888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 43324888Skarels register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; 43424888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 43524888Skarels 43624888Skarels /* 43724888Skarels * Set up comm regs. 43824888Skarels */ 43924888Skarels addr->iochn = hc->hc_chan; 44024888Skarels addr->ioadx = hc->hc_adx; 44124888Skarels addr->ioadl = hc->hc_addr; 44224888Skarels addr->iocnt = hc->hc_cnt; 44324888Skarels addr->iofcn = hc->hc_func; 44424888Skarels addr->iosbf = hc->hc_sbfc; 44524888Skarels addr->ioini = 1; 44624888Skarels 44724888Skarels /* signal UMC if necessary */ 44824888Skarels 44924888Skarels if (!(addr->ionmi)) { 45024888Skarels addr->ionmi = 1; 45124888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 45224888Skarels } 45324888Skarels } 45424888Skarels 45524888Skarels /* 45624888Skarels * IF-11/HDH interrupt handler 45724888Skarels */ 45824888Skarels hdhintr(unit) 45924888Skarels int unit; 46024888Skarels { 46124888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 46224888Skarels register struct hdh_chan *hc; 46324888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 46424888Skarels register struct mbuf *m; 46524888Skarels int lcn, type, cc, cnt, s; 46624888Skarels 46724888Skarels /* 46824888Skarels * Check for hardware errors. 46924888Skarels */ 47024888Skarels if (addr->csr & HDH_UER) { 47124888Skarels printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); 47224888Skarels addr->csr = 0; /* disable i/f */ 47324888Skarels return; 47424888Skarels } 47524888Skarels /* 47624888Skarels * Get logical channel info. 47724888Skarels */ 47824888Skarels if ((lcn = addr->stachn) >= (NHDHCH*2)) { 47924888Skarels printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); 48024888Skarels return; 48124888Skarels } 48224888Skarels 48324888Skarels hc = &sc->hdh_chan[lcn]; 48424888Skarels 48524888Skarels type = addr->statyp; 48624888Skarels cc = addr->stacc; 48724888Skarels cnt = hc->hc_cnt - addr->stacnt; 48824888Skarels 48924888Skarels /* Figure out what kind of interrupt it was */ 49024888Skarels 49124888Skarels switch(type) { 49224888Skarels 49324888Skarels case HDHSACK: /* start i/o accepted */ 49424888Skarels if (hc != sc->hdh_sioq.sioq_head) { 49524888Skarels printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", 49624888Skarels unit, lcn, hc, sc->hdh_sioq.sioq_head); 49724888Skarels return; 49824888Skarels } 49924888Skarels 50024888Skarels /* try to start any queued i/o request */ 50124888Skarels 50224888Skarels if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { 50324888Skarels start_chn(unit); 50424888Skarels } 50524888Skarels break; 50624888Skarels 50724888Skarels case HDHDONE: /* i/o completion */ 50824888Skarels switch (cc) { 50924888Skarels 51024888Skarels case HDHIOCABT: 51124888Skarels printf("hdh%d: I/O abort ", unit); 51224888Skarels goto daterr; 51324888Skarels 51424888Skarels case HDHIOCERR: 51524888Skarels printf("hdh%d: program error ", unit); 51624888Skarels goto daterr; 51724888Skarels 51824888Skarels case HDHIOCOVR: 51924888Skarels printf("hdh%d: overrun error ", unit); 52024888Skarels goto daterr; 52124888Skarels 52224888Skarels case HDHIOCUBE: 52324888Skarels printf("hdh%d: NXM timeout or UB parity error ", unit); 52424888Skarels 52524888Skarels daterr: 52624888Skarels printf("lcn=%d func=%x\n", lcn, hc->hc_func); 52724888Skarels if (hc->hc_func & HDHRDB) 52824888Skarels sc->hdh_if->if_ierrors++; 52924888Skarels else 53024888Skarels sc->hdh_if->if_oerrors++; 53124888Skarels } 53224888Skarels 53324888Skarels hc->hc_flags &= ~HCBUSY; 53424888Skarels 53524888Skarels /* was it supervisor or data traffic? */ 53624888Skarels 53724888Skarels if (lcn > HDHSUPW) 53824888Skarels hdh_data(unit, lcn, cc, cnt); 53924888Skarels else 54024888Skarels hdh_supr(unit, lcn, cc, cnt); 54124888Skarels 54224888Skarels } 54324888Skarels 54424888Skarels /* 54524888Skarels * Ack the interrupt 54624888Skarels */ 54724888Skarels addr->staack = 1; 54824888Skarels if (!(addr->ionmi)) { 54924888Skarels addr->ionmi = 1; 55024888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 55124888Skarels } 55224888Skarels } 55324888Skarels 55424888Skarels /* 55524888Skarels * data channel interrupt completion handler 55624888Skarels */ 55724888Skarels hdh_data(unit, lcn, cc, rcnt) 55824888Skarels int unit, lcn, cc, rcnt; 55924888Skarels { 56024888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 56124888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 56224888Skarels register struct mbuf *m; 56324888Skarels 56424888Skarels 56524888Skarels /* was it read or write? */ 56624888Skarels 56724888Skarels if (hc->hc_func & HDHRDB) { 56824888Skarels if (cc == HDHIOCOK) { 56924888Skarels /* 57024888Skarels * Queue good packet for input 57124888Skarels */ 57224888Skarels sc->hdh_if->if_ipackets++; 573*25461Skarels m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, 574*25461Skarels sc->hdh_if); 57524888Skarels impinput(unit, m); 57624888Skarels } 57724888Skarels 57824888Skarels /* hang a new data read */ 57924888Skarels 58024888Skarels hdh_iorq(unit, lcn, IMPMTU, HDHRDB+HDHSTR); 58124888Skarels 58224888Skarels } else { 58324888Skarels /* 58424888Skarels * fire up next output 58524888Skarels */ 58624888Skarels sc->hdh_if->if_opackets++; 58724888Skarels sc->hdh_ic->ic_oactive = 0; 58824888Skarels hdhstart(unit); 58924888Skarels } 59024888Skarels } 59124888Skarels 59224888Skarels /* 59324888Skarels * supervisor channel interrupt completion handler 59424888Skarels */ 59524888Skarels hdh_supr(unit, lcn, cc, rcnt) 59624888Skarels int unit, lcn, cc, rcnt; 59724888Skarels { 59824888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 59924888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 60024888Skarels register struct uba_device *ui; 60124888Skarels short *p; 60224888Skarels int i; 60324888Skarels 60424888Skarels 60524888Skarels /* was it read or write? */ 60624888Skarels 60724888Skarels if (hc->hc_func & HDHRDB) { 60824888Skarels if (cc == HDHIOCOK) { 60924888Skarels p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); 61024888Skarels 61124888Skarels /* figure out what kind of supervisor message */ 61224888Skarels 61324888Skarels switch (*p) { 61424888Skarels 61524888Skarels case HDHIACK: 61624888Skarels case HDHLNACK: 61724888Skarels break; 61824888Skarels 61924888Skarels case HDHLNUP: 62024888Skarels printf("hdh%d: LINE UP\n", unit); 62124888Skarels sc->hdh_flags |= HDH_UP; 62224888Skarels hdhstart(unit); 62324888Skarels break; 62424888Skarels 62524888Skarels case HDHLNDN: 62624888Skarels if (sc->hdh_flags & HDH_UP) 62724888Skarels printf("hdh%d: LINE DOWN\n", unit); 62824888Skarels sc->hdh_flags &= ~HDH_UP; 62924888Skarels break; 63024888Skarels 63124888Skarels case HDHLOOP: 63224888Skarels break; 63324888Skarels 63424888Skarels case HDHSQERR: 63524888Skarels printf("hdh%d: HOST SEQUENCE ERROR\n", unit); 63624888Skarels break; 63724888Skarels 63824888Skarels case HDHSQRCV: 63924888Skarels printf("hdh%d: IMP SEQUENCE ERROR\n", unit); 64024888Skarels break; 64124888Skarels 64224888Skarels case HDHDTERR: 64324888Skarels printf("hdh%d: HOST DATA ERROR\n", unit); 64424888Skarels break; 64524888Skarels 64624888Skarels case HDHTIMO: 64724888Skarels printf("hdh%d: TIMEOUT\n", unit); 64824888Skarels break; 64924888Skarels 65024888Skarels default: 65124888Skarels printf("hdh%d: supervisor error, code=%x\n", 65224888Skarels unit, *p); 65324888Skarels } 65424888Skarels } 65524888Skarels 65624888Skarels /* hang a new supr read */ 65724888Skarels 65824888Skarels hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB+HDHSTR); 65924888Skarels } 66024888Skarels } 66124888Skarels 66224888Skarels snd_supr(unit, msg, len) 66324888Skarels int unit, len; 66424888Skarels char *msg; 66524888Skarels { 66624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 66724888Skarels register struct hdh_chan *hc = &sc->hdh_chan[HDHSUPW]; 66824888Skarels register struct mbuf *m; 66924888Skarels register char *p; 67024888Skarels register int cnt; 67124888Skarels 67224888Skarels if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { 67324888Skarels printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); 67424888Skarels return(0); 67524888Skarels } 67624888Skarels 67724888Skarels cnt = len; 67824888Skarels m->m_len = len; 67924888Skarels p = mtod(m, char *); 68024888Skarels 68124888Skarels while(cnt--) *p++ = *msg++; 68224888Skarels 68324888Skarels cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); 68424888Skarels 68524888Skarels hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); 68624888Skarels 68724888Skarels return(1); 68824888Skarels } 68924888Skarels 69024888Skarels #endif NHDH 691