sbin/newfs_hammer2: Fail if input size is < alignment size
[dragonfly.git] / sys / dev / misc / kbd / kbdsw.c
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 }