xref: /netbsd-src/sys/arch/hp300/dev/nhpib.c (revision ae1bfcddc410612bc8c58b807e1830becb69a24c)
1 /*
2  * Copyright (c) 1982, 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	from: @(#)nhpib.c	8.2 (Berkeley) 1/12/94
34  *	$Id: nhpib.c,v 1.4 1994/05/23 05:59:10 mycroft Exp $
35  */
36 
37 /*
38  * Internal/98624 HPIB driver
39  */
40 #include "hpib.h"
41 #if NHPIB > 0
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/buf.h>
46 
47 #include <hp300/dev/device.h>
48 #include <hp300/dev/nhpibreg.h>
49 #include <hp300/dev/hpibvar.h>
50 #include <hp300/dev/dmavar.h>
51 
52 nhpibtype(hc)
53 	register struct hp_ctlr *hc;
54 {
55 	register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
56 	register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr;
57 
58 	if (hc->hp_addr == internalhpib) {
59 		hs->sc_type = HPIBA;
60 		hs->sc_ba = HPIBA_BA;
61 		hc->hp_ipl = HPIBA_IPL;
62 	}
63 	else if (hd->hpib_cid == HPIBB) {
64 		hs->sc_type = HPIBB;
65 		hs->sc_ba = hd->hpib_csa & CSA_BA;
66 		hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
67 	}
68 	else
69 		return(0);
70 	return(1);
71 }
72 
73 nhpibreset(unit)
74 	int unit;
75 {
76 	register struct hpib_softc *hs = &hpib_softc[unit];
77 	register struct nhpibdevice *hd;
78 
79 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
80 	hd->hpib_acr = AUX_SSWRST;
81 	hd->hpib_ar = hs->sc_ba;
82 	hd->hpib_lim = LIS_ERR;
83 	hd->hpib_mim = 0;
84 	hd->hpib_acr = AUX_CDAI;
85 	hd->hpib_acr = AUX_CSHDW;
86 	hd->hpib_acr = AUX_SSTD1;
87 	hd->hpib_acr = AUX_SVSTD1;
88 	hd->hpib_acr = AUX_CPP;
89 	hd->hpib_acr = AUX_CHDFA;
90 	hd->hpib_acr = AUX_CHDFE;
91 	hd->hpib_acr = AUX_RHDF;
92 	hd->hpib_acr = AUX_CSWRST;
93 	nhpibifc(hd);
94 	hd->hpib_ie = IDS_IE;
95 	hd->hpib_data = C_DCL;
96 	DELAY(100000);
97 }
98 
99 nhpibifc(hd)
100 	register struct nhpibdevice *hd;
101 {
102 	hd->hpib_acr = AUX_TCA;
103 	hd->hpib_acr = AUX_CSRE;
104 	hd->hpib_acr = AUX_SSIC;
105 	DELAY(100);
106 	hd->hpib_acr = AUX_CSIC;
107 	hd->hpib_acr = AUX_SSRE;
108 }
109 
110 nhpibsend(unit, slave, sec, addr, origcnt)
111 	int unit, slave, sec, origcnt;
112 	register char *addr;
113 {
114 	register struct hpib_softc *hs = &hpib_softc[unit];
115 	register struct nhpibdevice *hd;
116 	register int cnt = origcnt;
117 
118 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
119 	hd->hpib_acr = AUX_TCA;
120 	hd->hpib_data = C_UNL;
121 	if (nhpibwait(hd, MIS_BO))
122 		goto senderror;
123 	hd->hpib_data = C_TAG + hs->sc_ba;
124 	hd->hpib_acr = AUX_STON;
125 	if (nhpibwait(hd, MIS_BO))
126 		goto senderror;
127 	hd->hpib_data = C_LAG + slave;
128 	if (nhpibwait(hd, MIS_BO))
129 		goto senderror;
130 	if (sec != -1) {
131 		hd->hpib_data = C_SCG + sec;
132 		if (nhpibwait(hd, MIS_BO))
133 			goto senderror;
134 	}
135 	hd->hpib_acr = AUX_GTS;
136 	if (cnt) {
137 		while (--cnt > 0) {
138 			hd->hpib_data = *addr++;
139 			if (nhpibwait(hd, MIS_BO))
140 				goto senderror;
141 		}
142 		hd->hpib_acr = AUX_EOI;
143 		hd->hpib_data = *addr;
144 		if (nhpibwait(hd, MIS_BO))
145 			goto senderror;
146 		hd->hpib_acr = AUX_TCA;
147 #if 0
148 		/*
149 		 * May be causing 345 disks to hang due to interference
150 		 * with PPOLL mechanism.
151 		 */
152 		hd->hpib_data = C_UNL;
153 		(void) nhpibwait(hd, MIS_BO);
154 #endif
155 	}
156 	return(origcnt);
157 senderror:
158 	nhpibifc(hd);
159 	return(origcnt - cnt - 1);
160 }
161 
162 nhpibrecv(unit, slave, sec, addr, origcnt)
163 	int unit, slave, sec, origcnt;
164 	register char *addr;
165 {
166 	register struct hpib_softc *hs = &hpib_softc[unit];
167 	register struct nhpibdevice *hd;
168 	register int cnt = origcnt;
169 
170 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
171 	hd->hpib_acr = AUX_TCA;
172 	hd->hpib_data = C_UNL;
173 	if (nhpibwait(hd, MIS_BO))
174 		goto recverror;
175 	hd->hpib_data = C_LAG + hs->sc_ba;
176 	hd->hpib_acr = AUX_SLON;
177 	if (nhpibwait(hd, MIS_BO))
178 		goto recverror;
179 	hd->hpib_data = C_TAG + slave;
180 	if (nhpibwait(hd, MIS_BO))
181 		goto recverror;
182 	if (sec != -1) {
183 		hd->hpib_data = C_SCG + sec;
184 		if (nhpibwait(hd, MIS_BO))
185 			goto recverror;
186 	}
187 	hd->hpib_acr = AUX_RHDF;
188 	hd->hpib_acr = AUX_GTS;
189 	if (cnt) {
190 		while (--cnt >= 0) {
191 			if (nhpibwait(hd, MIS_BI))
192 				goto recvbyteserror;
193 			*addr++ = hd->hpib_data;
194 		}
195 		hd->hpib_acr = AUX_TCA;
196 		hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
197 		(void) nhpibwait(hd, MIS_BO);
198 	}
199 	return(origcnt);
200 recverror:
201 	nhpibifc(hd);
202 recvbyteserror:
203 	return(origcnt - cnt - 1);
204 }
205 
206 nhpibgo(unit, slave, sec, addr, count, rw)
207 	register int unit, slave;
208 	int sec, count, rw;
209 	char *addr;
210 {
211 	register struct hpib_softc *hs = &hpib_softc[unit];
212 	register struct nhpibdevice *hd;
213 
214 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
215 	hs->sc_flags |= HPIBF_IO;
216 	if (rw == B_READ)
217 		hs->sc_flags |= HPIBF_READ;
218 #ifdef DEBUG
219 	else if (hs->sc_flags & HPIBF_READ) {
220 		printf("nhpibgo: HPIBF_READ still set\n");
221 		hs->sc_flags &= ~HPIBF_READ;
222 	}
223 #endif
224 	hs->sc_count = count;
225 	hs->sc_addr = addr;
226 	if (hs->sc_flags & HPIBF_READ) {
227 		hs->sc_curcnt = count;
228 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
229 		nhpibrecv(unit, slave, sec, 0, 0);
230 		hd->hpib_mim = MIS_END;
231 	} else {
232 		hd->hpib_mim = 0;
233 		if (count < hpibdmathresh) {
234 			hs->sc_curcnt = count;
235 			nhpibsend(unit, slave, sec, addr, count);
236 			nhpibdone(unit);
237 			return;
238 		}
239 		hs->sc_curcnt = --count;
240 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
241 		nhpibsend(unit, slave, sec, 0, 0);
242 	}
243 	hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
244 }
245 
246 nhpibdone(unit)
247 	register int unit;
248 {
249 	register struct hpib_softc *hs = &hpib_softc[unit];
250 	register struct nhpibdevice *hd;
251 	register int cnt;
252 
253 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
254 	cnt = hs->sc_curcnt;
255 	hs->sc_addr += cnt;
256 	hs->sc_count -= cnt;
257 	hs->sc_flags |= HPIBF_DONE;
258 	hd->hpib_ie = IDS_IE;
259 	if ((hs->sc_flags & HPIBF_READ) == 0) {
260 		if (hs->sc_count == 1) {
261 			(void) nhpibwait(hd, MIS_BO);
262 			hd->hpib_acr = AUX_EOI;
263 			hd->hpib_data = *hs->sc_addr;
264 			hd->hpib_mim = MIS_BO;
265 		}
266 #ifdef DEBUG
267 		else if (hs->sc_count)
268 			panic("nhpibdone");
269 #endif
270 	}
271 }
272 
273 nhpibintr(unit)
274 	register int unit;
275 {
276 	register struct hpib_softc *hs = &hpib_softc[unit];
277 	register struct nhpibdevice *hd;
278 	register struct devqueue *dq;
279 	register int stat0;
280 	int stat1;
281 
282 #ifdef lint
283 	if (stat1 = unit) return(1);
284 #endif
285 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
286 	if ((hd->hpib_ids & IDS_IR) == 0)
287 		return(0);
288 	stat0 = hd->hpib_mis;
289 	stat1 = hd->hpib_lis;
290 	dq = hs->sc_sq.dq_forw;
291 	if (hs->sc_flags & HPIBF_IO) {
292 		hd->hpib_mim = 0;
293 		if ((hs->sc_flags & HPIBF_DONE) == 0)
294 			dmastop(hs->sc_dq.dq_ctlr);
295 		hd->hpib_acr = AUX_TCA;
296 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
297 		dmafree(&hs->sc_dq);
298 		(dq->dq_driver->d_intr)(dq->dq_unit);
299 	} else if (hs->sc_flags & HPIBF_PPOLL) {
300 		hd->hpib_mim = 0;
301 		stat0 = nhpibppoll(unit);
302 		if (stat0 & (0x80 >> dq->dq_slave)) {
303 			hs->sc_flags &= ~HPIBF_PPOLL;
304 			(dq->dq_driver->d_intr)(dq->dq_unit);
305 		}
306 #ifdef DEBUG
307 		else
308 			printf("hpib%d: PPOLL intr bad status %x\n",
309 			       unit, stat0);
310 #endif
311 	}
312 	return(1);
313 }
314 
315 nhpibppoll(unit)
316 	int unit;
317 {
318 	register struct nhpibdevice *hd;
319 	register int ppoll;
320 
321 	hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
322 	hd->hpib_acr = AUX_SPP;
323 	DELAY(25);
324 	ppoll = hd->hpib_cpt;
325 	hd->hpib_acr = AUX_CPP;
326 	return(ppoll);
327 }
328 
329 nhpibwait(hd, x)
330 	register struct nhpibdevice *hd;
331 	int x;
332 {
333 	register int timo = hpibtimeout;
334 
335 	while ((hd->hpib_mis & x) == 0 && --timo)
336 		DELAY(1);
337 	if (timo == 0)
338 		return(-1);
339 	return(0);
340 }
341 
342 void
343 nhpibppwatch(arg)
344 	void *arg;
345 {
346 	register struct hpib_softc *hs;
347 	register int unit;
348 	extern int cold;
349 
350 	unit = (int)arg;
351 	hs = &hpib_softc[unit];
352 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
353 		return;
354 again:
355 	if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
356        		((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
357 	else if (cold)
358 		/* timeouts not working yet */
359 		goto again;
360 	else
361 		timeout(nhpibppwatch, (void *)unit, 1);
362 }
363 #endif
364