xref: /csrg-svn/sys/hp300/dev/nhpib.c (revision 65637)
141480Smckusick /*
263151Sbostic  * Copyright (c) 1982, 1990, 1993
363151Sbostic  *	The Regents of the University of California.  All rights reserved.
441480Smckusick  *
541480Smckusick  * %sccs.include.redist.c%
641480Smckusick  *
7*65637Sbostic  *	@(#)nhpib.c	8.2 (Berkeley) 01/12/94
841480Smckusick  */
941480Smckusick 
1041480Smckusick /*
1141480Smckusick  * Internal/98624 HPIB driver
1241480Smckusick  */
1341480Smckusick #include "hpib.h"
1441480Smckusick #if NHPIB > 0
1541480Smckusick 
1656507Sbostic #include <sys/param.h>
1756507Sbostic #include <sys/systm.h>
1856507Sbostic #include <sys/buf.h>
1945788Sbostic 
2056507Sbostic #include <hp/dev/device.h>
2156507Sbostic #include <hp300/dev/nhpibreg.h>
2256507Sbostic #include <hp300/dev/hpibvar.h>
2356507Sbostic #include <hp300/dev/dmavar.h>
2441480Smckusick 
nhpibtype(hc)2541480Smckusick nhpibtype(hc)
2641480Smckusick 	register struct hp_ctlr *hc;
2741480Smckusick {
2841480Smckusick 	register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
2941480Smckusick 	register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
3041480Smckusick 
3149305Shibler 	if (hc->hp_addr == internalhpib) {
3241480Smckusick 		hs->sc_type = HPIBA;
3341480Smckusick 		hs->sc_ba = HPIBA_BA;
3441480Smckusick 		hc->hp_ipl = HPIBA_IPL;
3541480Smckusick 	}
3641480Smckusick 	else if (hd->hpib_cid == HPIBB) {
3741480Smckusick 		hs->sc_type = HPIBB;
3841480Smckusick 		hs->sc_ba = hd->hpib_csa & CSA_BA;
3941480Smckusick 		hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
4041480Smckusick 	}
4141480Smckusick 	else
4241480Smckusick 		return(0);
4341480Smckusick 	return(1);
4441480Smckusick }
4541480Smckusick 
nhpibreset(unit)4641480Smckusick nhpibreset(unit)
47*65637Sbostic 	int unit;
4841480Smckusick {
4941480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
5041480Smckusick 	register struct nhpibdevice *hd;
5141480Smckusick 
5241480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
5341480Smckusick 	hd->hpib_acr = AUX_SSWRST;
5441480Smckusick 	hd->hpib_ar = hs->sc_ba;
5541480Smckusick 	hd->hpib_lim = LIS_ERR;
5641480Smckusick 	hd->hpib_mim = 0;
5741480Smckusick 	hd->hpib_acr = AUX_CDAI;
5841480Smckusick 	hd->hpib_acr = AUX_CSHDW;
5941480Smckusick 	hd->hpib_acr = AUX_SSTD1;
6041480Smckusick 	hd->hpib_acr = AUX_SVSTD1;
6141480Smckusick 	hd->hpib_acr = AUX_CPP;
6241480Smckusick 	hd->hpib_acr = AUX_CHDFA;
6341480Smckusick 	hd->hpib_acr = AUX_CHDFE;
6441480Smckusick 	hd->hpib_acr = AUX_RHDF;
6541480Smckusick 	hd->hpib_acr = AUX_CSWRST;
6641480Smckusick 	nhpibifc(hd);
6741480Smckusick 	hd->hpib_ie = IDS_IE;
6841480Smckusick 	hd->hpib_data = C_DCL;
6941480Smckusick 	DELAY(100000);
7041480Smckusick }
7141480Smckusick 
nhpibifc(hd)7241480Smckusick nhpibifc(hd)
7341480Smckusick 	register struct nhpibdevice *hd;
7441480Smckusick {
7541480Smckusick 	hd->hpib_acr = AUX_TCA;
7641480Smckusick 	hd->hpib_acr = AUX_CSRE;
7741480Smckusick 	hd->hpib_acr = AUX_SSIC;
7841480Smckusick 	DELAY(100);
7941480Smckusick 	hd->hpib_acr = AUX_CSIC;
8041480Smckusick 	hd->hpib_acr = AUX_SSRE;
8141480Smckusick }
8241480Smckusick 
nhpibsend(unit,slave,sec,addr,origcnt)8345511Smckusick nhpibsend(unit, slave, sec, addr, origcnt)
84*65637Sbostic 	int unit, slave, sec, origcnt;
8541480Smckusick 	register char *addr;
8641480Smckusick {
8741480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
8841480Smckusick 	register struct nhpibdevice *hd;
8945511Smckusick 	register int cnt = origcnt;
9041480Smckusick 
9141480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
9241480Smckusick 	hd->hpib_acr = AUX_TCA;
9341480Smckusick 	hd->hpib_data = C_UNL;
9445511Smckusick 	if (nhpibwait(hd, MIS_BO))
9545511Smckusick 		goto senderror;
9641480Smckusick 	hd->hpib_data = C_TAG + hs->sc_ba;
9741480Smckusick 	hd->hpib_acr = AUX_STON;
9845511Smckusick 	if (nhpibwait(hd, MIS_BO))
9945511Smckusick 		goto senderror;
10041480Smckusick 	hd->hpib_data = C_LAG + slave;
10145511Smckusick 	if (nhpibwait(hd, MIS_BO))
10245511Smckusick 		goto senderror;
10341480Smckusick 	if (sec != -1) {
10441480Smckusick 		hd->hpib_data = C_SCG + sec;
10545511Smckusick 		if (nhpibwait(hd, MIS_BO))
10645511Smckusick 			goto senderror;
10741480Smckusick 	}
10841480Smckusick 	hd->hpib_acr = AUX_GTS;
10941480Smckusick 	if (cnt) {
11045511Smckusick 		while (--cnt > 0) {
11141480Smckusick 			hd->hpib_data = *addr++;
11245511Smckusick 			if (nhpibwait(hd, MIS_BO))
11345511Smckusick 				goto senderror;
11441480Smckusick 		}
11541480Smckusick 		hd->hpib_acr = AUX_EOI;
11641480Smckusick 		hd->hpib_data = *addr;
11745511Smckusick 		if (nhpibwait(hd, MIS_BO))
11845511Smckusick 			goto senderror;
11945511Smckusick 		hd->hpib_acr = AUX_TCA;
12045511Smckusick #if 0
12145511Smckusick 		/*
12245511Smckusick 		 * May be causing 345 disks to hang due to interference
12345511Smckusick 		 * with PPOLL mechanism.
12445511Smckusick 		 */
12545511Smckusick 		hd->hpib_data = C_UNL;
12645511Smckusick 		(void) nhpibwait(hd, MIS_BO);
12745511Smckusick #endif
12841480Smckusick 	}
12945511Smckusick 	return(origcnt);
13045511Smckusick senderror:
13145511Smckusick 	nhpibifc(hd);
13245511Smckusick 	return(origcnt - cnt - 1);
13341480Smckusick }
13441480Smckusick 
nhpibrecv(unit,slave,sec,addr,origcnt)13545511Smckusick nhpibrecv(unit, slave, sec, addr, origcnt)
136*65637Sbostic 	int unit, slave, sec, origcnt;
13741480Smckusick 	register char *addr;
13841480Smckusick {
13941480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
14041480Smckusick 	register struct nhpibdevice *hd;
14145511Smckusick 	register int cnt = origcnt;
14241480Smckusick 
14341480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
14441480Smckusick 	hd->hpib_acr = AUX_TCA;
14541480Smckusick 	hd->hpib_data = C_UNL;
14645511Smckusick 	if (nhpibwait(hd, MIS_BO))
14745511Smckusick 		goto recverror;
14841480Smckusick 	hd->hpib_data = C_LAG + hs->sc_ba;
14941480Smckusick 	hd->hpib_acr = AUX_SLON;
15045511Smckusick 	if (nhpibwait(hd, MIS_BO))
15145511Smckusick 		goto recverror;
15241480Smckusick 	hd->hpib_data = C_TAG + slave;
15345511Smckusick 	if (nhpibwait(hd, MIS_BO))
15445511Smckusick 		goto recverror;
15541480Smckusick 	if (sec != -1) {
15641480Smckusick 		hd->hpib_data = C_SCG + sec;
15745511Smckusick 		if (nhpibwait(hd, MIS_BO))
15845511Smckusick 			goto recverror;
15941480Smckusick 	}
16041480Smckusick 	hd->hpib_acr = AUX_RHDF;
16141480Smckusick 	hd->hpib_acr = AUX_GTS;
16241480Smckusick 	if (cnt) {
16341480Smckusick 		while (--cnt >= 0) {
16445511Smckusick 			if (nhpibwait(hd, MIS_BI))
16545511Smckusick 				goto recvbyteserror;
16641480Smckusick 			*addr++ = hd->hpib_data;
16741480Smckusick 		}
16841480Smckusick 		hd->hpib_acr = AUX_TCA;
16945511Smckusick 		hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
17045511Smckusick 		(void) nhpibwait(hd, MIS_BO);
17141480Smckusick 	}
17245511Smckusick 	return(origcnt);
17345511Smckusick recverror:
17445511Smckusick 	nhpibifc(hd);
17545511Smckusick recvbyteserror:
17645511Smckusick 	return(origcnt - cnt - 1);
17741480Smckusick }
17841480Smckusick 
nhpibgo(unit,slave,sec,addr,count,rw)17941480Smckusick nhpibgo(unit, slave, sec, addr, count, rw)
18041480Smckusick 	register int unit, slave;
181*65637Sbostic 	int sec, count, rw;
18241480Smckusick 	char *addr;
18341480Smckusick {
18441480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
18541480Smckusick 	register struct nhpibdevice *hd;
18641480Smckusick 
18741480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
18841480Smckusick 	hs->sc_flags |= HPIBF_IO;
18941480Smckusick 	if (rw == B_READ)
19041480Smckusick 		hs->sc_flags |= HPIBF_READ;
19141480Smckusick #ifdef DEBUG
19241480Smckusick 	else if (hs->sc_flags & HPIBF_READ) {
19341480Smckusick 		printf("nhpibgo: HPIBF_READ still set\n");
19441480Smckusick 		hs->sc_flags &= ~HPIBF_READ;
19541480Smckusick 	}
19641480Smckusick #endif
19741480Smckusick 	hs->sc_count = count;
19841480Smckusick 	hs->sc_addr = addr;
19941480Smckusick 	if (hs->sc_flags & HPIBF_READ) {
20041480Smckusick 		hs->sc_curcnt = count;
20141480Smckusick 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
20241480Smckusick 		nhpibrecv(unit, slave, sec, 0, 0);
20341480Smckusick 		hd->hpib_mim = MIS_END;
20445511Smckusick 	} else {
20545511Smckusick 		hd->hpib_mim = 0;
20645511Smckusick 		if (count < hpibdmathresh) {
20745511Smckusick 			hs->sc_curcnt = count;
20845511Smckusick 			nhpibsend(unit, slave, sec, addr, count);
20945511Smckusick 			nhpibdone(unit);
21045511Smckusick 			return;
21141480Smckusick 		}
21245511Smckusick 		hs->sc_curcnt = --count;
21345511Smckusick 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
21445511Smckusick 		nhpibsend(unit, slave, sec, 0, 0);
21541480Smckusick 	}
21641480Smckusick 	hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
21741480Smckusick }
21841480Smckusick 
nhpibdone(unit)21941480Smckusick nhpibdone(unit)
22041480Smckusick 	register int unit;
22141480Smckusick {
22241480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
22341480Smckusick 	register struct nhpibdevice *hd;
22441480Smckusick 	register int cnt;
22541480Smckusick 
22641480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
22741480Smckusick 	cnt = hs->sc_curcnt;
22841480Smckusick 	hs->sc_addr += cnt;
22941480Smckusick 	hs->sc_count -= cnt;
23045511Smckusick 	hs->sc_flags |= HPIBF_DONE;
23145511Smckusick 	hd->hpib_ie = IDS_IE;
23245511Smckusick 	if ((hs->sc_flags & HPIBF_READ) == 0) {
23341480Smckusick 		if (hs->sc_count == 1) {
23445511Smckusick 			(void) nhpibwait(hd, MIS_BO);
23541480Smckusick 			hd->hpib_acr = AUX_EOI;
23645511Smckusick 			hd->hpib_data = *hs->sc_addr;
23745511Smckusick 			hd->hpib_mim = MIS_BO;
23841480Smckusick 		}
23945511Smckusick #ifdef DEBUG
24045511Smckusick 		else if (hs->sc_count)
24145511Smckusick 			panic("nhpibdone");
24245511Smckusick #endif
24341480Smckusick 	}
24441480Smckusick }
24541480Smckusick 
nhpibintr(unit)24641480Smckusick nhpibintr(unit)
24741480Smckusick 	register int unit;
24841480Smckusick {
24941480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
25041480Smckusick 	register struct nhpibdevice *hd;
25145511Smckusick 	register struct devqueue *dq;
25241480Smckusick 	register int stat0;
25341480Smckusick 	int stat1;
25441480Smckusick 
25541480Smckusick #ifdef lint
25641480Smckusick 	if (stat1 = unit) return(1);
25741480Smckusick #endif
25841480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
25941480Smckusick 	if ((hd->hpib_ids & IDS_IR) == 0)
26041480Smckusick 		return(0);
26141480Smckusick 	stat0 = hd->hpib_mis;
26241480Smckusick 	stat1 = hd->hpib_lis;
26345511Smckusick 	dq = hs->sc_sq.dq_forw;
26441480Smckusick 	if (hs->sc_flags & HPIBF_IO) {
26541480Smckusick 		hd->hpib_mim = 0;
26641480Smckusick 		if ((hs->sc_flags & HPIBF_DONE) == 0)
26741480Smckusick 			dmastop(hs->sc_dq.dq_ctlr);
26841480Smckusick 		hd->hpib_acr = AUX_TCA;
26941480Smckusick 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
27041480Smckusick 		dmafree(&hs->sc_dq);
27141480Smckusick 		(dq->dq_driver->d_intr)(dq->dq_unit);
27245511Smckusick 	} else if (hs->sc_flags & HPIBF_PPOLL) {
27341480Smckusick 		hd->hpib_mim = 0;
27441480Smckusick 		stat0 = nhpibppoll(unit);
27541480Smckusick 		if (stat0 & (0x80 >> dq->dq_slave)) {
27641480Smckusick 			hs->sc_flags &= ~HPIBF_PPOLL;
27741480Smckusick 			(dq->dq_driver->d_intr)(dq->dq_unit);
27841480Smckusick 		}
27945511Smckusick #ifdef DEBUG
28045511Smckusick 		else
28145511Smckusick 			printf("hpib%d: PPOLL intr bad status %x\n",
28245511Smckusick 			       unit, stat0);
28345511Smckusick #endif
28441480Smckusick 	}
28541480Smckusick 	return(1);
28641480Smckusick }
28741480Smckusick 
nhpibppoll(unit)28841480Smckusick nhpibppoll(unit)
28945511Smckusick 	int unit;
29041480Smckusick {
29141480Smckusick 	register struct nhpibdevice *hd;
29241480Smckusick 	register int ppoll;
29341480Smckusick 
29445511Smckusick 	hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
29541480Smckusick 	hd->hpib_acr = AUX_SPP;
29641480Smckusick 	DELAY(25);
29741480Smckusick 	ppoll = hd->hpib_cpt;
29841480Smckusick 	hd->hpib_acr = AUX_CPP;
29941480Smckusick 	return(ppoll);
30041480Smckusick }
30141480Smckusick 
nhpibwait(hd,x)30245511Smckusick nhpibwait(hd, x)
30341480Smckusick 	register struct nhpibdevice *hd;
304*65637Sbostic 	int x;
30541480Smckusick {
30641480Smckusick 	register int timo = hpibtimeout;
30741480Smckusick 
30845511Smckusick 	while ((hd->hpib_mis & x) == 0 && --timo)
30945511Smckusick 		DELAY(1);
31041480Smckusick 	if (timo == 0)
31141480Smckusick 		return(-1);
31241480Smckusick 	return(0);
31341480Smckusick }
31441480Smckusick 
31554770Storek void
nhpibppwatch(arg)31654770Storek nhpibppwatch(arg)
31754770Storek 	void *arg;
31854770Storek {
31954770Storek 	register struct hpib_softc *hs;
32041480Smckusick 	register int unit;
32157347Shibler 	extern int cold;
32241480Smckusick 
32354770Storek 	unit = (int)arg;
32454770Storek 	hs = &hpib_softc[unit];
32541480Smckusick 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
32641480Smckusick 		return;
32757347Shibler again:
32845511Smckusick 	if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
32941480Smckusick        		((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
33057347Shibler 	else if (cold)
33157347Shibler 		/* timeouts not working yet */
33257347Shibler 		goto again;
33341480Smckusick 	else
33454770Storek 		timeout(nhpibppwatch, (void *)unit, 1);
33541480Smckusick }
33641480Smckusick #endif
337