xref: /netbsd-src/sys/arch/hp300/dev/nhpib.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
1 /*
2  * Copyright (c) 1982, 1990 The Regents of the University of California.
3  * 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	7.4 (Berkeley) 5/7/91
34  *	$Id: nhpib.c,v 1.2 1993/05/22 07:56:39 cgd 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 "device.h"
48 #include "nhpibreg.h"
49 #include "hpibvar.h"
50 #include "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 {
75 	register struct hpib_softc *hs = &hpib_softc[unit];
76 	register struct nhpibdevice *hd;
77 
78 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
79 	hd->hpib_acr = AUX_SSWRST;
80 	hd->hpib_ar = hs->sc_ba;
81 	hd->hpib_lim = LIS_ERR;
82 	hd->hpib_mim = 0;
83 	hd->hpib_acr = AUX_CDAI;
84 	hd->hpib_acr = AUX_CSHDW;
85 	hd->hpib_acr = AUX_SSTD1;
86 	hd->hpib_acr = AUX_SVSTD1;
87 	hd->hpib_acr = AUX_CPP;
88 	hd->hpib_acr = AUX_CHDFA;
89 	hd->hpib_acr = AUX_CHDFE;
90 	hd->hpib_acr = AUX_RHDF;
91 	hd->hpib_acr = AUX_CSWRST;
92 	nhpibifc(hd);
93 	hd->hpib_ie = IDS_IE;
94 	hd->hpib_data = C_DCL;
95 	DELAY(100000);
96 }
97 
98 nhpibifc(hd)
99 	register struct nhpibdevice *hd;
100 {
101 	hd->hpib_acr = AUX_TCA;
102 	hd->hpib_acr = AUX_CSRE;
103 	hd->hpib_acr = AUX_SSIC;
104 	DELAY(100);
105 	hd->hpib_acr = AUX_CSIC;
106 	hd->hpib_acr = AUX_SSRE;
107 }
108 
109 nhpibsend(unit, slave, sec, addr, origcnt)
110 	register char *addr;
111 {
112 	register struct hpib_softc *hs = &hpib_softc[unit];
113 	register struct nhpibdevice *hd;
114 	register int cnt = origcnt;
115 
116 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
117 	hd->hpib_acr = AUX_TCA;
118 	hd->hpib_data = C_UNL;
119 	if (nhpibwait(hd, MIS_BO))
120 		goto senderror;
121 	hd->hpib_data = C_TAG + hs->sc_ba;
122 	hd->hpib_acr = AUX_STON;
123 	if (nhpibwait(hd, MIS_BO))
124 		goto senderror;
125 	hd->hpib_data = C_LAG + slave;
126 	if (nhpibwait(hd, MIS_BO))
127 		goto senderror;
128 	if (sec != -1) {
129 		hd->hpib_data = C_SCG + sec;
130 		if (nhpibwait(hd, MIS_BO))
131 			goto senderror;
132 	}
133 	hd->hpib_acr = AUX_GTS;
134 	if (cnt) {
135 		while (--cnt > 0) {
136 			hd->hpib_data = *addr++;
137 			if (nhpibwait(hd, MIS_BO))
138 				goto senderror;
139 		}
140 		hd->hpib_acr = AUX_EOI;
141 		hd->hpib_data = *addr;
142 		if (nhpibwait(hd, MIS_BO))
143 			goto senderror;
144 		hd->hpib_acr = AUX_TCA;
145 #if 0
146 		/*
147 		 * May be causing 345 disks to hang due to interference
148 		 * with PPOLL mechanism.
149 		 */
150 		hd->hpib_data = C_UNL;
151 		(void) nhpibwait(hd, MIS_BO);
152 #endif
153 	}
154 	return(origcnt);
155 senderror:
156 	nhpibifc(hd);
157 	return(origcnt - cnt - 1);
158 }
159 
160 nhpibrecv(unit, slave, sec, addr, origcnt)
161 	register char *addr;
162 {
163 	register struct hpib_softc *hs = &hpib_softc[unit];
164 	register struct nhpibdevice *hd;
165 	register int cnt = origcnt;
166 
167 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
168 	hd->hpib_acr = AUX_TCA;
169 	hd->hpib_data = C_UNL;
170 	if (nhpibwait(hd, MIS_BO))
171 		goto recverror;
172 	hd->hpib_data = C_LAG + hs->sc_ba;
173 	hd->hpib_acr = AUX_SLON;
174 	if (nhpibwait(hd, MIS_BO))
175 		goto recverror;
176 	hd->hpib_data = C_TAG + slave;
177 	if (nhpibwait(hd, MIS_BO))
178 		goto recverror;
179 	if (sec != -1) {
180 		hd->hpib_data = C_SCG + sec;
181 		if (nhpibwait(hd, MIS_BO))
182 			goto recverror;
183 	}
184 	hd->hpib_acr = AUX_RHDF;
185 	hd->hpib_acr = AUX_GTS;
186 	if (cnt) {
187 		while (--cnt >= 0) {
188 			if (nhpibwait(hd, MIS_BI))
189 				goto recvbyteserror;
190 			*addr++ = hd->hpib_data;
191 		}
192 		hd->hpib_acr = AUX_TCA;
193 		hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
194 		(void) nhpibwait(hd, MIS_BO);
195 	}
196 	return(origcnt);
197 recverror:
198 	nhpibifc(hd);
199 recvbyteserror:
200 	return(origcnt - cnt - 1);
201 }
202 
203 nhpibgo(unit, slave, sec, addr, count, rw)
204 	register int unit, slave;
205 	char *addr;
206 {
207 	register struct hpib_softc *hs = &hpib_softc[unit];
208 	register struct nhpibdevice *hd;
209 
210 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
211 	hs->sc_flags |= HPIBF_IO;
212 	if (rw == B_READ)
213 		hs->sc_flags |= HPIBF_READ;
214 #ifdef DEBUG
215 	else if (hs->sc_flags & HPIBF_READ) {
216 		printf("nhpibgo: HPIBF_READ still set\n");
217 		hs->sc_flags &= ~HPIBF_READ;
218 	}
219 #endif
220 	hs->sc_count = count;
221 	hs->sc_addr = addr;
222 	if (hs->sc_flags & HPIBF_READ) {
223 		hs->sc_curcnt = count;
224 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ);
225 		nhpibrecv(unit, slave, sec, 0, 0);
226 		hd->hpib_mim = MIS_END;
227 	} else {
228 		hd->hpib_mim = 0;
229 		if (count < hpibdmathresh) {
230 			hs->sc_curcnt = count;
231 			nhpibsend(unit, slave, sec, addr, count);
232 			nhpibdone(unit);
233 			return;
234 		}
235 		hs->sc_curcnt = --count;
236 		dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE);
237 		nhpibsend(unit, slave, sec, 0, 0);
238 	}
239 	hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr);
240 }
241 
242 nhpibdone(unit)
243 	register int unit;
244 {
245 	register struct hpib_softc *hs = &hpib_softc[unit];
246 	register struct nhpibdevice *hd;
247 	register int cnt;
248 
249 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
250 	cnt = hs->sc_curcnt;
251 	hs->sc_addr += cnt;
252 	hs->sc_count -= cnt;
253 	hs->sc_flags |= HPIBF_DONE;
254 	hd->hpib_ie = IDS_IE;
255 	if ((hs->sc_flags & HPIBF_READ) == 0) {
256 		if (hs->sc_count == 1) {
257 			(void) nhpibwait(hd, MIS_BO);
258 			hd->hpib_acr = AUX_EOI;
259 			hd->hpib_data = *hs->sc_addr;
260 			hd->hpib_mim = MIS_BO;
261 		}
262 #ifdef DEBUG
263 		else if (hs->sc_count)
264 			panic("nhpibdone");
265 #endif
266 	}
267 }
268 
269 nhpibintr(unit)
270 	register int unit;
271 {
272 	register struct hpib_softc *hs = &hpib_softc[unit];
273 	register struct nhpibdevice *hd;
274 	register struct devqueue *dq;
275 	register int stat0;
276 	int stat1;
277 
278 #ifdef lint
279 	if (stat1 = unit) return(1);
280 #endif
281 	hd = (struct nhpibdevice *)hs->sc_hc->hp_addr;
282 	if ((hd->hpib_ids & IDS_IR) == 0)
283 		return(0);
284 	stat0 = hd->hpib_mis;
285 	stat1 = hd->hpib_lis;
286 	dq = hs->sc_sq.dq_forw;
287 	if (hs->sc_flags & HPIBF_IO) {
288 		hd->hpib_mim = 0;
289 		if ((hs->sc_flags & HPIBF_DONE) == 0)
290 			dmastop(hs->sc_dq.dq_ctlr);
291 		hd->hpib_acr = AUX_TCA;
292 		hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
293 		dmafree(&hs->sc_dq);
294 		(dq->dq_driver->d_intr)(dq->dq_unit);
295 	} else if (hs->sc_flags & HPIBF_PPOLL) {
296 		hd->hpib_mim = 0;
297 		stat0 = nhpibppoll(unit);
298 		if (stat0 & (0x80 >> dq->dq_slave)) {
299 			hs->sc_flags &= ~HPIBF_PPOLL;
300 			(dq->dq_driver->d_intr)(dq->dq_unit);
301 		}
302 #ifdef DEBUG
303 		else
304 			printf("hpib%d: PPOLL intr bad status %x\n",
305 			       unit, stat0);
306 #endif
307 	}
308 	return(1);
309 }
310 
311 nhpibppoll(unit)
312 	int unit;
313 {
314 	register struct nhpibdevice *hd;
315 	register int ppoll;
316 
317 	hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
318 	hd->hpib_acr = AUX_SPP;
319 	DELAY(25);
320 	ppoll = hd->hpib_cpt;
321 	hd->hpib_acr = AUX_CPP;
322 	return(ppoll);
323 }
324 
325 nhpibwait(hd, x)
326 	register struct nhpibdevice *hd;
327 {
328 	register int timo = hpibtimeout;
329 
330 	while ((hd->hpib_mis & x) == 0 && --timo)
331 		DELAY(1);
332 	if (timo == 0)
333 		return(-1);
334 	return(0);
335 }
336 
337 nhpibppwatch(unit)
338 	register int unit;
339 {
340 	register struct hpib_softc *hs = &hpib_softc[unit];
341 
342 	if ((hs->sc_flags & HPIBF_PPOLL) == 0)
343 		return;
344 	if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave))
345        		((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO;
346 	else
347 		timeout(nhpibppwatch, unit, 1);
348 }
349 #endif
350