xref: /dragonfly/sys/dev/misc/kbd/kbdsw.c (revision e6d22e9b)
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