1 /* 2 * Copyright (c) 1982, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ppi.c 8.2 (Berkeley) 01/09/95 8 */ 9 10 /* 11 * Printer/Plotter HPIB interface 12 */ 13 14 #include "ppi.h" 15 #if NPPI > 0 16 17 #include <sys/param.h> 18 #include <sys/systm.h> 19 #include <sys/errno.h> 20 #include <sys/uio.h> 21 #include <sys/malloc.h> 22 23 #include <hp/dev/device.h> 24 #include <hp300/dev/ppiioctl.h> 25 26 int ppiattach(), ppistart(); 27 void ppitimo(); 28 struct driver ppidriver = { 29 ppiattach, "ppi", ppistart, 30 }; 31 32 struct ppi_softc { 33 int sc_flags; 34 struct devqueue sc_dq; 35 struct hp_device *sc_hd; 36 struct ppiparam sc_param; 37 #define sc_burst sc_param.burst 38 #define sc_timo sc_param.timo 39 #define sc_delay sc_param.delay 40 int sc_sec; 41 } ppi_softc[NPPI]; 42 43 /* sc_flags values */ 44 #define PPIF_ALIVE 0x01 45 #define PPIF_OPEN 0x02 46 #define PPIF_UIO 0x04 47 #define PPIF_TIMO 0x08 48 #define PPIF_DELAY 0x10 49 50 #define UNIT(x) minor(x) 51 52 #ifdef DEBUG 53 int ppidebug = 0x80; 54 #define PDB_FOLLOW 0x01 55 #define PDB_IO 0x02 56 #define PDB_NOCHECK 0x80 57 #endif 58 59 ppiattach(hd) 60 register struct hp_device *hd; 61 { 62 register struct ppi_softc *sc = &ppi_softc[hd->hp_unit]; 63 64 #ifdef DEBUG 65 if ((ppidebug & PDB_NOCHECK) == 0) 66 #endif 67 /* 68 * XXX: the printer/plotter doesn't seem to really return 69 * an ID but this will at least prevent us from mistaking 70 * a cs80 disk or tape for a ppi device. 71 */ 72 if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200) 73 return(0); 74 sc->sc_flags = PPIF_ALIVE; 75 sc->sc_dq.dq_ctlr = hd->hp_ctlr; 76 sc->sc_dq.dq_unit = hd->hp_unit; 77 sc->sc_dq.dq_slave = hd->hp_slave; 78 sc->sc_dq.dq_driver = &ppidriver; 79 sc->sc_hd = hd; 80 return(1); 81 } 82 83 ppiopen(dev, flags) 84 dev_t dev; 85 { 86 register int unit = UNIT(dev); 87 register struct ppi_softc *sc = &ppi_softc[unit]; 88 89 if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0) 90 return(ENXIO); 91 #ifdef DEBUG 92 if (ppidebug & PDB_FOLLOW) 93 printf("ppiopen(%x, %x): flags %x\n", 94 dev, flags, sc->sc_flags); 95 #endif 96 if (sc->sc_flags & PPIF_OPEN) 97 return(EBUSY); 98 sc->sc_flags |= PPIF_OPEN; 99 sc->sc_burst = PPI_BURST; 100 sc->sc_timo = ppimstohz(PPI_TIMO); 101 sc->sc_delay = ppimstohz(PPI_DELAY); 102 sc->sc_sec = -1; 103 return(0); 104 } 105 106 ppiclose(dev, flags) 107 dev_t dev; 108 { 109 register int unit = UNIT(dev); 110 register struct ppi_softc *sc = &ppi_softc[unit]; 111 112 #ifdef DEBUG 113 if (ppidebug & PDB_FOLLOW) 114 printf("ppiclose(%x, %x): flags %x\n", 115 dev, flags, sc->sc_flags); 116 #endif 117 sc->sc_flags &= ~PPIF_OPEN; 118 return(0); 119 } 120 121 ppistart(unit) 122 int unit; 123 { 124 #ifdef DEBUG 125 if (ppidebug & PDB_FOLLOW) 126 printf("ppistart(%x)\n", unit); 127 #endif 128 ppi_softc[unit].sc_flags &= ~PPIF_DELAY; 129 wakeup(&ppi_softc[unit]); 130 return (0); 131 } 132 133 void 134 ppitimo(unit) 135 int unit; 136 { 137 #ifdef DEBUG 138 if (ppidebug & PDB_FOLLOW) 139 printf("ppitimo(%x)\n", unit); 140 #endif 141 ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO); 142 wakeup(&ppi_softc[unit]); 143 } 144 145 ppiread(dev, uio) 146 dev_t dev; 147 struct uio *uio; 148 { 149 150 #ifdef DEBUG 151 if (ppidebug & PDB_FOLLOW) 152 printf("ppiread(%x, %x)\n", dev, uio); 153 #endif 154 return (ppirw(dev, uio)); 155 } 156 157 ppiwrite(dev, uio) 158 dev_t dev; 159 struct uio *uio; 160 { 161 162 #ifdef DEBUG 163 if (ppidebug & PDB_FOLLOW) 164 printf("ppiwrite(%x, %x)\n", dev, uio); 165 #endif 166 return (ppirw(dev, uio)); 167 } 168 169 ppirw(dev, uio) 170 dev_t dev; 171 register struct uio *uio; 172 { 173 int unit = UNIT(dev); 174 register struct ppi_softc *sc = &ppi_softc[unit]; 175 register int s, len, cnt; 176 register char *cp; 177 int error = 0, gotdata = 0; 178 int buflen; 179 char *buf; 180 181 if (uio->uio_resid == 0) 182 return(0); 183 184 #ifdef DEBUG 185 if (ppidebug & (PDB_FOLLOW|PDB_IO)) 186 printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n", 187 dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', 188 sc->sc_burst, sc->sc_timo, uio->uio_resid); 189 #endif 190 buflen = min(sc->sc_burst, uio->uio_resid); 191 buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK); 192 sc->sc_flags |= PPIF_UIO; 193 if (sc->sc_timo > 0) { 194 sc->sc_flags |= PPIF_TIMO; 195 timeout(ppitimo, (void *)unit, sc->sc_timo); 196 } 197 while (uio->uio_resid > 0) { 198 len = min(buflen, uio->uio_resid); 199 cp = buf; 200 if (uio->uio_rw == UIO_WRITE) { 201 error = uiomove(cp, len, uio); 202 if (error) 203 break; 204 } 205 again: 206 s = splbio(); 207 if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0) 208 sleep(sc, PRIBIO+1); 209 /* 210 * Check if we timed out during sleep or uiomove 211 */ 212 (void) splsoftclock(); 213 if ((sc->sc_flags & PPIF_UIO) == 0) { 214 #ifdef DEBUG 215 if (ppidebug & PDB_IO) 216 printf("ppirw: uiomove/sleep timo, flags %x\n", 217 sc->sc_flags); 218 #endif 219 if (sc->sc_flags & PPIF_TIMO) { 220 untimeout(ppitimo, (void *)unit); 221 sc->sc_flags &= ~PPIF_TIMO; 222 } 223 splx(s); 224 break; 225 } 226 splx(s); 227 /* 228 * Perform the operation 229 */ 230 if (uio->uio_rw == UIO_WRITE) 231 cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 232 sc->sc_sec, cp, len); 233 else 234 cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 235 sc->sc_sec, cp, len); 236 s = splbio(); 237 hpibfree(&sc->sc_dq); 238 #ifdef DEBUG 239 if (ppidebug & PDB_IO) 240 printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n", 241 uio->uio_rw == UIO_READ ? "recv" : "send", 242 sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 243 sc->sc_sec, cp, len, cnt); 244 #endif 245 splx(s); 246 if (uio->uio_rw == UIO_READ) { 247 if (cnt) { 248 error = uiomove(cp, cnt, uio); 249 if (error) 250 break; 251 gotdata++; 252 } 253 /* 254 * Didn't get anything this time, but did in the past. 255 * Consider us done. 256 */ 257 else if (gotdata) 258 break; 259 } 260 s = splsoftclock(); 261 /* 262 * Operation timeout (or non-blocking), quit now. 263 */ 264 if ((sc->sc_flags & PPIF_UIO) == 0) { 265 #ifdef DEBUG 266 if (ppidebug & PDB_IO) 267 printf("ppirw: timeout/done\n"); 268 #endif 269 splx(s); 270 break; 271 } 272 /* 273 * Implement inter-read delay 274 */ 275 if (sc->sc_delay > 0) { 276 sc->sc_flags |= PPIF_DELAY; 277 timeout((void (*)__P((void *)))ppistart, (void *)unit, 278 sc->sc_delay); 279 error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0); 280 if (error) { 281 splx(s); 282 break; 283 } 284 } 285 splx(s); 286 /* 287 * Must not call uiomove again til we've used all data 288 * that we already grabbed. 289 */ 290 if (uio->uio_rw == UIO_WRITE && cnt != len) { 291 cp += cnt; 292 len -= cnt; 293 cnt = 0; 294 goto again; 295 } 296 } 297 s = splsoftclock(); 298 if (sc->sc_flags & PPIF_TIMO) { 299 untimeout(ppitimo, (void *)unit); 300 sc->sc_flags &= ~PPIF_TIMO; 301 } 302 if (sc->sc_flags & PPIF_DELAY) { 303 untimeout((void (*)__P((void *)))ppistart, (void *)unit); 304 sc->sc_flags &= ~PPIF_DELAY; 305 } 306 splx(s); 307 /* 308 * Adjust for those chars that we uiomove'ed but never wrote 309 */ 310 if (uio->uio_rw == UIO_WRITE && cnt != len) { 311 uio->uio_resid += (len - cnt); 312 #ifdef DEBUG 313 if (ppidebug & PDB_IO) 314 printf("ppirw: short write, adjust by %d\n", 315 len-cnt); 316 #endif 317 } 318 free(buf, M_DEVBUF); 319 #ifdef DEBUG 320 if (ppidebug & (PDB_FOLLOW|PDB_IO)) 321 printf("ppirw: return %d, resid %d\n", error, uio->uio_resid); 322 #endif 323 return (error); 324 } 325 326 ppiioctl(dev, cmd, data, flag) 327 dev_t dev; 328 u_long cmd; 329 caddr_t data; 330 int flag; 331 { 332 struct ppi_softc *sc = &ppi_softc[UNIT(dev)]; 333 struct ppiparam *pp, *upp; 334 int error = 0; 335 336 switch (cmd) { 337 case PPIIOCGPARAM: 338 pp = &sc->sc_param; 339 upp = (struct ppiparam *)data; 340 upp->burst = pp->burst; 341 upp->timo = ppihztoms(pp->timo); 342 upp->delay = ppihztoms(pp->delay); 343 break; 344 case PPIIOCSPARAM: 345 pp = &sc->sc_param; 346 upp = (struct ppiparam *)data; 347 if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX || 348 upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX) 349 return(EINVAL); 350 pp->burst = upp->burst; 351 pp->timo = ppimstohz(upp->timo); 352 pp->delay = ppimstohz(upp->delay); 353 break; 354 case PPIIOCSSEC: 355 sc->sc_sec = *(int *)data; 356 break; 357 default: 358 return(EINVAL); 359 } 360 return (error); 361 } 362 363 ppihztoms(h) 364 int h; 365 { 366 extern int hz; 367 register int m = h; 368 369 if (m > 0) 370 m = m * 1000 / hz; 371 return(m); 372 } 373 374 ppimstohz(m) 375 int m; 376 { 377 extern int hz; 378 register int h = m; 379 380 if (h > 0) { 381 h = h * hz / 1000; 382 if (h == 0) 383 h = 1000 / hz; 384 } 385 return(h); 386 } 387 #endif 388