xref: /netbsd-src/sys/dev/gpib/ppi.c (revision 6565c0bf2ba171913337f70f07b99fe057ec52e5)
1*6565c0bfSmsaitoh /*	$NetBSD: ppi.c,v 1.25 2019/11/12 13:17:44 msaitoh Exp $	*/
2cb93fa6aSgmcgarry 
3cb93fa6aSgmcgarry /*-
4cb93fa6aSgmcgarry  * Copyright (c) 1996-2003 The NetBSD Foundation, Inc.
5cb93fa6aSgmcgarry  * All rights reserved.
6cb93fa6aSgmcgarry  *
7cb93fa6aSgmcgarry  * This code is derived from software contributed to The NetBSD Foundation
8cb93fa6aSgmcgarry  * by Jason R. Thorpe.
9cb93fa6aSgmcgarry  *
10cb93fa6aSgmcgarry  * Redistribution and use in source and binary forms, with or without
11cb93fa6aSgmcgarry  * modification, are permitted provided that the following conditions
12cb93fa6aSgmcgarry  * are met:
13cb93fa6aSgmcgarry  * 1. Redistributions of source code must retain the above copyright
14cb93fa6aSgmcgarry  *    notice, this list of conditions and the following disclaimer.
15cb93fa6aSgmcgarry  * 2. Redistributions in binary form must reproduce the above copyright
16cb93fa6aSgmcgarry  *    notice, this list of conditions and the following disclaimer in the
17cb93fa6aSgmcgarry  *    documentation and/or other materials provided with the distribution.
18cb93fa6aSgmcgarry  *
19cb93fa6aSgmcgarry  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20cb93fa6aSgmcgarry  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21cb93fa6aSgmcgarry  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22cb93fa6aSgmcgarry  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23cb93fa6aSgmcgarry  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24cb93fa6aSgmcgarry  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25cb93fa6aSgmcgarry  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26cb93fa6aSgmcgarry  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27cb93fa6aSgmcgarry  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28cb93fa6aSgmcgarry  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29cb93fa6aSgmcgarry  * POSSIBILITY OF SUCH DAMAGE.
30cb93fa6aSgmcgarry  */
31cb93fa6aSgmcgarry 
32cb93fa6aSgmcgarry /*
33cb93fa6aSgmcgarry  * Copyright (c) 1982, 1990, 1993
34cb93fa6aSgmcgarry  *	The Regents of the University of California.  All rights reserved.
35cb93fa6aSgmcgarry  *
36cb93fa6aSgmcgarry  * Redistribution and use in source and binary forms, with or without
37cb93fa6aSgmcgarry  * modification, are permitted provided that the following conditions
38cb93fa6aSgmcgarry  * are met:
39cb93fa6aSgmcgarry  * 1. Redistributions of source code must retain the above copyright
40cb93fa6aSgmcgarry  *    notice, this list of conditions and the following disclaimer.
41cb93fa6aSgmcgarry  * 2. Redistributions in binary form must reproduce the above copyright
42cb93fa6aSgmcgarry  *    notice, this list of conditions and the following disclaimer in the
43cb93fa6aSgmcgarry  *    documentation and/or other materials provided with the distribution.
44aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
45cb93fa6aSgmcgarry  *    may be used to endorse or promote products derived from this software
46cb93fa6aSgmcgarry  *    without specific prior written permission.
47cb93fa6aSgmcgarry  *
48cb93fa6aSgmcgarry  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49cb93fa6aSgmcgarry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50cb93fa6aSgmcgarry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51cb93fa6aSgmcgarry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52cb93fa6aSgmcgarry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53cb93fa6aSgmcgarry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54cb93fa6aSgmcgarry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55cb93fa6aSgmcgarry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56cb93fa6aSgmcgarry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57cb93fa6aSgmcgarry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58cb93fa6aSgmcgarry  * SUCH DAMAGE.
59cb93fa6aSgmcgarry  *
60cb93fa6aSgmcgarry  *	@(#)ppi.c	8.1 (Berkeley) 6/16/93
61cb93fa6aSgmcgarry  */
62cb93fa6aSgmcgarry 
63cb93fa6aSgmcgarry /*
64cb93fa6aSgmcgarry  * Printer/Plotter GPIB interface
65cb93fa6aSgmcgarry  */
66cb93fa6aSgmcgarry 
67cb93fa6aSgmcgarry #include <sys/cdefs.h>
68*6565c0bfSmsaitoh __KERNEL_RCSID(0, "$NetBSD: ppi.c,v 1.25 2019/11/12 13:17:44 msaitoh Exp $");
69cb93fa6aSgmcgarry 
70cb93fa6aSgmcgarry #include <sys/param.h>
71cb93fa6aSgmcgarry #include <sys/systm.h>
72cb93fa6aSgmcgarry #include <sys/callout.h>
73cb93fa6aSgmcgarry #include <sys/conf.h>
74cb93fa6aSgmcgarry #include <sys/device.h>
75cb93fa6aSgmcgarry #include <sys/malloc.h>
76cb93fa6aSgmcgarry #include <sys/proc.h>
77cb93fa6aSgmcgarry #include <sys/uio.h>
78cb93fa6aSgmcgarry 
79cb93fa6aSgmcgarry #include <dev/gpib/gpibvar.h>
80cb93fa6aSgmcgarry 
81cb93fa6aSgmcgarry #include <dev/gpib/ppiio.h>
82cb93fa6aSgmcgarry 
8382b8cabaSriastradh #include "ioconf.h"
8482b8cabaSriastradh 
85cb93fa6aSgmcgarry struct	ppi_softc {
86cbab9cadSchs 	device_t sc_dev;
87cb93fa6aSgmcgarry 	gpib_chipset_tag_t sc_ic;
88cb93fa6aSgmcgarry 	gpib_handle_t sc_hdl;
89cb93fa6aSgmcgarry 
90cb93fa6aSgmcgarry 	int sc_address;			/* GPIB address */
91cb93fa6aSgmcgarry 	int	sc_flags;
92cb93fa6aSgmcgarry 	int	sc_sec;
93cb93fa6aSgmcgarry 	struct	ppiparam sc_param;
94cb93fa6aSgmcgarry #define sc_burst sc_param.burst
95cb93fa6aSgmcgarry #define sc_timo  sc_param.timo
96cb93fa6aSgmcgarry #define sc_delay sc_param.delay
97cb93fa6aSgmcgarry 	struct	callout sc_timo_ch;
98cb93fa6aSgmcgarry 	struct	callout sc_start_ch;
99cb93fa6aSgmcgarry };
100cb93fa6aSgmcgarry 
101cb93fa6aSgmcgarry /* sc_flags values */
102cb93fa6aSgmcgarry #define	PPIF_ALIVE	0x01
103cb93fa6aSgmcgarry #define	PPIF_OPEN	0x02
104cb93fa6aSgmcgarry #define PPIF_UIO	0x04
105cb93fa6aSgmcgarry #define PPIF_TIMO	0x08
106cb93fa6aSgmcgarry #define PPIF_DELAY	0x10
107cb93fa6aSgmcgarry 
108529e91fcScegger int	ppimatch(device_t, cfdata_t, void *);
109529e91fcScegger void	ppiattach(device_t, device_t, void *);
110cb93fa6aSgmcgarry 
111cbab9cadSchs CFATTACH_DECL_NEW(ppi, sizeof(struct ppi_softc),
112cb93fa6aSgmcgarry 	ppimatch, ppiattach, NULL, NULL);
113cb93fa6aSgmcgarry 
114cb93fa6aSgmcgarry void	ppicallback(void *, int);
115cb93fa6aSgmcgarry void	ppistart(void *);
116cb93fa6aSgmcgarry 
117cb93fa6aSgmcgarry void	ppitimo(void *);
118cb93fa6aSgmcgarry int	ppirw(dev_t, struct uio *);
119cb93fa6aSgmcgarry int	ppihztoms(int);
120cb93fa6aSgmcgarry int	ppimstohz(int);
121cb93fa6aSgmcgarry 
122cb93fa6aSgmcgarry dev_type_open(ppiopen);
123cb93fa6aSgmcgarry dev_type_close(ppiclose);
124cb93fa6aSgmcgarry dev_type_read(ppiread);
125cb93fa6aSgmcgarry dev_type_write(ppiwrite);
126cb93fa6aSgmcgarry dev_type_ioctl(ppiioctl);
127cb93fa6aSgmcgarry 
128cb93fa6aSgmcgarry const struct cdevsw ppi_cdevsw = {
129a68f9396Sdholland         .d_open = ppiopen,
130a68f9396Sdholland 	.d_close = ppiclose,
131a68f9396Sdholland 	.d_read = ppiread,
132a68f9396Sdholland 	.d_write = ppiwrite,
133a68f9396Sdholland 	.d_ioctl = ppiioctl,
134a68f9396Sdholland         .d_stop = nostop,
135a68f9396Sdholland 	.d_tty = notty,
136a68f9396Sdholland 	.d_poll = nopoll,
137a68f9396Sdholland 	.d_mmap = nommap,
138a68f9396Sdholland 	.d_kqfilter = nokqfilter,
139f9228f42Sdholland 	.d_discard = nodiscard,
140a68f9396Sdholland 	.d_flag = D_OTHER
141cb93fa6aSgmcgarry };
142cb93fa6aSgmcgarry 
143cb93fa6aSgmcgarry #define UNIT(x)		minor(x)
144cb93fa6aSgmcgarry 
145cb93fa6aSgmcgarry #ifdef DEBUG
146cb93fa6aSgmcgarry int	ppidebug = 0x80;
147cb93fa6aSgmcgarry #define PDB_FOLLOW	0x01
148cb93fa6aSgmcgarry #define PDB_IO		0x02
149cb93fa6aSgmcgarry #define PDB_NOCHECK	0x80
150cb93fa6aSgmcgarry #define DPRINTF(mask, str)	if (ppidebug & (mask)) printf str
151cb93fa6aSgmcgarry #else
152cb93fa6aSgmcgarry #define DPRINTF(mask, str)	/* nothing */
153cb93fa6aSgmcgarry #endif
154cb93fa6aSgmcgarry 
155cb93fa6aSgmcgarry int
ppimatch(device_t parent,cfdata_t match,void * aux)156529e91fcScegger ppimatch(device_t parent, cfdata_t match, void *aux)
157cb93fa6aSgmcgarry {
158cb93fa6aSgmcgarry 
159cb93fa6aSgmcgarry 	return (1);
160cb93fa6aSgmcgarry }
161cb93fa6aSgmcgarry 
162cb93fa6aSgmcgarry void
ppiattach(device_t parent,device_t self,void * aux)163529e91fcScegger ppiattach(device_t parent, device_t self, void *aux)
164cb93fa6aSgmcgarry {
16592c7bba3Sthorpej 	struct ppi_softc *sc = device_private(self);
166cb93fa6aSgmcgarry 	struct gpib_attach_args *ga = aux;
167cb93fa6aSgmcgarry 
168cb93fa6aSgmcgarry 	printf("\n");
169cb93fa6aSgmcgarry 
170*6565c0bfSmsaitoh 	sc->sc_dev = self;
171cb93fa6aSgmcgarry 	sc->sc_ic = ga->ga_ic;
172cb93fa6aSgmcgarry 	sc->sc_address = ga->ga_address;
173cb93fa6aSgmcgarry 
17488ab7da9Sad 	callout_init(&sc->sc_timo_ch, 0);
17588ab7da9Sad 	callout_init(&sc->sc_start_ch, 0);
176cb93fa6aSgmcgarry 
177cb93fa6aSgmcgarry 	if (gpibregister(sc->sc_ic, sc->sc_address, ppicallback, sc,
178cb93fa6aSgmcgarry 	    &sc->sc_hdl)) {
179cbab9cadSchs 		aprint_error_dev(sc->sc_dev, "can't register callback\n");
180cb93fa6aSgmcgarry 		return;
181cb93fa6aSgmcgarry 	}
182cb93fa6aSgmcgarry 
183cb93fa6aSgmcgarry 	sc->sc_flags = PPIF_ALIVE;
184cb93fa6aSgmcgarry }
185cb93fa6aSgmcgarry 
186cb93fa6aSgmcgarry int
ppiopen(dev_t dev,int flags,int fmt,struct lwp * l)187b0e5b3dcScegger ppiopen(dev_t dev, int flags, int fmt, struct lwp *l)
188cb93fa6aSgmcgarry {
189cb93fa6aSgmcgarry 	struct ppi_softc *sc;
190cb93fa6aSgmcgarry 
191b0e5b3dcScegger 	sc = device_lookup_private(&ppi_cd, UNIT(dev));
192b0e5b3dcScegger 	if (sc == NULL)
193b0e5b3dcScegger 		return (ENXIO);
194b0e5b3dcScegger 
195055ae9c8Stsutsui 	if ((sc->sc_flags & PPIF_ALIVE) == 0)
196cb93fa6aSgmcgarry 		return (ENXIO);
197cb93fa6aSgmcgarry 
1980762f691Stsutsui 	DPRINTF(PDB_FOLLOW, ("ppiopen(%" PRIx64 ", %x): flags %x\n",
199cb93fa6aSgmcgarry 	    dev, flags, sc->sc_flags));
200cb93fa6aSgmcgarry 
201cb93fa6aSgmcgarry 	if (sc->sc_flags & PPIF_OPEN)
202cb93fa6aSgmcgarry 		return (EBUSY);
203cb93fa6aSgmcgarry 	sc->sc_flags |= PPIF_OPEN;
204cb93fa6aSgmcgarry 	sc->sc_burst = PPI_BURST;
205cb93fa6aSgmcgarry 	sc->sc_timo = ppimstohz(PPI_TIMO);
206cb93fa6aSgmcgarry 	sc->sc_delay = ppimstohz(PPI_DELAY);
207cb93fa6aSgmcgarry 	sc->sc_sec = -1;
208cb93fa6aSgmcgarry 	return (0);
209cb93fa6aSgmcgarry }
210cb93fa6aSgmcgarry 
211cb93fa6aSgmcgarry int
ppiclose(dev_t dev,int flags,int fmt,struct lwp * l)212b0e5b3dcScegger ppiclose(dev_t dev, int flags, int fmt, struct lwp *l)
213cb93fa6aSgmcgarry {
214b0e5b3dcScegger 	struct ppi_softc *sc;
215b0e5b3dcScegger 
216b0e5b3dcScegger 	sc = device_lookup_private(&ppi_cd, UNIT(dev));
217cb93fa6aSgmcgarry 
2180762f691Stsutsui 	DPRINTF(PDB_FOLLOW, ("ppiclose(%" PRIx64 ", %x): flags %x\n",
219cb93fa6aSgmcgarry 		       dev, flags, sc->sc_flags));
220cb93fa6aSgmcgarry 
221cb93fa6aSgmcgarry 	sc->sc_flags &= ~PPIF_OPEN;
222cb93fa6aSgmcgarry 	return (0);
223cb93fa6aSgmcgarry }
224cb93fa6aSgmcgarry 
225cb93fa6aSgmcgarry void
ppicallback(void * v,int action)226454af1c0Sdsl ppicallback(void *v, int action)
227cb93fa6aSgmcgarry {
228cb93fa6aSgmcgarry 	struct ppi_softc *sc = v;
229cb93fa6aSgmcgarry 
230cb93fa6aSgmcgarry 	DPRINTF(PDB_FOLLOW, ("ppicallback: v=%p, action=%d\n", v, action));
231cb93fa6aSgmcgarry 
232cb93fa6aSgmcgarry 	switch (action) {
233cb93fa6aSgmcgarry 	case GPIBCBF_START:
234cb93fa6aSgmcgarry 		ppistart(sc);
235cb93fa6aSgmcgarry 	case GPIBCBF_INTR:
236cb93fa6aSgmcgarry 		/* no-op */
237cb93fa6aSgmcgarry 		break;
238cb93fa6aSgmcgarry #ifdef DEBUG
239cb93fa6aSgmcgarry 	default:
240cb93fa6aSgmcgarry 		DPRINTF(PDB_FOLLOW, ("ppicallback: unknown action %d\n",
241cb93fa6aSgmcgarry 		    action));
242cb93fa6aSgmcgarry 		break;
243cb93fa6aSgmcgarry #endif
244cb93fa6aSgmcgarry 	}
245cb93fa6aSgmcgarry }
246cb93fa6aSgmcgarry 
247cb93fa6aSgmcgarry void
ppistart(void * v)248b0e5b3dcScegger ppistart(void *v)
249cb93fa6aSgmcgarry {
250cb93fa6aSgmcgarry 	struct ppi_softc *sc = v;
251cb93fa6aSgmcgarry 
252cbab9cadSchs 	DPRINTF(PDB_FOLLOW, ("ppistart(%x)\n", device_unit(sc->sc_dev)));
253cb93fa6aSgmcgarry 
254cb93fa6aSgmcgarry 	sc->sc_flags &= ~PPIF_DELAY;
255cb93fa6aSgmcgarry 	wakeup(sc);
256cb93fa6aSgmcgarry }
257cb93fa6aSgmcgarry 
258cb93fa6aSgmcgarry void
ppitimo(void * arg)259b0e5b3dcScegger ppitimo(void *arg)
260cb93fa6aSgmcgarry {
261cb93fa6aSgmcgarry 	struct ppi_softc *sc = arg;
262cb93fa6aSgmcgarry 
263cbab9cadSchs 	DPRINTF(PDB_FOLLOW, ("ppitimo(%x)\n", device_unit(sc->sc_dev)));
264cb93fa6aSgmcgarry 
265cb93fa6aSgmcgarry 	sc->sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
266cb93fa6aSgmcgarry 	wakeup(sc);
267cb93fa6aSgmcgarry }
268cb93fa6aSgmcgarry 
269cb93fa6aSgmcgarry int
ppiread(dev_t dev,struct uio * uio,int flags)270b0e5b3dcScegger ppiread(dev_t dev, struct uio *uio, int flags)
271cb93fa6aSgmcgarry {
272cb93fa6aSgmcgarry 
2730762f691Stsutsui 	DPRINTF(PDB_FOLLOW, ("ppiread(%" PRIx64 ", %p)\n", dev, uio));
274cb93fa6aSgmcgarry 
275cb93fa6aSgmcgarry 	return (ppirw(dev, uio));
276cb93fa6aSgmcgarry }
277cb93fa6aSgmcgarry 
278cb93fa6aSgmcgarry int
ppiwrite(dev_t dev,struct uio * uio,int flags)279b0e5b3dcScegger ppiwrite(dev_t dev, struct uio *uio, int flags)
280cb93fa6aSgmcgarry {
281cb93fa6aSgmcgarry 
2820762f691Stsutsui 	DPRINTF(PDB_FOLLOW, ("ppiwrite(%" PRIx64 ", %p)\n", dev, uio));
283cb93fa6aSgmcgarry 
284cb93fa6aSgmcgarry 	return (ppirw(dev, uio));
285cb93fa6aSgmcgarry }
286cb93fa6aSgmcgarry 
287cb93fa6aSgmcgarry int
ppirw(dev_t dev,struct uio * uio)288b0e5b3dcScegger ppirw(dev_t dev, struct uio *uio)
289cb93fa6aSgmcgarry {
290b0e5b3dcScegger 	struct ppi_softc *sc = device_lookup_private(&ppi_cd, UNIT(dev));
291d14a7576Sad 	int s1, s2, len, cnt;
292cb93fa6aSgmcgarry 	char *cp;
293cb93fa6aSgmcgarry 	int error = 0, gotdata = 0;
294cb93fa6aSgmcgarry 	int buflen, address;
295cb93fa6aSgmcgarry 	char *buf;
296cb93fa6aSgmcgarry 
297cb93fa6aSgmcgarry 	if (uio->uio_resid == 0)
298cb93fa6aSgmcgarry 		return (0);
299cb93fa6aSgmcgarry 
300cb93fa6aSgmcgarry 	address = sc->sc_address;
301cb93fa6aSgmcgarry 
302cb93fa6aSgmcgarry 	DPRINTF(PDB_FOLLOW|PDB_IO,
3030762f691Stsutsui 	    ("ppirw(%" PRIx64 ", %p, %c): burst %d, timo %d, resid %x\n",
304cb93fa6aSgmcgarry 	    dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
305cb93fa6aSgmcgarry 	    sc->sc_burst, sc->sc_timo, uio->uio_resid));
306cb93fa6aSgmcgarry 
307d1579b2dSriastradh 	buflen = uimin(sc->sc_burst, uio->uio_resid);
308cb93fa6aSgmcgarry 	buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
309cb93fa6aSgmcgarry 	sc->sc_flags |= PPIF_UIO;
310cb93fa6aSgmcgarry 	if (sc->sc_timo > 0) {
311cb93fa6aSgmcgarry 		sc->sc_flags |= PPIF_TIMO;
312cb93fa6aSgmcgarry 		callout_reset(&sc->sc_timo_ch, sc->sc_timo, ppitimo, sc);
313cb93fa6aSgmcgarry 	}
314cb93fa6aSgmcgarry 	len = cnt = 0;
315cb93fa6aSgmcgarry 	while (uio->uio_resid > 0) {
316d1579b2dSriastradh 		len = uimin(buflen, uio->uio_resid);
317cb93fa6aSgmcgarry 		cp = buf;
318cb93fa6aSgmcgarry 		if (uio->uio_rw == UIO_WRITE) {
319cb93fa6aSgmcgarry 			error = uiomove(cp, len, uio);
320cb93fa6aSgmcgarry 			if (error)
321cb93fa6aSgmcgarry 				break;
322cb93fa6aSgmcgarry 		}
323cb93fa6aSgmcgarry again:
324d14a7576Sad 		s1 = splsoftclock();
325d14a7576Sad 		s2 = splbio();
326cb93fa6aSgmcgarry 		if (sc->sc_flags & PPIF_UIO) {
327cb93fa6aSgmcgarry 			if (gpibrequest(sc->sc_ic, sc->sc_hdl) == 0)
328cb93fa6aSgmcgarry 				(void) tsleep(sc, PRIBIO + 1, "ppirw", 0);
329cb93fa6aSgmcgarry 		}
330cb93fa6aSgmcgarry 		/*
331cb93fa6aSgmcgarry 		 * Check if we timed out during sleep or uiomove
332cb93fa6aSgmcgarry 		 */
333d14a7576Sad 		splx(s2);
334cb93fa6aSgmcgarry 		if ((sc->sc_flags & PPIF_UIO) == 0) {
335cb93fa6aSgmcgarry 			DPRINTF(PDB_IO,
336cb93fa6aSgmcgarry 			    ("ppirw: uiomove/sleep timo, flags %x\n",
337cb93fa6aSgmcgarry 			    sc->sc_flags));
338cb93fa6aSgmcgarry 			if (sc->sc_flags & PPIF_TIMO) {
339cb93fa6aSgmcgarry 				callout_stop(&sc->sc_timo_ch);
340cb93fa6aSgmcgarry 				sc->sc_flags &= ~PPIF_TIMO;
341cb93fa6aSgmcgarry 			}
342d14a7576Sad 			splx(s1);
343cb93fa6aSgmcgarry 			break;
344cb93fa6aSgmcgarry 		}
345d14a7576Sad 		splx(s1);
346cb93fa6aSgmcgarry 		/*
347cb93fa6aSgmcgarry 		 * Perform the operation
348cb93fa6aSgmcgarry 		 */
349cb93fa6aSgmcgarry 		if (uio->uio_rw == UIO_WRITE)
350cb93fa6aSgmcgarry 			cnt = gpibsend(sc->sc_ic, address, sc->sc_sec,
351cb93fa6aSgmcgarry 			    cp, len);
352cb93fa6aSgmcgarry 		else
353cb93fa6aSgmcgarry 			cnt = gpibrecv(sc->sc_ic, address, sc->sc_sec,
354cb93fa6aSgmcgarry 			    cp, len);
355d14a7576Sad 		s1 = splbio();
356cb93fa6aSgmcgarry 		gpibrelease(sc->sc_ic, sc->sc_hdl);
357cb93fa6aSgmcgarry 		DPRINTF(PDB_IO, ("ppirw: %s(%d, %x, %p, %d) -> %d\n",
358cb93fa6aSgmcgarry 		    uio->uio_rw == UIO_READ ? "recv" : "send",
359cb93fa6aSgmcgarry 		    address, sc->sc_sec, cp, len, cnt));
360d14a7576Sad 		splx(s1);
361cb93fa6aSgmcgarry 		if (uio->uio_rw == UIO_READ) {
362cb93fa6aSgmcgarry 			if (cnt) {
363cb93fa6aSgmcgarry 				error = uiomove(cp, cnt, uio);
364cb93fa6aSgmcgarry 				if (error)
365cb93fa6aSgmcgarry 					break;
366cb93fa6aSgmcgarry 				gotdata++;
367cb93fa6aSgmcgarry 			}
368cb93fa6aSgmcgarry 			/*
369cb93fa6aSgmcgarry 			 * Didn't get anything this time, but did in the past.
370cb93fa6aSgmcgarry 			 * Consider us done.
371cb93fa6aSgmcgarry 			 */
372cb93fa6aSgmcgarry 			else if (gotdata)
373cb93fa6aSgmcgarry 				break;
374cb93fa6aSgmcgarry 		}
375d14a7576Sad 		s1 = splsoftclock();
376cb93fa6aSgmcgarry 		/*
377cb93fa6aSgmcgarry 		 * Operation timeout (or non-blocking), quit now.
378cb93fa6aSgmcgarry 		 */
379cb93fa6aSgmcgarry 		if ((sc->sc_flags & PPIF_UIO) == 0) {
380cb93fa6aSgmcgarry 			DPRINTF(PDB_IO, ("ppirw: timeout/done\n"));
381d14a7576Sad 			splx(s1);
382cb93fa6aSgmcgarry 			break;
383cb93fa6aSgmcgarry 		}
384cb93fa6aSgmcgarry 		/*
385cb93fa6aSgmcgarry 		 * Implement inter-read delay
386cb93fa6aSgmcgarry 		 */
387cb93fa6aSgmcgarry 		if (sc->sc_delay > 0) {
388cb93fa6aSgmcgarry 			sc->sc_flags |= PPIF_DELAY;
389cb93fa6aSgmcgarry 			callout_reset(&sc->sc_start_ch, sc->sc_delay,
390cb93fa6aSgmcgarry 			    ppistart, sc);
391cb93fa6aSgmcgarry 			error = tsleep(sc, (PCATCH|PZERO) + 1, "gpib", 0);
392cb93fa6aSgmcgarry 			if (error) {
393d14a7576Sad 				splx(s1);
394cb93fa6aSgmcgarry 				break;
395cb93fa6aSgmcgarry 			}
396cb93fa6aSgmcgarry 		}
397d14a7576Sad 		splx(s1);
398cb93fa6aSgmcgarry 		/*
399cb93fa6aSgmcgarry 		 * Must not call uiomove again til we've used all data
400cb93fa6aSgmcgarry 		 * that we already grabbed.
401cb93fa6aSgmcgarry 		 */
402cb93fa6aSgmcgarry 		if (uio->uio_rw == UIO_WRITE && cnt != len) {
403cb93fa6aSgmcgarry 			cp += cnt;
404cb93fa6aSgmcgarry 			len -= cnt;
405cb93fa6aSgmcgarry 			cnt = 0;
406cb93fa6aSgmcgarry 			goto again;
407cb93fa6aSgmcgarry 		}
408cb93fa6aSgmcgarry 	}
409d14a7576Sad 	s1 = splsoftclock();
410cb93fa6aSgmcgarry 	if (sc->sc_flags & PPIF_TIMO) {
411cb93fa6aSgmcgarry 		callout_stop(&sc->sc_timo_ch);
412cb93fa6aSgmcgarry 		sc->sc_flags &= ~PPIF_TIMO;
413cb93fa6aSgmcgarry 	}
414cb93fa6aSgmcgarry 	if (sc->sc_flags & PPIF_DELAY) {
415cb93fa6aSgmcgarry 		callout_stop(&sc->sc_start_ch);
416cb93fa6aSgmcgarry 		sc->sc_flags &= ~PPIF_DELAY;
417cb93fa6aSgmcgarry 	}
418d14a7576Sad 	splx(s1);
419cb93fa6aSgmcgarry 	/*
420cb93fa6aSgmcgarry 	 * Adjust for those chars that we uiomove'ed but never wrote
421cb93fa6aSgmcgarry 	 */
422cb93fa6aSgmcgarry 	if (uio->uio_rw == UIO_WRITE && cnt != len) {
423cb93fa6aSgmcgarry 		uio->uio_resid += (len - cnt);
424cb93fa6aSgmcgarry 		DPRINTF(PDB_IO, ("ppirw: short write, adjust by %d\n",
425cb93fa6aSgmcgarry 		    len - cnt));
426cb93fa6aSgmcgarry 	}
427cb93fa6aSgmcgarry 	free(buf, M_DEVBUF);
428cb93fa6aSgmcgarry 	DPRINTF(PDB_FOLLOW|PDB_IO, ("ppirw: return %d, resid %d\n",
429cb93fa6aSgmcgarry 	    error, uio->uio_resid));
430cb93fa6aSgmcgarry 	return (error);
431cb93fa6aSgmcgarry }
432cb93fa6aSgmcgarry 
433cb93fa6aSgmcgarry int
ppiioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)434b0e5b3dcScegger ppiioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
435cb93fa6aSgmcgarry {
436b0e5b3dcScegger 	struct ppi_softc *sc = device_lookup_private(&ppi_cd, UNIT(dev));
437cb93fa6aSgmcgarry 	struct ppiparam *pp, *upp;
438cb93fa6aSgmcgarry 	int error = 0;
439cb93fa6aSgmcgarry 
440cb93fa6aSgmcgarry 	switch (cmd) {
441cb93fa6aSgmcgarry 	case PPIIOCGPARAM:
442cb93fa6aSgmcgarry 		pp = &sc->sc_param;
443cb93fa6aSgmcgarry 		upp = (struct ppiparam *)data;
444cb93fa6aSgmcgarry 		upp->burst = pp->burst;
445cb93fa6aSgmcgarry 		upp->timo = ppihztoms(pp->timo);
446cb93fa6aSgmcgarry 		upp->delay = ppihztoms(pp->delay);
447cb93fa6aSgmcgarry 		break;
448cb93fa6aSgmcgarry 	case PPIIOCSPARAM:
449cb93fa6aSgmcgarry 		pp = &sc->sc_param;
450cb93fa6aSgmcgarry 		upp = (struct ppiparam *)data;
451cb93fa6aSgmcgarry 		if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
452cb93fa6aSgmcgarry 		    upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
453cb93fa6aSgmcgarry 			return (EINVAL);
454cb93fa6aSgmcgarry 		pp->burst = upp->burst;
455cb93fa6aSgmcgarry 		pp->timo = ppimstohz(upp->timo);
456cb93fa6aSgmcgarry 		pp->delay = ppimstohz(upp->delay);
457cb93fa6aSgmcgarry 		break;
458cb93fa6aSgmcgarry 	case PPIIOCSSEC:
459cb93fa6aSgmcgarry 		sc->sc_sec = *(int *)data;
460cb93fa6aSgmcgarry 		break;
461cb93fa6aSgmcgarry 	default:
462cb93fa6aSgmcgarry 		return (EINVAL);
463cb93fa6aSgmcgarry 	}
464cb93fa6aSgmcgarry 	return (error);
465cb93fa6aSgmcgarry }
466cb93fa6aSgmcgarry 
467cb93fa6aSgmcgarry int
ppihztoms(int h)468b0e5b3dcScegger ppihztoms(int h)
469cb93fa6aSgmcgarry {
470cb93fa6aSgmcgarry 	extern int hz;
471cb93fa6aSgmcgarry 	int m = h;
472cb93fa6aSgmcgarry 
473cb93fa6aSgmcgarry 	if (m > 0)
474cb93fa6aSgmcgarry 		m = m * 1000 / hz;
475cb93fa6aSgmcgarry 	return (m);
476cb93fa6aSgmcgarry }
477cb93fa6aSgmcgarry 
478cb93fa6aSgmcgarry int
ppimstohz(int m)479b0e5b3dcScegger ppimstohz(int m)
480cb93fa6aSgmcgarry {
481cb93fa6aSgmcgarry 	extern int hz;
482cb93fa6aSgmcgarry 	int h = m;
483cb93fa6aSgmcgarry 
484cb93fa6aSgmcgarry 	if (h > 0) {
485cb93fa6aSgmcgarry 		h = h * hz / 1000;
486cb93fa6aSgmcgarry 		if (h == 0)
487cb93fa6aSgmcgarry 			h = 1000 / hz;
488cb93fa6aSgmcgarry 	}
489cb93fa6aSgmcgarry 	return (h);
490cb93fa6aSgmcgarry }
491