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