xref: /netbsd-src/sys/arch/hp300/dev/hpib.c (revision d0fed6c87ddc40a8bffa6f99e7433ddfc864dd83)
1 /*	$NetBSD: hpib.c,v 1.15 1997/04/14 02:31:33 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 1996, 1997 Jason R. Thorpe.  All rights reserved.
5  * Copyright (c) 1982, 1990, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)hpib.c	8.2 (Berkeley) 1/12/94
37  */
38 
39 /*
40  * HP-IB bus driver
41  */
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/buf.h>
46 #include <sys/malloc.h>
47 #include <sys/device.h>
48 
49 #include <hp300/dev/dmavar.h>
50 
51 #include <hp300/dev/hpibvar.h>
52 
53 #include <machine/cpu.h>
54 
55 int	hpibbusmatch __P((struct device *, struct cfdata *, void *));
56 void	hpibbusattach __P((struct device *, struct device *, void *));
57 
58 struct cfattach hpibbus_ca = {
59 	sizeof(struct hpibbus_softc), hpibbusmatch, hpibbusattach
60 };
61 
62 struct cfdriver hpibbus_cd = {
63 	NULL, "hpibbus", DV_DULL
64 };
65 
66 void	hpibbus_attach_children __P((struct hpibbus_softc *));
67 int	hpibbussearch __P((struct device *, struct cfdata *, void *));
68 int	hpibbusprint __P((void *, const char *));
69 
70 int	hpibbus_alloc __P((struct hpibbus_softc *, int, int));
71 void	hpibbus_free __P((struct hpibbus_softc *, int, int));
72 
73 void	hpibstart __P((void *));
74 void	hpibdone __P((void *));
75 
76 int	hpibtimeout = 100000;	/* # of status tests before we give up */
77 int	hpibidtimeout = 10000;	/* # of status tests for hpibid() calls */
78 int	hpibdmathresh = 3;	/* byte count beyond which to attempt dma */
79 
80 /*
81  * HP-IB is essentially an IEEE 488 bus, with an HP command
82  * set (CS/80 on `newer' devices, Amigo on before-you-were-born
83  * devices) thrown on top.  Devices that respond to CS/80 (and
84  * probably Amigo, too) are tagged with a 16-bit ID.
85  *
86  * HP-IB has a 2-level addressing scheme; slave, the analog
87  * of a SCSI ID, and punit, the analog of a SCSI LUN.  Unforunately,
88  * IDs are on a per-slave basis; punits are often used for disk
89  * drives that have an accompanying tape drive on the second punit.
90  *
91  * In addition, not all HP-IB devices speak CS/80 or Amigo.
92  * Examples of such devices are HP-IB plotters, which simply
93  * take raw plotter commands over 488.  These devices do not
94  * have ID tags, and often the host cannot even tell if such
95  * a device is attached to the system!
96  *
97  * These two nasty bits mean that we have to treat HP-IB as
98  * an indirect bus.  However, since we are given some ID
99  * information, it is unreasonable to disallow cloning of
100  * CS/80 devices.
101  *
102  * To deal with all of this, we use the semi-twisted scheme
103  * in hpibbus_attach_children().  For each HP-IB slave, we loop
104  * through all of the possibly-configured children, allowing
105  * them to modify the punit parameter (but NOT the slave!).
106  *
107  * This is evil, but what can you do?
108  */
109 
110 int
111 hpibbusmatch(parent, match, aux)
112 	struct device *parent;
113 	struct cfdata *match;
114 	void *aux;
115 {
116 
117 	return (1);
118 }
119 
120 void
121 hpibbusattach(parent, self, aux)
122 	struct device *parent, *self;
123 	void *aux;
124 {
125 	struct hpibbus_softc *sc = (struct hpibbus_softc *)self;
126 	struct hpibdev_attach_args *ha = aux;
127 
128 	printf("\n");
129 
130 	/* Get the operations vector for the controller. */
131 	sc->sc_ops = ha->ha_ops;
132 	sc->sc_type = ha->ha_type;		/* XXX */
133 	sc->sc_ba = ha->ha_ba;
134 	*(ha->ha_softcpp) = sc;			/* XXX */
135 
136 	hpibreset(self->dv_unit);		/* XXX souldn't be here */
137 
138 	/*
139 	 * Initialize the DMA queue entry.
140 	 */
141 	sc->sc_dq = (struct dmaqueue *)malloc(sizeof(struct dmaqueue),
142 	    M_DEVBUF, M_NOWAIT);
143 	if (sc->sc_dq == NULL) {
144 		printf("%s: can't allocate DMA queue entry\n", self->dv_xname);
145 		return;
146 	}
147 	sc->sc_dq->dq_softc = sc;
148 	sc->sc_dq->dq_start = hpibstart;
149 	sc->sc_dq->dq_done = hpibdone;
150 
151 	/* Initialize the slave request queue. */
152 	TAILQ_INIT(&sc->sc_queue);
153 
154 	/* Attach any devices on the bus. */
155 	hpibbus_attach_children(sc);
156 }
157 
158 void
159 hpibbus_attach_children(sc)
160 	struct hpibbus_softc *sc;
161 {
162 	struct hpibbus_attach_args ha;
163 	int slave;
164 
165 	for (slave = 0; slave < 8; slave++) {
166 		/*
167 		 * Get the ID tag for the device, if any.
168 		 * Plotters won't identify themselves, and
169 		 * get the same value as non-existent devices.
170 		 */
171 		ha.ha_id = hpibid(sc->sc_dev.dv_unit, slave);
172 
173 		ha.ha_slave = slave;	/* not to be modified by children */
174 		ha.ha_punit = 0;	/* children modify this */
175 
176 		/*
177 		 * Search though all configured children for this bus.
178 		 */
179 		(void)config_search(hpibbussearch, &sc->sc_dev, &ha);
180 	}
181 }
182 
183 int
184 hpibbussearch(parent, cf, aux)
185 	struct device *parent;
186 	struct cfdata *cf;
187 	void *aux;
188 {
189 	struct hpibbus_softc *sc = (struct hpibbus_softc *)parent;
190 	struct hpibbus_attach_args *ha = aux;
191 
192 	/* Make sure this is in a consistent state. */
193 	ha->ha_punit = 0;
194 
195 	if ((*cf->cf_attach->ca_match)(parent, cf, ha) > 0) {
196 		/*
197 		 * The device probe has succeeded, and filled in
198 		 * the punit information.  Make sure the configuration
199 		 * allows for this slave/punit combination.
200 		 */
201 		if (cf->hpibbuscf_slave != HPIBBUS_SLAVE_UNK &&
202 		    cf->hpibbuscf_slave != ha->ha_slave)
203 			goto out;
204 		if (cf->hpibbuscf_punit != HPIBBUS_PUNIT_UNK &&
205 		    cf->hpibbuscf_punit != ha->ha_punit)
206 			goto out;
207 
208 		/*
209 		 * Allocate the device's address from the bus's
210 		 * resource map.
211 		 */
212 		if (hpibbus_alloc(sc, ha->ha_slave, ha->ha_punit))
213 			goto out;
214 
215 		/*
216 		 * This device is allowed; attach it.
217 		 */
218 		config_attach(parent, cf, ha, hpibbusprint);
219 	}
220  out:
221 	return (0);
222 }
223 
224 int
225 hpibbusprint(aux, pnp)
226 	void *aux;
227 	const char *pnp;
228 {
229 	struct hpibbus_attach_args *ha = aux;
230 
231 	printf(" slave %d punit %d", ha->ha_slave, ha->ha_punit);
232 	return (UNCONF);
233 }
234 
235 int
236 hpibdevprint(aux, pnp)
237 	void *aux;
238 	const char *pnp;
239 {
240 
241 	/* only hpibbus's can attach to hpibdev's -- easy. */
242 	if (pnp != NULL)
243 		printf("hpibbus at %s", pnp);
244 	return (UNCONF);
245 }
246 
247 void
248 hpibreset(unit)
249 	int unit;
250 {
251 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
252 
253 	(*sc->sc_ops->hpib_reset)(sc);
254 }
255 
256 int
257 hpibreq(pdev, hq)
258 	struct device *pdev;
259 	struct hpibqueue *hq;
260 {
261 	struct hpibbus_softc *sc = (struct hpibbus_softc *)pdev;
262 	int s;
263 
264 	s = splhigh();	/* XXXthorpej */
265 	TAILQ_INSERT_TAIL(&sc->sc_queue, hq, hq_list);
266 	splx(s);
267 
268 	if (sc->sc_queue.tqh_first == hq)
269 		return (1);
270 
271 	return (0);
272 }
273 
274 void
275 hpibfree(pdev, hq)
276 	struct device *pdev;
277 	struct hpibqueue *hq;
278 {
279 	struct hpibbus_softc *sc = (struct hpibbus_softc *)pdev;
280 	int s;
281 
282 	s = splhigh();	/* XXXthorpej */
283 	TAILQ_REMOVE(&sc->sc_queue, hq, hq_list);
284 	splx(s);
285 
286 	if ((hq = sc->sc_queue.tqh_first) != NULL)
287 		(*hq->hq_start)(hq->hq_softc);
288 }
289 
290 int
291 hpibid(unit, slave)
292 	int unit, slave;
293 {
294 	short id;
295 	int ohpibtimeout;
296 
297 	/*
298 	 * XXX shorten timeout value so autoconfig doesn't
299 	 * take forever on slow CPUs.
300 	 */
301 	ohpibtimeout = hpibtimeout;
302 	hpibtimeout = hpibidtimeout * (cpuspeed / 8);
303 	if (hpibrecv(unit, 31, slave, &id, 2) != 2)
304 		id = 0;
305 	hpibtimeout = ohpibtimeout;
306 	return(id);
307 }
308 
309 int
310 hpibsend(unit, slave, sec, addr, cnt)
311 	int unit, slave, sec, cnt;
312 	void *addr;
313 {
314 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
315 
316 	return ((*sc->sc_ops->hpib_send)(sc, slave, sec, addr, cnt));
317 }
318 
319 int
320 hpibrecv(unit, slave, sec, addr, cnt)
321 	int unit, slave, sec, cnt;
322 	void *addr;
323 {
324 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
325 
326 	return ((*sc->sc_ops->hpib_recv)(sc, slave, sec, addr, cnt));
327 }
328 
329 int
330 hpibpptest(unit, slave)
331 	int unit;
332 	int slave;
333 {
334 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
335 
336 	return ((*sc->sc_ops->hpib_ppoll)(sc) & (0x80 >> slave));
337 }
338 
339 void
340 hpibppclear(unit)
341 	int unit;
342 {
343 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
344 
345 	sc->sc_flags &= ~HPIBF_PPOLL;
346 }
347 
348 void
349 hpibawait(unit)
350 	int unit;
351 {
352 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
353 
354 	sc->sc_flags |= HPIBF_PPOLL;
355 	(*sc->sc_ops->hpib_ppwatch)(sc);
356 }
357 
358 int
359 hpibswait(unit, slave)
360 	int unit;
361 	int slave;
362 {
363 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
364 	int timo = hpibtimeout;
365 	int mask, (*ppoll) __P((struct hpibbus_softc *));
366 
367 	ppoll = sc->sc_ops->hpib_ppoll;
368 	mask = 0x80 >> slave;
369 	while (((*ppoll)(sc) & mask) == 0) {
370 		if (--timo == 0) {
371 			printf("%s: swait timeout\n", sc->sc_dev.dv_xname);
372 			return(-1);
373 		}
374 	}
375 	return(0);
376 }
377 
378 int
379 hpibustart(unit)
380 	int unit;
381 {
382 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
383 
384 	if (sc->sc_type == HPIBA)
385 		sc->sc_dq->dq_chan = DMA0;
386 	else
387 		sc->sc_dq->dq_chan = DMA0 | DMA1;
388 	if (dmareq(sc->sc_dq))
389 		return(1);
390 	return(0);
391 }
392 
393 void
394 hpibstart(arg)
395 	void *arg;
396 {
397 	struct hpibbus_softc *sc = arg;
398 	struct hpibqueue *hq;
399 
400 	hq = sc->sc_queue.tqh_first;
401 	(*hq->hq_go)(hq->hq_softc);
402 }
403 
404 void
405 hpibgo(unit, slave, sec, vbuf, count, rw, timo)
406 	int unit, slave, sec;
407 	void *vbuf;
408 	int count, rw, timo;
409 {
410 	struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit];
411 
412 	(*sc->sc_ops->hpib_go)(sc, slave, sec, vbuf, count, rw, timo);
413 }
414 
415 void
416 hpibdone(arg)
417 	void *arg;
418 {
419 	struct hpibbus_softc *sc = arg;
420 
421 	(*sc->sc_ops->hpib_done)(sc);
422 }
423 
424 int
425 hpibintr(arg)
426 	void *arg;
427 {
428 	struct hpibbus_softc *sc = arg;
429 
430 	return ((sc->sc_ops->hpib_intr)(arg));
431 }
432 
433 int
434 hpibbus_alloc(sc, slave, punit)
435 	struct hpibbus_softc *sc;
436 	int slave, punit;
437 {
438 
439 	if (slave >= HPIB_NSLAVES ||
440 	    punit >= HPIB_NPUNITS)
441 		panic("hpibbus_alloc: device address out of range");
442 
443 	if (sc->sc_rmap[slave][punit] == 0) {
444 		sc->sc_rmap[slave][punit] = 1;
445 		return (0);
446 	}
447 	return (1);
448 }
449 
450 void
451 hpibbus_free(sc, slave, punit)
452 	struct hpibbus_softc *sc;
453 	int slave, punit;
454 {
455 
456 	if (slave >= HPIB_NSLAVES ||
457 	    punit >= HPIB_NPUNITS)
458 		panic("hpibbus_free: device address out of range");
459 
460 #ifdef DIAGNOSTIC
461 	if (sc->sc_rmap[slave][punit] == 0)
462 		panic("hpibbus_free: not allocated");
463 #endif
464 
465 	sc->sc_rmap[slave][punit] = 0;
466 }
467