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