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