xref: /csrg-svn/sys/hp300/dev/nhpib.c (revision 45788)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1982, 1990 The Regents of the University of California.
341480Smckusick  * All rights reserved.
441480Smckusick  *
541480Smckusick  * %sccs.include.redist.c%
641480Smckusick  *
7*45788Sbostic  *	@(#)nhpib.c	7.3 (Berkeley) 12/16/90
841480Smckusick  */
941480Smckusick 
1041480Smckusick /*
1141480Smckusick  * Internal/98624 HPIB driver
1241480Smckusick  */
1341480Smckusick #include "hpib.h"
1441480Smckusick #if NHPIB > 0
1541480Smckusick 
16*45788Sbostic #include "sys/param.h"
17*45788Sbostic #include "sys/systm.h"
18*45788Sbostic #include "sys/buf.h"
19*45788Sbostic 
2041480Smckusick #include "device.h"
2141480Smckusick #include "nhpibreg.h"
2241480Smckusick #include "hpibvar.h"
2341480Smckusick #include "dmavar.h"
2441480Smckusick 
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 
3141480Smckusick 	if ((int)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 
4641480Smckusick nhpibreset(unit)
4741480Smckusick {
4841480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
4941480Smckusick 	register struct nhpibdevice *hd;
5041480Smckusick 
5141480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
5241480Smckusick 	hd->hpib_acr = AUX_SSWRST;
5341480Smckusick 	hd->hpib_ar = hs->sc_ba;
5441480Smckusick 	hd->hpib_lim = LIS_ERR;
5541480Smckusick 	hd->hpib_mim = 0;
5641480Smckusick 	hd->hpib_acr = AUX_CDAI;
5741480Smckusick 	hd->hpib_acr = AUX_CSHDW;
5841480Smckusick 	hd->hpib_acr = AUX_SSTD1;
5941480Smckusick 	hd->hpib_acr = AUX_SVSTD1;
6041480Smckusick 	hd->hpib_acr = AUX_CPP;
6141480Smckusick 	hd->hpib_acr = AUX_CHDFA;
6241480Smckusick 	hd->hpib_acr = AUX_CHDFE;
6341480Smckusick 	hd->hpib_acr = AUX_RHDF;
6441480Smckusick 	hd->hpib_acr = AUX_CSWRST;
6541480Smckusick 	nhpibifc(hd);
6641480Smckusick 	hd->hpib_ie = IDS_IE;
6741480Smckusick 	hd->hpib_data = C_DCL;
6841480Smckusick 	DELAY(100000);
6941480Smckusick }
7041480Smckusick 
7141480Smckusick nhpibifc(hd)
7241480Smckusick 	register struct nhpibdevice *hd;
7341480Smckusick {
7441480Smckusick 	hd->hpib_acr = AUX_TCA;
7541480Smckusick 	hd->hpib_acr = AUX_CSRE;
7641480Smckusick 	hd->hpib_acr = AUX_SSIC;
7741480Smckusick 	DELAY(100);
7841480Smckusick 	hd->hpib_acr = AUX_CSIC;
7941480Smckusick 	hd->hpib_acr = AUX_SSRE;
8041480Smckusick }
8141480Smckusick 
8245511Smckusick nhpibsend(unit, slave, sec, addr, origcnt)
8341480Smckusick 	register char *addr;
8441480Smckusick {
8541480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
8641480Smckusick 	register struct nhpibdevice *hd;
8745511Smckusick 	register int cnt = origcnt;
8841480Smckusick 
8941480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
9041480Smckusick 	hd->hpib_acr = AUX_TCA;
9141480Smckusick 	hd->hpib_data = C_UNL;
9245511Smckusick 	if (nhpibwait(hd, MIS_BO))
9345511Smckusick 		goto senderror;
9441480Smckusick 	hd->hpib_data = C_TAG + hs->sc_ba;
9541480Smckusick 	hd->hpib_acr = AUX_STON;
9645511Smckusick 	if (nhpibwait(hd, MIS_BO))
9745511Smckusick 		goto senderror;
9841480Smckusick 	hd->hpib_data = C_LAG + slave;
9945511Smckusick 	if (nhpibwait(hd, MIS_BO))
10045511Smckusick 		goto senderror;
10141480Smckusick 	if (sec != -1) {
10241480Smckusick 		hd->hpib_data = C_SCG + sec;
10345511Smckusick 		if (nhpibwait(hd, MIS_BO))
10445511Smckusick 			goto senderror;
10541480Smckusick 	}
10641480Smckusick 	hd->hpib_acr = AUX_GTS;
10741480Smckusick 	if (cnt) {
10845511Smckusick 		while (--cnt > 0) {
10941480Smckusick 			hd->hpib_data = *addr++;
11045511Smckusick 			if (nhpibwait(hd, MIS_BO))
11145511Smckusick 				goto senderror;
11241480Smckusick 		}
11341480Smckusick 		hd->hpib_acr = AUX_EOI;
11441480Smckusick 		hd->hpib_data = *addr;
11545511Smckusick 		if (nhpibwait(hd, MIS_BO))
11645511Smckusick 			goto senderror;
11745511Smckusick 		hd->hpib_acr = AUX_TCA;
11845511Smckusick #if 0
11945511Smckusick 		/*
12045511Smckusick 		 * May be causing 345 disks to hang due to interference
12145511Smckusick 		 * with PPOLL mechanism.
12245511Smckusick 		 */
12345511Smckusick 		hd->hpib_data = C_UNL;
12445511Smckusick 		(void) nhpibwait(hd, MIS_BO);
12545511Smckusick #endif
12641480Smckusick 	}
12745511Smckusick 	return(origcnt);
12845511Smckusick senderror:
12945511Smckusick 	nhpibifc(hd);
13045511Smckusick 	return(origcnt - cnt - 1);
13141480Smckusick }
13241480Smckusick 
13345511Smckusick nhpibrecv(unit, slave, sec, addr, origcnt)
13441480Smckusick 	register char *addr;
13541480Smckusick {
13641480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
13741480Smckusick 	register struct nhpibdevice *hd;
13845511Smckusick 	register int cnt = origcnt;
13941480Smckusick 
14041480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
14141480Smckusick 	hd->hpib_acr = AUX_TCA;
14241480Smckusick 	hd->hpib_data = C_UNL;
14345511Smckusick 	if (nhpibwait(hd, MIS_BO))
14445511Smckusick 		goto recverror;
14541480Smckusick 	hd->hpib_data = C_LAG + hs->sc_ba;
14641480Smckusick 	hd->hpib_acr = AUX_SLON;
14745511Smckusick 	if (nhpibwait(hd, MIS_BO))
14845511Smckusick 		goto recverror;
14941480Smckusick 	hd->hpib_data = C_TAG + slave;
15045511Smckusick 	if (nhpibwait(hd, MIS_BO))
15145511Smckusick 		goto recverror;
15241480Smckusick 	if (sec != -1) {
15341480Smckusick 		hd->hpib_data = C_SCG + sec;
15445511Smckusick 		if (nhpibwait(hd, MIS_BO))
15545511Smckusick 			goto recverror;
15641480Smckusick 	}
15741480Smckusick 	hd->hpib_acr = AUX_RHDF;
15841480Smckusick 	hd->hpib_acr = AUX_GTS;
15941480Smckusick 	if (cnt) {
16041480Smckusick 		while (--cnt >= 0) {
16145511Smckusick 			if (nhpibwait(hd, MIS_BI))
16245511Smckusick 				goto recvbyteserror;
16341480Smckusick 			*addr++ = hd->hpib_data;
16441480Smckusick 		}
16541480Smckusick 		hd->hpib_acr = AUX_TCA;
16645511Smckusick 		hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
16745511Smckusick 		(void) nhpibwait(hd, MIS_BO);
16841480Smckusick 	}
16945511Smckusick 	return(origcnt);
17045511Smckusick recverror:
17145511Smckusick 	nhpibifc(hd);
17245511Smckusick recvbyteserror:
17345511Smckusick 	return(origcnt - cnt - 1);
17441480Smckusick }
17541480Smckusick 
17641480Smckusick nhpibgo(unit, slave, sec, addr, count, rw)
17741480Smckusick 	register int unit, slave;
17841480Smckusick 	char *addr;
17941480Smckusick {
18041480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
18141480Smckusick 	register struct nhpibdevice *hd;
18241480Smckusick 
18341480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
18441480Smckusick 	hs->sc_flags |= HPIBF_IO;
18541480Smckusick 	if (rw == B_READ)
18641480Smckusick 		hs->sc_flags |= HPIBF_READ;
18741480Smckusick #ifdef DEBUG
18841480Smckusick 	else if (hs->sc_flags & HPIBF_READ) {
18941480Smckusick 		printf("nhpibgo: HPIBF_READ still set\n");
19041480Smckusick 		hs->sc_flags &= ~HPIBF_READ;
19141480Smckusick 	}
19241480Smckusick #endif
19341480Smckusick 	hs->sc_count = count;
19441480Smckusick 	hs->sc_addr = addr;
19541480Smckusick 	if (hs->sc_flags & HPIBF_READ) {
19641480Smckusick 		hs->sc_curcnt = count;
19741480Smckusick 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
19841480Smckusick 		nhpibrecv(unit, slave, sec, 0, 0);
19941480Smckusick 		hd->hpib_mim = MIS_END;
20045511Smckusick 	} else {
20145511Smckusick 		hd->hpib_mim = 0;
20245511Smckusick 		if (count < hpibdmathresh) {
20345511Smckusick 			hs->sc_curcnt = count;
20445511Smckusick 			nhpibsend(unit, slave, sec, addr, count);
20545511Smckusick 			nhpibdone(unit);
20645511Smckusick 			return;
20741480Smckusick 		}
20845511Smckusick 		hs->sc_curcnt = --count;
20945511Smckusick 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
21045511Smckusick 		nhpibsend(unit, slave, sec, 0, 0);
21141480Smckusick 	}
21241480Smckusick 	hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
21341480Smckusick }
21441480Smckusick 
21541480Smckusick nhpibdone(unit)
21641480Smckusick 	register int unit;
21741480Smckusick {
21841480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
21941480Smckusick 	register struct nhpibdevice *hd;
22041480Smckusick 	register int cnt;
22141480Smckusick 
22241480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
22341480Smckusick 	cnt = hs->sc_curcnt;
22441480Smckusick 	hs->sc_addr += cnt;
22541480Smckusick 	hs->sc_count -= cnt;
22645511Smckusick 	hs->sc_flags |= HPIBF_DONE;
22745511Smckusick 	hd->hpib_ie = IDS_IE;
22845511Smckusick 	if ((hs->sc_flags & HPIBF_READ) == 0) {
22941480Smckusick 		if (hs->sc_count == 1) {
23045511Smckusick 			(void) nhpibwait(hd, MIS_BO);
23141480Smckusick 			hd->hpib_acr = AUX_EOI;
23245511Smckusick 			hd->hpib_data = *hs->sc_addr;
23345511Smckusick 			hd->hpib_mim = MIS_BO;
23441480Smckusick 		}
23545511Smckusick #ifdef DEBUG
23645511Smckusick 		else if (hs->sc_count)
23745511Smckusick 			panic("nhpibdone");
23845511Smckusick #endif
23941480Smckusick 	}
24041480Smckusick }
24141480Smckusick 
24241480Smckusick nhpibintr(unit)
24341480Smckusick 	register int unit;
24441480Smckusick {
24541480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
24641480Smckusick 	register struct nhpibdevice *hd;
24745511Smckusick 	register struct devqueue *dq;
24841480Smckusick 	register int stat0;
24941480Smckusick 	int stat1;
25041480Smckusick 
25141480Smckusick #ifdef lint
25241480Smckusick 	if (stat1 = unit) return(1);
25341480Smckusick #endif
25441480Smckusick 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
25541480Smckusick 	if ((hd->hpib_ids & IDS_IR) == 0)
25641480Smckusick 		return(0);
25741480Smckusick 	stat0 = hd->hpib_mis;
25841480Smckusick 	stat1 = hd->hpib_lis;
25945511Smckusick 	dq = hs->sc_sq.dq_forw;
26041480Smckusick 	if (hs->sc_flags & HPIBF_IO) {
26141480Smckusick 		hd->hpib_mim = 0;
26241480Smckusick 		if ((hs->sc_flags & HPIBF_DONE) == 0)
26341480Smckusick 			dmastop(hs->sc_dq.dq_ctlr);
26441480Smckusick 		hd->hpib_acr = AUX_TCA;
26541480Smckusick 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
26641480Smckusick 		dmafree(&hs->sc_dq);
26741480Smckusick 		(dq->dq_driver->d_intr)(dq->dq_unit);
26845511Smckusick 	} else if (hs->sc_flags & HPIBF_PPOLL) {
26941480Smckusick 		hd->hpib_mim = 0;
27041480Smckusick 		stat0 = nhpibppoll(unit);
27141480Smckusick 		if (stat0 & (0x80 >> dq->dq_slave)) {
27241480Smckusick 			hs->sc_flags &= ~HPIBF_PPOLL;
27341480Smckusick 			(dq->dq_driver->d_intr)(dq->dq_unit);
27441480Smckusick 		}
27545511Smckusick #ifdef DEBUG
27645511Smckusick 		else
27745511Smckusick 			printf("hpib%d: PPOLL intr bad status %x\n",
27845511Smckusick 			       unit, stat0);
27945511Smckusick #endif
28041480Smckusick 	}
28141480Smckusick 	return(1);
28241480Smckusick }
28341480Smckusick 
28441480Smckusick nhpibppoll(unit)
28545511Smckusick 	int unit;
28641480Smckusick {
28741480Smckusick 	register struct nhpibdevice *hd;
28841480Smckusick 	register int ppoll;
28941480Smckusick 
29045511Smckusick 	hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
29141480Smckusick 	hd->hpib_acr = AUX_SPP;
29241480Smckusick 	DELAY(25);
29341480Smckusick 	ppoll = hd->hpib_cpt;
29441480Smckusick 	hd->hpib_acr = AUX_CPP;
29541480Smckusick 	return(ppoll);
29641480Smckusick }
29741480Smckusick 
29845511Smckusick nhpibwait(hd, x)
29941480Smckusick 	register struct nhpibdevice *hd;
30041480Smckusick {
30141480Smckusick 	register int timo = hpibtimeout;
30241480Smckusick 
30345511Smckusick 	while ((hd->hpib_mis & x) == 0 && --timo)
30445511Smckusick 		DELAY(1);
30541480Smckusick 	if (timo == 0)
30641480Smckusick 		return(-1);
30741480Smckusick 	return(0);
30841480Smckusick }
30941480Smckusick 
31041480Smckusick nhpibppwatch(unit)
31141480Smckusick 	register int unit;
31241480Smckusick {
31341480Smckusick 	register struct hpib_softc *hs = &hpib_softc[unit];
31441480Smckusick 
31541480Smckusick 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
31641480Smckusick 		return;
31745511Smckusick 	if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
31841480Smckusick        		((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
31941480Smckusick 	else
32041480Smckusick 		timeout(nhpibppwatch, unit, 1);
32141480Smckusick }
32241480Smckusick #endif
323