1 /* 2 * Copyright (c) 1982, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)ppi.c 7.3 (Berkeley) 12/16/90 34 * $Id: par.c,v 1.1.1.1 1993/09/02 16:53:41 mw Exp $ 35 */ 36 37 /* 38 * parallel port interface 39 40 XXXX NOT YET WORKING XXXXX 41 */ 42 43 #include "ppi.h" 44 #if NPAR > 0 45 46 #include "sys/param.h" 47 #include "sys/errno.h" 48 #include "sys/uio.h" 49 #include "sys/malloc.h" 50 51 #include "device.h" 52 #include "parioctl.h" 53 54 int parattach(), parstart(), partimo(), parintr(); 55 struct driver pardriver = { 56 parattach, "par", parstart, 57 }; 58 59 struct par_softc { 60 int sc_flags; 61 struct amiga_device *sc_ad; 62 struct parparam sc_param; 63 #define sc_burst sc_param.burst 64 #define sc_timo sc_param.timo 65 #define sc_delay sc_param.delay 66 } par_softc[NPPI]; 67 68 /* sc_flags values */ 69 #define PARF_ALIVE 0x01 70 #define PARF_OPEN 0x02 71 #define PARF_UIO 0x04 72 #define PARF_TIMO 0x08 73 #define PARF_DELAY 0x10 74 #define PARF_OREAD 0x40 75 #define PARF_OWRITE 0x80 76 77 #define UNIT(x) minor(x) 78 79 #ifdef DEBUG 80 int pardebug = 0x80; 81 #define PDB_FOLLOW 0x01 82 #define PDB_IO 0x02 83 #define PDB_NOCHECK 0x80 84 #endif 85 86 parattach(ad) 87 register struct amiga_device *ad; 88 { 89 register struct par_softc *sc = &par_softc[ad->amiga_unit]; 90 91 #ifdef DEBUG 92 if ((pardebug & PDB_NOCHECK) == 0) 93 #endif 94 sc->sc_flags = PARF_ALIVE; 95 sc->sc_ad = ad; 96 return(1); 97 } 98 99 paropen(dev, flags) 100 dev_t dev; 101 { 102 register int unit = UNIT(dev); 103 register struct par_softc *sc = &par_softc[unit]; 104 105 if (unit >= NPAR || (sc->sc_flags & PARF_ALIVE) == 0) 106 return(ENXIO); 107 #ifdef DEBUG 108 if (pardebug & PDB_FOLLOW) 109 printf("paropen(%x, %x): flags %x\n", 110 dev, flags, sc->sc_flags); 111 #endif 112 if (sc->sc_flags & PARF_OPEN) 113 return(EBUSY); 114 /* can either read or write, but not both */ 115 if ((flags & (FREAD|FWRITE)) == (FREAD|FWRITE)) 116 return EINVAL; 117 118 sc->sc_flags |= PARF_OPEN; 119 if (flags & FREAD) 120 sc->sc_flags |= PARF_OREAD; 121 else 122 sc->sc_flags |= PARF_OWRITE; 123 sc->sc_burst = PAR_BURST; 124 sc->sc_timo = parmstohz(PAR_TIMO); 125 sc->sc_delay = parmstohz(PAR_DELAY); 126 /* enable interrupts for CIAA-FLG */ 127 ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_FLG; 128 return(0); 129 } 130 131 parclose(dev, flags) 132 dev_t dev; 133 { 134 register int unit = UNIT(dev); 135 register struct par_softc *sc = &par_softc[unit]; 136 137 #ifdef DEBUG 138 if (pardebug & PDB_FOLLOW) 139 printf("parclose(%x, %x): flags %x\n", 140 dev, flags, sc->sc_flags); 141 #endif 142 sc->sc_flags &= ~(PARF_OPEN|PARF_OREAD|PARF_OWRITE); 143 /* don't allow interrupts for CIAA-FLG any longer */ 144 ciaa.icr = CIA_ICR_FLG; 145 return(0); 146 } 147 148 parstart(unit) 149 int unit; 150 { 151 #ifdef DEBUG 152 if (pardebug & PDB_FOLLOW) 153 printf("parstart(%x)\n", unit); 154 #endif 155 par_softc[unit].sc_flags &= ~PARF_DELAY; 156 wakeup(&par_softc[unit]); 157 } 158 159 partimo(unit) 160 int unit; 161 { 162 #ifdef DEBUG 163 if (pardebug & PDB_FOLLOW) 164 printf("partimo(%x)\n", unit); 165 #endif 166 par_softc[unit].sc_flags &= ~(PARF_UIO|PARF_TIMO); 167 wakeup(&par_softc[unit]); 168 } 169 170 parread(dev, uio) 171 dev_t dev; 172 struct uio *uio; 173 { 174 175 #ifdef DEBUG 176 if (pardebug & PDB_FOLLOW) 177 printf("parread(%x, %x)\n", dev, uio); 178 #endif 179 return (parrw(dev, uio)); 180 } 181 182 parwrite(dev, uio) 183 dev_t dev; 184 struct uio *uio; 185 { 186 187 #ifdef DEBUG 188 if (pardebug & PDB_FOLLOW) 189 printf("parwrite(%x, %x)\n", dev, uio); 190 #endif 191 return (parrw(dev, uio)); 192 } 193 194 parrw(dev, uio) 195 dev_t dev; 196 register struct uio *uio; 197 { 198 int unit = UNIT(dev); 199 register struct par_softc *sc = &par_softc[unit]; 200 register int s, len, cnt; 201 register char *cp; 202 int error = 0, gotdata = 0; 203 int buflen; 204 char *buf; 205 206 if ((sc->sc_flags & PARF_OREAD) ^^ (uio->uio_rw == UIO_READ)) 207 return EINVAL; 208 209 if (uio->uio_resid == 0) 210 return(0); 211 212 #ifdef DEBUG 213 if (pardebug & (PDB_FOLLOW|PDB_IO)) 214 printf("parrw(%x, %x, %c): burst %d, timo %d, resid %x\n", 215 dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', 216 sc->sc_burst, sc->sc_timo, uio->uio_resid); 217 #endif 218 buflen = MIN(sc->sc_burst, uio->uio_resid); 219 buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK); 220 sc->sc_flags |= PARF_UIO; 221 if (sc->sc_timo > 0) { 222 sc->sc_flags |= PARF_TIMO; 223 timeout(partimo, unit, sc->sc_timo); 224 } 225 while (uio->uio_resid > 0) { 226 len = MIN(buflen, uio->uio_resid); 227 cp = buf; 228 if (uio->uio_rw == UIO_WRITE) { 229 error = uiomove(cp, len, uio); 230 if (error) 231 break; 232 } 233 again: 234 s = splbio(); 235 #if 0 236 if ((sc->sc_flags & PARF_UIO) && hpibreq(&sc->sc_dq) == 0) 237 sleep(sc, PRIBIO+1); 238 #endif 239 /* 240 * Check if we timed out during sleep or uiomove 241 */ 242 (void) splsoftclock(); 243 if ((sc->sc_flags & PARF_UIO) == 0) { 244 #ifdef DEBUG 245 if (pardebug & PDB_IO) 246 printf("parrw: uiomove/sleep timo, flags %x\n", 247 sc->sc_flags); 248 #endif 249 if (sc->sc_flags & PARF_TIMO) { 250 untimeout(partimo, unit); 251 sc->sc_flags &= ~PARF_TIMO; 252 } 253 splx(s); 254 break; 255 } 256 splx(s); 257 /* 258 * Perform the operation 259 */ 260 if (uio->uio_rw == UIO_WRITE) 261 cnt = hpibsend(sc->sc_ad->amiga_ctlr, sc->sc_ad->amiga_slave, 262 sc->sc_sec, cp, len); 263 else 264 cnt = hpibrecv(sc->sc_ad->amiga_ctlr, sc->sc_ad->amiga_slave, 265 sc->sc_sec, cp, len); 266 s = splbio(); 267 hpibfree(&sc->sc_dq); 268 #ifdef DEBUG 269 if (pardebug & PDB_IO) 270 printf("parrw: %s(%d, %d, %x, %x, %d) -> %d\n", 271 uio->uio_rw == UIO_READ ? "recv" : "send", 272 sc->sc_ad->amiga_ctlr, sc->sc_ad->amiga_slave, 273 sc->sc_sec, cp, len, cnt); 274 #endif 275 splx(s); 276 if (uio->uio_rw == UIO_READ) { 277 if (cnt) { 278 error = uiomove(cp, cnt, uio); 279 if (error) 280 break; 281 gotdata++; 282 } 283 /* 284 * Didn't get anything this time, but did in the past. 285 * Consider us done. 286 */ 287 else if (gotdata) 288 break; 289 } 290 s = splsoftclock(); 291 /* 292 * Operation timeout (or non-blocking), quit now. 293 */ 294 if ((sc->sc_flags & PARF_UIO) == 0) { 295 #ifdef DEBUG 296 if (pardebug & PDB_IO) 297 printf("parrw: timeout/done\n"); 298 #endif 299 splx(s); 300 break; 301 } 302 /* 303 * Implement inter-read delay 304 */ 305 if (sc->sc_delay > 0) { 306 sc->sc_flags |= PARF_DELAY; 307 timeout(parstart, unit, sc->sc_delay); 308 error = tsleep(sc, PCATCH|PZERO-1, "par-cdelay", 0); 309 if (error) { 310 splx(s); 311 break; 312 } 313 } 314 splx(s); 315 /* 316 * Must not call uiomove again til we've used all data 317 * that we already grabbed. 318 */ 319 if (uio->uio_rw == UIO_WRITE && cnt != len) { 320 cp += cnt; 321 len -= cnt; 322 cnt = 0; 323 goto again; 324 } 325 } 326 s = splsoftclock(); 327 if (sc->sc_flags & PARF_TIMO) { 328 untimeout(partimo, unit); 329 sc->sc_flags &= ~PARF_TIMO; 330 } 331 if (sc->sc_flags & PARF_DELAY) { 332 untimeout(parstart, unit); 333 sc->sc_flags &= ~PARF_DELAY; 334 } 335 splx(s); 336 /* 337 * Adjust for those chars that we uiomove'ed but never wrote 338 */ 339 if (uio->uio_rw == UIO_WRITE && cnt != len) { 340 uio->uio_resid += (len - cnt); 341 #ifdef DEBUG 342 if (pardebug & PDB_IO) 343 printf("parrw: short write, adjust by %d\n", 344 len-cnt); 345 #endif 346 } 347 free(buf, M_DEVBUF); 348 #ifdef DEBUG 349 if (pardebug & (PDB_FOLLOW|PDB_IO)) 350 printf("parrw: return %d, resid %d\n", error, uio->uio_resid); 351 #endif 352 return (error); 353 } 354 355 parioctl(dev, cmd, data, flag) 356 dev_t dev; 357 int cmd; 358 caddr_t data; 359 int flag; 360 { 361 struct par_softc *sc = &par_softc[UNIT(dev)]; 362 struct parparam *pp, *upp; 363 int error = 0; 364 365 switch (cmd) { 366 case PARIOCGPARAM: 367 pp = &sc->sc_param; 368 upp = (struct parparam *)data; 369 upp->burst = pp->burst; 370 upp->timo = parhztoms(pp->timo); 371 upp->delay = parhztoms(pp->delay); 372 break; 373 case PARIOCSPARAM: 374 pp = &sc->sc_param; 375 upp = (struct parparam *)data; 376 if (upp->burst < PAR_BURST_MIN || upp->burst > PAR_BURST_MAX || 377 upp->delay < PAR_DELAY_MIN || upp->delay > PAR_DELAY_MAX) 378 return(EINVAL); 379 pp->burst = upp->burst; 380 pp->timo = parmstohz(upp->timo); 381 pp->delay = parmstohz(upp->delay); 382 break; 383 default: 384 return(EINVAL); 385 } 386 return (error); 387 } 388 389 parhztoms(h) 390 int h; 391 { 392 extern int hz; 393 register int m = h; 394 395 if (m > 0) 396 m = m * 1000 / hz; 397 return(m); 398 } 399 400 parmstohz(m) 401 int m; 402 { 403 extern int hz; 404 register int h = m; 405 406 if (h > 0) { 407 h = h * hz / 1000; 408 if (h == 0) 409 h = 1000 / hz; 410 } 411 return(h); 412 } 413 414 void 415 parintr (mask) 416 int mask; 417 { 418 wakeup (parintr); 419 } 420 421 int 422 parsend (buf, len) 423 u_char *buf; 424 int len; 425 { 426 /* make sure I/O lines are setup right for output */ 427 428 /* control lines set to input */ 429 ciab.ddra &= ~(CIAB_PRA_SEL|CIAB_PRA_POUT|CIAB_PRA_BUSY); 430 /* data lines to output */ 431 ciaa.ddrb = 0xff; 432 433 while (len) 434 { 435 436 } 437 } 438 439 440 441 442 443 444 #endif 445