1 1.48 thorpej /* $NetBSD: ppi.c,v 1.48 2020/11/18 02:22:16 thorpej Exp $ */ 2 1.15 thorpej 3 1.15 thorpej /*- 4 1.15 thorpej * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 1.15 thorpej * All rights reserved. 6 1.15 thorpej * 7 1.15 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.15 thorpej * by Jason R. Thorpe. 9 1.15 thorpej * 10 1.15 thorpej * Redistribution and use in source and binary forms, with or without 11 1.15 thorpej * modification, are permitted provided that the following conditions 12 1.15 thorpej * are met: 13 1.15 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.15 thorpej * notice, this list of conditions and the following disclaimer. 15 1.15 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.15 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.15 thorpej * documentation and/or other materials provided with the distribution. 18 1.15 thorpej * 19 1.15 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.15 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.15 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.15 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.15 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.15 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.15 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.15 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.15 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.15 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.15 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.15 thorpej */ 31 1.6 cgd 32 1.1 cgd /* 33 1.5 mycroft * Copyright (c) 1982, 1990, 1993 34 1.5 mycroft * The Regents of the University of California. All rights reserved. 35 1.1 cgd * 36 1.1 cgd * Redistribution and use in source and binary forms, with or without 37 1.1 cgd * modification, are permitted provided that the following conditions 38 1.1 cgd * are met: 39 1.1 cgd * 1. Redistributions of source code must retain the above copyright 40 1.1 cgd * notice, this list of conditions and the following disclaimer. 41 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 cgd * notice, this list of conditions and the following disclaimer in the 43 1.1 cgd * documentation and/or other materials provided with the distribution. 44 1.27 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 cgd * may be used to endorse or promote products derived from this software 46 1.1 cgd * without specific prior written permission. 47 1.1 cgd * 48 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 cgd * SUCH DAMAGE. 59 1.1 cgd * 60 1.6 cgd * @(#)ppi.c 8.1 (Berkeley) 6/16/93 61 1.1 cgd */ 62 1.1 cgd 63 1.1 cgd /* 64 1.1 cgd * Printer/Plotter HPIB interface 65 1.1 cgd */ 66 1.20 gmcgarry 67 1.20 gmcgarry #include <sys/cdefs.h> 68 1.48 thorpej __KERNEL_RCSID(0, "$NetBSD: ppi.c,v 1.48 2020/11/18 02:22:16 thorpej Exp $"); 69 1.1 cgd 70 1.3 mycroft #include <sys/param.h> 71 1.3 mycroft #include <sys/systm.h> 72 1.46 tsutsui #include <sys/kernel.h> 73 1.18 thorpej #include <sys/callout.h> 74 1.12 scottr #include <sys/conf.h> 75 1.12 scottr #include <sys/device.h> 76 1.3 mycroft #include <sys/errno.h> 77 1.48 thorpej #include <sys/kmem.h> 78 1.12 scottr #include <sys/proc.h> 79 1.3 mycroft #include <sys/uio.h> 80 1.11 thorpej 81 1.11 thorpej #include <hp300/dev/hpibvar.h> 82 1.1 cgd 83 1.3 mycroft #include <hp300/dev/ppiioctl.h> 84 1.1 cgd 85 1.30 tsutsui #include "ioconf.h" 86 1.30 tsutsui 87 1.1 cgd struct ppi_softc { 88 1.39 tsutsui device_t sc_dev; 89 1.1 cgd int sc_flags; 90 1.11 thorpej struct hpibqueue sc_hq; /* HP-IB job queue entry */ 91 1.1 cgd struct ppiparam sc_param; 92 1.1 cgd #define sc_burst sc_param.burst 93 1.1 cgd #define sc_timo sc_param.timo 94 1.1 cgd #define sc_delay sc_param.delay 95 1.1 cgd int sc_sec; 96 1.11 thorpej int sc_slave; /* HP-IB slave address */ 97 1.18 thorpej struct callout sc_timo_ch; 98 1.18 thorpej struct callout sc_start_ch; 99 1.11 thorpej }; 100 1.1 cgd 101 1.1 cgd /* sc_flags values */ 102 1.28 tsutsui #define PPIF_ALIVE 0x01 103 1.28 tsutsui #define PPIF_OPEN 0x02 104 1.1 cgd #define PPIF_UIO 0x04 105 1.1 cgd #define PPIF_TIMO 0x08 106 1.1 cgd #define PPIF_DELAY 0x10 107 1.1 cgd 108 1.39 tsutsui static int ppimatch(device_t, cfdata_t, void *); 109 1.39 tsutsui static void ppiattach(device_t, device_t, void *); 110 1.11 thorpej 111 1.39 tsutsui CFATTACH_DECL_NEW(ppi, sizeof(struct ppi_softc), 112 1.23 thorpej ppimatch, ppiattach, NULL, NULL); 113 1.11 thorpej 114 1.29 thorpej static dev_type_open(ppiopen); 115 1.29 thorpej static dev_type_close(ppiclose); 116 1.29 thorpej static dev_type_read(ppiread); 117 1.29 thorpej static dev_type_write(ppiwrite); 118 1.29 thorpej static dev_type_ioctl(ppiioctl); 119 1.21 gehenna 120 1.21 gehenna const struct cdevsw ppi_cdevsw = { 121 1.44 dholland .d_open = ppiopen, 122 1.44 dholland .d_close = ppiclose, 123 1.44 dholland .d_read = ppiread, 124 1.44 dholland .d_write = ppiwrite, 125 1.44 dholland .d_ioctl = ppiioctl, 126 1.44 dholland .d_stop = nostop, 127 1.44 dholland .d_tty = notty, 128 1.44 dholland .d_poll = nopoll, 129 1.44 dholland .d_mmap = nommap, 130 1.44 dholland .d_kqfilter = nokqfilter, 131 1.45 dholland .d_discard = nodiscard, 132 1.44 dholland .d_flag = 0 133 1.21 gehenna }; 134 1.21 gehenna 135 1.29 thorpej static void ppistart(void *); 136 1.29 thorpej static void ppinoop(void *); 137 1.11 thorpej 138 1.29 thorpej static void ppitimo(void *); 139 1.29 thorpej static int ppirw(dev_t, struct uio *); 140 1.29 thorpej static int ppihztoms(int); 141 1.29 thorpej static int ppimstohz(int); 142 1.11 thorpej 143 1.1 cgd #define UNIT(x) minor(x) 144 1.1 cgd 145 1.1 cgd #ifdef DEBUG 146 1.1 cgd int ppidebug = 0x80; 147 1.1 cgd #define PDB_FOLLOW 0x01 148 1.1 cgd #define PDB_IO 0x02 149 1.1 cgd #define PDB_NOCHECK 0x80 150 1.1 cgd #endif 151 1.1 cgd 152 1.29 thorpej static int 153 1.39 tsutsui ppimatch(device_t parent, cfdata_t cf, void *aux) 154 1.1 cgd { 155 1.11 thorpej struct hpibbus_attach_args *ha = aux; 156 1.11 thorpej 157 1.11 thorpej /* 158 1.11 thorpej * The printer/plotter doesn't return an ID tag. 159 1.11 thorpej * The check below prevents us from matching a CS80 160 1.11 thorpej * device by mistake. 161 1.11 thorpej */ 162 1.11 thorpej if (ha->ha_id & 0x200) 163 1.34 tsutsui return 0; 164 1.1 cgd 165 1.1 cgd /* 166 1.11 thorpej * To prevent matching all unused slots on the bus, we 167 1.11 thorpej * don't allow wildcarded locators. 168 1.1 cgd */ 169 1.39 tsutsui if (cf->hpibbuscf_slave == HPIBBUSCF_SLAVE_DEFAULT || 170 1.39 tsutsui cf->hpibbuscf_punit == HPIBBUSCF_PUNIT_DEFAULT) 171 1.34 tsutsui return 0; 172 1.7 thorpej 173 1.34 tsutsui return 1; 174 1.7 thorpej } 175 1.7 thorpej 176 1.29 thorpej static void 177 1.39 tsutsui ppiattach(device_t parent, device_t self, void *aux) 178 1.7 thorpej { 179 1.39 tsutsui struct ppi_softc *sc = device_private(self); 180 1.11 thorpej struct hpibbus_attach_args *ha = aux; 181 1.7 thorpej 182 1.39 tsutsui sc->sc_dev = self; 183 1.39 tsutsui aprint_normal("\n"); 184 1.7 thorpej 185 1.11 thorpej sc->sc_slave = ha->ha_slave; 186 1.11 thorpej 187 1.37 he callout_init(&sc->sc_timo_ch, 0); 188 1.37 he callout_init(&sc->sc_start_ch, 0); 189 1.18 thorpej 190 1.11 thorpej /* Initialize the hpib queue entry. */ 191 1.11 thorpej sc->sc_hq.hq_softc = sc; 192 1.11 thorpej sc->sc_hq.hq_slave = sc->sc_slave; 193 1.11 thorpej sc->sc_hq.hq_start = ppistart; 194 1.11 thorpej sc->sc_hq.hq_go = ppinoop; 195 1.11 thorpej sc->sc_hq.hq_intr = ppinoop; 196 1.11 thorpej 197 1.1 cgd sc->sc_flags = PPIF_ALIVE; 198 1.1 cgd } 199 1.1 cgd 200 1.29 thorpej static void 201 1.29 thorpej ppinoop(void *arg) 202 1.11 thorpej { 203 1.11 thorpej /* Noop! */ 204 1.11 thorpej } 205 1.11 thorpej 206 1.11 thorpej int 207 1.31 christos ppiopen(dev_t dev, int flags, int fmt, struct lwp *l) 208 1.1 cgd { 209 1.11 thorpej struct ppi_softc *sc; 210 1.11 thorpej 211 1.41 cegger sc = device_lookup_private(&ppi_cd,UNIT(dev)); 212 1.41 cegger if (sc == NULL) 213 1.41 cegger return ENXIO; 214 1.41 cegger 215 1.42 tsutsui if ((sc->sc_flags & PPIF_ALIVE) == 0) 216 1.34 tsutsui return ENXIO; 217 1.1 cgd 218 1.1 cgd #ifdef DEBUG 219 1.1 cgd if (ppidebug & PDB_FOLLOW) 220 1.43 uebayasi printf("ppiopen(%"PRIx64", %x): flags %x\n", 221 1.1 cgd dev, flags, sc->sc_flags); 222 1.1 cgd #endif 223 1.1 cgd if (sc->sc_flags & PPIF_OPEN) 224 1.34 tsutsui return EBUSY; 225 1.1 cgd sc->sc_flags |= PPIF_OPEN; 226 1.1 cgd sc->sc_burst = PPI_BURST; 227 1.1 cgd sc->sc_timo = ppimstohz(PPI_TIMO); 228 1.1 cgd sc->sc_delay = ppimstohz(PPI_DELAY); 229 1.1 cgd sc->sc_sec = -1; 230 1.34 tsutsui return 0; 231 1.1 cgd } 232 1.1 cgd 233 1.29 thorpej static int 234 1.31 christos ppiclose(dev_t dev, int flags, int fmt, struct lwp *l) 235 1.1 cgd { 236 1.41 cegger struct ppi_softc *sc = device_lookup_private(&ppi_cd, UNIT(dev)); 237 1.1 cgd 238 1.1 cgd #ifdef DEBUG 239 1.1 cgd if (ppidebug & PDB_FOLLOW) 240 1.43 uebayasi printf("ppiclose(%"PRIx64", %x): flags %x\n", 241 1.1 cgd dev, flags, sc->sc_flags); 242 1.1 cgd #endif 243 1.1 cgd sc->sc_flags &= ~PPIF_OPEN; 244 1.34 tsutsui return 0; 245 1.1 cgd } 246 1.1 cgd 247 1.29 thorpej static void 248 1.29 thorpej ppistart(void *arg) 249 1.1 cgd { 250 1.11 thorpej struct ppi_softc *sc = arg; 251 1.11 thorpej 252 1.1 cgd #ifdef DEBUG 253 1.1 cgd if (ppidebug & PDB_FOLLOW) 254 1.39 tsutsui printf("ppistart(%x)\n", device_unit(sc->sc_dev)); 255 1.1 cgd #endif 256 1.11 thorpej sc->sc_flags &= ~PPIF_DELAY; 257 1.11 thorpej wakeup(sc); 258 1.1 cgd } 259 1.1 cgd 260 1.29 thorpej static void 261 1.29 thorpej ppitimo(void *arg) 262 1.1 cgd { 263 1.11 thorpej struct ppi_softc *sc = arg; 264 1.11 thorpej 265 1.1 cgd #ifdef DEBUG 266 1.1 cgd if (ppidebug & PDB_FOLLOW) 267 1.39 tsutsui printf("ppitimo(%x)\n", device_unit(sc->sc_dev)); 268 1.1 cgd #endif 269 1.11 thorpej sc->sc_flags &= ~(PPIF_UIO|PPIF_TIMO); 270 1.11 thorpej wakeup(sc); 271 1.1 cgd } 272 1.1 cgd 273 1.29 thorpej static int 274 1.29 thorpej ppiread(dev_t dev, struct uio *uio, int flags) 275 1.1 cgd { 276 1.1 cgd 277 1.1 cgd #ifdef DEBUG 278 1.1 cgd if (ppidebug & PDB_FOLLOW) 279 1.43 uebayasi printf("ppiread(%"PRIx64", %p)\n", dev, uio); 280 1.1 cgd #endif 281 1.34 tsutsui return ppirw(dev, uio); 282 1.1 cgd } 283 1.1 cgd 284 1.29 thorpej static int 285 1.29 thorpej ppiwrite(dev_t dev, struct uio *uio, int flags) 286 1.1 cgd { 287 1.1 cgd 288 1.1 cgd #ifdef DEBUG 289 1.1 cgd if (ppidebug & PDB_FOLLOW) 290 1.43 uebayasi printf("ppiwrite(%"PRIx64", %p)\n", dev, uio); 291 1.1 cgd #endif 292 1.34 tsutsui return ppirw(dev, uio); 293 1.1 cgd } 294 1.1 cgd 295 1.29 thorpej static int 296 1.29 thorpej ppirw(dev_t dev, struct uio *uio) 297 1.1 cgd { 298 1.41 cegger struct ppi_softc *sc = device_lookup_private(&ppi_cd, UNIT(dev)); 299 1.35 ad int s, s2, len, cnt; 300 1.12 scottr char *cp; 301 1.1 cgd int error = 0, gotdata = 0; 302 1.48 thorpej int ctlr, slave; 303 1.1 cgd char *buf; 304 1.1 cgd 305 1.1 cgd if (uio->uio_resid == 0) 306 1.34 tsutsui return 0; 307 1.1 cgd 308 1.39 tsutsui ctlr = device_unit(device_parent(sc->sc_dev)); 309 1.11 thorpej slave = sc->sc_slave; 310 1.11 thorpej 311 1.1 cgd #ifdef DEBUG 312 1.1 cgd if (ppidebug & (PDB_FOLLOW|PDB_IO)) 313 1.43 uebayasi printf("ppirw(%"PRIx64", %p, %c): burst %d, timo %d, resid %x\n", 314 1.1 cgd dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', 315 1.1 cgd sc->sc_burst, sc->sc_timo, uio->uio_resid); 316 1.1 cgd #endif 317 1.48 thorpej const int buflen = uimin(sc->sc_burst, uio->uio_resid); 318 1.48 thorpej buf = kmem_alloc(buflen, KM_SLEEP); 319 1.1 cgd sc->sc_flags |= PPIF_UIO; 320 1.1 cgd if (sc->sc_timo > 0) { 321 1.1 cgd sc->sc_flags |= PPIF_TIMO; 322 1.18 thorpej callout_reset(&sc->sc_timo_ch, sc->sc_timo, ppitimo, sc); 323 1.1 cgd } 324 1.12 scottr len = cnt = 0; 325 1.1 cgd while (uio->uio_resid > 0) { 326 1.47 riastrad len = uimin(buflen, uio->uio_resid); 327 1.1 cgd cp = buf; 328 1.1 cgd if (uio->uio_rw == UIO_WRITE) { 329 1.1 cgd error = uiomove(cp, len, uio); 330 1.1 cgd if (error) 331 1.1 cgd break; 332 1.1 cgd } 333 1.1 cgd again: 334 1.35 ad s = splsoftclock(); 335 1.35 ad s2 = splbio(); 336 1.11 thorpej if ((sc->sc_flags & PPIF_UIO) && 337 1.39 tsutsui hpibreq(device_parent(sc->sc_dev), &sc->sc_hq) == 0) 338 1.19 thorpej (void) tsleep(sc, PRIBIO + 1, "ppirw", 0); 339 1.1 cgd /* 340 1.1 cgd * Check if we timed out during sleep or uiomove 341 1.1 cgd */ 342 1.35 ad splx(s2); 343 1.1 cgd if ((sc->sc_flags & PPIF_UIO) == 0) { 344 1.1 cgd #ifdef DEBUG 345 1.1 cgd if (ppidebug & PDB_IO) 346 1.10 christos printf("ppirw: uiomove/sleep timo, flags %x\n", 347 1.1 cgd sc->sc_flags); 348 1.1 cgd #endif 349 1.1 cgd if (sc->sc_flags & PPIF_TIMO) { 350 1.18 thorpej callout_stop(&sc->sc_timo_ch); 351 1.1 cgd sc->sc_flags &= ~PPIF_TIMO; 352 1.1 cgd } 353 1.1 cgd splx(s); 354 1.1 cgd break; 355 1.1 cgd } 356 1.1 cgd splx(s); 357 1.1 cgd /* 358 1.1 cgd * Perform the operation 359 1.1 cgd */ 360 1.1 cgd if (uio->uio_rw == UIO_WRITE) 361 1.11 thorpej cnt = hpibsend(ctlr, slave, sc->sc_sec, cp, len); 362 1.1 cgd else 363 1.11 thorpej cnt = hpibrecv(ctlr, slave, sc->sc_sec, cp, len); 364 1.1 cgd s = splbio(); 365 1.39 tsutsui hpibfree(device_parent(sc->sc_dev), &sc->sc_hq); 366 1.1 cgd #ifdef DEBUG 367 1.1 cgd if (ppidebug & PDB_IO) 368 1.13 scottr printf("ppirw: %s(%d, %d, %x, %p, %d) -> %d\n", 369 1.1 cgd uio->uio_rw == UIO_READ ? "recv" : "send", 370 1.11 thorpej ctlr, slave, sc->sc_sec, cp, len, cnt); 371 1.1 cgd #endif 372 1.1 cgd splx(s); 373 1.1 cgd if (uio->uio_rw == UIO_READ) { 374 1.1 cgd if (cnt) { 375 1.1 cgd error = uiomove(cp, cnt, uio); 376 1.1 cgd if (error) 377 1.1 cgd break; 378 1.1 cgd gotdata++; 379 1.1 cgd } 380 1.1 cgd /* 381 1.1 cgd * Didn't get anything this time, but did in the past. 382 1.1 cgd * Consider us done. 383 1.1 cgd */ 384 1.1 cgd else if (gotdata) 385 1.1 cgd break; 386 1.1 cgd } 387 1.1 cgd s = splsoftclock(); 388 1.1 cgd /* 389 1.1 cgd * Operation timeout (or non-blocking), quit now. 390 1.1 cgd */ 391 1.1 cgd if ((sc->sc_flags & PPIF_UIO) == 0) { 392 1.1 cgd #ifdef DEBUG 393 1.1 cgd if (ppidebug & PDB_IO) 394 1.10 christos printf("ppirw: timeout/done\n"); 395 1.1 cgd #endif 396 1.1 cgd splx(s); 397 1.1 cgd break; 398 1.1 cgd } 399 1.1 cgd /* 400 1.1 cgd * Implement inter-read delay 401 1.1 cgd */ 402 1.1 cgd if (sc->sc_delay > 0) { 403 1.1 cgd sc->sc_flags |= PPIF_DELAY; 404 1.18 thorpej callout_reset(&sc->sc_start_ch, sc->sc_delay, 405 1.18 thorpej ppistart, sc); 406 1.12 scottr error = tsleep(sc, (PCATCH|PZERO) + 1, "hpib", 0); 407 1.1 cgd if (error) { 408 1.1 cgd splx(s); 409 1.1 cgd break; 410 1.1 cgd } 411 1.1 cgd } 412 1.1 cgd splx(s); 413 1.1 cgd /* 414 1.1 cgd * Must not call uiomove again til we've used all data 415 1.1 cgd * that we already grabbed. 416 1.1 cgd */ 417 1.1 cgd if (uio->uio_rw == UIO_WRITE && cnt != len) { 418 1.1 cgd cp += cnt; 419 1.1 cgd len -= cnt; 420 1.1 cgd cnt = 0; 421 1.1 cgd goto again; 422 1.1 cgd } 423 1.1 cgd } 424 1.1 cgd s = splsoftclock(); 425 1.1 cgd if (sc->sc_flags & PPIF_TIMO) { 426 1.18 thorpej callout_stop(&sc->sc_timo_ch); 427 1.1 cgd sc->sc_flags &= ~PPIF_TIMO; 428 1.1 cgd } 429 1.1 cgd if (sc->sc_flags & PPIF_DELAY) { 430 1.18 thorpej callout_stop(&sc->sc_start_ch); 431 1.1 cgd sc->sc_flags &= ~PPIF_DELAY; 432 1.1 cgd } 433 1.1 cgd splx(s); 434 1.1 cgd /* 435 1.1 cgd * Adjust for those chars that we uiomove'ed but never wrote 436 1.1 cgd */ 437 1.1 cgd if (uio->uio_rw == UIO_WRITE && cnt != len) { 438 1.1 cgd uio->uio_resid += (len - cnt); 439 1.1 cgd #ifdef DEBUG 440 1.1 cgd if (ppidebug & PDB_IO) 441 1.10 christos printf("ppirw: short write, adjust by %d\n", 442 1.1 cgd len-cnt); 443 1.1 cgd #endif 444 1.1 cgd } 445 1.48 thorpej kmem_free(buf, buflen); 446 1.1 cgd #ifdef DEBUG 447 1.1 cgd if (ppidebug & (PDB_FOLLOW|PDB_IO)) 448 1.10 christos printf("ppirw: return %d, resid %d\n", error, uio->uio_resid); 449 1.1 cgd #endif 450 1.34 tsutsui return error; 451 1.1 cgd } 452 1.1 cgd 453 1.29 thorpej static int 454 1.36 christos ppiioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 455 1.1 cgd { 456 1.41 cegger struct ppi_softc *sc = device_lookup_private(&ppi_cd,UNIT(dev)); 457 1.1 cgd struct ppiparam *pp, *upp; 458 1.1 cgd int error = 0; 459 1.1 cgd 460 1.1 cgd switch (cmd) { 461 1.1 cgd case PPIIOCGPARAM: 462 1.1 cgd pp = &sc->sc_param; 463 1.1 cgd upp = (struct ppiparam *)data; 464 1.1 cgd upp->burst = pp->burst; 465 1.1 cgd upp->timo = ppihztoms(pp->timo); 466 1.1 cgd upp->delay = ppihztoms(pp->delay); 467 1.1 cgd break; 468 1.1 cgd case PPIIOCSPARAM: 469 1.1 cgd pp = &sc->sc_param; 470 1.1 cgd upp = (struct ppiparam *)data; 471 1.1 cgd if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX || 472 1.1 cgd upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX) 473 1.34 tsutsui return EINVAL; 474 1.1 cgd pp->burst = upp->burst; 475 1.1 cgd pp->timo = ppimstohz(upp->timo); 476 1.1 cgd pp->delay = ppimstohz(upp->delay); 477 1.1 cgd break; 478 1.1 cgd case PPIIOCSSEC: 479 1.1 cgd sc->sc_sec = *(int *)data; 480 1.1 cgd break; 481 1.1 cgd default: 482 1.34 tsutsui return EINVAL; 483 1.1 cgd } 484 1.34 tsutsui return error; 485 1.1 cgd } 486 1.1 cgd 487 1.29 thorpej static int 488 1.29 thorpej ppihztoms(int h) 489 1.1 cgd { 490 1.12 scottr int m = h; 491 1.1 cgd 492 1.1 cgd if (m > 0) 493 1.1 cgd m = m * 1000 / hz; 494 1.34 tsutsui return m; 495 1.1 cgd } 496 1.1 cgd 497 1.29 thorpej static int 498 1.29 thorpej ppimstohz(int m) 499 1.1 cgd { 500 1.12 scottr int h = m; 501 1.1 cgd 502 1.1 cgd if (h > 0) { 503 1.1 cgd h = h * hz / 1000; 504 1.1 cgd if (h == 0) 505 1.1 cgd h = 1000 / hz; 506 1.1 cgd } 507 1.34 tsutsui return h; 508 1.1 cgd } 509