1 1.41 riastrad /* $NetBSD: par.c,v 1.41 2018/09/03 16:29:22 riastradh Exp $ */ 2 1.9 cgd 3 1.1 mw /* 4 1.1 mw * Copyright (c) 1982, 1990 The Regents of the University of California. 5 1.1 mw * All rights reserved. 6 1.1 mw * 7 1.1 mw * Redistribution and use in source and binary forms, with or without 8 1.1 mw * modification, are permitted provided that the following conditions 9 1.1 mw * are met: 10 1.1 mw * 1. Redistributions of source code must retain the above copyright 11 1.1 mw * notice, this list of conditions and the following disclaimer. 12 1.1 mw * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mw * notice, this list of conditions and the following disclaimer in the 14 1.1 mw * documentation and/or other materials provided with the distribution. 15 1.30 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 mw * may be used to endorse or promote products derived from this software 17 1.1 mw * without specific prior written permission. 18 1.1 mw * 19 1.1 mw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 mw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 mw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 mw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 mw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 mw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 mw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 mw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 mw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 mw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 mw * SUCH DAMAGE. 30 1.1 mw * 31 1.10 cgd * @(#)ppi.c 7.3 (Berkeley) 12/16/90 32 1.1 mw */ 33 1.25 aymeric 34 1.25 aymeric #include <sys/cdefs.h> 35 1.41 riastrad __KERNEL_RCSID(0, "$NetBSD: par.c,v 1.41 2018/09/03 16:29:22 riastradh Exp $"); 36 1.1 mw 37 1.1 mw /* 38 1.1 mw * parallel port interface 39 1.1 mw */ 40 1.1 mw 41 1.2 mw #include "par.h" 42 1.1 mw #if NPAR > 0 43 1.1 mw 44 1.6 chopps #include <sys/param.h> 45 1.6 chopps #include <sys/errno.h> 46 1.6 chopps #include <sys/uio.h> 47 1.7 chopps #include <sys/device.h> 48 1.6 chopps #include <sys/malloc.h> 49 1.6 chopps #include <sys/file.h> 50 1.6 chopps #include <sys/systm.h> 51 1.20 thorpej #include <sys/callout.h> 52 1.13 veego #include <sys/proc.h> 53 1.26 gehenna #include <sys/conf.h> 54 1.1 mw 55 1.7 chopps #include <amiga/amiga/device.h> 56 1.7 chopps #include <amiga/amiga/cia.h> 57 1.6 chopps #include <amiga/dev/parioctl.h> 58 1.1 mw 59 1.1 mw struct par_softc { 60 1.38 chs device_t sc_dev; 61 1.21 frueauf 62 1.1 mw int sc_flags; 63 1.1 mw struct parparam sc_param; 64 1.1 mw #define sc_burst sc_param.burst 65 1.1 mw #define sc_timo sc_param.timo 66 1.1 mw #define sc_delay sc_param.delay 67 1.20 thorpej 68 1.20 thorpej struct callout sc_timo_ch; 69 1.20 thorpej struct callout sc_start_ch; 70 1.7 chopps } *par_softcp; 71 1.7 chopps 72 1.7 chopps #define getparsp(x) (x > 0 ? NULL : par_softcp) 73 1.1 mw 74 1.1 mw /* sc_flags values */ 75 1.24 aymeric #define PARF_ALIVE 0x01 76 1.24 aymeric #define PARF_OPEN 0x02 77 1.1 mw #define PARF_UIO 0x04 78 1.1 mw #define PARF_TIMO 0x08 79 1.1 mw #define PARF_DELAY 0x10 80 1.1 mw #define PARF_OREAD 0x40 81 1.1 mw #define PARF_OWRITE 0x80 82 1.1 mw 83 1.1 mw #define UNIT(x) minor(x) 84 1.1 mw 85 1.1 mw #ifdef DEBUG 86 1.2 mw int pardebug = 0; 87 1.1 mw #define PDB_FOLLOW 0x01 88 1.1 mw #define PDB_IO 0x02 89 1.2 mw #define PDB_INTERRUPT 0x04 90 1.1 mw #define PDB_NOCHECK 0x80 91 1.1 mw #endif 92 1.1 mw 93 1.24 aymeric int parrw(dev_t, struct uio *); 94 1.24 aymeric int parhztoms(int); 95 1.24 aymeric int parmstohz(int); 96 1.24 aymeric int parsend(u_char *, int); 97 1.24 aymeric int parreceive(u_char *, int); 98 1.24 aymeric int parsendch(u_char); 99 1.24 aymeric 100 1.24 aymeric void partimo(void *); 101 1.24 aymeric void parstart(void *); 102 1.24 aymeric void parintr(void *); 103 1.7 chopps 104 1.38 chs void parattach(device_t, device_t, void *); 105 1.38 chs int parmatch(device_t, cfdata_t, void *); 106 1.7 chopps 107 1.38 chs CFATTACH_DECL_NEW(par, sizeof(struct par_softc), 108 1.28 thorpej parmatch, parattach, NULL, NULL); 109 1.26 gehenna 110 1.26 gehenna dev_type_open(paropen); 111 1.26 gehenna dev_type_close(parclose); 112 1.26 gehenna dev_type_read(parread); 113 1.26 gehenna dev_type_write(parwrite); 114 1.26 gehenna dev_type_ioctl(parioctl); 115 1.26 gehenna 116 1.26 gehenna const struct cdevsw par_cdevsw = { 117 1.39 dholland .d_open = paropen, 118 1.39 dholland .d_close = parclose, 119 1.39 dholland .d_read = parread, 120 1.39 dholland .d_write = parwrite, 121 1.39 dholland .d_ioctl = parioctl, 122 1.39 dholland .d_stop = nostop, 123 1.39 dholland .d_tty = notty, 124 1.39 dholland .d_poll = nopoll, 125 1.39 dholland .d_mmap = nommap, 126 1.39 dholland .d_kqfilter = nokqfilter, 127 1.40 dholland .d_discard = nodiscard, 128 1.39 dholland .d_flag = 0 129 1.12 thorpej }; 130 1.7 chopps 131 1.7 chopps /*ARGSUSED*/ 132 1.7 chopps int 133 1.38 chs parmatch(device_t parent, cfdata_t cf, void *aux) 134 1.7 chopps { 135 1.19 kleink static int par_found = 0; 136 1.12 thorpej 137 1.38 chs if (!matchname((char *)aux, "par") || par_found) 138 1.19 kleink return(0); 139 1.19 kleink 140 1.19 kleink par_found = 1; 141 1.19 kleink return(1); 142 1.7 chopps } 143 1.7 chopps 144 1.7 chopps void 145 1.38 chs parattach(device_t parent, device_t self, void *aux) 146 1.1 mw { 147 1.38 chs par_softcp = device_private(self); 148 1.38 chs 149 1.38 chs par_softcp->sc_dev = self; 150 1.1 mw 151 1.1 mw #ifdef DEBUG 152 1.7 chopps if ((pardebug & PDB_NOCHECK) == 0) 153 1.1 mw #endif 154 1.7 chopps par_softcp->sc_flags = PARF_ALIVE; 155 1.15 christos printf("\n"); 156 1.20 thorpej 157 1.35 ad callout_init(&par_softcp->sc_timo_ch, 0); 158 1.35 ad callout_init(&par_softcp->sc_start_ch, 0); 159 1.1 mw } 160 1.1 mw 161 1.13 veego int 162 1.31 christos paropen(dev_t dev, int flags, int mode, struct lwp *l) 163 1.1 mw { 164 1.7 chopps int unit = UNIT(dev); 165 1.7 chopps struct par_softc *sc = getparsp(unit); 166 1.24 aymeric 167 1.7 chopps if (unit >= NPAR || (sc->sc_flags & PARF_ALIVE) == 0) 168 1.7 chopps return(ENXIO); 169 1.1 mw #ifdef DEBUG 170 1.7 chopps if (pardebug & PDB_FOLLOW) { 171 1.37 phx printf("paropen(%llx, %x): flags %x, ", 172 1.7 chopps dev, flags, sc->sc_flags); 173 1.15 christos printf ("port = $%x\n", ((ciab.pra ^ CIAB_PRA_SEL) 174 1.7 chopps & (CIAB_PRA_SEL|CIAB_PRA_BUSY|CIAB_PRA_POUT))); 175 1.7 chopps } 176 1.1 mw #endif 177 1.7 chopps if (sc->sc_flags & PARF_OPEN) 178 1.7 chopps return(EBUSY); 179 1.7 chopps /* can either read or write, but not both */ 180 1.7 chopps if ((flags & (FREAD|FWRITE)) == (FREAD|FWRITE)) 181 1.7 chopps return EINVAL; 182 1.24 aymeric 183 1.7 chopps sc->sc_flags |= PARF_OPEN; 184 1.7 chopps 185 1.7 chopps if (flags & FREAD) 186 1.7 chopps sc->sc_flags |= PARF_OREAD; 187 1.7 chopps else 188 1.7 chopps sc->sc_flags |= PARF_OWRITE; 189 1.7 chopps 190 1.7 chopps sc->sc_burst = PAR_BURST; 191 1.7 chopps sc->sc_timo = parmstohz(PAR_TIMO); 192 1.7 chopps sc->sc_delay = parmstohz(PAR_DELAY); 193 1.7 chopps /* enable interrupts for CIAA-FLG */ 194 1.7 chopps ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_FLG; 195 1.7 chopps return(0); 196 1.1 mw } 197 1.1 mw 198 1.13 veego int 199 1.31 christos parclose(dev_t dev, int flags, int mode, struct lwp *l) 200 1.1 mw { 201 1.7 chopps int unit = UNIT(dev); 202 1.7 chopps struct par_softc *sc = getparsp(unit); 203 1.1 mw 204 1.1 mw #ifdef DEBUG 205 1.1 mw if (pardebug & PDB_FOLLOW) 206 1.37 phx printf("parclose(%llx, %x): flags %x\n", 207 1.1 mw dev, flags, sc->sc_flags); 208 1.1 mw #endif 209 1.1 mw sc->sc_flags &= ~(PARF_OPEN|PARF_OREAD|PARF_OWRITE); 210 1.1 mw /* don't allow interrupts for CIAA-FLG any longer */ 211 1.1 mw ciaa.icr = CIA_ICR_FLG; 212 1.1 mw return(0); 213 1.1 mw } 214 1.1 mw 215 1.7 chopps void 216 1.24 aymeric parstart(void *arg) 217 1.1 mw { 218 1.20 thorpej struct par_softc *sc = arg; 219 1.7 chopps 220 1.1 mw #ifdef DEBUG 221 1.7 chopps if (pardebug & PDB_FOLLOW) 222 1.38 chs printf("parstart(%x)\n", device_unit(sc->sc_dev)); 223 1.1 mw #endif 224 1.7 chopps sc->sc_flags &= ~PARF_DELAY; 225 1.7 chopps wakeup(sc); 226 1.1 mw } 227 1.1 mw 228 1.7 chopps void 229 1.24 aymeric partimo(void *arg) 230 1.1 mw { 231 1.20 thorpej struct par_softc *sc = arg; 232 1.7 chopps 233 1.1 mw #ifdef DEBUG 234 1.7 chopps if (pardebug & PDB_FOLLOW) 235 1.38 chs printf("partimo(%x)\n", device_unit(sc->sc_dev)); 236 1.1 mw #endif 237 1.7 chopps sc->sc_flags &= ~(PARF_UIO|PARF_TIMO); 238 1.7 chopps wakeup(sc); 239 1.1 mw } 240 1.1 mw 241 1.13 veego int 242 1.24 aymeric parread(dev_t dev, struct uio *uio, int flags) 243 1.1 mw { 244 1.1 mw 245 1.1 mw #ifdef DEBUG 246 1.13 veego if (pardebug & PDB_FOLLOW) 247 1.37 phx printf("parread(%llx, %p)\n", dev, uio); 248 1.1 mw #endif 249 1.13 veego return (parrw(dev, uio)); 250 1.1 mw } 251 1.1 mw 252 1.13 veego 253 1.13 veego int 254 1.24 aymeric parwrite(dev_t dev, struct uio *uio, int flags) 255 1.1 mw { 256 1.1 mw 257 1.1 mw #ifdef DEBUG 258 1.13 veego if (pardebug & PDB_FOLLOW) 259 1.37 phx printf("parwrite(%llx, %p)\n", dev, uio); 260 1.1 mw #endif 261 1.13 veego return (parrw(dev, uio)); 262 1.1 mw } 263 1.1 mw 264 1.13 veego 265 1.13 veego int 266 1.24 aymeric parrw(dev_t dev, register struct uio *uio) 267 1.1 mw { 268 1.1 mw int unit = UNIT(dev); 269 1.7 chopps register struct par_softc *sc = getparsp(unit); 270 1.1 mw register int s, len, cnt; 271 1.1 mw register char *cp; 272 1.1 mw int error = 0, gotdata = 0; 273 1.1 mw int buflen; 274 1.1 mw char *buf; 275 1.1 mw 276 1.13 veego len = 0; 277 1.13 veego cnt = 0; 278 1.2 mw if (!!(sc->sc_flags & PARF_OREAD) ^ (uio->uio_rw == UIO_READ)) 279 1.1 mw return EINVAL; 280 1.1 mw 281 1.1 mw if (uio->uio_resid == 0) 282 1.1 mw return(0); 283 1.1 mw 284 1.1 mw #ifdef DEBUG 285 1.1 mw if (pardebug & (PDB_FOLLOW|PDB_IO)) 286 1.37 phx printf("parrw(%llx, %p, %c): burst %d, timo %d, resid %x\n", 287 1.1 mw dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', 288 1.1 mw sc->sc_burst, sc->sc_timo, uio->uio_resid); 289 1.1 mw #endif 290 1.41 riastrad buflen = uimin(sc->sc_burst, uio->uio_resid); 291 1.1 mw buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK); 292 1.1 mw sc->sc_flags |= PARF_UIO; 293 1.24 aymeric if (sc->sc_timo > 0) 294 1.2 mw { 295 1.2 mw sc->sc_flags |= PARF_TIMO; 296 1.20 thorpej callout_reset(&sc->sc_timo_ch, sc->sc_timo, partimo, sc); 297 1.1 mw } 298 1.24 aymeric while (uio->uio_resid > 0) 299 1.2 mw { 300 1.41 riastrad len = uimin(buflen, uio->uio_resid); 301 1.2 mw cp = buf; 302 1.24 aymeric if (uio->uio_rw == UIO_WRITE) 303 1.2 mw { 304 1.2 mw error = uiomove(cp, len, uio); 305 1.2 mw if (error) 306 1.2 mw break; 307 1.2 mw } 308 1.2 mw again: 309 1.2 mw #if 0 310 1.2 mw if ((sc->sc_flags & PARF_UIO) && hpibreq(&sc->sc_dq) == 0) 311 1.2 mw sleep(sc, PRIBIO+1); 312 1.2 mw #endif 313 1.2 mw /* 314 1.2 mw * Check if we timed out during sleep or uiomove 315 1.2 mw */ 316 1.33 ad s = splsoftclock(); 317 1.24 aymeric if ((sc->sc_flags & PARF_UIO) == 0) 318 1.2 mw { 319 1.2 mw #ifdef DEBUG 320 1.2 mw if (pardebug & PDB_IO) 321 1.15 christos printf("parrw: uiomove/sleep timo, flags %x\n", 322 1.2 mw sc->sc_flags); 323 1.2 mw #endif 324 1.24 aymeric if (sc->sc_flags & PARF_TIMO) 325 1.2 mw { 326 1.20 thorpej callout_stop(&sc->sc_timo_ch); 327 1.2 mw sc->sc_flags &= ~PARF_TIMO; 328 1.2 mw } 329 1.2 mw splx(s); 330 1.2 mw break; 331 1.2 mw } 332 1.2 mw splx(s); 333 1.2 mw /* 334 1.2 mw * Perform the operation 335 1.2 mw */ 336 1.2 mw if (uio->uio_rw == UIO_WRITE) 337 1.2 mw cnt = parsend (cp, len); 338 1.2 mw else 339 1.2 mw cnt = parreceive (cp, len); 340 1.24 aymeric 341 1.2 mw if (cnt < 0) 342 1.2 mw { 343 1.2 mw error = -cnt; 344 1.2 mw break; 345 1.2 mw } 346 1.24 aymeric 347 1.2 mw s = splbio(); 348 1.1 mw #if 0 349 1.2 mw hpibfree(&sc->sc_dq); 350 1.1 mw #endif 351 1.1 mw #ifdef DEBUG 352 1.1 mw if (pardebug & PDB_IO) 353 1.15 christos printf("parrw: %s(%p, %d) -> %d\n", 354 1.2 mw uio->uio_rw == UIO_READ ? "recv" : "send", cp, len, cnt); 355 1.1 mw #endif 356 1.1 mw splx(s); 357 1.24 aymeric if (uio->uio_rw == UIO_READ) 358 1.2 mw { 359 1.24 aymeric if (cnt) 360 1.2 mw { 361 1.2 mw error = uiomove(cp, cnt, uio); 362 1.2 mw if (error) 363 1.2 mw break; 364 1.2 mw gotdata++; 365 1.2 mw } 366 1.2 mw /* 367 1.2 mw * Didn't get anything this time, but did in the past. 368 1.2 mw * Consider us done. 369 1.2 mw */ 370 1.2 mw else if (gotdata) 371 1.2 mw break; 372 1.2 mw } 373 1.2 mw s = splsoftclock(); 374 1.1 mw /* 375 1.2 mw * Operation timeout (or non-blocking), quit now. 376 1.1 mw */ 377 1.24 aymeric if ((sc->sc_flags & PARF_UIO) == 0) 378 1.2 mw { 379 1.1 mw #ifdef DEBUG 380 1.2 mw if (pardebug & PDB_IO) 381 1.15 christos printf("parrw: timeout/done\n"); 382 1.1 mw #endif 383 1.2 mw splx(s); 384 1.2 mw break; 385 1.2 mw } 386 1.2 mw /* 387 1.2 mw * Implement inter-read delay 388 1.2 mw */ 389 1.24 aymeric if (sc->sc_delay > 0) 390 1.2 mw { 391 1.2 mw sc->sc_flags |= PARF_DELAY; 392 1.20 thorpej callout_reset(&sc->sc_start_ch, sc->sc_delay, parstart, sc); 393 1.13 veego error = tsleep(sc, PCATCH | (PZERO - 1), "par-cdelay", 0); 394 1.24 aymeric if (error) 395 1.2 mw { 396 1.2 mw splx(s); 397 1.2 mw break; 398 1.2 mw } 399 1.2 mw } 400 1.1 mw splx(s); 401 1.2 mw /* 402 1.2 mw * Must not call uiomove again til we've used all data 403 1.2 mw * that we already grabbed. 404 1.2 mw */ 405 1.24 aymeric if (uio->uio_rw == UIO_WRITE && cnt != len) 406 1.2 mw { 407 1.2 mw cp += cnt; 408 1.2 mw len -= cnt; 409 1.2 mw cnt = 0; 410 1.2 mw goto again; 411 1.2 mw } 412 1.1 mw } 413 1.2 mw s = splsoftclock(); 414 1.24 aymeric if (sc->sc_flags & PARF_TIMO) 415 1.2 mw { 416 1.20 thorpej callout_stop(&sc->sc_timo_ch); 417 1.2 mw sc->sc_flags &= ~PARF_TIMO; 418 1.1 mw } 419 1.24 aymeric if (sc->sc_flags & PARF_DELAY) 420 1.2 mw { 421 1.20 thorpej callout_stop(&sc->sc_start_ch); 422 1.2 mw sc->sc_flags &= ~PARF_DELAY; 423 1.1 mw } 424 1.1 mw splx(s); 425 1.1 mw /* 426 1.1 mw * Adjust for those chars that we uiomove'ed but never wrote 427 1.1 mw */ 428 1.24 aymeric if (uio->uio_rw == UIO_WRITE && cnt != len) 429 1.2 mw { 430 1.2 mw uio->uio_resid += (len - cnt); 431 1.1 mw #ifdef DEBUG 432 1.2 mw if (pardebug & PDB_IO) 433 1.15 christos printf("parrw: short write, adjust by %d\n", 434 1.2 mw len-cnt); 435 1.1 mw #endif 436 1.2 mw } 437 1.1 mw free(buf, M_DEVBUF); 438 1.1 mw #ifdef DEBUG 439 1.1 mw if (pardebug & (PDB_FOLLOW|PDB_IO)) 440 1.15 christos printf("parrw: return %d, resid %d\n", error, uio->uio_resid); 441 1.1 mw #endif 442 1.1 mw return (error); 443 1.1 mw } 444 1.1 mw 445 1.2 mw int 446 1.34 christos parioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 447 1.1 mw { 448 1.7 chopps struct par_softc *sc = getparsp(UNIT(dev)); 449 1.1 mw struct parparam *pp, *upp; 450 1.1 mw int error = 0; 451 1.1 mw 452 1.24 aymeric switch (cmd) 453 1.2 mw { 454 1.2 mw case PARIOCGPARAM: 455 1.2 mw pp = &sc->sc_param; 456 1.2 mw upp = (struct parparam *)data; 457 1.2 mw upp->burst = pp->burst; 458 1.2 mw upp->timo = parhztoms(pp->timo); 459 1.2 mw upp->delay = parhztoms(pp->delay); 460 1.2 mw break; 461 1.2 mw 462 1.2 mw case PARIOCSPARAM: 463 1.2 mw pp = &sc->sc_param; 464 1.2 mw upp = (struct parparam *)data; 465 1.2 mw if (upp->burst < PAR_BURST_MIN || upp->burst > PAR_BURST_MAX || 466 1.2 mw upp->delay < PAR_DELAY_MIN || upp->delay > PAR_DELAY_MAX) 467 1.2 mw return(EINVAL); 468 1.2 mw pp->burst = upp->burst; 469 1.2 mw pp->timo = parmstohz(upp->timo); 470 1.2 mw pp->delay = parmstohz(upp->delay); 471 1.2 mw break; 472 1.2 mw 473 1.2 mw default: 474 1.1 mw return(EINVAL); 475 1.2 mw } 476 1.1 mw return (error); 477 1.1 mw } 478 1.1 mw 479 1.2 mw int 480 1.24 aymeric parhztoms(int h) 481 1.1 mw { 482 1.1 mw extern int hz; 483 1.1 mw register int m = h; 484 1.1 mw 485 1.1 mw if (m > 0) 486 1.1 mw m = m * 1000 / hz; 487 1.1 mw return(m); 488 1.1 mw } 489 1.1 mw 490 1.2 mw int 491 1.24 aymeric parmstohz(int m) 492 1.1 mw { 493 1.1 mw extern int hz; 494 1.1 mw register int h = m; 495 1.1 mw 496 1.1 mw if (h > 0) { 497 1.1 mw h = h * hz / 1000; 498 1.1 mw if (h == 0) 499 1.1 mw h = 1000 / hz; 500 1.1 mw } 501 1.1 mw return(h); 502 1.1 mw } 503 1.1 mw 504 1.2 mw /* stuff below here if for interrupt driven output of data thru 505 1.2 mw the parallel port. */ 506 1.2 mw 507 1.2 mw int parsend_pending; 508 1.2 mw 509 1.1 mw void 510 1.24 aymeric parintr(void *arg) 511 1.1 mw { 512 1.23 is int s; 513 1.7 chopps 514 1.7 chopps s = splclock(); 515 1.7 chopps 516 1.2 mw #ifdef DEBUG 517 1.7 chopps if (pardebug & PDB_INTERRUPT) 518 1.23 is printf("parintr\n"); 519 1.7 chopps #endif 520 1.23 is parsend_pending = 0; 521 1.24 aymeric 522 1.7 chopps wakeup(parintr); 523 1.7 chopps splx(s); 524 1.2 mw } 525 1.2 mw 526 1.2 mw int 527 1.24 aymeric parsendch (u_char ch) 528 1.2 mw { 529 1.2 mw int error = 0; 530 1.2 mw int s; 531 1.2 mw 532 1.2 mw /* if either offline, busy or out of paper, wait for that 533 1.2 mw condition to clear */ 534 1.2 mw s = splclock(); 535 1.24 aymeric while (!error 536 1.24 aymeric && (parsend_pending 537 1.2 mw || ((ciab.pra ^ CIAB_PRA_SEL) 538 1.2 mw & (CIAB_PRA_SEL|CIAB_PRA_BUSY|CIAB_PRA_POUT)))) 539 1.2 mw { 540 1.2 mw extern int hz; 541 1.2 mw 542 1.2 mw #ifdef DEBUG 543 1.2 mw if (pardebug & PDB_INTERRUPT) 544 1.15 christos printf ("parsendch, port = $%x\n", 545 1.2 mw ((ciab.pra ^ CIAB_PRA_SEL) 546 1.2 mw & (CIAB_PRA_SEL|CIAB_PRA_BUSY|CIAB_PRA_POUT))); 547 1.2 mw #endif 548 1.2 mw /* this is essentially a flipflop to have us wait for the 549 1.2 mw first character being transmitted when trying to transmit 550 1.2 mw the second, etc. */ 551 1.2 mw parsend_pending = 0; 552 1.2 mw /* it's quite important that a parallel putc can be 553 1.2 mw interrupted, given the possibility to lock a printer 554 1.2 mw in an offline condition.. */ 555 1.23 is error = tsleep(parintr, PCATCH | (PZERO - 1), "parsendch", hz); 556 1.23 is if (error == EWOULDBLOCK) 557 1.23 is error = 0; 558 1.23 is if (error > 0) 559 1.2 mw { 560 1.2 mw #ifdef DEBUG 561 1.2 mw if (pardebug & PDB_INTERRUPT) 562 1.15 christos printf ("parsendch interrupted, error = %d\n", error); 563 1.2 mw #endif 564 1.2 mw } 565 1.2 mw } 566 1.2 mw 567 1.2 mw if (! error) 568 1.2 mw { 569 1.2 mw #ifdef DEBUG 570 1.2 mw if (pardebug & PDB_INTERRUPT) 571 1.15 christos printf ("#%d", ch); 572 1.2 mw #endif 573 1.2 mw ciaa.prb = ch; 574 1.2 mw parsend_pending = 1; 575 1.2 mw } 576 1.2 mw 577 1.2 mw splx (s); 578 1.2 mw 579 1.2 mw return error; 580 1.1 mw } 581 1.1 mw 582 1.2 mw 583 1.1 mw int 584 1.24 aymeric parsend (u_char *buf, int len) 585 1.1 mw { 586 1.2 mw int err, orig_len = len; 587 1.2 mw 588 1.1 mw /* make sure I/O lines are setup right for output */ 589 1.1 mw 590 1.1 mw /* control lines set to input */ 591 1.1 mw ciab.ddra &= ~(CIAB_PRA_SEL|CIAB_PRA_POUT|CIAB_PRA_BUSY); 592 1.1 mw /* data lines to output */ 593 1.1 mw ciaa.ddrb = 0xff; 594 1.24 aymeric 595 1.2 mw for (; len; len--, buf++) 596 1.13 veego if ((err = parsendch (*buf)) != 0) 597 1.2 mw return err < 0 ? -EINTR : -err; 598 1.2 mw 599 1.2 mw /* either all or nothing.. */ 600 1.2 mw return orig_len; 601 1.1 mw } 602 1.1 mw 603 1.1 mw 604 1.1 mw 605 1.2 mw int 606 1.24 aymeric parreceive (u_char *buf, int len) 607 1.2 mw { 608 1.2 mw /* oh deary me, something's gotta be left to be implemented 609 1.2 mw later... */ 610 1.2 mw return 0; 611 1.2 mw } 612 1.1 mw 613 1.1 mw 614 1.1 mw #endif 615