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