1*33452Skarels /* @(#)if_hdh.c 7.3 (Berkeley) 02/08/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: 45*33452Skarels 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 74*33452Skarels #include "../machine/pte.h" 75*33452Skarels 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 95*33452Skarels 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 */ 156*33452Skarels 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) 21024888Skarels struct uba_device *ui; 21124888Skarels { 21224888Skarels register struct hdh_softc *sc = &hdh_softc[ui->ui_unit]; 21324888Skarels register struct impcb *ip; 21424888Skarels 215*33452Skarels if ((sc->hdh_imp = impattach(ui, hdhreset)) == 0) 21625461Skarels return;; 217*33452Skarels ip = &sc->hdh_imp->imp_cb; 21824888Skarels ip->ic_init = hdhinit; 219*33452Skarels ip->ic_output = hdhoutput; 22024888Skarels sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT; 22124888Skarels } 22224888Skarels 22324888Skarels /* 22424888Skarels * Reset interface after UNIBUS reset. 22524888Skarels */ 22624888Skarels hdhreset(unit, uban) 22724888Skarels int unit, uban; 22824888Skarels { 22924888Skarels register struct uba_device *ui = hdhinfo[unit]; 23024888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 23124888Skarels 23224888Skarels #ifdef HDHDEBUG 23324888Skarels printf("HDH RESET\n"); 23424888Skarels #endif HDHDEBUG 23524888Skarels 23624888Skarels if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0) 23724888Skarels || (ui->ui_ubanum != uban)) 23824888Skarels return; 23924888Skarels printf(" hdh%d", unit); 240*33452Skarels sc->hdh_imp->imp_if.if_flags &= ~IFF_RUNNING; 24125461Skarels sc->hdh_flags = 0; 242*33452Skarels (*sc->hdh_imp->imp_if.if_init)(sc->hdh_imp->imp_if.if_unit); 24324888Skarels } 24424888Skarels 24524888Skarels /* 24624888Skarels * Initialize the imp interface. 24724888Skarels */ 24824888Skarels 24924888Skarels static char init_blk[] = 25024888Skarels { 25124888Skarels HDHINIT, /* SYSINIT opcode */ 25224888Skarels HDHRQUP & 0xff, /* control code (LSB) */ 25324888Skarels (HDHRQUP>>8) & 0xff, /* control code (MSB) */ 25424888Skarels 10, /* command extension len */ 25524888Skarels 0, /* loopback mode (off) */ 25624888Skarels 3, /* our address (3=DTE) */ 25724888Skarels 1, /* their address (1=DCE) */ 25824888Skarels 3, /* frame ack t1 timeout */ 25924888Skarels 3, /* poll ack timeout */ 26024888Skarels 30, /* adm wait timeout */ 26124888Skarels 3, /* rej wait timeout */ 26224888Skarels 10, /* max retries */ 26324888Skarels 3, /* watchdog timeout */ 26424888Skarels 0xaa /* baud rate (0xaa=38.4KB) */ 26524888Skarels /* (output on RS-232 pin 24, */ 26624888Skarels /* send/receive timing is always */ 26724888Skarels /* taken from pins 15/17) */ 26824888Skarels }; 26924888Skarels 27024888Skarels hdhinit(unit) 27124888Skarels int unit; 27224888Skarels { 27324888Skarels register struct hdh_softc *sc; 27424888Skarels register struct uba_device *ui; 27526283Skarels int i; 27624888Skarels 27724888Skarels #ifdef HDHDEBUG 27824888Skarels printf("HDH INIT\n"); 27924888Skarels #endif HDHDEBUG 28024888Skarels 28124888Skarels if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL 28224888Skarels || ui->ui_alive == 0) { 28324888Skarels printf("hdh%d: not alive\n", unit); 28424888Skarels return(0); 28524888Skarels } 28624888Skarels sc = &hdh_softc[unit]; 28724888Skarels 28825461Skarels if (sc->hdh_flags & HDH_STARTED) 28924888Skarels return(1); 29024888Skarels 29124888Skarels /* 29224888Skarels * Alloc uba resources 29324888Skarels */ 294*33452Skarels if ((sc->hdh_imp->imp_if.if_flags & IFF_RUNNING) == 0) 295*33452Skarels for(i=0;i<NHDHCH;i++) { 29624888Skarels if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0, 297*33452Skarels (int)btoc(IMP_RCVBUF)) == 0) { 29824888Skarels printf("hdh%d: cannot get chan %d uba resources\n", 29924888Skarels unit, i); 30024888Skarels ui->ui_alive = 0; 30124888Skarels return(0); 30224888Skarels } 30324888Skarels } 30424888Skarels 305*33452Skarels sc->hdh_imp->imp_if.if_flags |= IFF_RUNNING; 30624888Skarels sc->hdh_flags = HDH_STARTED; 30724888Skarels 30824888Skarels /* 30924888Skarels * hang a supervisor read (for line status) 31024888Skarels */ 311*33452Skarels hdh_iorq(unit, HDHSUPR, IMP_RCVBUF, HDHRDB); 31224888Skarels 31324888Skarels /* 31424888Skarels * hang a data read 31524888Skarels */ 316*33452Skarels hdh_iorq(unit, HDHDATR, IMP_RCVBUF, HDHRDB+HDHSTR); 31724888Skarels 31824888Skarels /* 31924888Skarels * bring up line to IMP 32024888Skarels */ 32124888Skarels 32224888Skarels snd_supr(unit, init_blk, sizeof(init_blk)); 32324888Skarels 32424888Skarels return(1); 32524888Skarels } 32624888Skarels 32724888Skarels /* 32824888Skarels * Start an output operation on an mbuf. 32924888Skarels */ 330*33452Skarels hdhoutput(unit, m) 331*33452Skarels int unit; 332*33452Skarels struct mbuf *m; 33324888Skarels { 33424888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 33524888Skarels int len; 33624888Skarels 33724888Skarels /* 33824888Skarels * If output isn't active, attempt to 33924888Skarels * start sending a new packet. 34024888Skarels */ 34124888Skarels 342*33452Skarels if (sc->hdh_imp->imp_cb.ic_oactive) { 34324888Skarels printf("hdh%d: start on active unit\n", unit); 34424888Skarels return; 34524888Skarels } 34624888Skarels 34724888Skarels if ((sc->hdh_flags & HDH_UP) == 0) { 348*33452Skarels /* Link not up, can't xmit */ 34924888Skarels return; 35024888Skarels } 35124888Skarels 35224888Skarels len = if_wubaput(&sc->hdh_ifuba[DATA], m); /* copy data to mapped mem */ 353*33452Skarels sc->hdh_imp->imp_cb.ic_oactive = 1; 35424888Skarels 35524888Skarels hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS); 35624888Skarels } 35724888Skarels 35824888Skarels /* 35924888Skarels * Start i/o operation on a UMC logical channel 36024888Skarels */ 36124888Skarels hdh_iorq(unit, lcn, len, func) 36224888Skarels int unit, lcn, len, func; 36324888Skarels { 36424888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 36524888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 36624888Skarels register int info, s; 36724888Skarels 36824888Skarels /* 36924888Skarels * If channel is busy (shouldn't be), drop. 37024888Skarels */ 37124888Skarels if (hc->hc_flags & HCBUSY) { 37224888Skarels printf("hdh%d: channel busy lcn=%d\n", unit, lcn); 37324888Skarels return; 37424888Skarels } 37524888Skarels 37624888Skarels /* get appropriate UNIBUS mapping info */ 37724888Skarels 37824888Skarels if (lcn & 1) /* read or write? */ 37924888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info; 38024888Skarels else 38124888Skarels info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info; 38224888Skarels 38324888Skarels /* set channel info */ 38424888Skarels 38524888Skarels hc->hc_flags |= HCBUSY; 38624888Skarels hc->hc_chan = lcn; 38724888Skarels hc->hc_adx = (char)((info & 0x30000) >> 12); 38824888Skarels hc->hc_addr = (unsigned short)(info & 0xffff); 38924888Skarels hc->hc_cnt = len; 39024888Skarels hc->hc_func = (char)func; 39124888Skarels hc->hc_sbfc = 0; 39224888Skarels 39324888Skarels s = splimp(); 39424888Skarels /* 39524888Skarels * If UMC comm regs busy, queue start i/o for later. 39624888Skarels */ 39724888Skarels if (sc->hdh_sioq.sioq_head) { 39824888Skarels (sc->hdh_sioq.sioq_tail)->hc_next = hc; 39924888Skarels sc->hdh_sioq.sioq_tail = hc; 40024888Skarels hc->hc_next = 0; 40124888Skarels splx(s); 40224888Skarels return; 40324888Skarels } 40424888Skarels 40524888Skarels /* start i/o on channel now */ 40624888Skarels 40724888Skarels sc->hdh_sioq.sioq_head = hc; 40824888Skarels sc->hdh_sioq.sioq_tail = hc; 40924888Skarels hc->hc_next = 0; 41024888Skarels start_chn(unit); 41124888Skarels splx(s); 41224888Skarels } 41324888Skarels 41424888Skarels start_chn(unit) 41524888Skarels int unit; 41624888Skarels { 41724888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 41824888Skarels register struct hdh_chan *hc = sc->hdh_sioq.sioq_head; 41924888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 42024888Skarels 42124888Skarels /* 42224888Skarels * Set up comm regs. 42324888Skarels */ 42424888Skarels addr->iochn = hc->hc_chan; 42524888Skarels addr->ioadx = hc->hc_adx; 42624888Skarels addr->ioadl = hc->hc_addr; 42724888Skarels addr->iocnt = hc->hc_cnt; 42824888Skarels addr->iofcn = hc->hc_func; 42924888Skarels addr->iosbf = hc->hc_sbfc; 43024888Skarels addr->ioini = 1; 43124888Skarels 43224888Skarels /* signal UMC if necessary */ 43324888Skarels 43424888Skarels if (!(addr->ionmi)) { 43524888Skarels addr->ionmi = 1; 43624888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 43724888Skarels } 43824888Skarels } 43924888Skarels 44024888Skarels /* 44124888Skarels * IF-11/HDH interrupt handler 44224888Skarels */ 44324888Skarels hdhintr(unit) 44424888Skarels int unit; 44524888Skarels { 44624888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 44724888Skarels register struct hdh_chan *hc; 44824888Skarels register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr; 44926283Skarels int lcn, type, cc, cnt; 45024888Skarels 45124888Skarels /* 45224888Skarels * Check for hardware errors. 45324888Skarels */ 45424888Skarels if (addr->csr & HDH_UER) { 45524888Skarels printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS); 45624888Skarels addr->csr = 0; /* disable i/f */ 45724888Skarels return; 45824888Skarels } 45924888Skarels /* 46024888Skarels * Get logical channel info. 46124888Skarels */ 46224888Skarels if ((lcn = addr->stachn) >= (NHDHCH*2)) { 46324888Skarels printf("hdh%d: unknown channel lcn=%d\n", unit, lcn); 46424888Skarels return; 46524888Skarels } 46624888Skarels 46724888Skarels hc = &sc->hdh_chan[lcn]; 46824888Skarels 46924888Skarels type = addr->statyp; 47024888Skarels cc = addr->stacc; 47124888Skarels cnt = hc->hc_cnt - addr->stacnt; 47224888Skarels 47324888Skarels /* Figure out what kind of interrupt it was */ 47424888Skarels 47524888Skarels switch(type) { 47624888Skarels 47724888Skarels case HDHSACK: /* start i/o accepted */ 47824888Skarels if (hc != sc->hdh_sioq.sioq_head) { 47924888Skarels printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n", 48024888Skarels unit, lcn, hc, sc->hdh_sioq.sioq_head); 48124888Skarels return; 48224888Skarels } 48324888Skarels 48424888Skarels /* try to start any queued i/o request */ 48524888Skarels 48624888Skarels if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) { 48724888Skarels start_chn(unit); 48824888Skarels } 48924888Skarels break; 49024888Skarels 49124888Skarels case HDHDONE: /* i/o completion */ 49224888Skarels switch (cc) { 49324888Skarels 49424888Skarels case HDHIOCABT: 49524888Skarels printf("hdh%d: I/O abort ", unit); 49624888Skarels goto daterr; 49724888Skarels 49824888Skarels case HDHIOCERR: 49924888Skarels printf("hdh%d: program error ", unit); 50024888Skarels goto daterr; 50124888Skarels 50224888Skarels case HDHIOCOVR: 50324888Skarels printf("hdh%d: overrun error ", unit); 50424888Skarels goto daterr; 50524888Skarels 50624888Skarels case HDHIOCUBE: 50724888Skarels printf("hdh%d: NXM timeout or UB parity error ", unit); 50824888Skarels 50924888Skarels daterr: 51024888Skarels printf("lcn=%d func=%x\n", lcn, hc->hc_func); 51124888Skarels if (hc->hc_func & HDHRDB) 512*33452Skarels sc->hdh_imp->imp_if.if_ierrors++; 51324888Skarels else 514*33452Skarels sc->hdh_imp->imp_if.if_oerrors++; 51524888Skarels } 51624888Skarels 51724888Skarels hc->hc_flags &= ~HCBUSY; 51824888Skarels 51924888Skarels /* was it supervisor or data traffic? */ 52024888Skarels 52124888Skarels if (lcn > HDHSUPW) 52224888Skarels hdh_data(unit, lcn, cc, cnt); 52324888Skarels else 52426310Skarels hdh_supr(unit, lcn, cc); 52524888Skarels 52624888Skarels } 52724888Skarels 52824888Skarels /* 52924888Skarels * Ack the interrupt 53024888Skarels */ 53124888Skarels addr->staack = 1; 53224888Skarels if (!(addr->ionmi)) { 53324888Skarels addr->ionmi = 1; 53424888Skarels addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI; 53524888Skarels } 53624888Skarels } 53724888Skarels 53824888Skarels /* 53924888Skarels * data channel interrupt completion handler 54024888Skarels */ 54124888Skarels hdh_data(unit, lcn, cc, rcnt) 54224888Skarels int unit, lcn, cc, rcnt; 54324888Skarels { 54424888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 54524888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 54624888Skarels register struct mbuf *m; 54724888Skarels 54824888Skarels 54924888Skarels /* was it read or write? */ 55024888Skarels 55124888Skarels if (hc->hc_func & HDHRDB) { 55224888Skarels if (cc == HDHIOCOK) { 55324888Skarels /* 55424888Skarels * Queue good packet for input 55524888Skarels */ 556*33452Skarels sc->hdh_imp->imp_if.if_ipackets++; 55725461Skarels m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0, 558*33452Skarels &sc->hdh_imp->imp_if); 55924888Skarels impinput(unit, m); 56024888Skarels } 56124888Skarels 56224888Skarels /* hang a new data read */ 56324888Skarels 564*33452Skarels hdh_iorq(unit, lcn, IMP_RCVBUF, HDHRDB+HDHSTR); 56524888Skarels 56624888Skarels } else { 56724888Skarels /* 56824888Skarels * fire up next output 56924888Skarels */ 570*33452Skarels sc->hdh_imp->imp_if.if_opackets++; 571*33452Skarels sc->hdh_imp->imp_cb.ic_oactive = 0; 572*33452Skarels impstart(sc->hdh_imp->imp_if.if_unit); 57324888Skarels } 57424888Skarels } 57524888Skarels 57624888Skarels /* 57724888Skarels * supervisor channel interrupt completion handler 57824888Skarels */ 57926310Skarels hdh_supr(unit, lcn, cc) 58026310Skarels int unit, lcn, cc; 58124888Skarels { 58224888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 58324888Skarels register struct hdh_chan *hc = &sc->hdh_chan[lcn]; 58424888Skarels short *p; 58524888Skarels 58624888Skarels 58724888Skarels /* was it read or write? */ 58824888Skarels 58924888Skarels if (hc->hc_func & HDHRDB) { 59024888Skarels if (cc == HDHIOCOK) { 59124888Skarels p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr); 59224888Skarels 59324888Skarels /* figure out what kind of supervisor message */ 59424888Skarels 59524888Skarels switch (*p) { 59624888Skarels 59724888Skarels case HDHIACK: 59824888Skarels case HDHLNACK: 59924888Skarels break; 60024888Skarels 60124888Skarels case HDHLNUP: 60224888Skarels printf("hdh%d: LINE UP\n", unit); 60324888Skarels sc->hdh_flags |= HDH_UP; 604*33452Skarels impstart(sc->hdh_imp->imp_if.if_unit); 60524888Skarels break; 60624888Skarels 60724888Skarels case HDHLNDN: 60824888Skarels if (sc->hdh_flags & HDH_UP) 60924888Skarels printf("hdh%d: LINE DOWN\n", unit); 61024888Skarels sc->hdh_flags &= ~HDH_UP; 61124888Skarels break; 61224888Skarels 61324888Skarels case HDHLOOP: 61424888Skarels break; 61524888Skarels 61624888Skarels case HDHSQERR: 61724888Skarels printf("hdh%d: HOST SEQUENCE ERROR\n", unit); 61824888Skarels break; 61924888Skarels 62024888Skarels case HDHSQRCV: 62124888Skarels printf("hdh%d: IMP SEQUENCE ERROR\n", unit); 62224888Skarels break; 62324888Skarels 62424888Skarels case HDHDTERR: 62524888Skarels printf("hdh%d: HOST DATA ERROR\n", unit); 62624888Skarels break; 62724888Skarels 62824888Skarels case HDHTIMO: 62924888Skarels printf("hdh%d: TIMEOUT\n", unit); 63024888Skarels break; 63124888Skarels 63224888Skarels default: 63324888Skarels printf("hdh%d: supervisor error, code=%x\n", 63424888Skarels unit, *p); 63524888Skarels } 63624888Skarels } 63724888Skarels 63824888Skarels /* hang a new supr read */ 63924888Skarels 640*33452Skarels hdh_iorq(unit, HDHSUPR, IMP_RCVBUF, HDHRDB+HDHSTR); 64124888Skarels } 64224888Skarels } 64324888Skarels 64424888Skarels snd_supr(unit, msg, len) 64524888Skarels int unit, len; 64624888Skarels char *msg; 64724888Skarels { 64824888Skarels register struct hdh_softc *sc = &hdh_softc[unit]; 64924888Skarels register struct mbuf *m; 65024888Skarels register char *p; 65124888Skarels register int cnt; 65224888Skarels 65324888Skarels if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) { 65424888Skarels printf("hdh%d: cannot get supervisor cmnd buffer\n", unit); 65528951Skarels return; 65624888Skarels } 65724888Skarels 65824888Skarels cnt = len; 65924888Skarels m->m_len = len; 66024888Skarels p = mtod(m, char *); 66124888Skarels 66224888Skarels while(cnt--) *p++ = *msg++; 66324888Skarels 66424888Skarels cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m); 66524888Skarels 66624888Skarels hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS); 66724888Skarels } 66824888Skarels #endif NHDH 669