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
sw_probe(keyboard_switch_t * sw,int unit,void * arg,int flags)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
sw_init(keyboard_switch_t * sw,int unit,keyboard_t ** kbdpp,void * arg,int flags)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
kbd_term(keyboard_t * kbd)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
kbd_intr(keyboard_t * kbd,void * arg)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
kbd_test_if(keyboard_t * kbd)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
kbd_enable(keyboard_t * kbd)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
kbd_disable(keyboard_t * kbd)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
kbd_read(keyboard_t * kbd,int wait)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
kbd_check(keyboard_t * kbd)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
kbd_read_char(keyboard_t * kbd,int wait)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
kbd_check_char(keyboard_t * kbd)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
kbd_ioctl(keyboard_t * kbd,u_long cmd,caddr_t data)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
kbd_lock(keyboard_t * kbd,int xlock)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
kbd_clear_state(keyboard_t * kbd)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
kbd_get_state(keyboard_t * kbd,void * buf,size_t len)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
kbd_set_state(keyboard_t * kbd,void * buf,size_t len)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 *
kbd_get_fkeystr(keyboard_t * kbd,int fkey,size_t * len)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
kbd_poll(keyboard_t * kbd,int on)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
kbd_diag(keyboard_t * kbd,int level)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