xref: /original-bsd/sys/hp300/dev/nhpib.c (revision 333da485)
1 /*
2  * Copyright (c) 1982, 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)nhpib.c	8.2 (Berkeley) 01/12/94
8  */
9 
10 /*
11  * Internal/98624 HPIB driver
12  */
13 #include "hpib.h"
14 #if NHPIB > 0
15 
16 #include <sys/param.h>
17 #include <sys/systm.h>
18 #include <sys/buf.h>
19 
20 #include <hp/dev/device.h>
21 #include <hp300/dev/nhpibreg.h>
22 #include <hp300/dev/hpibvar.h>
23 #include <hp300/dev/dmavar.h>
24 
25 nhpibtype(hc)
26 	register struct hp_ctlr *hc;
27 {
28 	register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
29 	register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
30 
31 	if (hc->hp_addr == internalhpib) {
32 		hs->sc_type = HPIBA;
33 		hs->sc_ba = HPIBA_BA;
34 		hc->hp_ipl = HPIBA_IPL;
35 	}
36 	else if (hd->hpib_cid == HPIBB) {
37 		hs->sc_type = HPIBB;
38 		hs->sc_ba = hd->hpib_csa & CSA_BA;
39 		hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
40 	}
41 	else
42 		return(0);
43 	return(1);
44 }
45 
46 nhpibreset(unit)
47 	int unit;
48 {
49 	register struct hpib_softc *hs = &hpib_softc[unit];
50 	register struct nhpibdevice *hd;
51 
52 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
53 	hd->hpib_acr = AUX_SSWRST;
54 	hd->hpib_ar = hs->sc_ba;
55 	hd->hpib_lim = LIS_ERR;
56 	hd->hpib_mim = 0;
57 	hd->hpib_acr = AUX_CDAI;
58 	hd->hpib_acr = AUX_CSHDW;
59 	hd->hpib_acr = AUX_SSTD1;
60 	hd->hpib_acr = AUX_SVSTD1;
61 	hd->hpib_acr = AUX_CPP;
62 	hd->hpib_acr = AUX_CHDFA;
63 	hd->hpib_acr = AUX_CHDFE;
64 	hd->hpib_acr = AUX_RHDF;
65 	hd->hpib_acr = AUX_CSWRST;
66 	nhpibifc(hd);
67 	hd->hpib_ie = IDS_IE;
68 	hd->hpib_data = C_DCL;
69 	DELAY(100000);
70 }
71 
72 nhpibifc(hd)
73 	register struct nhpibdevice *hd;
74 {
75 	hd->hpib_acr = AUX_TCA;
76 	hd->hpib_acr = AUX_CSRE;
77 	hd->hpib_acr = AUX_SSIC;
78 	DELAY(100);
79 	hd->hpib_acr = AUX_CSIC;
80 	hd->hpib_acr = AUX_SSRE;
81 }
82 
83 nhpibsend(unit, slave, sec, addr, origcnt)
84 	int unit, slave, sec, origcnt;
85 	register char *addr;
86 {
87 	register struct hpib_softc *hs = &hpib_softc[unit];
88 	register struct nhpibdevice *hd;
89 	register int cnt = origcnt;
90 
91 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
92 	hd->hpib_acr = AUX_TCA;
93 	hd->hpib_data = C_UNL;
94 	if (nhpibwait(hd, MIS_BO))
95 		goto senderror;
96 	hd->hpib_data = C_TAG + hs->sc_ba;
97 	hd->hpib_acr = AUX_STON;
98 	if (nhpibwait(hd, MIS_BO))
99 		goto senderror;
100 	hd->hpib_data = C_LAG + slave;
101 	if (nhpibwait(hd, MIS_BO))
102 		goto senderror;
103 	if (sec != -1) {
104 		hd->hpib_data = C_SCG + sec;
105 		if (nhpibwait(hd, MIS_BO))
106 			goto senderror;
107 	}
108 	hd->hpib_acr = AUX_GTS;
109 	if (cnt) {
110 		while (--cnt > 0) {
111 			hd->hpib_data = *addr++;
112 			if (nhpibwait(hd, MIS_BO))
113 				goto senderror;
114 		}
115 		hd->hpib_acr = AUX_EOI;
116 		hd->hpib_data = *addr;
117 		if (nhpibwait(hd, MIS_BO))
118 			goto senderror;
119 		hd->hpib_acr = AUX_TCA;
120 #if 0
121 		/*
122 		 * May be causing 345 disks to hang due to interference
123 		 * with PPOLL mechanism.
124 		 */
125 		hd->hpib_data = C_UNL;
126 		(void) nhpibwait(hd, MIS_BO);
127 #endif
128 	}
129 	return(origcnt);
130 senderror:
131 	nhpibifc(hd);
132 	return(origcnt - cnt - 1);
133 }
134 
135 nhpibrecv(unit, slave, sec, addr, origcnt)
136 	int unit, slave, sec, origcnt;
137 	register char *addr;
138 {
139 	register struct hpib_softc *hs = &hpib_softc[unit];
140 	register struct nhpibdevice *hd;
141 	register int cnt = origcnt;
142 
143 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
144 	hd->hpib_acr = AUX_TCA;
145 	hd->hpib_data = C_UNL;
146 	if (nhpibwait(hd, MIS_BO))
147 		goto recverror;
148 	hd->hpib_data = C_LAG + hs->sc_ba;
149 	hd->hpib_acr = AUX_SLON;
150 	if (nhpibwait(hd, MIS_BO))
151 		goto recverror;
152 	hd->hpib_data = C_TAG + slave;
153 	if (nhpibwait(hd, MIS_BO))
154 		goto recverror;
155 	if (sec != -1) {
156 		hd->hpib_data = C_SCG + sec;
157 		if (nhpibwait(hd, MIS_BO))
158 			goto recverror;
159 	}
160 	hd->hpib_acr = AUX_RHDF;
161 	hd->hpib_acr = AUX_GTS;
162 	if (cnt) {
163 		while (--cnt >= 0) {
164 			if (nhpibwait(hd, MIS_BI))
165 				goto recvbyteserror;
166 			*addr++ = hd->hpib_data;
167 		}
168 		hd->hpib_acr = AUX_TCA;
169 		hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
170 		(void) nhpibwait(hd, MIS_BO);
171 	}
172 	return(origcnt);
173 recverror:
174 	nhpibifc(hd);
175 recvbyteserror:
176 	return(origcnt - cnt - 1);
177 }
178 
179 nhpibgo(unit, slave, sec, addr, count, rw)
180 	register int unit, slave;
181 	int sec, count, rw;
182 	char *addr;
183 {
184 	register struct hpib_softc *hs = &hpib_softc[unit];
185 	register struct nhpibdevice *hd;
186 
187 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
188 	hs->sc_flags |= HPIBF_IO;
189 	if (rw == B_READ)
190 		hs->sc_flags |= HPIBF_READ;
191 #ifdef DEBUG
192 	else if (hs->sc_flags & HPIBF_READ) {
193 		printf("nhpibgo: HPIBF_READ still set\n");
194 		hs->sc_flags &= ~HPIBF_READ;
195 	}
196 #endif
197 	hs->sc_count = count;
198 	hs->sc_addr = addr;
199 	if (hs->sc_flags & HPIBF_READ) {
200 		hs->sc_curcnt = count;
201 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
202 		nhpibrecv(unit, slave, sec, 0, 0);
203 		hd->hpib_mim = MIS_END;
204 	} else {
205 		hd->hpib_mim = 0;
206 		if (count < hpibdmathresh) {
207 			hs->sc_curcnt = count;
208 			nhpibsend(unit, slave, sec, addr, count);
209 			nhpibdone(unit);
210 			return;
211 		}
212 		hs->sc_curcnt = --count;
213 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
214 		nhpibsend(unit, slave, sec, 0, 0);
215 	}
216 	hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
217 }
218 
219 nhpibdone(unit)
220 	register int unit;
221 {
222 	register struct hpib_softc *hs = &hpib_softc[unit];
223 	register struct nhpibdevice *hd;
224 	register int cnt;
225 
226 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
227 	cnt = hs->sc_curcnt;
228 	hs->sc_addr += cnt;
229 	hs->sc_count -= cnt;
230 	hs->sc_flags |= HPIBF_DONE;
231 	hd->hpib_ie = IDS_IE;
232 	if ((hs->sc_flags & HPIBF_READ) == 0) {
233 		if (hs->sc_count == 1) {
234 			(void) nhpibwait(hd, MIS_BO);
235 			hd->hpib_acr = AUX_EOI;
236 			hd->hpib_data = *hs->sc_addr;
237 			hd->hpib_mim = MIS_BO;
238 		}
239 #ifdef DEBUG
240 		else if (hs->sc_count)
241 			panic("nhpibdone");
242 #endif
243 	}
244 }
245 
246 nhpibintr(unit)
247 	register int unit;
248 {
249 	register struct hpib_softc *hs = &hpib_softc[unit];
250 	register struct nhpibdevice *hd;
251 	register struct devqueue *dq;
252 	register int stat0;
253 	int stat1;
254 
255 #ifdef lint
256 	if (stat1 = unit) return(1);
257 #endif
258 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
259 	if ((hd->hpib_ids & IDS_IR) == 0)
260 		return(0);
261 	stat0 = hd->hpib_mis;
262 	stat1 = hd->hpib_lis;
263 	dq = hs->sc_sq.dq_forw;
264 	if (hs->sc_flags & HPIBF_IO) {
265 		hd->hpib_mim = 0;
266 		if ((hs->sc_flags & HPIBF_DONE) == 0)
267 			dmastop(hs->sc_dq.dq_ctlr);
268 		hd->hpib_acr = AUX_TCA;
269 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
270 		dmafree(&hs->sc_dq);
271 		(dq->dq_driver->d_intr)(dq->dq_unit);
272 	} else if (hs->sc_flags & HPIBF_PPOLL) {
273 		hd->hpib_mim = 0;
274 		stat0 = nhpibppoll(unit);
275 		if (stat0 & (0x80 >> dq->dq_slave)) {
276 			hs->sc_flags &= ~HPIBF_PPOLL;
277 			(dq->dq_driver->d_intr)(dq->dq_unit);
278 		}
279 #ifdef DEBUG
280 		else
281 			printf("hpib%d: PPOLL intr bad status %x\n",
282 			       unit, stat0);
283 #endif
284 	}
285 	return(1);
286 }
287 
288 nhpibppoll(unit)
289 	int unit;
290 {
291 	register struct nhpibdevice *hd;
292 	register int ppoll;
293 
294 	hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
295 	hd->hpib_acr = AUX_SPP;
296 	DELAY(25);
297 	ppoll = hd->hpib_cpt;
298 	hd->hpib_acr = AUX_CPP;
299 	return(ppoll);
300 }
301 
302 nhpibwait(hd, x)
303 	register struct nhpibdevice *hd;
304 	int x;
305 {
306 	register int timo = hpibtimeout;
307 
308 	while ((hd->hpib_mis & x) == 0 && --timo)
309 		DELAY(1);
310 	if (timo == 0)
311 		return(-1);
312 	return(0);
313 }
314 
315 void
316 nhpibppwatch(arg)
317 	void *arg;
318 {
319 	register struct hpib_softc *hs;
320 	register int unit;
321 	extern int cold;
322 
323 	unit = (int)arg;
324 	hs = &hpib_softc[unit];
325 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
326 		return;
327 again:
328 	if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
329        		((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
330 	else if (cold)
331 		/* timeouts not working yet */
332 		goto again;
333 	else
334 		timeout(nhpibppwatch, (void *)unit, 1);
335 }
336 #endif
337