1 /* 2 * (MPSAFE) 3 * 4 * Copyright (c) 2010 The DragonFly Project. All rights reserved. 5 * 6 * This code is derived from software contributed to The DragonFly Project 7 * by Matthew Dillon <dillon@backplane.com> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 3. Neither the name of The DragonFly Project nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific, prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include "opt_kbd.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/conf.h> 44 #include <sys/proc.h> 45 #include <sys/tty.h> 46 #include <sys/event.h> 47 #include <sys/vnode.h> 48 #include <sys/uio.h> 49 #include <sys/thread.h> 50 #include <sys/thread2.h> 51 52 #include <machine/console.h> 53 54 #include "kbdreg.h" 55 56 int 57 sw_probe(keyboard_switch_t *sw, int unit, void *arg, int flags) 58 { 59 int error; 60 61 error = (*sw->probe)(unit, arg, flags); 62 return (error); 63 } 64 65 int 66 sw_init(keyboard_switch_t *sw, int unit, keyboard_t **kbdpp, 67 void *arg, int flags) 68 { 69 int error; 70 71 error = (*sw->init)(unit, kbdpp, arg, flags); 72 return (error); 73 } 74 75 int 76 kbd_term(keyboard_t *kbd) 77 { 78 int error; 79 80 KBD_ALWAYS_LOCK(kbd); 81 error = (*kbdsw[kbd->kb_index]->term)(kbd); 82 if (error) 83 KBD_ALWAYS_UNLOCK(kbd); 84 /* kbd structure is stale if error is 0 */ 85 return (error); 86 } 87 88 /* 89 * Handle a keyboard interrupt. 90 * 91 * Be suspicious, just in case kbd_intr() is called from an interrupt 92 * before the keyboard switch is completely installed. 93 */ 94 int 95 kbd_intr(keyboard_t *kbd, void *arg) 96 { 97 int error; 98 int i; 99 KBD_LOCK_DECLARE; 100 101 error = EINVAL; 102 i = kbd->kb_index; 103 104 if (i >= 0 && i < KBD_MAXKEYBOARDS && kbdsw[i]) { 105 KBD_LOCK(kbd); 106 error = (*kbdsw[i]->intr)(kbd, arg); 107 KBD_UNLOCK(kbd); 108 } 109 return (error); 110 } 111 112 int 113 kbd_test_if(keyboard_t *kbd) 114 { 115 int error; 116 KBD_LOCK_DECLARE; 117 118 KBD_LOCK(kbd); 119 error = (*kbdsw[kbd->kb_index]->test_if)(kbd); 120 KBD_UNLOCK(kbd); 121 122 return (error); 123 } 124 125 int 126 kbd_enable(keyboard_t *kbd) 127 { 128 int error; 129 KBD_LOCK_DECLARE; 130 131 KBD_LOCK(kbd); 132 error = (*kbdsw[kbd->kb_index]->enable)(kbd); 133 KBD_UNLOCK(kbd); 134 135 return (error); 136 } 137 138 int 139 kbd_disable(keyboard_t *kbd) 140 { 141 int error; 142 KBD_LOCK_DECLARE; 143 144 KBD_LOCK(kbd); 145 error = (*kbdsw[kbd->kb_index]->disable)(kbd); 146 KBD_UNLOCK(kbd); 147 148 return (error); 149 } 150 151 int 152 kbd_read(keyboard_t *kbd, int wait) 153 { 154 int error; 155 KBD_LOCK_DECLARE; 156 157 KBD_LOCK(kbd); 158 error = (*kbdsw[kbd->kb_index]->read)(kbd, wait); 159 KBD_UNLOCK(kbd); 160 161 return (error); 162 } 163 164 int 165 kbd_check(keyboard_t *kbd) 166 { 167 int error; 168 KBD_LOCK_DECLARE; 169 170 KBD_LOCK(kbd); 171 error = (*kbdsw[kbd->kb_index]->check)(kbd); 172 KBD_UNLOCK(kbd); 173 174 return (error); 175 } 176 177 u_int 178 kbd_read_char(keyboard_t *kbd, int wait) 179 { 180 int error; 181 KBD_LOCK_DECLARE; 182 183 KBD_LOCK(kbd); 184 error = (*kbdsw[kbd->kb_index]->read_char)(kbd, wait); 185 KBD_UNLOCK(kbd); 186 187 return (error); 188 } 189 190 int 191 kbd_check_char(keyboard_t *kbd) 192 { 193 int error; 194 KBD_LOCK_DECLARE; 195 196 KBD_LOCK(kbd); 197 error = (*kbdsw[kbd->kb_index]->check_char)(kbd); 198 KBD_UNLOCK(kbd); 199 200 return (error); 201 } 202 203 int 204 kbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 205 { 206 int error; 207 KBD_LOCK_DECLARE; 208 209 if (kbd) { 210 KBD_LOCK(kbd); 211 error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, data); 212 KBD_UNLOCK(kbd); 213 } else { 214 error = ENODEV; 215 } 216 return (error); 217 } 218 219 int 220 kbd_lock(keyboard_t *kbd, int xlock) 221 { 222 int error; 223 KBD_LOCK_DECLARE; 224 225 KBD_LOCK(kbd); 226 error = (*kbdsw[kbd->kb_index]->lock)(kbd, xlock); 227 KBD_UNLOCK(kbd); 228 229 return (error); 230 } 231 232 void 233 kbd_clear_state(keyboard_t *kbd) 234 { 235 KBD_LOCK_DECLARE; 236 237 KBD_LOCK(kbd); 238 (*kbdsw[kbd->kb_index]->clear_state)(kbd); 239 KBD_UNLOCK(kbd); 240 } 241 242 int 243 kbd_get_state(keyboard_t *kbd, void *buf, size_t len) 244 { 245 int error; 246 KBD_LOCK_DECLARE; 247 248 KBD_LOCK(kbd); 249 error = (*kbdsw[kbd->kb_index]->get_state)(kbd, buf, len); 250 KBD_UNLOCK(kbd); 251 252 return (error); 253 } 254 255 int 256 kbd_set_state(keyboard_t *kbd, void *buf, size_t len) 257 { 258 int error; 259 KBD_LOCK_DECLARE; 260 261 KBD_LOCK(kbd); 262 error = (*kbdsw[kbd->kb_index]->set_state)(kbd, buf, len); 263 KBD_UNLOCK(kbd); 264 265 return (error); 266 } 267 268 u_char * 269 kbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 270 { 271 KBD_LOCK_DECLARE; 272 u_char *retstr; 273 274 KBD_LOCK(kbd); 275 retstr = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd, fkey, len); 276 KBD_UNLOCK(kbd); 277 278 return (retstr); 279 } 280 281 /* 282 * Polling mode set by debugger, we cannot lock! 283 */ 284 int 285 kbd_poll(keyboard_t *kbd, int on) 286 { 287 int error; 288 289 if (!on) 290 KBD_UNPOLL(kbd); 291 error = (*kbdsw[kbd->kb_index]->poll)(kbd, on); 292 if (on) 293 KBD_POLL(kbd); 294 295 return (error); 296 } 297 298 void 299 kbd_diag(keyboard_t *kbd, int level) 300 { 301 KBD_LOCK_DECLARE; 302 303 KBD_LOCK(kbd); 304 (*kbdsw[kbd->kb_index]->diag)(kbd, level); 305 KBD_UNLOCK(kbd); 306 } 307