1/*- 2 * Copyright (c) 2004 Mark R V Murray 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 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h>
|
29__FBSDID("$FreeBSD: head/sys/dev/io/iodev.c 202097 2010-01-11 18:10:13Z marcel $");
|
29__FBSDID("$FreeBSD: head/sys/dev/io/iodev.c 207329 2010-04-28 15:38:01Z attilio $"); |
30 31#include <sys/param.h> 32#include <sys/conf.h>
|
33#include <sys/fcntl.h>
|
33#include <sys/kernel.h>
|
35#include <sys/lock.h>
36#include <sys/malloc.h>
|
34#include <sys/ioccom.h> |
35#include <sys/module.h>
|
38#include <sys/mutex.h>
|
36#include <sys/priv.h> |
37#include <sys/proc.h>
|
40#include <sys/signalvar.h>
|
38#include <sys/systm.h>
|
42#include <sys/uio.h>
|
39
|
44#include <vm/vm.h>
45#include <vm/pmap.h>
46
|
40#include <machine/iodev.h> 41
|
42#include <dev/io/iodev.h> 43 44static int ioopen(struct cdev *dev, int flags, int fmt, 45 struct thread *td); 46static int ioclose(struct cdev *dev, int flags, int fmt, 47 struct thread *td); 48static int ioioctl(struct cdev *dev, u_long cmd, caddr_t data, 49 int fflag, struct thread *td); 50 51static int iopio_read(struct iodev_pio_req *req); 52static int iopio_write(struct iodev_pio_req *req); 53 |
54static struct cdev *iodev; 55 56static struct cdevsw io_cdevsw = { 57 .d_version = D_VERSION, 58 .d_open = ioopen, 59 .d_close = ioclose, 60 .d_ioctl = ioioctl, 61 .d_name = "io", 62}; 63 64/* ARGSUSED */ 65static int
|
66ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, 67 struct thread *td) 68{ 69 int error; 70 71 error = priv_check(td, PRIV_IO); 72 if (error != 0) 73 return (error); 74 error = securelevel_gt(td->td_ucred, 0); 75 if (error != 0) 76 return (error); 77 error = iodev_open(td); 78 79 return (error); 80} 81 82/* ARGSUSED */ 83static int 84ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, 85 struct thread *td) 86{ 87 88 return (iodev_close(td)); 89} 90 91/* ARGSUSED */ 92static int 93ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, 94 int fflag __unused, struct thread *td __unused) 95{ 96 struct iodev_pio_req *pio_req; 97 int error; 98 99 switch (cmd) { 100 case IODEV_PIO: 101 pio_req = (struct iodev_pio_req *)data; 102 switch (pio_req->access) { 103 case IODEV_PIO_READ: 104 error = iopio_read(pio_req); 105 break; 106 case IODEV_PIO_WRITE: 107 error = iopio_write(pio_req); 108 break; 109 default: 110 error = EINVAL; 111 break; 112 } 113 break; 114 default: 115 error = iodev_ioctl(cmd, data); 116 } 117 118 return (error); 119} 120 121static int 122iopio_read(struct iodev_pio_req *req) 123{ 124 125 switch (req->width) { 126 case 1: 127 req->val = iodev_read_1(req->port); 128 break; 129 case 2: 130 if (req->port & 1) { 131 req->val = iodev_read_1(req->port); 132 req->val |= iodev_read_1(req->port + 1) << 8; 133 } else 134 req->val = iodev_read_2(req->port); 135 break; 136 case 4: 137 if (req->port & 1) { 138 req->val = iodev_read_1(req->port); 139 req->val |= iodev_read_2(req->port + 1) << 8; 140 req->val |= iodev_read_1(req->port + 3) << 24; 141 } else if (req->port & 2) { 142 req->val = iodev_read_2(req->port); 143 req->val |= iodev_read_2(req->port + 2) << 16; 144 } else 145 req->val = iodev_read_4(req->port); 146 break; 147 default: 148 return (EINVAL); 149 } 150 151 return (0); 152} 153 154static int 155iopio_write(struct iodev_pio_req *req) 156{ 157 158 switch (req->width) { 159 case 1: 160 iodev_write_1(req->port, req->val); 161 break; 162 case 2: 163 if (req->port & 1) { 164 iodev_write_1(req->port, req->val); 165 iodev_write_1(req->port + 1, req->val >> 8); 166 } else 167 iodev_write_2(req->port, req->val); 168 break; 169 case 4: 170 if (req->port & 1) { 171 iodev_write_1(req->port, req->val); 172 iodev_write_2(req->port + 1, req->val >> 8); 173 iodev_write_1(req->port + 3, req->val >> 24); 174 } else if (req->port & 2) { 175 iodev_write_2(req->port, req->val); 176 iodev_write_2(req->port + 2, req->val >> 16); 177 } else 178 iodev_write_4(req->port, req->val); 179 break; 180 default: 181 return (EINVAL); 182 } 183 184 return (0); 185} 186 187/* ARGSUSED */ 188static int |
189io_modevent(module_t mod __unused, int type, void *data __unused) 190{ 191 switch(type) { 192 case MOD_LOAD: 193 if (bootverbose) 194 printf("io: <I/O>\n"); 195 iodev = make_dev(&io_cdevsw, 0, 196 UID_ROOT, GID_WHEEL, 0600, "io"); 197 break; 198 199 case MOD_UNLOAD: 200 destroy_dev(iodev); 201 break; 202 203 case MOD_SHUTDOWN: 204 break; 205 206 default: 207 return(EOPNOTSUPP); 208 break; 209 210 } 211 212 return (0); 213} 214 215DEV_MODULE(io, io_modevent, NULL); 216MODULE_VERSION(io, 1);
|