spic.c revision 115703
1147997Srwatson/* 2147997Srwatson * Copyright (c) 2000 Nick Sayer 3147997Srwatson * All rights reserved. 4147997Srwatson * 5147997Srwatson * Redistribution and use in source and binary forms, with or without 6147997Srwatson * modification, are permitted provided that the following conditions 7147997Srwatson * are met: 8147997Srwatson * 1. Redistributions of source code must retain the above copyright 9147997Srwatson * notice, this list of conditions and the following disclaimer. 10147997Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11147997Srwatson * notice, this list of conditions and the following disclaimer in the 12147997Srwatson * documentation and/or other materials provided with the distribution. 13147997Srwatson * 14147997Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15147997Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16147997Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17147997Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18147997Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19147997Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20147997Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21147997Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22147997Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23147997Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24147997Srwatson * SUCH DAMAGE. 25147997Srwatson * 26147997Srwatson * spic -- the Sony Programmable I/O Controller 27147997Srwatson * 28147997Srwatson * This device exists on most recent Sony laptops. It is the means by which 29147997Srwatson * you can watch the Jog Dial and some other functions. 30147997Srwatson * 31147997Srwatson * At the moment, this driver merely tries to turn the jog dial into a 32148693Srwatson * device that moused can park on, with the intent of supplying a Z axis 33148627Srwatson * and mouse button out of the jog dial. I suspect that this device will 34148627Srwatson * end up having to support at least 2 different minor devices: One to be 35148627Srwatson * the jog wheel device for moused to camp out on and the other to perform 36147997Srwatson * all of the other miscelaneous functions of this device. But for now, 37148627Srwatson * the jog wheel is all you get. 38147997Srwatson * 39147997Srwatson * At the moment, the data sent back by the device is rather primitive. 40147997Srwatson * It sends a single character per event: 41148627Srwatson * u = up, d = down -- that's the jog button 42148627Srwatson * l = left, r = right -- that's the dial. 43155550Srwatson * "left" and "right" are rather caprecious. They actually represent 44147997Srwatson * ccw and cw, respectively 45147997Srwatson * 46147997Srwatson * What documentation exists is thanks to Andrew Tridge, and his page at 47147997Srwatson * http://samba.org/picturebook/ Special thanks also to Ian Dowse, who 48147997Srwatson * also provided sample code upon which this driver was based. 49147997Srwatson */ 50147997Srwatson 51148627Srwatson#include <sys/cdefs.h> 52148627Srwatson__FBSDID("$FreeBSD: head/sys/i386/isa/spic.c 115703 2003-06-02 16:32:55Z obrien $"); 53148627Srwatson 54148627Srwatson#include <sys/param.h> 55148627Srwatson#include <sys/systm.h> 56155547Srwatson#include <sys/kernel.h> 57155547Srwatson#include <sys/bus.h> 58148627Srwatson#include <machine/bus.h> 59148627Srwatson#include <sys/rman.h> 60148627Srwatson#include <machine/resource.h> 61147997Srwatson#include <isa/isavar.h> 62147997Srwatson#include <sys/poll.h> 63147997Srwatson#include <machine/pci_cfgreg.h> 64147997Srwatson#include <machine/clock.h> 65147997Srwatson#include <sys/tty.h> 66147997Srwatson#include <sys/conf.h> 67147997Srwatson#include <sys/fcntl.h> 68147997Srwatson#include <sys/malloc.h> 69147997Srwatson#include <sys/sysctl.h> 70147997Srwatson#include <sys/uio.h> 71147997Srwatson 72147997Srwatson#include <i386/isa/spicreg.h> 73147997Srwatson 74147997Srwatsonstatic int spic_pollrate; 75147997Srwatson 76147997SrwatsonSYSCTL_INT(_machdep, OID_AUTO, spic_pollrate, CTLFLAG_RW, &spic_pollrate, 0, "") 77147997Srwatson; 78147997Srwatson 79147997Srwatsondevclass_t spic_devclass; 80148357Srwatson 81147997Srwatsonstatic d_open_t spicopen; 82147997Srwatsonstatic d_close_t spicclose; 83147997Srwatsonstatic d_read_t spicread; 84148357Srwatsonstatic d_ioctl_t spicioctl; 85147997Srwatsonstatic d_poll_t spicpoll; 86147997Srwatson 87147997Srwatsonstatic struct cdevsw spic_cdevsw = { 88147997Srwatson .d_open = spicopen, 89147997Srwatson .d_close = spicclose, 90147997Srwatson .d_read = spicread, 91147997Srwatson .d_ioctl = spicioctl, 92147997Srwatson .d_poll = spicpoll, 93147997Srwatson .d_name = "spic", 94147997Srwatson .d_maj = CDEV_MAJOR, 95147997Srwatson}; 96148357Srwatson 97148357Srwatson#define SCBUFLEN 128 98148357Srwatson 99148357Srwatsonstruct spic_softc { 100147997Srwatson u_short sc_port_addr; 101147997Srwatson u_char sc_intr; 102147997Srwatson struct resource *sc_port_res,*sc_intr_res; 103148357Srwatson int sc_port_rid,sc_intr_rid; 104147997Srwatson int sc_opened; 105147997Srwatson int sc_sleeping; 106147997Srwatson int sc_buttonlast; 107147997Srwatson struct callout_handle sc_timeout_ch; 108148357Srwatson device_t sc_dev; 109147997Srwatson struct selinfo sc_rsel; 110147997Srwatson u_char sc_buf[SCBUFLEN]; 111147997Srwatson int sc_count; 112147997Srwatson int sc_model; 113147997Srwatson}; 114148357Srwatson 115148357Srwatsonstatic void 116148357Srwatsonwrite_port1(struct spic_softc *sc, u_char val) 117148357Srwatson{ 118147997Srwatson DELAY(10); 119147997Srwatson outb(sc->sc_port_addr, val); 120147997Srwatson} 121148357Srwatson 122147997Srwatsonstatic void 123147997Srwatsonwrite_port2(struct spic_softc *sc, u_char val) 124147997Srwatson{ 125147997Srwatson DELAY(10); 126147997Srwatson outb(sc->sc_port_addr + 4, val); 127147997Srwatson} 128147997Srwatson 129147997Srwatsonstatic u_char 130148357Srwatsonread_port1(struct spic_softc *sc) 131147997Srwatson{ 132147997Srwatson DELAY(10); 133147997Srwatson return inb(sc->sc_port_addr); 134147997Srwatson} 135147997Srwatson 136147997Srwatsonstatic u_char 137147997Srwatsonread_port2(struct spic_softc *sc) 138147997Srwatson{ 139147997Srwatson DELAY(10); 140147997Srwatson return inb(sc->sc_port_addr + 4); 141147997Srwatson} 142147997Srwatson 143148357Srwatsonstatic u_char 144148357Srwatsonread_port_cst(struct spic_softc *sc) 145148357Srwatson{ 146148357Srwatson DELAY(10); 147147997Srwatson return inb(SPIC_CST_IOPORT); 148147997Srwatson} 149147997Srwatson 150147997Srwatsonstatic void 151147997Srwatsonbusy_wait(struct spic_softc *sc) 152147997Srwatson{ 153147997Srwatson int i=0; 154147997Srwatson 155147997Srwatson while(read_port2(sc) & 2) { 156147997Srwatson DELAY(10); 157148357Srwatson if (i++>10000) { 158147997Srwatson printf("spic busy wait abort\n"); 159147997Srwatson return; 160147997Srwatson } 161147997Srwatson } 162147997Srwatson} 163147997Srwatson 164147997Srwatsonstatic void 165147997Srwatsonbusy_wait_cst(struct spic_softc *sc, int mask) 166148357Srwatson{ 167147997Srwatson int i=0; 168147997Srwatson 169147997Srwatson while(read_port_cst(sc) & mask) { 170147997Srwatson DELAY(10); 171147997Srwatson if (i++>10000) { 172148357Srwatson printf("spic busy wait abort\n"); 173147997Srwatson return; 174147997Srwatson } 175147997Srwatson } 176147997Srwatson} 177147997Srwatson 178147997Srwatsonstatic u_char 179147997Srwatsonspic_call1(struct spic_softc *sc, u_char dev) { 180147997Srwatson busy_wait(sc); 181147997Srwatson write_port2(sc, dev); 182147997Srwatson read_port2(sc); 183147997Srwatson return read_port1(sc); 184147997Srwatson} 185147997Srwatson 186147997Srwatsonstatic u_char 187147997Srwatsonspic_call2(struct spic_softc *sc, u_char dev, u_char fn) 188147997Srwatson{ 189147997Srwatson busy_wait(sc); 190147997Srwatson write_port2(sc, dev); 191147997Srwatson busy_wait(sc); 192147997Srwatson write_port1(sc, fn); 193147997Srwatson return read_port1(sc); 194148354Srwatson} 195147997Srwatson 196147997Srwatsonstatic void 197148619Srwatsonspic_ecrset(struct spic_softc *sc, u_int16_t addr, u_int16_t value) 198147997Srwatson{ 199148357Srwatson busy_wait_cst(sc, 3); 200147997Srwatson outb(SPIC_CST_IOPORT, 0x81); 201147997Srwatson busy_wait_cst(sc, 2); 202147997Srwatson outb(SPIC_DATA_IOPORT, addr); 203147997Srwatson busy_wait_cst(sc, 2); 204147997Srwatson outb(SPIC_DATA_IOPORT, value); 205147997Srwatson busy_wait_cst(sc, 2); 206148354Srwatson} 207147997Srwatson 208148007Srwatsonstatic void 209148007Srwatsonspic_type2_srs(struct spic_softc *sc) 210148071Srwatson{ 211148007Srwatson spic_ecrset(sc, SPIC_SHIB, (sc->sc_port_addr & 0xFF00) >> 8); 212147997Srwatson spic_ecrset(sc, SPIC_SLOB, sc->sc_port_addr & 0x00FF); 213147997Srwatson spic_ecrset(sc, SPIC_SIRQ, 0x00); /* using polling mode (IRQ=0)*/ 214147997Srwatson DELAY(10); 215147997Srwatson} 216147997Srwatson 217147997Srwatsonstatic int 218147997Srwatsonspic_probe(device_t dev) 219147997Srwatson{ 220147997Srwatson struct spic_softc *sc; 221147997Srwatson u_char t, spic_irq; 222147997Srwatson 223147997Srwatson sc = device_get_softc(dev); 224148007Srwatson 225148007Srwatson /* 226147997Srwatson * We can only have 1 of these. Attempting to probe for a unit 1 227147997Srwatson * will destroy the work we did for unit 0 228147997Srwatson */ 229147997Srwatson if (device_get_unit(dev)) 230147997Srwatson return ENXIO; 231148170Srwatson 232148381Srwatson bzero(sc, sizeof(struct spic_softc)); 233148381Srwatson 234148381Srwatson if (!(sc->sc_port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, 235148381Srwatson &sc->sc_port_rid, 0, ~0, 5, RF_ACTIVE))) { 236148381Srwatson device_printf(dev,"Couldn't map I/O\n"); 237148381Srwatson return ENXIO; 238148381Srwatson } 239148619Srwatson sc->sc_port_addr = (u_short)rman_get_start(sc->sc_port_res); 240148381Srwatson 241148381Srwatson#ifdef notyet 242147997Srwatson if (!(sc->sc_intr_res = bus_alloc_resource(dev, SYS_RES_IRQ, 243147997Srwatson &sc->sc_intr_rid, 0, ~0, 1, RF_ACTIVE))) { 244147997Srwatson device_printf(dev,"Couldn't map IRQ\n"); 245147997Srwatson bus_release_resource(dev, SYS_RES_IOPORT, 246147997Srwatson sc->sc_port_rid, sc->sc_port_res); 247147997Srwatson return ENXIO; 248147997Srwatson } 249148627Srwatson sc->sc_intr = (u_short)rman_get_start(sc->sc_intr_res); 250148627Srwatson 251148627Srwatson switch (sc->sc_intr) { 252148627Srwatson case 0: spic_irq = 3; break; 253148627Srwatson case 5: spic_irq = 0; break; 254148627Srwatson case 0xa: spic_irq = 1; break; 255148627Srwatson case 0xb: spic_irq = 2; break; 256148627Srwatson default: device_printf(dev,"Invalid IRQ\n"); 257148627Srwatson bus_release_resource(dev, SYS_RES_IOPORT, 258148627Srwatson sc->sc_port_rid, sc->sc_port_res); 259148627Srwatson bus_release_resource(dev, SYS_RES_IRQ, 260148627Srwatson sc->sc_intr_rid, sc->sc_intr_res); 261148627Srwatson return ENXIO; 262148627Srwatson } 263148627Srwatson#else 264148627Srwatson spic_irq = 3; 265148627Srwatson#endif 266148627Srwatson 267148627Srwatson#if 0 268148627Srwatson if (sc->sc_port_addr != 0x10A0) { 269148627Srwatson bus_release_resource(dev, SYS_RES_IOPORT, 270148627Srwatson sc->sc_port_rid, sc->sc_port_res); 271148627Srwatson bus_release_resource(dev, SYS_RES_IRQ, 272148627Srwatson sc->sc_intr_rid, sc->sc_intr_res); 273148627Srwatson return ENXIO; 274148627Srwatson } 275148627Srwatson#endif 276148627Srwatson 277148627Srwatson /* PIIX4 chipset at least? */ 278148627Srwatson if (pci_cfgregread(PIIX4_BUS, PIIX4_SLOT, PIIX4_FUNC, 0, 4) == 279148627Srwatson PIIX4_DEVID) { 280148627Srwatson sc->sc_model = SPIC_DEVICE_MODEL_TYPE1; 281148627Srwatson } else { 282148627Srwatson /* For newer VAIOs (R505, SRX7, ...) */ 283148627Srwatson sc->sc_model = SPIC_DEVICE_MODEL_TYPE2; 284148627Srwatson } 285148627Srwatson 286148627Srwatson /* 287148627Srwatson * This is an ugly hack. It is necessary until ACPI works correctly. 288148627Srwatson * 289148627Srwatson * The SPIC consists of 2 registers. They are mapped onto I/O by the 290148627Srwatson * PIIX4's General Device 10 function. There is also an interrupt 291148627Srwatson * control port at a somewhat magic location, but this first pass is 292148627Srwatson * polled. 293148627Srwatson * 294148627Srwatson * So the first thing we need to do is map the G10 space in. 295148627Srwatson * 296148627Srwatson */ 297148627Srwatson 298148627Srwatson /* Enable ACPI mode to get Fn key events */ 299148627Srwatson /* XXX This may slow down your VAIO if ACPI is not supported in the kernel. 300148627Srwatson outb(0xb2, 0xf0); 301148627Srwatson */ 302148627Srwatson 303148627Srwatson device_printf(dev,"device model type = %d\n", sc->sc_model); 304148627Srwatson 305148627Srwatson if(sc->sc_model == SPIC_DEVICE_MODEL_TYPE1) { 306148627Srwatson pci_cfgregwrite(PIIX4_BUS, PIIX4_SLOT, PIIX4_FUNC, G10A, 307154416Srwatson sc->sc_port_addr, 2); 308148627Srwatson t = pci_cfgregread(PIIX4_BUS, PIIX4_SLOT, PIIX4_FUNC, G10L, 1); 309148627Srwatson t &= 0xf0; 310155550Srwatson t |= 4; 311148627Srwatson pci_cfgregwrite(PIIX4_BUS, PIIX4_SLOT, PIIX4_FUNC, G10L, t, 1); 312148627Srwatson outw(SPIC_IRQ_PORT, (inw(SPIC_IRQ_PORT) & ~(0x3 << SPIC_IRQ_SHIFT)) | (spic_irq << SPIC_IRQ_SHIFT)); 313148627Srwatson t = pci_cfgregread(PIIX4_BUS, PIIX4_SLOT, PIIX4_FUNC, G10L, 1); 314148627Srwatson t &= 0x1f; 315155547Srwatson t |= 0xc0; 316148627Srwatson pci_cfgregwrite(PIIX4_BUS, PIIX4_SLOT, PIIX4_FUNC, G10L, t, 1); 317148627Srwatson } else { 318148627Srwatson spic_type2_srs(sc); 319148627Srwatson } 320148627Srwatson 321148627Srwatson /* 322148627Srwatson * XXX: Should try and see if there's anything actually there. 323148627Srwatson */ 324148627Srwatson 325148627Srwatson device_set_desc(dev, "Sony Programmable I/O Controller"); 326148627Srwatson 327148627Srwatson return 0; 328148627Srwatson} 329148627Srwatson 330148627Srwatsonstatic int 331148627Srwatsonspic_attach(device_t dev) 332148627Srwatson{ 333148627Srwatson struct spic_softc *sc; 334148627Srwatson 335148627Srwatson sc = device_get_softc(dev); 336148627Srwatson 337148627Srwatson sc->sc_dev = dev; 338148627Srwatson 339155547Srwatson spic_pollrate = (hz/50); /* Every 50th of a second */ 340155547Srwatson 341155547Srwatson spic_call1(sc, 0x82); 342155547Srwatson spic_call2(sc, 0x81, 0xff); 343155547Srwatson spic_call1(sc, 0x92); 344155550Srwatson 345155550Srwatson /* There can be only one */ 346155550Srwatson make_dev(&spic_cdevsw, 0, 0, 0, 0600, "jogdial"); 347155550Srwatson 348155550Srwatson return 0; 349148627Srwatson} 350148627Srwatson 351148627Srwatsonstatic void 352148627Srwatsonspictimeout(void *arg) 353155550Srwatson{ 354148627Srwatson struct spic_softc *sc = arg; 355148627Srwatson u_char b, event, param; 356148627Srwatson int j; 357148627Srwatson 358148627Srwatson if (!sc->sc_opened) { 359148627Srwatson device_printf(sc->sc_dev, "timeout called while closed!\n"); 360148627Srwatson return; 361148627Srwatson } 362155550Srwatson 363148627Srwatson event = read_port2(sc); 364148627Srwatson param = read_port1(sc); 365148627Srwatson 366148627Srwatson if ((event != 4) && (!(event & 0x1))) 367155550Srwatson switch(event) { 368155550Srwatson case 0x10: /* jog wheel event (type1) */ 369155550Srwatson if (sc->sc_model == SPIC_DEVICE_MODEL_TYPE1) { 370155550Srwatson b = !!(param & 0x40); 371155550Srwatson if (b != sc->sc_buttonlast) { 372155550Srwatson sc->sc_buttonlast = b; 373155550Srwatson sc->sc_buf[sc->sc_count++] = 374155550Srwatson b?'d':'u'; 375155550Srwatson } 376148627Srwatson j = (param & 0xf) | ((param & 0x10)? ~0xf:0); 377148627Srwatson if (j<0) 378148627Srwatson while(j++!=0) { 379155550Srwatson sc->sc_buf[sc->sc_count++] = 380148627Srwatson 'l'; 381148627Srwatson } 382148627Srwatson else if (j>0) 383148627Srwatson while(j--!=0) { 384148627Srwatson sc->sc_buf[sc->sc_count++] = 385148627Srwatson 'r'; 386148627Srwatson } 387148627Srwatson } 388148627Srwatson break; 389148627Srwatson case 0x08: /* jog wheel event (type2) */ 390148627Srwatson case 0x00: 391148627Srwatson /* SPIC_DEVICE_MODEL_TYPE2 returns jog wheel event=0x00 */ 392148627Srwatson if (sc->sc_model == SPIC_DEVICE_MODEL_TYPE2) { 393155550Srwatson b = !!(param & 0x40); 394148627Srwatson if (b != sc->sc_buttonlast) { 395148627Srwatson sc->sc_buttonlast = b; 396148627Srwatson sc->sc_buf[sc->sc_count++] = 397148627Srwatson b?'d':'u'; 398148627Srwatson } 399148627Srwatson j = (param & 0xf) | ((param & 0x10)? ~0xf:0); 400148627Srwatson if (j<0) 401148627Srwatson while(j++!=0) { 402148627Srwatson sc->sc_buf[sc->sc_count++] = 403148627Srwatson 'l'; 404148627Srwatson } 405148627Srwatson else if (j>0) 406148627Srwatson while(j--!=0) { 407148627Srwatson sc->sc_buf[sc->sc_count++] = 408155547Srwatson 'r'; 409155547Srwatson } 410155550Srwatson } 411148627Srwatson break; 412148627Srwatson case 0x60: /* Capture button */ 413148627Srwatson printf("Capture button event: %x\n",param); 414148627Srwatson break; 415148627Srwatson case 0x30: /* Lid switch */ 416148627Srwatson printf("Lid switch event: %x\n",param); 417148627Srwatson break; 418155550Srwatson case 0x0c: /* We must ignore these type of event for C1VP... */ 419148627Srwatson case 0x70: /* Closing/Opening the lid on C1VP */ 420155549Srwatson break; 421148627Srwatson default: 422148627Srwatson printf("Unknown event: event %02x param %02x\n", event, param); 423148627Srwatson break; 424148627Srwatson } 425148627Srwatson else { 426148627Srwatson /* No event. Wait some more */ 427148627Srwatson sc->sc_timeout_ch = timeout(spictimeout, sc, spic_pollrate); 428148627Srwatson return; 429155550Srwatson } 430148627Srwatson 431155549Srwatson if (sc->sc_count) { 432148627Srwatson if (sc->sc_sleeping) { 433148627Srwatson sc->sc_sleeping = 0; 434148627Srwatson wakeup( sc); 435148627Srwatson } 436148627Srwatson selwakeup(&sc->sc_rsel); 437148627Srwatson } 438148627Srwatson spic_call2(sc, 0x81, 0xff); /* Clear event */ 439148627Srwatson 440148627Srwatson sc->sc_timeout_ch = timeout(spictimeout, sc, spic_pollrate); 441155542Srwatson} 442148627Srwatson 443148627Srwatsonstatic int 444148627Srwatsonspicopen(dev_t dev, int flag, int fmt, struct thread *td) 445148627Srwatson{ 446148627Srwatson struct spic_softc *sc; 447148627Srwatson 448148627Srwatson sc = devclass_get_softc(spic_devclass, 0); 449148627Srwatson 450148627Srwatson if (sc->sc_opened) 451148627Srwatson return EBUSY; 452148627Srwatson 453148627Srwatson sc->sc_opened++; 454148627Srwatson sc->sc_count=0; 455148627Srwatson 456148627Srwatson /* Start the polling */ 457148627Srwatson timeout(spictimeout, sc, spic_pollrate); 458148627Srwatson return 0; 459148627Srwatson} 460148627Srwatson 461148627Srwatsonstatic int 462148627Srwatsonspicclose(dev_t dev, int flag, int fmt, struct thread *td) 463155550Srwatson{ 464148627Srwatson struct spic_softc *sc; 465148627Srwatson 466 sc = devclass_get_softc(spic_devclass, 0); 467 468 /* Stop polling */ 469 untimeout(spictimeout, sc, sc->sc_timeout_ch); 470 sc->sc_opened = 0; 471 return 0; 472} 473 474static int 475spicread(dev_t dev, struct uio *uio, int flag) 476{ 477 struct spic_softc *sc; 478 int l, s, error; 479 u_char buf[SCBUFLEN]; 480 481 sc = devclass_get_softc(spic_devclass, 0); 482 483 if (uio->uio_resid <= 0) /* What kind of a read is this?! */ 484 return 0; 485 486 s = spltty(); 487 while (!(sc->sc_count)) { 488 sc->sc_sleeping=1; 489 error = tsleep( sc, PZERO | PCATCH, "jogrea", 0); 490 sc->sc_sleeping=0; 491 if (error) { 492 splx(s); 493 return error; 494 } 495 } 496 splx(s); 497 498 s = spltty(); 499 l = min(uio->uio_resid, sc->sc_count); 500 bcopy(sc->sc_buf, buf, l); 501 sc->sc_count -= l; 502 bcopy(sc->sc_buf + l, sc->sc_buf, l); 503 splx(s); 504 return uiomove(buf, l, uio); 505 506} 507 508static int 509spicioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 510{ 511 struct spic_softc *sc; 512 513 sc = devclass_get_softc(spic_devclass, 0); 514 515 return EIO; 516} 517 518static int 519spicpoll(dev_t dev, int events, struct thread *td) 520{ 521 struct spic_softc *sc; 522 int revents = 0, s; 523 524 sc = devclass_get_softc(spic_devclass, 0); 525 s = spltty(); 526 if (events & (POLLIN | POLLRDNORM)) { 527 if (sc->sc_count) 528 revents |= events & (POLLIN | POLLRDNORM); 529 else 530 selrecord(td, &sc->sc_rsel); /* Who shall we wake? */ 531 } 532 splx(s); 533 534 return revents; 535} 536 537 538static device_method_t spic_methods[] = { 539 DEVMETHOD(device_probe, spic_probe), 540 DEVMETHOD(device_attach, spic_attach), 541 542 { 0, 0 } 543}; 544 545static driver_t spic_driver = { 546 "spic", 547 spic_methods, 548 sizeof(struct spic_softc), 549}; 550 551DRIVER_MODULE(spic, isa, spic_driver, spic_devclass, 0, 0); 552 553