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 51 #include <machine/console.h> 52 53 #include "kbdreg.h" 54 55 int 56 sw_probe(keyboard_switch_t *sw, int unit, void *arg, int flags) 57 { 58 int error; 59 60 error = (*sw->probe)(unit, arg, flags); 61 return (error); 62 } 63 64 int 65 sw_init(keyboard_switch_t *sw, int unit, keyboard_t **kbdpp, 66 void *arg, int flags) 67 { 68 int error; 69 70 error = (*sw->init)(unit, kbdpp, arg, flags); 71 return (error); 72 } 73 74 int 75 kbd_term(keyboard_t *kbd) 76 { 77 int error; 78 79 KBD_ALWAYS_LOCK(kbd); 80 error = (*kbdsw[kbd->kb_index]->term)(kbd); 81 if (error) 82 KBD_ALWAYS_UNLOCK(kbd); 83 /* kbd structure is stale if error is 0 */ 84 return (error); 85 } 86 87 /* 88 * Handle a keyboard interrupt. 89 * 90 * Be suspicious, just in case kbd_intr() is called from an interrupt 91 * before the keyboard switch is completely installed. 92 */ 93 int 94 kbd_intr(keyboard_t *kbd, void *arg) 95 { 96 int error; 97 int i; 98 KBD_LOCK_DECLARE; 99 100 error = EINVAL; 101 i = kbd->kb_index; 102 103 if (i >= 0 && i < KBD_MAXKEYBOARDS && kbdsw[i]) { 104 KBD_LOCK(kbd); 105 error = (*kbdsw[i]->intr)(kbd, arg); 106 KBD_UNLOCK(kbd); 107 } 108 return (error); 109 } 110 111 int 112 kbd_test_if(keyboard_t *kbd) 113 { 114 int error; 115 KBD_LOCK_DECLARE; 116 117 KBD_LOCK(kbd); 118 error = (*kbdsw[kbd->kb_index]->test_if)(kbd); 119 KBD_UNLOCK(kbd); 120 121 return (error); 122 } 123 124 int 125 kbd_enable(keyboard_t *kbd) 126 { 127 int error; 128 KBD_LOCK_DECLARE; 129 130 KBD_LOCK(kbd); 131 error = (*kbdsw[kbd->kb_index]->enable)(kbd); 132 KBD_UNLOCK(kbd); 133 134 return (error); 135 } 136 137 int 138 kbd_disable(keyboard_t *kbd) 139 { 140 int error; 141 KBD_LOCK_DECLARE; 142 143 KBD_LOCK(kbd); 144 error = (*kbdsw[kbd->kb_index]->disable)(kbd); 145 KBD_UNLOCK(kbd); 146 147 return (error); 148 } 149 150 int 151 kbd_read(keyboard_t *kbd, int wait) 152 { 153 int error; 154 KBD_LOCK_DECLARE; 155 156 KBD_LOCK(kbd); 157 error = (*kbdsw[kbd->kb_index]->read)(kbd, wait); 158 KBD_UNLOCK(kbd); 159 160 return (error); 161 } 162 163 int 164 kbd_check(keyboard_t *kbd) 165 { 166 int error; 167 KBD_LOCK_DECLARE; 168 169 KBD_LOCK(kbd); 170 error = (*kbdsw[kbd->kb_index]->check)(kbd); 171 KBD_UNLOCK(kbd); 172 173 return (error); 174 } 175 176 u_int 177 kbd_read_char(keyboard_t *kbd, int wait) 178 { 179 int error; 180 KBD_LOCK_DECLARE; 181 182 KBD_LOCK(kbd); 183 error = (*kbdsw[kbd->kb_index]->read_char)(kbd, wait); 184 KBD_UNLOCK(kbd); 185 186 return (error); 187 } 188 189 int 190 kbd_check_char(keyboard_t *kbd) 191 { 192 int error; 193 KBD_LOCK_DECLARE; 194 195 KBD_LOCK(kbd); 196 error = (*kbdsw[kbd->kb_index]->check_char)(kbd); 197 KBD_UNLOCK(kbd); 198 199 return (error); 200 } 201 202 int 203 kbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data) 204 { 205 int error; 206 KBD_LOCK_DECLARE; 207 208 if (kbd) { 209 KBD_LOCK(kbd); 210 error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, data); 211 KBD_UNLOCK(kbd); 212 } else { 213 error = ENODEV; 214 } 215 return (error); 216 } 217 218 int 219 kbd_lock(keyboard_t *kbd, int xlock) 220 { 221 int error; 222 KBD_LOCK_DECLARE; 223 224 KBD_LOCK(kbd); 225 error = (*kbdsw[kbd->kb_index]->lock)(kbd, xlock); 226 KBD_UNLOCK(kbd); 227 228 return (error); 229 } 230 231 void 232 kbd_clear_state(keyboard_t *kbd) 233 { 234 KBD_LOCK_DECLARE; 235 236 KBD_LOCK(kbd); 237 (*kbdsw[kbd->kb_index]->clear_state)(kbd); 238 KBD_UNLOCK(kbd); 239 } 240 241 int 242 kbd_get_state(keyboard_t *kbd, void *buf, size_t len) 243 { 244 int error; 245 KBD_LOCK_DECLARE; 246 247 KBD_LOCK(kbd); 248 error = (*kbdsw[kbd->kb_index]->get_state)(kbd, buf, len); 249 KBD_UNLOCK(kbd); 250 251 return (error); 252 } 253 254 int 255 kbd_set_state(keyboard_t *kbd, void *buf, size_t len) 256 { 257 int error; 258 KBD_LOCK_DECLARE; 259 260 KBD_LOCK(kbd); 261 error = (*kbdsw[kbd->kb_index]->set_state)(kbd, buf, len); 262 KBD_UNLOCK(kbd); 263 264 return (error); 265 } 266 267 u_char * 268 kbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 269 { 270 KBD_LOCK_DECLARE; 271 u_char *retstr; 272 273 KBD_LOCK(kbd); 274 retstr = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd, fkey, len); 275 KBD_UNLOCK(kbd); 276 277 return (retstr); 278 } 279 280 /* 281 * Polling mode set by debugger, we cannot lock! 282 */ 283 int 284 kbd_poll(keyboard_t *kbd, int on) 285 { 286 int error; 287 288 if (!on) 289 KBD_UNPOLL(kbd); 290 error = (*kbdsw[kbd->kb_index]->poll)(kbd, on); 291 if (on) 292 KBD_POLL(kbd); 293 294 return (error); 295 } 296 297 void 298 kbd_diag(keyboard_t *kbd, int level) 299 { 300 KBD_LOCK_DECLARE; 301 302 KBD_LOCK(kbd); 303 (*kbdsw[kbd->kb_index]->diag)(kbd, level); 304 KBD_UNLOCK(kbd); 305 } 306