1 /* $NetBSD: ppi.c,v 1.41 2008/06/13 09:41:15 cegger Exp $ */
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1982, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * @(#)ppi.c 8.1 (Berkeley) 6/16/93
64 * Printer/Plotter HPIB interface
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: ppi.c,v 1.41 2008/06/13 09:41:15 cegger Exp $");
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/callout.h>
74 #include <sys/device.h>
75 #include <sys/errno.h>
76 #include <sys/malloc.h>
80 #include <hp300/dev/hpibvar.h>
82 #include <hp300/dev/ppiioctl.h>
89 struct hpibqueue sc_hq
; /* HP-IB job queue entry */
90 struct ppiparam sc_param
;
91 #define sc_burst sc_param.burst
92 #define sc_timo sc_param.timo
93 #define sc_delay sc_param.delay
95 int sc_slave
; /* HP-IB slave address */
96 struct callout sc_timo_ch
;
97 struct callout sc_start_ch
;
100 /* sc_flags values */
101 #define PPIF_ALIVE 0x01
102 #define PPIF_OPEN 0x02
103 #define PPIF_UIO 0x04
104 #define PPIF_TIMO 0x08
105 #define PPIF_DELAY 0x10
107 static int ppimatch(device_t
, cfdata_t
, void *);
108 static void ppiattach(device_t
, device_t
, void *);
110 CFATTACH_DECL_NEW(ppi
, sizeof(struct ppi_softc
),
111 ppimatch
, ppiattach
, NULL
, NULL
);
113 static dev_type_open(ppiopen
);
114 static dev_type_close(ppiclose
);
115 static dev_type_read(ppiread
);
116 static dev_type_write(ppiwrite
);
117 static dev_type_ioctl(ppiioctl
);
119 const struct cdevsw ppi_cdevsw
= {
120 ppiopen
, ppiclose
, ppiread
, ppiwrite
, ppiioctl
,
121 nostop
, notty
, nopoll
, nommap
, nokqfilter
,
124 static void ppistart(void *);
125 static void ppinoop(void *);
127 static void ppitimo(void *);
128 static int ppirw(dev_t
, struct uio
*);
129 static int ppihztoms(int);
130 static int ppimstohz(int);
132 #define UNIT(x) minor(x)
136 #define PDB_FOLLOW 0x01
138 #define PDB_NOCHECK 0x80
142 ppimatch(device_t parent
, cfdata_t cf
, void *aux
)
144 struct hpibbus_attach_args
*ha
= aux
;
147 * The printer/plotter doesn't return an ID tag.
148 * The check below prevents us from matching a CS80
151 if (ha
->ha_id
& 0x200)
155 * To prevent matching all unused slots on the bus, we
156 * don't allow wildcarded locators.
158 if (cf
->hpibbuscf_slave
== HPIBBUSCF_SLAVE_DEFAULT
||
159 cf
->hpibbuscf_punit
== HPIBBUSCF_PUNIT_DEFAULT
)
166 ppiattach(device_t parent
, device_t self
, void *aux
)
168 struct ppi_softc
*sc
= device_private(self
);
169 struct hpibbus_attach_args
*ha
= aux
;
174 sc
->sc_slave
= ha
->ha_slave
;
176 callout_init(&sc
->sc_timo_ch
, 0);
177 callout_init(&sc
->sc_start_ch
, 0);
179 /* Initialize the hpib queue entry. */
180 sc
->sc_hq
.hq_softc
= sc
;
181 sc
->sc_hq
.hq_slave
= sc
->sc_slave
;
182 sc
->sc_hq
.hq_start
= ppistart
;
183 sc
->sc_hq
.hq_go
= ppinoop
;
184 sc
->sc_hq
.hq_intr
= ppinoop
;
186 sc
->sc_flags
= PPIF_ALIVE
;
196 ppiopen(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
198 struct ppi_softc
*sc
;
200 sc
= device_lookup_private(&ppi_cd
,UNIT(dev
));
204 if ((sc
->sc_flags
& PPIF_ALIVE
) == 0)
208 if (ppidebug
& PDB_FOLLOW
)
209 printf("ppiopen(%x, %x): flags %x\n",
210 dev
, flags
, sc
->sc_flags
);
212 if (sc
->sc_flags
& PPIF_OPEN
)
214 sc
->sc_flags
|= PPIF_OPEN
;
215 sc
->sc_burst
= PPI_BURST
;
216 sc
->sc_timo
= ppimstohz(PPI_TIMO
);
217 sc
->sc_delay
= ppimstohz(PPI_DELAY
);
223 ppiclose(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
225 struct ppi_softc
*sc
= device_lookup_private(&ppi_cd
, UNIT(dev
));
228 if (ppidebug
& PDB_FOLLOW
)
229 printf("ppiclose(%x, %x): flags %x\n",
230 dev
, flags
, sc
->sc_flags
);
232 sc
->sc_flags
&= ~PPIF_OPEN
;
239 struct ppi_softc
*sc
= arg
;
242 if (ppidebug
& PDB_FOLLOW
)
243 printf("ppistart(%x)\n", device_unit(sc
->sc_dev
));
245 sc
->sc_flags
&= ~PPIF_DELAY
;
252 struct ppi_softc
*sc
= arg
;
255 if (ppidebug
& PDB_FOLLOW
)
256 printf("ppitimo(%x)\n", device_unit(sc
->sc_dev
));
258 sc
->sc_flags
&= ~(PPIF_UIO
|PPIF_TIMO
);
263 ppiread(dev_t dev
, struct uio
*uio
, int flags
)
267 if (ppidebug
& PDB_FOLLOW
)
268 printf("ppiread(%x, %p)\n", dev
, uio
);
270 return ppirw(dev
, uio
);
274 ppiwrite(dev_t dev
, struct uio
*uio
, int flags
)
278 if (ppidebug
& PDB_FOLLOW
)
279 printf("ppiwrite(%x, %p)\n", dev
, uio
);
281 return ppirw(dev
, uio
);
285 ppirw(dev_t dev
, struct uio
*uio
)
287 struct ppi_softc
*sc
= device_lookup_private(&ppi_cd
, UNIT(dev
));
290 int error
= 0, gotdata
= 0;
291 int buflen
, ctlr
, slave
;
294 if (uio
->uio_resid
== 0)
297 ctlr
= device_unit(device_parent(sc
->sc_dev
));
298 slave
= sc
->sc_slave
;
301 if (ppidebug
& (PDB_FOLLOW
|PDB_IO
))
302 printf("ppirw(%x, %p, %c): burst %d, timo %d, resid %x\n",
303 dev
, uio
, uio
->uio_rw
== UIO_READ
? 'R' : 'W',
304 sc
->sc_burst
, sc
->sc_timo
, uio
->uio_resid
);
306 buflen
= min(sc
->sc_burst
, uio
->uio_resid
);
307 buf
= (char *)malloc(buflen
, M_DEVBUF
, M_WAITOK
);
308 sc
->sc_flags
|= PPIF_UIO
;
309 if (sc
->sc_timo
> 0) {
310 sc
->sc_flags
|= PPIF_TIMO
;
311 callout_reset(&sc
->sc_timo_ch
, sc
->sc_timo
, ppitimo
, sc
);
314 while (uio
->uio_resid
> 0) {
315 len
= min(buflen
, uio
->uio_resid
);
317 if (uio
->uio_rw
== UIO_WRITE
) {
318 error
= uiomove(cp
, len
, uio
);
325 if ((sc
->sc_flags
& PPIF_UIO
) &&
326 hpibreq(device_parent(sc
->sc_dev
), &sc
->sc_hq
) == 0)
327 (void) tsleep(sc
, PRIBIO
+ 1, "ppirw", 0);
329 * Check if we timed out during sleep or uiomove
332 if ((sc
->sc_flags
& PPIF_UIO
) == 0) {
334 if (ppidebug
& PDB_IO
)
335 printf("ppirw: uiomove/sleep timo, flags %x\n",
338 if (sc
->sc_flags
& PPIF_TIMO
) {
339 callout_stop(&sc
->sc_timo_ch
);
340 sc
->sc_flags
&= ~PPIF_TIMO
;
347 * Perform the operation
349 if (uio
->uio_rw
== UIO_WRITE
)
350 cnt
= hpibsend(ctlr
, slave
, sc
->sc_sec
, cp
, len
);
352 cnt
= hpibrecv(ctlr
, slave
, sc
->sc_sec
, cp
, len
);
354 hpibfree(device_parent(sc
->sc_dev
), &sc
->sc_hq
);
356 if (ppidebug
& PDB_IO
)
357 printf("ppirw: %s(%d, %d, %x, %p, %d) -> %d\n",
358 uio
->uio_rw
== UIO_READ
? "recv" : "send",
359 ctlr
, slave
, sc
->sc_sec
, cp
, len
, cnt
);
362 if (uio
->uio_rw
== UIO_READ
) {
364 error
= uiomove(cp
, cnt
, uio
);
370 * Didn't get anything this time, but did in the past.
378 * Operation timeout (or non-blocking), quit now.
380 if ((sc
->sc_flags
& PPIF_UIO
) == 0) {
382 if (ppidebug
& PDB_IO
)
383 printf("ppirw: timeout/done\n");
389 * Implement inter-read delay
391 if (sc
->sc_delay
> 0) {
392 sc
->sc_flags
|= PPIF_DELAY
;
393 callout_reset(&sc
->sc_start_ch
, sc
->sc_delay
,
395 error
= tsleep(sc
, (PCATCH
|PZERO
) + 1, "hpib", 0);
403 * Must not call uiomove again til we've used all data
404 * that we already grabbed.
406 if (uio
->uio_rw
== UIO_WRITE
&& cnt
!= len
) {
414 if (sc
->sc_flags
& PPIF_TIMO
) {
415 callout_stop(&sc
->sc_timo_ch
);
416 sc
->sc_flags
&= ~PPIF_TIMO
;
418 if (sc
->sc_flags
& PPIF_DELAY
) {
419 callout_stop(&sc
->sc_start_ch
);
420 sc
->sc_flags
&= ~PPIF_DELAY
;
424 * Adjust for those chars that we uiomove'ed but never wrote
426 if (uio
->uio_rw
== UIO_WRITE
&& cnt
!= len
) {
427 uio
->uio_resid
+= (len
- cnt
);
429 if (ppidebug
& PDB_IO
)
430 printf("ppirw: short write, adjust by %d\n",
436 if (ppidebug
& (PDB_FOLLOW
|PDB_IO
))
437 printf("ppirw: return %d, resid %d\n", error
, uio
->uio_resid
);
443 ppiioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
445 struct ppi_softc
*sc
= device_lookup_private(&ppi_cd
,UNIT(dev
));
446 struct ppiparam
*pp
, *upp
;
452 upp
= (struct ppiparam
*)data
;
453 upp
->burst
= pp
->burst
;
454 upp
->timo
= ppihztoms(pp
->timo
);
455 upp
->delay
= ppihztoms(pp
->delay
);
459 upp
= (struct ppiparam
*)data
;
460 if (upp
->burst
< PPI_BURST_MIN
|| upp
->burst
> PPI_BURST_MAX
||
461 upp
->delay
< PPI_DELAY_MIN
|| upp
->delay
> PPI_DELAY_MAX
)
463 pp
->burst
= upp
->burst
;
464 pp
->timo
= ppimstohz(upp
->timo
);
465 pp
->delay
= ppimstohz(upp
->delay
);
468 sc
->sc_sec
= *(int *)data
;