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