Home | History | Annotate | Line # | Download | only in dev
ppi.c revision 1.7
      1 /*	$NetBSD: ppi.c,v 1.7 1995/12/02 18:22:08 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1990, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  *	@(#)ppi.c	8.1 (Berkeley) 6/16/93
     36  */
     37 
     38 /*
     39  * Printer/Plotter HPIB interface
     40  */
     41 
     42 #include "ppi.h"
     43 #if NPPI > 0
     44 
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/errno.h>
     48 #include <sys/uio.h>
     49 #include <sys/malloc.h>
     50 
     51 #include <hp300/dev/device.h>
     52 #include <hp300/dev/ppiioctl.h>
     53 
     54 int	ppimatch(), ppistart();
     55 void	ppiattach(), ppitimo();
     56 struct	driver ppidriver = {
     57 	ppimatch, ppiattach, "ppi", ppistart,
     58 };
     59 
     60 struct	ppi_softc {
     61 	int	sc_flags;
     62 	struct	devqueue sc_dq;
     63 	struct	hp_device *sc_hd;
     64 	struct	ppiparam sc_param;
     65 #define sc_burst sc_param.burst
     66 #define sc_timo  sc_param.timo
     67 #define sc_delay sc_param.delay
     68 	int	sc_sec;
     69 } ppi_softc[NPPI];
     70 
     71 /* sc_flags values */
     72 #define	PPIF_ALIVE	0x01
     73 #define	PPIF_OPEN	0x02
     74 #define PPIF_UIO	0x04
     75 #define PPIF_TIMO	0x08
     76 #define PPIF_DELAY	0x10
     77 
     78 #define UNIT(x)		minor(x)
     79 
     80 #ifdef DEBUG
     81 int	ppidebug = 0x80;
     82 #define PDB_FOLLOW	0x01
     83 #define PDB_IO		0x02
     84 #define PDB_NOCHECK	0x80
     85 #endif
     86 
     87 int
     88 ppimatch(hd)
     89 	register struct hp_device *hd;
     90 {
     91 	register struct ppi_softc *sc = &ppi_softc[hd->hp_unit];
     92 
     93 #ifdef DEBUG
     94 	if ((ppidebug & PDB_NOCHECK) == 0)
     95 #endif
     96 	/*
     97 	 * XXX: the printer/plotter doesn't seem to really return
     98 	 * an ID but this will at least prevent us from mistaking
     99 	 * a cs80 disk or tape for a ppi device.
    100 	 */
    101 	if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200)
    102 		return (0);
    103 
    104 	sc->sc_hd = hd;
    105 	return (1);
    106 }
    107 
    108 void
    109 ppiattach(hd)
    110 	register struct hp_device *hd;
    111 {
    112 	struct ppi_softc *sc = &ppi_softc[hd->hp_unit];
    113 
    114 	printf("\n");
    115 
    116 	sc->sc_flags = PPIF_ALIVE;
    117 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
    118 	sc->sc_dq.dq_unit = hd->hp_unit;
    119 	sc->sc_dq.dq_slave = hd->hp_slave;
    120 	sc->sc_dq.dq_driver = &ppidriver;
    121 }
    122 
    123 ppiopen(dev, flags)
    124 	dev_t dev;
    125 {
    126 	register int unit = UNIT(dev);
    127 	register struct ppi_softc *sc = &ppi_softc[unit];
    128 
    129 	if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0)
    130 		return(ENXIO);
    131 #ifdef DEBUG
    132 	if (ppidebug & PDB_FOLLOW)
    133 		printf("ppiopen(%x, %x): flags %x\n",
    134 		       dev, flags, sc->sc_flags);
    135 #endif
    136 	if (sc->sc_flags & PPIF_OPEN)
    137 		return(EBUSY);
    138 	sc->sc_flags |= PPIF_OPEN;
    139 	sc->sc_burst = PPI_BURST;
    140 	sc->sc_timo = ppimstohz(PPI_TIMO);
    141 	sc->sc_delay = ppimstohz(PPI_DELAY);
    142 	sc->sc_sec = -1;
    143 	return(0);
    144 }
    145 
    146 ppiclose(dev, flags)
    147 	dev_t dev;
    148 {
    149 	register int unit = UNIT(dev);
    150 	register struct ppi_softc *sc = &ppi_softc[unit];
    151 
    152 #ifdef DEBUG
    153 	if (ppidebug & PDB_FOLLOW)
    154 		printf("ppiclose(%x, %x): flags %x\n",
    155 		       dev, flags, sc->sc_flags);
    156 #endif
    157 	sc->sc_flags &= ~PPIF_OPEN;
    158 	return(0);
    159 }
    160 
    161 ppistart(unit)
    162 	int unit;
    163 {
    164 #ifdef DEBUG
    165 	if (ppidebug & PDB_FOLLOW)
    166 		printf("ppistart(%x)\n", unit);
    167 #endif
    168 	ppi_softc[unit].sc_flags &= ~PPIF_DELAY;
    169 	wakeup(&ppi_softc[unit]);
    170 	return (0);
    171 }
    172 
    173 void
    174 ppitimo(unit)
    175 	int unit;
    176 {
    177 #ifdef DEBUG
    178 	if (ppidebug & PDB_FOLLOW)
    179 		printf("ppitimo(%x)\n", unit);
    180 #endif
    181 	ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
    182 	wakeup(&ppi_softc[unit]);
    183 }
    184 
    185 ppiread(dev, uio)
    186 	dev_t dev;
    187 	struct uio *uio;
    188 {
    189 
    190 #ifdef DEBUG
    191 	if (ppidebug & PDB_FOLLOW)
    192 		printf("ppiread(%x, %x)\n", dev, uio);
    193 #endif
    194 	return (ppirw(dev, uio));
    195 }
    196 
    197 ppiwrite(dev, uio)
    198 	dev_t dev;
    199 	struct uio *uio;
    200 {
    201 
    202 #ifdef DEBUG
    203 	if (ppidebug & PDB_FOLLOW)
    204 		printf("ppiwrite(%x, %x)\n", dev, uio);
    205 #endif
    206 	return (ppirw(dev, uio));
    207 }
    208 
    209 ppirw(dev, uio)
    210 	dev_t dev;
    211 	register struct uio *uio;
    212 {
    213 	int unit = UNIT(dev);
    214 	register struct ppi_softc *sc = &ppi_softc[unit];
    215 	register int s, len, cnt;
    216 	register char *cp;
    217 	int error = 0, gotdata = 0;
    218 	int buflen;
    219 	char *buf;
    220 
    221 	if (uio->uio_resid == 0)
    222 		return(0);
    223 
    224 #ifdef DEBUG
    225 	if (ppidebug & (PDB_FOLLOW|PDB_IO))
    226 		printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n",
    227 		       dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
    228 		       sc->sc_burst, sc->sc_timo, uio->uio_resid);
    229 #endif
    230 	buflen = min(sc->sc_burst, uio->uio_resid);
    231 	buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
    232 	sc->sc_flags |= PPIF_UIO;
    233 	if (sc->sc_timo > 0) {
    234 		sc->sc_flags |= PPIF_TIMO;
    235 		timeout(ppitimo, (void *)unit, sc->sc_timo);
    236 	}
    237 	while (uio->uio_resid > 0) {
    238 		len = min(buflen, uio->uio_resid);
    239 		cp = buf;
    240 		if (uio->uio_rw == UIO_WRITE) {
    241 			error = uiomove(cp, len, uio);
    242 			if (error)
    243 				break;
    244 		}
    245 again:
    246 		s = splbio();
    247 		if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0)
    248 			sleep(sc, PRIBIO+1);
    249 		/*
    250 		 * Check if we timed out during sleep or uiomove
    251 		 */
    252 		(void) splsoftclock();
    253 		if ((sc->sc_flags & PPIF_UIO) == 0) {
    254 #ifdef DEBUG
    255 			if (ppidebug & PDB_IO)
    256 				printf("ppirw: uiomove/sleep timo, flags %x\n",
    257 				       sc->sc_flags);
    258 #endif
    259 			if (sc->sc_flags & PPIF_TIMO) {
    260 				untimeout(ppitimo, (void *)unit);
    261 				sc->sc_flags &= ~PPIF_TIMO;
    262 			}
    263 			splx(s);
    264 			break;
    265 		}
    266 		splx(s);
    267 		/*
    268 		 * Perform the operation
    269 		 */
    270 		if (uio->uio_rw == UIO_WRITE)
    271 			cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
    272 				       sc->sc_sec, cp, len);
    273 		else
    274 			cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
    275 				       sc->sc_sec, cp, len);
    276 		s = splbio();
    277 		hpibfree(&sc->sc_dq);
    278 #ifdef DEBUG
    279 		if (ppidebug & PDB_IO)
    280 			printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n",
    281 			       uio->uio_rw == UIO_READ ? "recv" : "send",
    282 			       sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
    283 			       sc->sc_sec, cp, len, cnt);
    284 #endif
    285 		splx(s);
    286 		if (uio->uio_rw == UIO_READ) {
    287 			if (cnt) {
    288 				error = uiomove(cp, cnt, uio);
    289 				if (error)
    290 					break;
    291 				gotdata++;
    292 			}
    293 			/*
    294 			 * Didn't get anything this time, but did in the past.
    295 			 * Consider us done.
    296 			 */
    297 			else if (gotdata)
    298 				break;
    299 		}
    300 		s = splsoftclock();
    301 		/*
    302 		 * Operation timeout (or non-blocking), quit now.
    303 		 */
    304 		if ((sc->sc_flags & PPIF_UIO) == 0) {
    305 #ifdef DEBUG
    306 			if (ppidebug & PDB_IO)
    307 				printf("ppirw: timeout/done\n");
    308 #endif
    309 			splx(s);
    310 			break;
    311 		}
    312 		/*
    313 		 * Implement inter-read delay
    314 		 */
    315 		if (sc->sc_delay > 0) {
    316 			sc->sc_flags |= PPIF_DELAY;
    317 			timeout((void (*)__P((void *)))ppistart, (void *)unit,
    318 			    sc->sc_delay);
    319 			error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0);
    320 			if (error) {
    321 				splx(s);
    322 				break;
    323 			}
    324 		}
    325 		splx(s);
    326 		/*
    327 		 * Must not call uiomove again til we've used all data
    328 		 * that we already grabbed.
    329 		 */
    330 		if (uio->uio_rw == UIO_WRITE && cnt != len) {
    331 			cp += cnt;
    332 			len -= cnt;
    333 			cnt = 0;
    334 			goto again;
    335 		}
    336 	}
    337 	s = splsoftclock();
    338 	if (sc->sc_flags & PPIF_TIMO) {
    339 		untimeout(ppitimo, (void *)unit);
    340 		sc->sc_flags &= ~PPIF_TIMO;
    341 	}
    342 	if (sc->sc_flags & PPIF_DELAY) {
    343 		untimeout((void (*)__P((void *)))ppistart, (void *)unit);
    344 		sc->sc_flags &= ~PPIF_DELAY;
    345 	}
    346 	splx(s);
    347 	/*
    348 	 * Adjust for those chars that we uiomove'ed but never wrote
    349 	 */
    350 	if (uio->uio_rw == UIO_WRITE && cnt != len) {
    351 		uio->uio_resid += (len - cnt);
    352 #ifdef DEBUG
    353 		if (ppidebug & PDB_IO)
    354 			printf("ppirw: short write, adjust by %d\n",
    355 			       len-cnt);
    356 #endif
    357 	}
    358 	free(buf, M_DEVBUF);
    359 #ifdef DEBUG
    360 	if (ppidebug & (PDB_FOLLOW|PDB_IO))
    361 		printf("ppirw: return %d, resid %d\n", error, uio->uio_resid);
    362 #endif
    363 	return (error);
    364 }
    365 
    366 ppiioctl(dev, cmd, data, flag, p)
    367 	dev_t dev;
    368 	int cmd;
    369 	caddr_t data;
    370 	int flag;
    371 	struct proc *p;
    372 {
    373 	struct ppi_softc *sc = &ppi_softc[UNIT(dev)];
    374 	struct ppiparam *pp, *upp;
    375 	int error = 0;
    376 
    377 	switch (cmd) {
    378 	case PPIIOCGPARAM:
    379 		pp = &sc->sc_param;
    380 		upp = (struct ppiparam *)data;
    381 		upp->burst = pp->burst;
    382 		upp->timo = ppihztoms(pp->timo);
    383 		upp->delay = ppihztoms(pp->delay);
    384 		break;
    385 	case PPIIOCSPARAM:
    386 		pp = &sc->sc_param;
    387 		upp = (struct ppiparam *)data;
    388 		if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
    389 		    upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
    390 			return(EINVAL);
    391 		pp->burst = upp->burst;
    392 		pp->timo = ppimstohz(upp->timo);
    393 		pp->delay = ppimstohz(upp->delay);
    394 		break;
    395 	case PPIIOCSSEC:
    396 		sc->sc_sec = *(int *)data;
    397 		break;
    398 	default:
    399 		return(EINVAL);
    400 	}
    401 	return (error);
    402 }
    403 
    404 ppihztoms(h)
    405 	int h;
    406 {
    407 	extern int hz;
    408 	register int m = h;
    409 
    410 	if (m > 0)
    411 		m = m * 1000 / hz;
    412 	return(m);
    413 }
    414 
    415 ppimstohz(m)
    416 	int m;
    417 {
    418 	extern int hz;
    419 	register int h = m;
    420 
    421 	if (h > 0) {
    422 		h = h * hz / 1000;
    423 		if (h == 0)
    424 			h = 1000 / hz;
    425 	}
    426 	return(h);
    427 }
    428 #endif
    429