xref: /csrg-svn/sys/vax/if/if_hdh.c (revision 24888)
1*24888Skarels 
2*24888Skarels 
3*24888Skarels 
4*24888Skarels /************************************************************************\
5*24888Skarels 
6*24888Skarels      ________________________________________________________
7*24888Skarels     /                                                        \
8*24888Skarels    |          AAA          CCCCCCCCCCCCCC    CCCCCCCCCCCCCC   |
9*24888Skarels    |         AAAAA        CCCCCCCCCCCCCCCC  CCCCCCCCCCCCCCCC  |
10*24888Skarels    |        AAAAAAA       CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC |
11*24888Skarels    |       AAAA AAAA      CCCC              CCCC              |
12*24888Skarels    |      AAAA   AAAA     CCCC              CCCC              |
13*24888Skarels    |     AAAA     AAAA    CCCC              CCCC              |
14*24888Skarels    |    AAAA       AAAA   CCCC              CCCC              |
15*24888Skarels    |   AAAA  AAAAAAAAAAA  CCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCC |
16*24888Skarels    |  AAAA    AAAAAAAAAAA CCCCCCCCCCCCCCCC  CCCCCCCCCCCCCCCC  |
17*24888Skarels    | AAAA      AAAAAAAAA   CCCCCCCCCCCCCC    CCCCCCCCCCCCCC   |
18*24888Skarels     \________________________________________________________/
19*24888Skarels 
20*24888Skarels 	Copyright (c) 1984 by Advanced Computer Communications
21*24888Skarels 	720 Santa Barbara Street, Santa Barbara, California  93101
22*24888Skarels 	(805) 963-9431
23*24888Skarels 
24*24888Skarels 	This software may be duplicated and used on systems
25*24888Skarels 	which are licensed to run U.C. Berkeley versions of
26*24888Skarels 	the UNIX operating system.  Any duplication of any
27*24888Skarels 	part of this software must include a copy of ACC's
28*24888Skarels 	copyright notice.
29*24888Skarels 
30*24888Skarels 
31*24888Skarels File:
32*24888Skarels 		if_hdh.c
33*24888Skarels 
34*24888Skarels Author:
35*24888Skarels 		Art Berggreen
36*24888Skarels 
37*24888Skarels Project:
38*24888Skarels 		4.2BSD HDH
39*24888Skarels 
40*24888Skarels Function:
41*24888Skarels 		Device specific driver for IF-11/HDH under 4.2BSD
42*24888Skarels     		networking code.
43*24888Skarels 
44*24888Skarels Revision History:
45*24888Skarels 		31-Aug-1984: V1.0 - First Implementation. A.B.
46*24888Skarels 		 6-Nov-1984: V1.1 - Supress extra "LINE DOWN" msgs. A.B.
47*24888Skarels 		13-Jan-1984: V1.2 - Add conditionals for TWG. A.B.
48*24888Skarels 
49*24888Skarels \************************************************************************/
50*24888Skarels 
51*24888Skarels 
52*24888Skarels 
53*24888Skarels 
54*24888Skarels /* $Header$ */
55*24888Skarels 
56*24888Skarels #include "hdh.h"
57*24888Skarels #ifdef NHDH > 0
58*24888Skarels 
59*24888Skarels /*
60*24888Skarels  *
61*24888Skarels  * ACC IF-11/HDH interface
62*24888Skarels  *
63*24888Skarels  */
64*24888Skarels 
65*24888Skarels #include "../machine/pte.h"
66*24888Skarels 
67*24888Skarels #include "../h/param.h"
68*24888Skarels #include "../h/systm.h"
69*24888Skarels #include "../h/mbuf.h"
70*24888Skarels #include "../h/buf.h"
71*24888Skarels #include "../h/protosw.h"
72*24888Skarels #include "../h/socket.h"
73*24888Skarels #include "../h/vmmac.h"
74*24888Skarels 
75*24888Skarels #include "../net/if.h"
76*24888Skarels #include "../netimp/if_imp.h"
77*24888Skarels 
78*24888Skarels #include "../vax/cpu.h"
79*24888Skarels #include "../vax/mtpr.h"
80*24888Skarels #include "../vaxif/if_hdhreg.h"
81*24888Skarels #include "../vaxif/if_uba.h"
82*24888Skarels #include "../vaxuba/ubareg.h"
83*24888Skarels #include "../vaxuba/ubavar.h"
84*24888Skarels 
85*24888Skarels int     hdhprobe(), hdhattach(), hdhrint(), hdhxint();
86*24888Skarels struct  uba_device *hdhinfo[NHDH];
87*24888Skarels u_short hdhstd[] = { 0 };
88*24888Skarels struct  uba_driver hdhdriver =
89*24888Skarels 	{ hdhprobe, 0, hdhattach, 0, hdhstd, "hdh", hdhinfo };
90*24888Skarels 
91*24888Skarels #define	HDHUNIT(x)	minor(x)
92*24888Skarels 
93*24888Skarels int	hdhinit(), hdhstart(), hdhreset();
94*24888Skarels 
95*24888Skarels /*
96*24888Skarels  * "Lower half" of IMP interface driver.
97*24888Skarels  *
98*24888Skarels  * Each IMP interface is handled by a common module which handles
99*24888Skarels  * the IMP-host protocol and a hardware driver which manages the
100*24888Skarels  * hardware specific details of talking with the IMP.
101*24888Skarels  *
102*24888Skarels  * The hardware portion of the IMP driver handles DMA and related
103*24888Skarels  * management of UNIBUS resources.  The IMP protocol module interprets
104*24888Skarels  * contents of these messages and "controls" the actions of the
105*24888Skarels  * hardware module during IMP resets, but not, for instance, during
106*24888Skarels  * UNIBUS resets.
107*24888Skarels  *
108*24888Skarels  * The two modules are coupled at "attach time", and ever after,
109*24888Skarels  * through the imp interface structure.  Higher level protocols,
110*24888Skarels  * e.g. IP, interact with the IMP driver, rather than the HDH.
111*24888Skarels  */
112*24888Skarels 
113*24888Skarels #define NHDHCH	2		/* no. of FDX channels for HDH */
114*24888Skarels #define SUPR	0		/* supervisor channel */
115*24888Skarels #define	DATA	1		/* data channel */
116*24888Skarels #define HDHSUPR	0		/* supervisor read */
117*24888Skarels #define HDHSUPW	1		/* supervisor write */
118*24888Skarels #define HDHDATR	2		/* data read */
119*24888Skarels #define HDHDATW	3		/* data write */
120*24888Skarels 
121*24888Skarels #define HDH_UP		2	/* HDH protocol is up */
122*24888Skarels #define HDH_STARTED	1	/* HDH has been initialized */
123*24888Skarels 
124*24888Skarels #define HCBUSY	1		/* HDH HDX channel busy flag */
125*24888Skarels 
126*24888Skarels /*
127*24888Skarels /* The IF-11/HDH has four independent dath flow channels between the
128*24888Skarels /* front-end and the host.  Two are used for reading and writing
129*24888Skarels /* control messages and two are used for data flow.  Each IF-11/HDH
130*24888Skarels /* has a device dependent data structure (hdh_softc) which contains
131*24888Skarels /* an array of four channel dependent structures (hdh_chan) to maintain
132*24888Skarels /* the context of each channel.  Channel structures can be linked into
133*24888Skarels /* a queue of I/O requests pending for the hardware interface.
134*24888Skarels /* UNIBUS mapping resources are allocated for each channel pair.
135*24888Skarels */
136*24888Skarels 
137*24888Skarels struct	hdh_chan {		/* HDH HDX channel structure */
138*24888Skarels 	struct hdh_chan	*hc_next;	/* link for Start I/O queuing */
139*24888Skarels 	char		hc_chan;	/* HDX chan number */
140*24888Skarels 	char		hc_adx;		/* extended UNIBUS address bits */
141*24888Skarels 	short		hc_addr;	/* lower UNIBUS address bits */
142*24888Skarels 	short		hc_cnt;		/* byte count */
143*24888Skarels 	char		hc_func;	/* UMC I/O function */
144*24888Skarels 	char		hc_sbfc;	/* UMC I/O subfunction */
145*24888Skarels 	short		hc_flags;	/* status flags */
146*24888Skarels };
147*24888Skarels 
148*24888Skarels struct	hdh_sioq {		/* Start I/O queue head structure */
149*24888Skarels 	struct hdh_chan *sioq_head;	/* pointer to queue head */
150*24888Skarels 	struct hdh_chan *sioq_tail;	/* pointer to queue tail */
151*24888Skarels };
152*24888Skarels 
153*24888Skarels struct	hdh_softc {		/* HDH device dependent structure */
154*24888Skarels 	struct ifnet	*hdh_if;	/* pointer to IMP's ifnet struct */
155*24888Skarels 	struct impcb	*hdh_ic;	/* data structure shared with IMP */
156*24888Skarels 	struct ifuba	hdh_ifuba[NHDHCH]; /* UNIBUS resources */
157*24888Skarels 	struct hdh_chan hdh_chan[2*NHDHCH]; /* HDX HDH channels */
158*24888Skarels 	struct hdh_sioq hdh_sioq;	/* start i/o queue */
159*24888Skarels 	short		hdh_flags;	/* various status conditions */
160*24888Skarels } hdh_softc[NHDH];
161*24888Skarels 
162*24888Skarels 
163*24888Skarels /*
164*24888Skarels  * Normally, code goes here to cause the device to interrupt to determine its
165*24888Skarels  * interrupt vector.  However, since the UMC must be told its vector in order
166*24888Skarels  * to interrupt, we allocate and return an unused vector and initialize the
167*24888Skarels  * UMC.
168*24888Skarels  */
169*24888Skarels hdhprobe(reg)
170*24888Skarels caddr_t reg;
171*24888Skarels {
172*24888Skarels 	register int br, cvec;
173*24888Skarels 	struct hdhregs *addr = (struct hdhregs *)reg;
174*24888Skarels #ifdef lint
175*24888Skarels 	br = 0; cvec = br; br = cvec;
176*24888Skarels #endif
177*24888Skarels 
178*24888Skarels 	br = 0x15;			/* priority 21 (5 on UNIBUS) */
179*24888Skarels 
180*24888Skarels #ifdef HDHDEBUG
181*24888Skarels 	cvec = 0270;			/* use constant for now ... */
182*24888Skarels #else
183*24888Skarels 
184*24888Skarels #ifdef VAXVMS				/* if VMS */
185*24888Skarels 	cvec = 0270;			/*   we can't allocate vectors */
186*24888Skarels #else
187*24888Skarels 	cvec = (uba_hd[numuba].uh_lastiv -= 4);  /* available vector */
188*24888Skarels #endif VAXVMS
189*24888Skarels 
190*24888Skarels #endif HDHDEBUG
191*24888Skarels 
192*24888Skarels 	addr->ioini = (char) 0;		/* init UMC regs */
193*24888Skarels 	addr->staack = (char) 0;	/*   pass vector */
194*24888Skarels 	addr->ionmi = (char) 0;		/*     and kick UMC */
195*24888Skarels 	addr->iochn = (char) (cvec >> 2);
196*24888Skarels 	addr->csr = (short) HDH_RST;
197*24888Skarels 	addr->csr = (short) (HDH_IEN|HDH_DMA|HDH_WRT); /* set enables */
198*24888Skarels 	DELAY(5000);			/* give the UMC some time */
199*24888Skarels 	return(1);
200*24888Skarels }
201*24888Skarels 
202*24888Skarels /*
203*24888Skarels  * Call the IMP module to allow it to set up its internal
204*24888Skarels  * state, then tie the two modules together by setting up
205*24888Skarels  * the back pointers to common data structures.
206*24888Skarels  */
207*24888Skarels hdhattach(ui)
208*24888Skarels 	struct uba_device *ui;
209*24888Skarels {
210*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[ui->ui_unit];
211*24888Skarels 	register struct impcb *ip;
212*24888Skarels 	struct ifimpcb {
213*24888Skarels 		struct	ifnet ifimp_if;
214*24888Skarels 		struct	impcb ifimp_impcb;
215*24888Skarels 	} *ifimp;
216*24888Skarels 
217*24888Skarels 	if ((ifimp = (struct ifimpcb *)impattach(ui, hdhreset)) == 0)
218*24888Skarels 		panic("hdhattach");
219*24888Skarels 	sc->hdh_if = &ifimp->ifimp_if;
220*24888Skarels 	ip = &ifimp->ifimp_impcb;
221*24888Skarels 	sc->hdh_ic = ip;
222*24888Skarels 	ip->ic_init = hdhinit;
223*24888Skarels 	ip->ic_start = hdhstart;
224*24888Skarels 	sc->hdh_ifuba[ui->ui_unit].ifu_flags = UBA_CANTWAIT;
225*24888Skarels }
226*24888Skarels 
227*24888Skarels /*
228*24888Skarels  * Reset interface after UNIBUS reset.
229*24888Skarels  */
230*24888Skarels hdhreset(unit, uban)
231*24888Skarels int unit, uban;
232*24888Skarels {
233*24888Skarels 	register struct uba_device *ui = hdhinfo[unit];
234*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
235*24888Skarels 
236*24888Skarels #ifdef HDHDEBUG
237*24888Skarels 	printf("HDH RESET\n");
238*24888Skarels #endif HDHDEBUG
239*24888Skarels 
240*24888Skarels 	if ((unit >= NHDH) || (ui == 0) || (ui->ui_alive == 0)
241*24888Skarels 	    || (ui->ui_ubanum != uban))
242*24888Skarels 		return;
243*24888Skarels 	printf(" hdh%d", unit);
244*24888Skarels 	(*sc->hdh_if->if_init)(unit);
245*24888Skarels }
246*24888Skarels 
247*24888Skarels /*
248*24888Skarels  * Initialize the imp interface.
249*24888Skarels  */
250*24888Skarels 
251*24888Skarels static char init_blk[] =
252*24888Skarels     {
253*24888Skarels 	HDHINIT,		/* SYSINIT opcode			*/
254*24888Skarels 	HDHRQUP & 0xff,		/* control code (LSB)			*/
255*24888Skarels 	(HDHRQUP>>8) & 0xff,	/* control code (MSB)			*/
256*24888Skarels 	10,			/* command extension len		*/
257*24888Skarels 	0,			/* loopback mode (off)			*/
258*24888Skarels 	3,			/* our address (3=DTE)			*/
259*24888Skarels 	1,			/* their address (1=DCE)		*/
260*24888Skarels 	3,			/* frame ack t1 timeout			*/
261*24888Skarels 	3,			/* poll ack timeout			*/
262*24888Skarels 	30,			/* adm wait timeout			*/
263*24888Skarels 	3,			/* rej wait timeout			*/
264*24888Skarels 	10,			/* max retries				*/
265*24888Skarels 	3,			/* watchdog timeout			*/
266*24888Skarels 	0xaa			/* baud rate (0xaa=38.4KB)		*/
267*24888Skarels 				/*   (output on RS-232 pin 24,		*/
268*24888Skarels 				/*    send/receive timing is always	*/
269*24888Skarels 				/*    taken from pins 15/17)		*/
270*24888Skarels     };
271*24888Skarels 
272*24888Skarels hdhinit(unit)
273*24888Skarels int unit;
274*24888Skarels {
275*24888Skarels 	register struct hdh_softc *sc;
276*24888Skarels 	register struct hdhregs *addr;
277*24888Skarels 	register struct uba_device *ui;
278*24888Skarels 	register struct umc_chan *up;
279*24888Skarels 	register struct mbuf *m, *n;
280*24888Skarels 	int i, s, ubano;
281*24888Skarels 
282*24888Skarels #ifdef HDHDEBUG
283*24888Skarels 	printf("HDH INIT\n");
284*24888Skarels #endif HDHDEBUG
285*24888Skarels 
286*24888Skarels 	if (unit >= NHDH || (ui = hdhinfo[unit]) == NULL
287*24888Skarels 	    || ui->ui_alive == 0) {
288*24888Skarels 		printf("hdh%d: not alive\n", unit);
289*24888Skarels 		return(0);
290*24888Skarels 	}
291*24888Skarels 	addr = (struct hdhregs *)ui->ui_addr;
292*24888Skarels 	sc = &hdh_softc[unit];
293*24888Skarels 
294*24888Skarels 	if (sc->hdh_flags & HDH_STARTED) {
295*24888Skarels 		printf("hdh%d: re-init\n", unit);
296*24888Skarels 		return(1);
297*24888Skarels 	}
298*24888Skarels 
299*24888Skarels 	/*
300*24888Skarels 	 * Alloc uba resources
301*24888Skarels 	 */
302*24888Skarels 	for(i=0;i<NHDHCH;i++) {
303*24888Skarels 		if (if_ubainit(&sc->hdh_ifuba[i], ui->ui_ubanum, 0,
304*24888Skarels 		    (int)btoc(IMPMTU)) == 0) {
305*24888Skarels 			printf("hdh%d: cannot get chan %d uba resources\n",
306*24888Skarels 				unit, i);
307*24888Skarels 			ui->ui_alive = 0;
308*24888Skarels 			return(0);
309*24888Skarels 		}
310*24888Skarels 	}
311*24888Skarels 
312*24888Skarels 	sc->hdh_flags = HDH_STARTED;
313*24888Skarels 
314*24888Skarels 	/*
315*24888Skarels 	 * hang a supervisor read (for line status)
316*24888Skarels 	 */
317*24888Skarels 	hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB);
318*24888Skarels 
319*24888Skarels 	/*
320*24888Skarels 	 * hang a data read
321*24888Skarels 	 */
322*24888Skarels 	hdh_iorq(unit, HDHDATR, IMPMTU, HDHRDB+HDHSTR);
323*24888Skarels 
324*24888Skarels 	/*
325*24888Skarels 	 * bring up line to IMP
326*24888Skarels 	 */
327*24888Skarels 
328*24888Skarels 	snd_supr(unit, init_blk, sizeof(init_blk));
329*24888Skarels 
330*24888Skarels 	return(1);
331*24888Skarels }
332*24888Skarels 
333*24888Skarels /*
334*24888Skarels  * Start an output operation on an mbuf.
335*24888Skarels  */
336*24888Skarels hdhstart(dev)
337*24888Skarels dev_t dev;
338*24888Skarels {
339*24888Skarels 	int unit = HDHUNIT(dev);
340*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
341*24888Skarels 	register struct mbuf *m;
342*24888Skarels         int len;
343*24888Skarels 
344*24888Skarels 	/*
345*24888Skarels 	 * If output isn't active, attempt to
346*24888Skarels 	 * start sending a new packet.
347*24888Skarels 	 */
348*24888Skarels 
349*24888Skarels 	if (sc->hdh_ic->ic_oactive) {
350*24888Skarels 		printf("hdh%d: start on active unit\n", unit);
351*24888Skarels 		return;
352*24888Skarels 	}
353*24888Skarels 
354*24888Skarels 	if ((sc->hdh_flags & HDH_UP) == 0) {
355*24888Skarels 		sc->hdh_ic->ic_oactive = 0;	/* Link not up, can't xmit */
356*24888Skarels 		return;
357*24888Skarels 	}
358*24888Skarels 
359*24888Skarels 	IF_DEQUEUE(&sc->hdh_if->if_snd, m);
360*24888Skarels 	if (m == 0) {
361*24888Skarels 		sc->hdh_ic->ic_oactive = 0;
362*24888Skarels 		return;
363*24888Skarels 	}
364*24888Skarels 
365*24888Skarels 	len = if_wubaput(&sc->hdh_ifuba[DATA], m);	/* copy data to mapped mem */
366*24888Skarels 	sc->hdh_ic->ic_oactive = 1;
367*24888Skarels 
368*24888Skarels 	hdh_iorq(unit, HDHDATW, len, HDHWRT+HDHEOS);
369*24888Skarels }
370*24888Skarels 
371*24888Skarels /*
372*24888Skarels  * Start i/o operation on a UMC logical channel
373*24888Skarels  */
374*24888Skarels hdh_iorq(unit, lcn, len, func)
375*24888Skarels int unit, lcn, len, func;
376*24888Skarels {
377*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
378*24888Skarels 	register struct hdh_chan *hc = &sc->hdh_chan[lcn];
379*24888Skarels 	register int info, s;
380*24888Skarels 
381*24888Skarels 	/*
382*24888Skarels 	 * If channel is busy (shouldn't be), drop.
383*24888Skarels 	 */
384*24888Skarels 	if  (hc->hc_flags & HCBUSY) {
385*24888Skarels 		printf("hdh%d: channel busy lcn=%d\n", unit, lcn);
386*24888Skarels 		return;
387*24888Skarels 	}
388*24888Skarels 
389*24888Skarels  	/* get appropriate UNIBUS mapping info */
390*24888Skarels 
391*24888Skarels 	if (lcn & 1)		/* read or write? */
392*24888Skarels 		info = sc->hdh_ifuba[lcn>>1].ifu_w.ifrw_info;
393*24888Skarels 	else
394*24888Skarels 		info = sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_info;
395*24888Skarels 
396*24888Skarels 	/* set channel info */
397*24888Skarels 
398*24888Skarels 	hc->hc_flags |= HCBUSY;
399*24888Skarels 	hc->hc_chan = lcn;
400*24888Skarels 	hc->hc_adx = (char)((info & 0x30000) >> 12);
401*24888Skarels 	hc->hc_addr = (unsigned short)(info & 0xffff);
402*24888Skarels 	hc->hc_cnt = len;
403*24888Skarels 	hc->hc_func = (char)func;
404*24888Skarels 	hc->hc_sbfc = 0;
405*24888Skarels 
406*24888Skarels 	s = splimp();
407*24888Skarels 	/*
408*24888Skarels 	 * If UMC comm regs busy, queue start i/o for later.
409*24888Skarels 	 */
410*24888Skarels 	if (sc->hdh_sioq.sioq_head) {
411*24888Skarels 		(sc->hdh_sioq.sioq_tail)->hc_next = hc;
412*24888Skarels 		sc->hdh_sioq.sioq_tail = hc;
413*24888Skarels 		hc->hc_next = 0;
414*24888Skarels 		splx(s);
415*24888Skarels 		return;
416*24888Skarels 	}
417*24888Skarels 
418*24888Skarels 	/* start i/o on channel now */
419*24888Skarels 
420*24888Skarels 	sc->hdh_sioq.sioq_head = hc;
421*24888Skarels 	sc->hdh_sioq.sioq_tail = hc;
422*24888Skarels 	hc->hc_next = 0;
423*24888Skarels 	start_chn(unit);
424*24888Skarels 	splx(s);
425*24888Skarels }
426*24888Skarels 
427*24888Skarels start_chn(unit)
428*24888Skarels int unit;
429*24888Skarels {
430*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
431*24888Skarels 	register struct hdh_chan *hc = sc->hdh_sioq.sioq_head;
432*24888Skarels 	register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr;
433*24888Skarels 
434*24888Skarels 	/*
435*24888Skarels 	 * Set up comm regs.
436*24888Skarels 	 */
437*24888Skarels 	addr->iochn = hc->hc_chan;
438*24888Skarels 	addr->ioadx = hc->hc_adx;
439*24888Skarels 	addr->ioadl = hc->hc_addr;
440*24888Skarels 	addr->iocnt = hc->hc_cnt;
441*24888Skarels 	addr->iofcn = hc->hc_func;
442*24888Skarels 	addr->iosbf = hc->hc_sbfc;
443*24888Skarels 	addr->ioini = 1;
444*24888Skarels 
445*24888Skarels 	/* signal UMC if necessary */
446*24888Skarels 
447*24888Skarels 	if (!(addr->ionmi)) {
448*24888Skarels 		addr->ionmi = 1;
449*24888Skarels 		addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI;
450*24888Skarels 	}
451*24888Skarels }
452*24888Skarels 
453*24888Skarels /*
454*24888Skarels  * IF-11/HDH interrupt handler
455*24888Skarels  */
456*24888Skarels hdhintr(unit)
457*24888Skarels int unit;
458*24888Skarels {
459*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
460*24888Skarels 	register struct hdh_chan *hc;
461*24888Skarels 	register struct hdhregs *addr = (struct hdhregs *)hdhinfo[unit]->ui_addr;
462*24888Skarels 	register struct mbuf *m;
463*24888Skarels 	int lcn, type, cc, cnt, s;
464*24888Skarels 
465*24888Skarels 	/*
466*24888Skarels 	 * Check for hardware errors.
467*24888Skarels 	 */
468*24888Skarels 	if (addr->csr & HDH_UER) {
469*24888Skarels 		printf("hdh%d: hard error csr=%b\n", unit, addr->csr, HDH_BITS);
470*24888Skarels 		addr->csr = 0;		/* disable i/f */
471*24888Skarels 		return;
472*24888Skarels 	}
473*24888Skarels 	/*
474*24888Skarels 	 * Get logical channel info.
475*24888Skarels 	 */
476*24888Skarels 	if ((lcn = addr->stachn) >= (NHDHCH*2)) {
477*24888Skarels 		printf("hdh%d: unknown channel lcn=%d\n", unit, lcn);
478*24888Skarels 		return;
479*24888Skarels 	}
480*24888Skarels 
481*24888Skarels 	hc = &sc->hdh_chan[lcn];
482*24888Skarels 
483*24888Skarels 	type = addr->statyp;
484*24888Skarels 	cc = addr->stacc;
485*24888Skarels 	cnt = hc->hc_cnt - addr->stacnt;
486*24888Skarels 
487*24888Skarels 	/* Figure out what kind of interrupt it was */
488*24888Skarels 
489*24888Skarels 	switch(type) {
490*24888Skarels 
491*24888Skarels 	case HDHSACK:		/* start i/o accepted */
492*24888Skarels 		if (hc != sc->hdh_sioq.sioq_head) {
493*24888Skarels 			printf("hdh%d: STARTIO error lcn=%d hc=%x sq=%x\n",
494*24888Skarels 				unit, lcn, hc, sc->hdh_sioq.sioq_head);
495*24888Skarels 			return;
496*24888Skarels 		}
497*24888Skarels 
498*24888Skarels 		/* try to start any queued i/o request */
499*24888Skarels 
500*24888Skarels 		if (sc->hdh_sioq.sioq_head = sc->hdh_sioq.sioq_head->hc_next) {
501*24888Skarels 			start_chn(unit);
502*24888Skarels 		}
503*24888Skarels 		break;
504*24888Skarels 
505*24888Skarels 	case HDHDONE:		/* i/o completion */
506*24888Skarels 		switch (cc) {
507*24888Skarels 
508*24888Skarels 		case HDHIOCABT:
509*24888Skarels 			printf("hdh%d: I/O abort ", unit);
510*24888Skarels 			goto daterr;
511*24888Skarels 
512*24888Skarels 		case HDHIOCERR:
513*24888Skarels 			printf("hdh%d: program error ", unit);
514*24888Skarels 			goto daterr;
515*24888Skarels 
516*24888Skarels 		case HDHIOCOVR:
517*24888Skarels 			printf("hdh%d: overrun error ", unit);
518*24888Skarels 			goto daterr;
519*24888Skarels 
520*24888Skarels 		case HDHIOCUBE:
521*24888Skarels 			printf("hdh%d: NXM timeout or UB parity error ", unit);
522*24888Skarels 
523*24888Skarels 		daterr:
524*24888Skarels 			printf("lcn=%d func=%x\n", lcn, hc->hc_func);
525*24888Skarels 			if (hc->hc_func & HDHRDB)
526*24888Skarels 				sc->hdh_if->if_ierrors++;
527*24888Skarels 			else
528*24888Skarels 				sc->hdh_if->if_oerrors++;
529*24888Skarels 		}
530*24888Skarels 
531*24888Skarels 		hc->hc_flags &= ~HCBUSY;
532*24888Skarels 
533*24888Skarels 		/* was it supervisor or data traffic? */
534*24888Skarels 
535*24888Skarels 		if (lcn > HDHSUPW)
536*24888Skarels 			hdh_data(unit, lcn, cc, cnt);
537*24888Skarels 		else
538*24888Skarels 			hdh_supr(unit, lcn, cc, cnt);
539*24888Skarels 
540*24888Skarels 	}
541*24888Skarels 
542*24888Skarels 	/*
543*24888Skarels 	 * Ack the interrupt
544*24888Skarels 	 */
545*24888Skarels 	addr->staack = 1;
546*24888Skarels 	if (!(addr->ionmi)) {
547*24888Skarels 		addr->ionmi = 1;
548*24888Skarels 		addr->csr = HDH_DMA|HDH_WRT|HDH_IEN|HDH_NMI;
549*24888Skarels 	}
550*24888Skarels }
551*24888Skarels 
552*24888Skarels /*
553*24888Skarels  * data channel interrupt completion handler
554*24888Skarels  */
555*24888Skarels hdh_data(unit, lcn, cc, rcnt)
556*24888Skarels int unit, lcn, cc, rcnt;
557*24888Skarels {
558*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
559*24888Skarels 	register struct hdh_chan *hc = &sc->hdh_chan[lcn];
560*24888Skarels 	register struct mbuf *m;
561*24888Skarels 
562*24888Skarels 
563*24888Skarels 	/* was it read or write? */
564*24888Skarels 
565*24888Skarels 	if (hc->hc_func & HDHRDB) {
566*24888Skarels 		if (cc == HDHIOCOK) {
567*24888Skarels 			/*
568*24888Skarels 			 * Queue good packet for input
569*24888Skarels 			 */
570*24888Skarels 			sc->hdh_if->if_ipackets++;
571*24888Skarels 			m = if_rubaget(&sc->hdh_ifuba[lcn>>1], rcnt, 0);
572*24888Skarels 			impinput(unit, m);
573*24888Skarels 		}
574*24888Skarels 
575*24888Skarels 		/* hang a new data read */
576*24888Skarels 
577*24888Skarels 		hdh_iorq(unit, lcn, IMPMTU, HDHRDB+HDHSTR);
578*24888Skarels 
579*24888Skarels 	} else {
580*24888Skarels 		/*
581*24888Skarels 		 * fire up next output
582*24888Skarels 		 */
583*24888Skarels 		sc->hdh_if->if_opackets++;
584*24888Skarels 		sc->hdh_ic->ic_oactive = 0;
585*24888Skarels 		hdhstart(unit);
586*24888Skarels 	}
587*24888Skarels }
588*24888Skarels 
589*24888Skarels /*
590*24888Skarels  * supervisor channel interrupt completion handler
591*24888Skarels  */
592*24888Skarels hdh_supr(unit, lcn, cc, rcnt)
593*24888Skarels int unit, lcn, cc, rcnt;
594*24888Skarels {
595*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
596*24888Skarels 	register struct hdh_chan *hc = &sc->hdh_chan[lcn];
597*24888Skarels 	register struct uba_device *ui;
598*24888Skarels 	short *p;
599*24888Skarels 	int i;
600*24888Skarels 
601*24888Skarels 
602*24888Skarels 	/* was it read or write? */
603*24888Skarels 
604*24888Skarels 	if (hc->hc_func & HDHRDB) {
605*24888Skarels 		if (cc == HDHIOCOK) {
606*24888Skarels 			p = (short *)(sc->hdh_ifuba[lcn>>1].ifu_r.ifrw_addr);
607*24888Skarels 
608*24888Skarels 			/* figure out what kind of supervisor message */
609*24888Skarels 
610*24888Skarels 			switch (*p) {
611*24888Skarels 
612*24888Skarels 			case HDHIACK:
613*24888Skarels 			case HDHLNACK:
614*24888Skarels 				break;
615*24888Skarels 
616*24888Skarels 			case HDHLNUP:
617*24888Skarels 				printf("hdh%d: LINE UP\n", unit);
618*24888Skarels 				sc->hdh_flags |= HDH_UP;
619*24888Skarels 				hdhstart(unit);
620*24888Skarels 				break;
621*24888Skarels 
622*24888Skarels 			case HDHLNDN:
623*24888Skarels 				if (sc->hdh_flags & HDH_UP)
624*24888Skarels 					printf("hdh%d: LINE DOWN\n", unit);
625*24888Skarels 				sc->hdh_flags &= ~HDH_UP;
626*24888Skarels 				break;
627*24888Skarels 
628*24888Skarels 			case HDHLOOP:
629*24888Skarels 				break;
630*24888Skarels 
631*24888Skarels 			case HDHSQERR:
632*24888Skarels 				printf("hdh%d: HOST SEQUENCE ERROR\n", unit);
633*24888Skarels 				break;
634*24888Skarels 
635*24888Skarels 			case HDHSQRCV:
636*24888Skarels 				printf("hdh%d: IMP SEQUENCE ERROR\n", unit);
637*24888Skarels 				break;
638*24888Skarels 
639*24888Skarels 			case HDHDTERR:
640*24888Skarels 				printf("hdh%d: HOST DATA ERROR\n", unit);
641*24888Skarels 				break;
642*24888Skarels 
643*24888Skarels 			case HDHTIMO:
644*24888Skarels 				printf("hdh%d: TIMEOUT\n", unit);
645*24888Skarels 				break;
646*24888Skarels 
647*24888Skarels 			default:
648*24888Skarels 				printf("hdh%d: supervisor error, code=%x\n",
649*24888Skarels 					unit, *p);
650*24888Skarels 			}
651*24888Skarels 		}
652*24888Skarels 
653*24888Skarels 		/* hang a new supr read */
654*24888Skarels 
655*24888Skarels 		hdh_iorq(unit, HDHSUPR, IMPMTU, HDHRDB+HDHSTR);
656*24888Skarels 	}
657*24888Skarels }
658*24888Skarels 
659*24888Skarels snd_supr(unit, msg, len)
660*24888Skarels int unit, len;
661*24888Skarels char *msg;
662*24888Skarels {
663*24888Skarels 	register struct hdh_softc *sc = &hdh_softc[unit];
664*24888Skarels 	register struct hdh_chan *hc = &sc->hdh_chan[HDHSUPW];
665*24888Skarels 	register struct mbuf *m;
666*24888Skarels 	register char *p;
667*24888Skarels 	register int cnt;
668*24888Skarels 
669*24888Skarels 	if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL) {
670*24888Skarels 		printf("hdh%d: cannot get supervisor cmnd buffer\n", unit);
671*24888Skarels 			return(0);
672*24888Skarels 	}
673*24888Skarels 
674*24888Skarels 	cnt = len;
675*24888Skarels 	m->m_len = len;
676*24888Skarels 	p = mtod(m, char *);
677*24888Skarels 
678*24888Skarels 	while(cnt--) *p++ = *msg++;
679*24888Skarels 
680*24888Skarels 	cnt = if_wubaput(&sc->hdh_ifuba[SUPR], m);
681*24888Skarels 
682*24888Skarels 	hdh_iorq(unit, HDHSUPW, cnt, HDHWRT+HDHEOS);
683*24888Skarels 
684*24888Skarels 	return(1);
685*24888Skarels }
686*24888Skarels 
687*24888Skarels #endif NHDH
688