150476Speter/*- 23455Sache * Copyright (c) 2004 Mark R V Murray 3166130Srafan * All rights reserved. 4156837Sru * 5245887Sbrooks * Redistribution and use in source and binary forms, with or without 6245887Sbrooks * modification, are permitted provided that the following conditions 7245887Sbrooks * are met: 8245887Sbrooks * 1. Redistributions of source code must retain the above copyright 9156813Sru * notice, this list of conditions and the following disclaimer 10156813Sru * in this position and unchanged. 11167358Srafan * 2. Redistributions in binary form must reproduce the above copyright 123410Sache * notice, this list of conditions and the following disclaimer in the 13167359Srafan * documentation and/or other materials provided with the distribution. 14195767Skensmith * 153410Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16166130Srafan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 173523Sache * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18166130Srafan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19166130Srafan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20166130Srafan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 213410Sache * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2250624Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23167359Srafan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24167359Srafan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25174999Srafan * 26167359Srafan */ 27167359Srafan 28166130Srafan#include <sys/cdefs.h> 29174999Srafan__FBSDID("$FreeBSD$"); 30166130Srafan 31167359Srafan#include <sys/param.h> 3297053Speter#include <sys/conf.h> 33166130Srafan#include <sys/kernel.h> 3497053Speter#include <sys/ioccom.h> 35166130Srafan#include <sys/module.h> 3697053Speter#include <sys/priv.h> 3797053Speter#include <sys/proc.h> 38166130Srafan#include <sys/systm.h> 39174999Srafan 40166130Srafan#include <machine/iodev.h> 41166130Srafan 42174999Srafan#include <dev/io/iodev.h> 43166130Srafan 44166130Srafanstatic int ioopen(struct cdev *dev, int flags, int fmt, 45166130Srafan struct thread *td); 46166130Srafanstatic int ioclose(struct cdev *dev, int flags, int fmt, 4797053Speter struct thread *td); 4897053Speterstatic int ioioctl(struct cdev *dev, u_long cmd, caddr_t data, 49166130Srafan int fflag, struct thread *td); 50174999Srafan 51174999Srafanstatic int iopio_read(struct iodev_pio_req *req); 52166130Srafanstatic int iopio_write(struct iodev_pio_req *req); 53166130Srafan 54166130Srafanstatic struct cdev *iodev; 5597053Speter 5697053Speterstatic struct cdevsw io_cdevsw = { 57166130Srafan .d_version = D_VERSION, 58166130Srafan .d_open = ioopen, 59166130Srafan .d_close = ioclose, 60166130Srafan .d_ioctl = ioioctl, 6197053Speter .d_name = "io", 62174999Srafan}; 63166130Srafan 643410Sache/* ARGSUSED */ 65167358Srafanstatic int 66167358Srafanioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, 67167358Srafan struct thread *td) 68167358Srafan{ 69167358Srafan int error; 70167358Srafan 71167358Srafan error = priv_check(td, PRIV_IO); 72167358Srafan if (error != 0) 733410Sache return (error); 74167358Srafan error = securelevel_gt(td->td_ucred, 0); 75167358Srafan if (error != 0) 76167358Srafan return (error); 77167358Srafan error = iodev_open(td); 78167358Srafan 79167358Srafan return (error); 80167358Srafan} 81167358Srafan 82167358Srafan/* ARGSUSED */ 83167358Srafanstatic int 843410Sacheioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, 85167358Srafan struct thread *td) 863410Sache{ 87167358Srafan 88167358Srafan return (iodev_close(td)); 89167358Srafan} 90167358Srafan 91167358Srafan/* ARGSUSED */ 92167358Srafanstatic int 93167358Srafanioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, 94167358Srafan int fflag __unused, struct thread *td __unused) 95167358Srafan{ 96167358Srafan struct iodev_pio_req *pio_req; 97167358Srafan int error; 98167358Srafan 99167358Srafan switch (cmd) { 100167358Srafan case IODEV_PIO: 101167358Srafan pio_req = (struct iodev_pio_req *)data; 102167358Srafan switch (pio_req->access) { 103167358Srafan case IODEV_PIO_READ: 104167358Srafan error = iopio_read(pio_req); 105167358Srafan break; 106167358Srafan case IODEV_PIO_WRITE: 107167358Srafan error = iopio_write(pio_req); 108167358Srafan break; 109167358Srafan default: 110167358Srafan error = EINVAL; 111167358Srafan break; 112167358Srafan } 113167358Srafan break; 114167358Srafan default: 115167358Srafan error = iodev_ioctl(cmd, data); 116167358Srafan } 117167358Srafan 118167358Srafan return (error); 119167358Srafan} 120167358Srafan 121167358Srafanstatic int 122167358Srafaniopio_read(struct iodev_pio_req *req) 123167358Srafan{ 124167358Srafan 125167358Srafan switch (req->width) { 126167358Srafan case 1: 127167358Srafan req->val = iodev_read_1(req->port); 128167358Srafan break; 129167358Srafan case 2: 130167358Srafan if (req->port & 1) { 131167358Srafan req->val = iodev_read_1(req->port); 132167358Srafan req->val |= iodev_read_1(req->port + 1) << 8; 133167358Srafan } else 134167358Srafan req->val = iodev_read_2(req->port); 135167358Srafan break; 136167358Srafan case 4: 137167358Srafan if (req->port & 1) { 138167358Srafan req->val = iodev_read_1(req->port); 139167358Srafan req->val |= iodev_read_2(req->port + 1) << 8; 140167358Srafan req->val |= iodev_read_1(req->port + 3) << 24; 141167358Srafan } else if (req->port & 2) { 142167358Srafan req->val = iodev_read_2(req->port); 143167358Srafan req->val |= iodev_read_2(req->port + 2) << 16; 144167358Srafan } else 145167358Srafan req->val = iodev_read_4(req->port); 146167358Srafan break; 147167358Srafan default: 148167358Srafan return (EINVAL); 149167358Srafan } 150167358Srafan 151167358Srafan return (0); 152167358Srafan} 153167358Srafan 154167358Srafanstatic int 155167358Srafaniopio_write(struct iodev_pio_req *req) 156167358Srafan{ 157167358Srafan 158167358Srafan switch (req->width) { 159167358Srafan case 1: 160167358Srafan iodev_write_1(req->port, req->val); 161167358Srafan break; 162167358Srafan case 2: 163167358Srafan if (req->port & 1) { 164167358Srafan iodev_write_1(req->port, req->val); 165167358Srafan iodev_write_1(req->port + 1, req->val >> 8); 166167358Srafan } else 167167358Srafan iodev_write_2(req->port, req->val); 168167358Srafan break; 169167358Srafan case 4: 170167358Srafan if (req->port & 1) { 171167358Srafan iodev_write_1(req->port, req->val); 17250624Speter iodev_write_2(req->port + 1, req->val >> 8); 173167358Srafan iodev_write_1(req->port + 3, req->val >> 24); 174167358Srafan } else if (req->port & 2) { 175167358Srafan iodev_write_2(req->port, req->val); 176167358Srafan iodev_write_2(req->port + 2, req->val >> 16); 177167358Srafan } else 178167358Srafan iodev_write_4(req->port, req->val); 179167358Srafan break; 180167358Srafan default: 181167358Srafan return (EINVAL); 182167358Srafan } 183167358Srafan 184167358Srafan return (0); 185167358Srafan} 186167358Srafan 187167358Srafan/* ARGSUSED */ 188174999Srafanstatic int 189167358Srafanio_modevent(module_t mod __unused, int type, void *data __unused) 190167358Srafan{ 191167358Srafan switch(type) { 192167358Srafan case MOD_LOAD: 193167358Srafan if (bootverbose) 194167358Srafan printf("io: <I/O>\n"); 195167358Srafan iodev = make_dev(&io_cdevsw, 0, 196167358Srafan UID_ROOT, GID_WHEEL, 0600, "io"); 197167358Srafan break; 198167358Srafan 199167358Srafan case MOD_UNLOAD: 200167358Srafan destroy_dev(iodev); 201167358Srafan break; 202167358Srafan 203167358Srafan case MOD_SHUTDOWN: 204167358Srafan break; 205167358Srafan 206167358Srafan default: 207167358Srafan return(EOPNOTSUPP); 208167358Srafan break; 209167358Srafan 210167358Srafan } 211167358Srafan 212167358Srafan return (0); 213167358Srafan} 214167358Srafan 215167358SrafanDEV_MODULE(io, io_modevent, NULL); 216167358SrafanMODULE_VERSION(io, 1); 217167358Srafan