adb_kbd.c revision 226449
1184299Snwhitehorn/*-
2184299Snwhitehorn * Copyright (C) 2008 Nathan Whitehorn
3184299Snwhitehorn * All rights reserved.
4184299Snwhitehorn *
5184299Snwhitehorn * Redistribution and use in source and binary forms, with or without
6184299Snwhitehorn * modification, are permitted provided that the following conditions
7184299Snwhitehorn * are met:
8184299Snwhitehorn * 1. Redistributions of source code must retain the above copyright
9184299Snwhitehorn *    notice, this list of conditions and the following disclaimer.
10184299Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
11184299Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
12184299Snwhitehorn *    documentation and/or other materials provided with the distribution.
13184299Snwhitehorn *
14184299Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15184299Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16184299Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17184299Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18184299Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19184299Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20184299Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21184299Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22184299Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23184299Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24184299Snwhitehorn *
25184299Snwhitehorn * $FreeBSD: head/sys/dev/adb/adb_kbd.c 226449 2011-10-16 21:01:42Z nwhitehorn $
26184299Snwhitehorn */
27184299Snwhitehorn
28184299Snwhitehorn#include <sys/cdefs.h>
29184299Snwhitehorn#include <sys/param.h>
30184299Snwhitehorn#include <sys/systm.h>
31184299Snwhitehorn#include <sys/module.h>
32184299Snwhitehorn#include <sys/bus.h>
33184299Snwhitehorn#include <sys/conf.h>
34184299Snwhitehorn#include <sys/kbio.h>
35184299Snwhitehorn#include <sys/condvar.h>
36184299Snwhitehorn#include <sys/callout.h>
37184299Snwhitehorn#include <sys/kernel.h>
38226449Snwhitehorn#include <sys/sysctl.h>
39184299Snwhitehorn
40184299Snwhitehorn#include <machine/bus.h>
41184299Snwhitehorn
42184299Snwhitehorn#include "opt_kbd.h"
43184299Snwhitehorn#include <dev/kbd/kbdreg.h>
44184299Snwhitehorn#include <dev/kbd/kbdtables.h>
45226449Snwhitehorn#include <dev/ofw/openfirm.h>
46226449Snwhitehorn#include <dev/ofw/ofw_bus.h>
47184299Snwhitehorn
48184299Snwhitehorn#include <vm/vm.h>
49184299Snwhitehorn#include <vm/pmap.h>
50184299Snwhitehorn
51184299Snwhitehorn#include "adb.h"
52184299Snwhitehorn
53184299Snwhitehorn#define KBD_DRIVER_NAME "akbd"
54184299Snwhitehorn
55184299Snwhitehorn#define AKBD_EMULATE_ATKBD 1
56184299Snwhitehorn
57184299Snwhitehornstatic int adb_kbd_probe(device_t dev);
58184299Snwhitehornstatic int adb_kbd_attach(device_t dev);
59184299Snwhitehornstatic int adb_kbd_detach(device_t dev);
60184299Snwhitehornstatic void akbd_repeat(void *xsc);
61226449Snwhitehornstatic int adb_fn_keys(SYSCTL_HANDLER_ARGS);
62184299Snwhitehorn
63184299Snwhitehornstatic u_int adb_kbd_receive_packet(device_t dev, u_char status,
64184299Snwhitehorn	u_char command, u_char reg, int len, u_char *data);
65184299Snwhitehorn
66184299Snwhitehornstruct adb_kbd_softc {
67184299Snwhitehorn	keyboard_t sc_kbd;
68184299Snwhitehorn
69184299Snwhitehorn	device_t sc_dev;
70184299Snwhitehorn	struct mtx sc_mutex;
71184299Snwhitehorn	struct cv  sc_cv;
72184299Snwhitehorn
73184299Snwhitehorn	int sc_mode;
74184299Snwhitehorn	int sc_state;
75184299Snwhitehorn
76184299Snwhitehorn	int have_led_control;
77184299Snwhitehorn
78184299Snwhitehorn	uint8_t buffer[8];
79186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD
80186906Snwhitehorn	uint8_t at_buffered_char[2];
81186906Snwhitehorn#endif
82184299Snwhitehorn	volatile int buffers;
83184299Snwhitehorn
84184299Snwhitehorn	struct callout sc_repeater;
85184299Snwhitehorn	int sc_repeatstart;
86184299Snwhitehorn	int sc_repeatcontinue;
87184299Snwhitehorn	uint8_t last_press;
88184299Snwhitehorn};
89184299Snwhitehorn
90184299Snwhitehornstatic device_method_t adb_kbd_methods[] = {
91184299Snwhitehorn	/* Device interface */
92184299Snwhitehorn	DEVMETHOD(device_probe,         adb_kbd_probe),
93184299Snwhitehorn        DEVMETHOD(device_attach,        adb_kbd_attach),
94184299Snwhitehorn        DEVMETHOD(device_detach,        adb_kbd_detach),
95184299Snwhitehorn        DEVMETHOD(device_shutdown,      bus_generic_shutdown),
96184299Snwhitehorn        DEVMETHOD(device_suspend,       bus_generic_suspend),
97184299Snwhitehorn        DEVMETHOD(device_resume,        bus_generic_resume),
98184299Snwhitehorn
99184299Snwhitehorn	/* ADB interface */
100184299Snwhitehorn	DEVMETHOD(adb_receive_packet,	adb_kbd_receive_packet),
101184299Snwhitehorn
102184299Snwhitehorn	{ 0, 0 }
103184299Snwhitehorn};
104184299Snwhitehorn
105184299Snwhitehornstatic driver_t adb_kbd_driver = {
106184299Snwhitehorn	"akbd",
107184299Snwhitehorn	adb_kbd_methods,
108184299Snwhitehorn	sizeof(struct adb_kbd_softc),
109184299Snwhitehorn};
110184299Snwhitehorn
111184299Snwhitehornstatic devclass_t adb_kbd_devclass;
112184299Snwhitehorn
113184299SnwhitehornDRIVER_MODULE(akbd, adb, adb_kbd_driver, adb_kbd_devclass, 0, 0);
114184299Snwhitehorn
115186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD
116186906Snwhitehorn
117186906Snwhitehorn#define	SCAN_PRESS		0x000
118186906Snwhitehorn#define	SCAN_RELEASE		0x080
119186906Snwhitehorn#define	SCAN_PREFIX_E0		0x100
120186906Snwhitehorn#define	SCAN_PREFIX_E1		0x200
121186906Snwhitehorn#define	SCAN_PREFIX_CTL		0x400
122186906Snwhitehorn#define	SCAN_PREFIX_SHIFT	0x800
123186906Snwhitehorn#define	SCAN_PREFIX		(SCAN_PREFIX_E0 | SCAN_PREFIX_E1 |	\
124186906Snwhitehorn				SCAN_PREFIX_CTL | SCAN_PREFIX_SHIFT)
125186906Snwhitehorn
126184299Snwhitehornstatic const uint8_t adb_to_at_scancode_map[128] = { 30, 31, 32, 33, 35, 34,
127184299Snwhitehorn	44, 45, 46, 47, 0, 48, 16, 17, 18, 19, 21, 20, 2, 3, 4, 5, 7, 6, 13,
128184299Snwhitehorn	10, 8, 12, 9, 11, 27, 24, 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43,
129184299Snwhitehorn	51, 53, 49, 50, 52, 15, 57, 41, 14, 0, 1, 29, 0, 42, 58, 56, 97, 98,
130184299Snwhitehorn	100, 95, 0, 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 91, 89, 0, 74, 13, 0,
131184299Snwhitehorn	0, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73, 0, 0, 0, 63, 64, 65, 61,
132184299Snwhitehorn	66, 67, 0, 87, 0, 105, 0, 70, 0, 68, 0, 88, 0, 107, 102, 94, 96, 103,
133184299Snwhitehorn	62, 99, 60, 101, 59, 54, 93, 90, 0, 0 };
134184299Snwhitehorn
135186906Snwhitehornstatic int
136186906Snwhitehornkeycode2scancode(int keycode, int shift, int up)
137186906Snwhitehorn{
138186906Snwhitehorn	static const int scan[] = {
139186906Snwhitehorn		/* KP enter, right ctrl, KP divide */
140186906Snwhitehorn		0x1c , 0x1d , 0x35 ,
141186906Snwhitehorn		/* print screen */
142186906Snwhitehorn		0x37 | SCAN_PREFIX_SHIFT,
143186906Snwhitehorn		/* right alt, home, up, page up, left, right, end */
144186906Snwhitehorn		0x38, 0x47, 0x48, 0x49, 0x4b, 0x4d, 0x4f,
145186906Snwhitehorn		/* down, page down, insert, delete */
146186906Snwhitehorn		0x50, 0x51, 0x52, 0x53,
147186906Snwhitehorn		/* pause/break (see also below) */
148186906Snwhitehorn		0x46,
149186906Snwhitehorn		/*
150186906Snwhitehorn		 * MS: left window, right window, menu
151186906Snwhitehorn		 * also Sun: left meta, right meta, compose
152186906Snwhitehorn		 */
153186906Snwhitehorn		0x5b, 0x5c, 0x5d,
154186906Snwhitehorn		/* Sun type 6 USB */
155186906Snwhitehorn		/* help, stop, again, props, undo, front, copy */
156186906Snwhitehorn		0x68, 0x5e, 0x5f, 0x60,	0x61, 0x62, 0x63,
157186906Snwhitehorn		/* open, paste, find, cut, audiomute, audiolower, audioraise */
158186906Snwhitehorn		0x64, 0x65, 0x66, 0x67, 0x25, 0x1f, 0x1e,
159186906Snwhitehorn		/* power */
160186906Snwhitehorn		0x20
161186906Snwhitehorn	};
162186906Snwhitehorn	int scancode;
163186906Snwhitehorn
164186906Snwhitehorn	scancode = keycode;
165186906Snwhitehorn	if ((keycode >= 89) && (keycode < 89 + sizeof(scan) / sizeof(scan[0])))
166186906Snwhitehorn	scancode = scan[keycode - 89] | SCAN_PREFIX_E0;
167186906Snwhitehorn	/* pause/break */
168186906Snwhitehorn	if ((keycode == 104) && !(shift & CTLS))
169186906Snwhitehorn		scancode = 0x45 | SCAN_PREFIX_E1 | SCAN_PREFIX_CTL;
170186906Snwhitehorn	if (shift & SHIFTS)
171186906Snwhitehorn		scancode &= ~SCAN_PREFIX_SHIFT;
172186906Snwhitehorn	return (scancode | (up ? SCAN_RELEASE : SCAN_PRESS));
173186906Snwhitehorn}
174186906Snwhitehorn#endif
175186906Snwhitehorn
176184299Snwhitehorn/* keyboard driver declaration */
177184299Snwhitehornstatic int              akbd_configure(int flags);
178184299Snwhitehornstatic kbd_probe_t      akbd_probe;
179184299Snwhitehornstatic kbd_init_t       akbd_init;
180184299Snwhitehornstatic kbd_term_t       akbd_term;
181184299Snwhitehornstatic kbd_intr_t       akbd_interrupt;
182184299Snwhitehornstatic kbd_test_if_t    akbd_test_if;
183184299Snwhitehornstatic kbd_enable_t     akbd_enable;
184184299Snwhitehornstatic kbd_disable_t    akbd_disable;
185184299Snwhitehornstatic kbd_read_t       akbd_read;
186184299Snwhitehornstatic kbd_check_t      akbd_check;
187184299Snwhitehornstatic kbd_read_char_t  akbd_read_char;
188184299Snwhitehornstatic kbd_check_char_t akbd_check_char;
189184299Snwhitehornstatic kbd_ioctl_t      akbd_ioctl;
190184299Snwhitehornstatic kbd_lock_t       akbd_lock;
191184299Snwhitehornstatic kbd_clear_state_t akbd_clear_state;
192184299Snwhitehornstatic kbd_get_state_t  akbd_get_state;
193184299Snwhitehornstatic kbd_set_state_t  akbd_set_state;
194184299Snwhitehornstatic kbd_poll_mode_t  akbd_poll;
195184299Snwhitehorn
196184299Snwhitehornkeyboard_switch_t akbdsw = {
197184299Snwhitehorn        akbd_probe,
198184299Snwhitehorn        akbd_init,
199184299Snwhitehorn        akbd_term,
200184299Snwhitehorn        akbd_interrupt,
201184299Snwhitehorn        akbd_test_if,
202184299Snwhitehorn        akbd_enable,
203184299Snwhitehorn        akbd_disable,
204184299Snwhitehorn        akbd_read,
205184299Snwhitehorn        akbd_check,
206184299Snwhitehorn        akbd_read_char,
207184299Snwhitehorn        akbd_check_char,
208184299Snwhitehorn        akbd_ioctl,
209184299Snwhitehorn        akbd_lock,
210184299Snwhitehorn        akbd_clear_state,
211184299Snwhitehorn        akbd_get_state,
212184299Snwhitehorn        akbd_set_state,
213184299Snwhitehorn        genkbd_get_fkeystr,
214184299Snwhitehorn        akbd_poll,
215184299Snwhitehorn        genkbd_diag,
216184299Snwhitehorn};
217184299Snwhitehorn
218184299SnwhitehornKEYBOARD_DRIVER(akbd, akbdsw, akbd_configure);
219184299Snwhitehorn
220184299Snwhitehornstatic int
221184299Snwhitehornadb_kbd_probe(device_t dev)
222184299Snwhitehorn{
223184299Snwhitehorn	uint8_t type;
224184299Snwhitehorn
225184299Snwhitehorn	type = adb_get_device_type(dev);
226184299Snwhitehorn
227184299Snwhitehorn	if (type != ADB_DEVICE_KEYBOARD)
228184299Snwhitehorn		return (ENXIO);
229184299Snwhitehorn
230184299Snwhitehorn	switch(adb_get_device_handler(dev)) {
231184299Snwhitehorn	case 1:
232184299Snwhitehorn		device_set_desc(dev,"Apple Standard Keyboard");
233184299Snwhitehorn		break;
234184299Snwhitehorn	case 2:
235184299Snwhitehorn		device_set_desc(dev,"Apple Extended Keyboard");
236184299Snwhitehorn		break;
237184299Snwhitehorn	case 4:
238184299Snwhitehorn		device_set_desc(dev,"Apple ISO Keyboard");
239184299Snwhitehorn		break;
240184299Snwhitehorn	case 5:
241184299Snwhitehorn		device_set_desc(dev,"Apple Extended ISO Keyboard");
242184299Snwhitehorn		break;
243184299Snwhitehorn	case 8:
244184299Snwhitehorn		device_set_desc(dev,"Apple Keyboard II");
245184299Snwhitehorn		break;
246184299Snwhitehorn	case 9:
247184299Snwhitehorn		device_set_desc(dev,"Apple ISO Keyboard II");
248184299Snwhitehorn		break;
249184299Snwhitehorn	case 12:
250184299Snwhitehorn		device_set_desc(dev,"PowerBook Keyboard");
251184299Snwhitehorn		break;
252184299Snwhitehorn	case 13:
253184299Snwhitehorn		device_set_desc(dev,"PowerBook ISO Keyboard");
254184299Snwhitehorn		break;
255184299Snwhitehorn	case 24:
256184299Snwhitehorn		device_set_desc(dev,"PowerBook Extended Keyboard");
257184299Snwhitehorn		break;
258184299Snwhitehorn	case 27:
259184299Snwhitehorn		device_set_desc(dev,"Apple Design Keyboard");
260184299Snwhitehorn		break;
261184299Snwhitehorn	case 195:
262184299Snwhitehorn		device_set_desc(dev,"PowerBook G3 Keyboard");
263184299Snwhitehorn		break;
264184299Snwhitehorn	case 196:
265184299Snwhitehorn		device_set_desc(dev,"iBook Keyboard");
266184299Snwhitehorn		break;
267184299Snwhitehorn	default:
268184299Snwhitehorn		device_set_desc(dev,"ADB Keyboard");
269184299Snwhitehorn		break;
270184299Snwhitehorn	}
271184299Snwhitehorn
272184299Snwhitehorn	return (0);
273184299Snwhitehorn}
274184299Snwhitehorn
275184299Snwhitehornstatic int
276184299Snwhitehornms_to_ticks(int ms)
277184299Snwhitehorn{
278184299Snwhitehorn	if (hz > 1000)
279184299Snwhitehorn		return ms*(hz/1000);
280184299Snwhitehorn
281184299Snwhitehorn	return ms/(1000/hz);
282184299Snwhitehorn}
283184299Snwhitehorn
284184299Snwhitehornstatic int
285184299Snwhitehornadb_kbd_attach(device_t dev)
286184299Snwhitehorn{
287184299Snwhitehorn	struct adb_kbd_softc *sc;
288184299Snwhitehorn	keyboard_switch_t *sw;
289226449Snwhitehorn	uint32_t fkeys;
290226449Snwhitehorn	phandle_t handle;
291184299Snwhitehorn
292184299Snwhitehorn	sw = kbd_get_switch(KBD_DRIVER_NAME);
293184299Snwhitehorn	if (sw == NULL) {
294184299Snwhitehorn		return ENXIO;
295184299Snwhitehorn	}
296184299Snwhitehorn
297184299Snwhitehorn	sc = device_get_softc(dev);
298184299Snwhitehorn	sc->sc_dev = dev;
299184299Snwhitehorn	sc->sc_mode = K_RAW;
300184299Snwhitehorn	sc->sc_state = 0;
301184299Snwhitehorn	sc->have_led_control = 0;
302184299Snwhitehorn	sc->buffers = 0;
303184299Snwhitehorn
304184299Snwhitehorn	/* Try stepping forward to the extended keyboard protocol */
305184299Snwhitehorn	adb_set_device_handler(dev,3);
306184299Snwhitehorn
307184299Snwhitehorn	mtx_init(&sc->sc_mutex,KBD_DRIVER_NAME,MTX_DEF,0);
308184299Snwhitehorn	cv_init(&sc->sc_cv,KBD_DRIVER_NAME);
309184299Snwhitehorn	callout_init(&sc->sc_repeater, 0);
310184299Snwhitehorn
311184299Snwhitehorn#ifdef AKBD_EMULATE_ATKBD
312184299Snwhitehorn	kbd_init_struct(&sc->sc_kbd, KBD_DRIVER_NAME, KB_101, 0, 0, 0, 0);
313184299Snwhitehorn	kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab,
314184299Snwhitehorn            sizeof(fkey_tab) / sizeof(fkey_tab[0]));
315184299Snwhitehorn#else
316184299Snwhitehorn	#error ADB raw mode not implemented
317184299Snwhitehorn#endif
318184299Snwhitehorn
319184299Snwhitehorn	KBD_FOUND_DEVICE(&sc->sc_kbd);
320184299Snwhitehorn	KBD_PROBE_DONE(&sc->sc_kbd);
321184299Snwhitehorn	KBD_INIT_DONE(&sc->sc_kbd);
322184299Snwhitehorn	KBD_CONFIG_DONE(&sc->sc_kbd);
323184299Snwhitehorn
324184299Snwhitehorn	(*sw->enable)(&sc->sc_kbd);
325184299Snwhitehorn
326184299Snwhitehorn	kbd_register(&sc->sc_kbd);
327184299Snwhitehorn
328184299Snwhitehorn#ifdef KBD_INSTALL_CDEV
329184299Snwhitehorn	if (kbd_attach(&sc->sc_kbd)) {
330184299Snwhitehorn		adb_kbd_detach(dev);
331184299Snwhitehorn		return ENXIO;
332184299Snwhitehorn	}
333184299Snwhitehorn#endif
334184299Snwhitehorn
335185724Snwhitehorn	/* Check if we can read out the LED state from
336185724Snwhitehorn	   this keyboard by reading the key state register */
337185724Snwhitehorn	if (adb_read_register(dev, 2, NULL) == 2)
338185724Snwhitehorn		sc->have_led_control = 1;
339185724Snwhitehorn
340184299Snwhitehorn	adb_set_autopoll(dev,1);
341184299Snwhitehorn
342226449Snwhitehorn	handle = OF_finddevice("mac-io/via-pmu/adb/keyboard");
343226449Snwhitehorn	if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys",
344226449Snwhitehorn	    &fkeys, sizeof(fkeys)) != -1) {
345226449Snwhitehorn		static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5",
346226449Snwhitehorn		    "F6", "F7", "F8", "F9", "F10", "F11", "F12"};
347226449Snwhitehorn		struct sysctl_ctx_list *ctx;
348226449Snwhitehorn		struct sysctl_oid *tree;
349226449Snwhitehorn		int i;
350226449Snwhitehorn
351226449Snwhitehorn		if (bootverbose)
352226449Snwhitehorn			device_printf(dev, "Keyboard has embedded Fn keys\n");
353226449Snwhitehorn
354226449Snwhitehorn		for (i = 0; i < 12; i++) {
355226449Snwhitehorn			uint32_t keyval;
356226449Snwhitehorn			char buf[3];
357226449Snwhitehorn			if (OF_getprop(handle, key_names[i], &keyval,
358226449Snwhitehorn			    sizeof(keyval)) < 0)
359226449Snwhitehorn				continue;
360226449Snwhitehorn			buf[0] = 1;
361226449Snwhitehorn			buf[1] = i+1;
362226449Snwhitehorn			buf[2] = keyval;
363226449Snwhitehorn			adb_write_register(dev, 0, 3, buf);
364226449Snwhitehorn		}
365226449Snwhitehorn		adb_write_register(dev, 1, 2, &(uint16_t){0});
366226449Snwhitehorn
367226449Snwhitehorn		ctx = device_get_sysctl_ctx(dev);
368226449Snwhitehorn		tree = device_get_sysctl_tree(dev);
369226449Snwhitehorn
370226449Snwhitehorn		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
371226449Snwhitehorn		    "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc,
372226449Snwhitehorn		    0, adb_fn_keys, "I",
373226449Snwhitehorn		    "Set the Fn keys to be their F-key type as default");
374226449Snwhitehorn	}
375226449Snwhitehorn
376184299Snwhitehorn	return (0);
377184299Snwhitehorn}
378184299Snwhitehorn
379184299Snwhitehornstatic int
380184299Snwhitehornadb_kbd_detach(device_t dev)
381184299Snwhitehorn{
382184299Snwhitehorn	struct adb_kbd_softc *sc;
383184299Snwhitehorn	keyboard_t *kbd;
384184299Snwhitehorn
385184299Snwhitehorn	sc = device_get_softc(dev);
386184299Snwhitehorn
387184299Snwhitehorn	adb_set_autopoll(dev,0);
388184299Snwhitehorn	callout_stop(&sc->sc_repeater);
389184299Snwhitehorn
390184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
391184299Snwhitehorn
392184299Snwhitehorn	kbd = kbd_get_keyboard(kbd_find_keyboard(KBD_DRIVER_NAME,
393184299Snwhitehorn	          device_get_unit(dev)));
394184299Snwhitehorn
395184299Snwhitehorn	kbdd_disable(kbd);
396184299Snwhitehorn
397184299Snwhitehorn#ifdef KBD_INSTALL_CDEV
398184299Snwhitehorn	kbd_detach(kbd);
399184299Snwhitehorn#endif
400184299Snwhitehorn
401184299Snwhitehorn	kbdd_term(kbd);
402184299Snwhitehorn
403184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
404184299Snwhitehorn
405184299Snwhitehorn	mtx_destroy(&sc->sc_mutex);
406184299Snwhitehorn	cv_destroy(&sc->sc_cv);
407184299Snwhitehorn
408184299Snwhitehorn	return (0);
409184299Snwhitehorn}
410184299Snwhitehorn
411184299Snwhitehornstatic u_int
412184299Snwhitehornadb_kbd_receive_packet(device_t dev, u_char status,
413184299Snwhitehorn    u_char command, u_char reg, int len, u_char *data)
414184299Snwhitehorn{
415184299Snwhitehorn	struct adb_kbd_softc *sc;
416184299Snwhitehorn
417184299Snwhitehorn	sc = device_get_softc(dev);
418184299Snwhitehorn
419184299Snwhitehorn	if (command != ADB_COMMAND_TALK)
420184299Snwhitehorn		return 0;
421184299Snwhitehorn
422184299Snwhitehorn	if (reg != 0 || len != 2)
423184299Snwhitehorn		return (0);
424184299Snwhitehorn
425184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
426226449Snwhitehorn		/* 0x7f is always the power button */
427226449Snwhitehorn		if (data[0] == 0x7f && devctl_process_running()) {
428226449Snwhitehorn			devctl_notify("PMU", "Button", "pressed", NULL);
429226449Snwhitehorn			return (0);
430226449Snwhitehorn		} else if (data[0] == 0xff) {
431226449Snwhitehorn			return (0);	/* Ignore power button release. */
432226449Snwhitehorn		}
433184299Snwhitehorn		if ((data[0] & 0x7f) == 57 && sc->buffers < 7) {
434184299Snwhitehorn			/* Fake the down/up cycle for caps lock */
435184299Snwhitehorn			sc->buffer[sc->buffers++] = data[0] & 0x7f;
436184299Snwhitehorn			sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7);
437184299Snwhitehorn		} else {
438184299Snwhitehorn			sc->buffer[sc->buffers++] = data[0];
439184299Snwhitehorn		}
440184299Snwhitehorn		if (sc->buffer[sc->buffers-1] < 0xff)
441184299Snwhitehorn			sc->last_press = sc->buffer[sc->buffers-1];
442184299Snwhitehorn
443184299Snwhitehorn		if ((data[1] & 0x7f) == 57 && sc->buffers < 7) {
444184299Snwhitehorn			/* Fake the down/up cycle for caps lock */
445184299Snwhitehorn			sc->buffer[sc->buffers++] = data[1] & 0x7f;
446184299Snwhitehorn			sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7);
447184299Snwhitehorn		} else {
448184299Snwhitehorn			sc->buffer[sc->buffers++] = data[1];
449184299Snwhitehorn		}
450184299Snwhitehorn
451184299Snwhitehorn		if (sc->buffer[sc->buffers-1] < 0xff)
452184299Snwhitehorn			sc->last_press = sc->buffer[sc->buffers-1];
453184299Snwhitehorn
454184299Snwhitehorn		/* Stop any existing key repeating */
455184299Snwhitehorn		callout_stop(&sc->sc_repeater);
456184299Snwhitehorn
457184299Snwhitehorn		/* Schedule a repeat callback on keydown */
458184299Snwhitehorn		if (!(sc->last_press & (1 << 7))) {
459184299Snwhitehorn			callout_reset(&sc->sc_repeater,
460184299Snwhitehorn			    ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc);
461184299Snwhitehorn		}
462184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
463184299Snwhitehorn
464184299Snwhitehorn	cv_broadcast(&sc->sc_cv);
465184299Snwhitehorn
466184299Snwhitehorn	if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
467184299Snwhitehorn		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
468184299Snwhitehorn			 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
469184299Snwhitehorn	}
470184299Snwhitehorn
471184299Snwhitehorn	return (0);
472184299Snwhitehorn}
473184299Snwhitehorn
474184299Snwhitehornstatic void
475184299Snwhitehornakbd_repeat(void *xsc) {
476184299Snwhitehorn	struct adb_kbd_softc *sc = xsc;
477184299Snwhitehorn	int notify_kbd = 0;
478184299Snwhitehorn
479184299Snwhitehorn	/* Fake an up/down key repeat so long as we have the
480184299Snwhitehorn	   free buffers */
481184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
482184299Snwhitehorn		if (sc->buffers < 7) {
483184299Snwhitehorn			sc->buffer[sc->buffers++] = sc->last_press | (1 << 7);
484184299Snwhitehorn			sc->buffer[sc->buffers++] = sc->last_press;
485184299Snwhitehorn
486184299Snwhitehorn			notify_kbd = 1;
487184299Snwhitehorn		}
488184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
489184299Snwhitehorn
490184299Snwhitehorn	if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd)
491184299Snwhitehorn	    && KBD_IS_BUSY(&sc->sc_kbd)) {
492184299Snwhitehorn		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
493184299Snwhitehorn		    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
494184299Snwhitehorn	}
495184299Snwhitehorn
496184299Snwhitehorn	/* Reschedule the callout */
497184299Snwhitehorn	callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2),
498184299Snwhitehorn	    akbd_repeat, sc);
499184299Snwhitehorn}
500184299Snwhitehorn
501184299Snwhitehornstatic int
502184299Snwhitehornakbd_configure(int flags)
503184299Snwhitehorn{
504184299Snwhitehorn	return 0;
505184299Snwhitehorn}
506184299Snwhitehorn
507184299Snwhitehornstatic int
508184299Snwhitehornakbd_probe(int unit, void *arg, int flags)
509184299Snwhitehorn{
510184299Snwhitehorn	return 0;
511184299Snwhitehorn}
512184299Snwhitehorn
513184299Snwhitehornstatic int
514184299Snwhitehornakbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
515184299Snwhitehorn{
516184299Snwhitehorn	return 0;
517184299Snwhitehorn}
518184299Snwhitehorn
519184299Snwhitehornstatic int
520184299Snwhitehornakbd_term(keyboard_t *kbd)
521184299Snwhitehorn{
522184299Snwhitehorn	return 0;
523184299Snwhitehorn}
524184299Snwhitehorn
525184299Snwhitehornstatic int
526184299Snwhitehornakbd_interrupt(keyboard_t *kbd, void *arg)
527184299Snwhitehorn{
528184299Snwhitehorn	return 0;
529184299Snwhitehorn}
530184299Snwhitehorn
531184299Snwhitehornstatic int
532184299Snwhitehornakbd_test_if(keyboard_t *kbd)
533184299Snwhitehorn{
534184299Snwhitehorn	return 0;
535184299Snwhitehorn}
536184299Snwhitehorn
537184299Snwhitehornstatic int
538184299Snwhitehornakbd_enable(keyboard_t *kbd)
539184299Snwhitehorn{
540184299Snwhitehorn	KBD_ACTIVATE(kbd);
541184299Snwhitehorn	return (0);
542184299Snwhitehorn}
543184299Snwhitehorn
544184299Snwhitehornstatic int
545184299Snwhitehornakbd_disable(keyboard_t *kbd)
546184299Snwhitehorn{
547184299Snwhitehorn	struct adb_kbd_softc *sc;
548184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
549184299Snwhitehorn
550184299Snwhitehorn	callout_stop(&sc->sc_repeater);
551184299Snwhitehorn	KBD_DEACTIVATE(kbd);
552184299Snwhitehorn	return (0);
553184299Snwhitehorn}
554184299Snwhitehorn
555184299Snwhitehornstatic int
556184299Snwhitehornakbd_read(keyboard_t *kbd, int wait)
557184299Snwhitehorn{
558184299Snwhitehorn	return (0);
559184299Snwhitehorn}
560184299Snwhitehorn
561184299Snwhitehornstatic int
562184299Snwhitehornakbd_check(keyboard_t *kbd)
563184299Snwhitehorn{
564184299Snwhitehorn	struct adb_kbd_softc *sc;
565184299Snwhitehorn
566184299Snwhitehorn	if (!KBD_IS_ACTIVE(kbd))
567184299Snwhitehorn		return (FALSE);
568184299Snwhitehorn
569184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
570184299Snwhitehorn
571184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
572186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD
573186906Snwhitehorn		if (sc->at_buffered_char[0]) {
574186906Snwhitehorn			mtx_unlock(&sc->sc_mutex);
575186906Snwhitehorn			return (TRUE);
576186906Snwhitehorn		}
577186906Snwhitehorn#endif
578186906Snwhitehorn
579184299Snwhitehorn		if (sc->buffers > 0) {
580184299Snwhitehorn			mtx_unlock(&sc->sc_mutex);
581184299Snwhitehorn			return (TRUE);
582184299Snwhitehorn		}
583184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
584184299Snwhitehorn
585184299Snwhitehorn	return (FALSE);
586184299Snwhitehorn}
587184299Snwhitehorn
588184299Snwhitehornstatic u_int
589184299Snwhitehornakbd_read_char(keyboard_t *kbd, int wait)
590184299Snwhitehorn{
591184299Snwhitehorn	struct adb_kbd_softc *sc;
592186906Snwhitehorn	uint16_t key;
593186906Snwhitehorn	uint8_t adb_code;
594184299Snwhitehorn	int i;
595184299Snwhitehorn
596184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
597184299Snwhitehorn
598184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
599184299Snwhitehorn
600186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD)
601186906Snwhitehorn	if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) {
602186906Snwhitehorn		key = sc->at_buffered_char[0];
603186906Snwhitehorn		if (key & SCAN_PREFIX) {
604186906Snwhitehorn			sc->at_buffered_char[0] = key & ~SCAN_PREFIX;
605186906Snwhitehorn			key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
606186906Snwhitehorn		} else {
607186906Snwhitehorn			sc->at_buffered_char[0] = sc->at_buffered_char[1];
608186906Snwhitehorn			sc->at_buffered_char[1] = 0;
609184299Snwhitehorn		}
610184299Snwhitehorn
611186906Snwhitehorn		mtx_unlock(&sc->sc_mutex);
612184299Snwhitehorn
613186906Snwhitehorn		return (key);
614186906Snwhitehorn	}
615186906Snwhitehorn#endif
616184299Snwhitehorn
617186906Snwhitehorn	if (!sc->buffers && wait)
618186906Snwhitehorn		cv_wait(&sc->sc_cv,&sc->sc_mutex);
619184299Snwhitehorn
620186906Snwhitehorn	if (!sc->buffers) {
621186906Snwhitehorn		mtx_unlock(&sc->sc_mutex);
622186906Snwhitehorn		return (0);
623186906Snwhitehorn	}
624186906Snwhitehorn
625186906Snwhitehorn	adb_code = sc->buffer[0];
626186906Snwhitehorn
627186906Snwhitehorn	for (i = 1; i < sc->buffers; i++)
628186906Snwhitehorn		sc->buffer[i-1] = sc->buffer[i];
629186906Snwhitehorn
630186906Snwhitehorn	sc->buffers--;
631186906Snwhitehorn
632184299Snwhitehorn	#ifdef AKBD_EMULATE_ATKBD
633186906Snwhitehorn		key = adb_to_at_scancode_map[adb_code & 0x7f];
634186906Snwhitehorn		if (sc->sc_mode == K_CODE) {
635186906Snwhitehorn			/* Add the key-release bit */
636186906Snwhitehorn			key |= adb_code & 0x80;
637186906Snwhitehorn		} else if (sc->sc_mode == K_RAW) {
638186906Snwhitehorn			/*
639186906Snwhitehorn			 * In the raw case, we have to emulate the gross
640186906Snwhitehorn			 * variable-length AT keyboard thing. Since this code
641186906Snwhitehorn			 * is copied from sunkbd, which is the same code
642186906Snwhitehorn			 * as ukbd, it might be nice to have this centralized.
643186906Snwhitehorn			 */
644186906Snwhitehorn
645186906Snwhitehorn			key = keycode2scancode(key,
646186906Snwhitehorn			    0, adb_code & 0x80);
647186906Snwhitehorn
648186906Snwhitehorn			if (key & SCAN_PREFIX) {
649186906Snwhitehorn				if (key & SCAN_PREFIX_CTL) {
650186906Snwhitehorn					sc->at_buffered_char[0] =
651186906Snwhitehorn					    0x1d | (key & SCAN_RELEASE);
652186906Snwhitehorn					sc->at_buffered_char[1] =
653186906Snwhitehorn					    key & ~SCAN_PREFIX;
654186906Snwhitehorn				} else if (key & SCAN_PREFIX_SHIFT) {
655186906Snwhitehorn					sc->at_buffered_char[0] =
656186906Snwhitehorn					    0x2a | (key & SCAN_RELEASE);
657186906Snwhitehorn					sc->at_buffered_char[1] =
658186906Snwhitehorn					    key & ~SCAN_PREFIX_SHIFT;
659186906Snwhitehorn				} else {
660186906Snwhitehorn					sc->at_buffered_char[0] =
661186906Snwhitehorn					    key & ~SCAN_PREFIX;
662186906Snwhitehorn					sc->at_buffered_char[1] = 0;
663186906Snwhitehorn				}
664186906Snwhitehorn
665186906Snwhitehorn				key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
666186906Snwhitehorn			}
667186906Snwhitehorn		}
668184299Snwhitehorn	#else
669186906Snwhitehorn		key = adb_code;
670184299Snwhitehorn	#endif
671184299Snwhitehorn
672186906Snwhitehorn	mtx_unlock(&sc->sc_mutex);
673186906Snwhitehorn
674186906Snwhitehorn	return (key);
675184299Snwhitehorn}
676184299Snwhitehorn
677184299Snwhitehornstatic int
678184299Snwhitehornakbd_check_char(keyboard_t *kbd)
679184299Snwhitehorn{
680184299Snwhitehorn	if (!KBD_IS_ACTIVE(kbd))
681184299Snwhitehorn		return (FALSE);
682184299Snwhitehorn
683184299Snwhitehorn	return (akbd_check(kbd));
684184299Snwhitehorn}
685184299Snwhitehorn
686184299Snwhitehornstatic int
687184299Snwhitehornset_typematic(keyboard_t *kbd, int code)
688184299Snwhitehorn{
689184299Snwhitehorn	/* These numbers are in microseconds, so convert to ticks */
690184299Snwhitehorn
691184299Snwhitehorn	static int delays[] = { 250, 500, 750, 1000 };
692184299Snwhitehorn	static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
693184299Snwhitehorn				68,  76,  84,  92, 100, 110, 118, 126,
694184299Snwhitehorn				136, 152, 168, 184, 200, 220, 236, 252,
695184299Snwhitehorn				272, 304, 336, 368, 400, 440, 472, 504 };
696184299Snwhitehorn
697184299Snwhitehorn	if (code & ~0x7f)
698184299Snwhitehorn		return EINVAL;
699184299Snwhitehorn	kbd->kb_delay1 = delays[(code >> 5) & 3];
700184299Snwhitehorn	kbd->kb_delay2 = rates[code & 0x1f];
701184299Snwhitehorn	return 0;
702184299Snwhitehorn}
703184299Snwhitehorn
704184299Snwhitehornstatic int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
705184299Snwhitehorn{
706184299Snwhitehorn	struct adb_kbd_softc *sc;
707184299Snwhitehorn	uint16_t r2;
708184299Snwhitehorn	int error;
709184299Snwhitehorn
710184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
711184299Snwhitehorn	error = 0;
712184299Snwhitehorn
713184299Snwhitehorn	switch (cmd) {
714184299Snwhitehorn	case KDGKBMODE:
715184299Snwhitehorn		*(int *)data = sc->sc_mode;
716184299Snwhitehorn		break;
717184299Snwhitehorn	case KDSKBMODE:
718184299Snwhitehorn		switch (*(int *)data) {
719184299Snwhitehorn		case K_XLATE:
720184299Snwhitehorn			if (sc->sc_mode != K_XLATE) {
721184299Snwhitehorn				/* make lock key state and LED state match */
722184299Snwhitehorn				sc->sc_state &= ~LOCK_MASK;
723184299Snwhitehorn				sc->sc_state |= KBD_LED_VAL(kbd);
724184299Snwhitehorn			}
725184299Snwhitehorn			/* FALLTHROUGH */
726184299Snwhitehorn		case K_RAW:
727184299Snwhitehorn		case K_CODE:
728184299Snwhitehorn			if (sc->sc_mode != *(int *)data)
729184299Snwhitehorn				sc->sc_mode = *(int *)data;
730184299Snwhitehorn			break;
731184299Snwhitehorn		default:
732184299Snwhitehorn			error = EINVAL;
733184299Snwhitehorn			break;
734184299Snwhitehorn		}
735184299Snwhitehorn
736184299Snwhitehorn		break;
737184299Snwhitehorn
738184299Snwhitehorn	case KDGETLED:
739184299Snwhitehorn		*(int *)data = KBD_LED_VAL(kbd);
740184299Snwhitehorn		break;
741184299Snwhitehorn
742184299Snwhitehorn	case KDSKBSTATE:
743184299Snwhitehorn		if (*(int *)data & ~LOCK_MASK) {
744184299Snwhitehorn			error = EINVAL;
745184299Snwhitehorn			break;
746184299Snwhitehorn		}
747184299Snwhitehorn		sc->sc_state &= ~LOCK_MASK;
748184299Snwhitehorn		sc->sc_state |= *(int *)data;
749184299Snwhitehorn
750184299Snwhitehorn		/* FALLTHROUGH */
751184299Snwhitehorn
752184299Snwhitehorn	case KDSETLED:
753184299Snwhitehorn		KBD_LED_VAL(kbd) = *(int *)data;
754184299Snwhitehorn
755184299Snwhitehorn		if (!sc->have_led_control)
756184299Snwhitehorn			break;
757184299Snwhitehorn
758184299Snwhitehorn		r2 = (~0 & 0x04) | 3;
759184299Snwhitehorn
760184299Snwhitehorn		if (*(int *)data & NLKED)
761184299Snwhitehorn			r2 &= ~1;
762184299Snwhitehorn		if (*(int *)data & CLKED)
763184299Snwhitehorn			r2 &= ~2;
764184299Snwhitehorn		if (*(int *)data & SLKED)
765184299Snwhitehorn			r2 &= ~4;
766184299Snwhitehorn
767184299Snwhitehorn		adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2,
768184299Snwhitehorn			sizeof(uint16_t),(u_char *)&r2);
769184299Snwhitehorn
770184299Snwhitehorn		break;
771184299Snwhitehorn
772184299Snwhitehorn	case KDGKBSTATE:
773184299Snwhitehorn		*(int *)data = sc->sc_state & LOCK_MASK;
774184299Snwhitehorn		break;
775184299Snwhitehorn
776184299Snwhitehorn	case KDSETREPEAT:
777184299Snwhitehorn		if (!KBD_HAS_DEVICE(kbd))
778184299Snwhitehorn			return 0;
779184299Snwhitehorn		if (((int *)data)[1] < 0)
780184299Snwhitehorn			return EINVAL;
781184299Snwhitehorn		if (((int *)data)[0] < 0)
782184299Snwhitehorn			return EINVAL;
783184299Snwhitehorn		else if (((int *)data)[0] == 0)  /* fastest possible value */
784184299Snwhitehorn			kbd->kb_delay1 = 200;
785184299Snwhitehorn		else
786184299Snwhitehorn			kbd->kb_delay1 = ((int *)data)[0];
787184299Snwhitehorn		kbd->kb_delay2 = ((int *)data)[1];
788184299Snwhitehorn
789184299Snwhitehorn		break;
790184299Snwhitehorn
791184299Snwhitehorn	case KDSETRAD:
792184299Snwhitehorn		error = set_typematic(kbd, *(int *)data);
793184299Snwhitehorn		break;
794184299Snwhitehorn
795184299Snwhitehorn	case PIO_KEYMAP:
796224126Sed	case OPIO_KEYMAP:
797184299Snwhitehorn	case PIO_KEYMAPENT:
798184299Snwhitehorn	case PIO_DEADKEYMAP:
799184299Snwhitehorn	default:
800184299Snwhitehorn		return (genkbd_commonioctl(kbd, cmd, data));
801184299Snwhitehorn	}
802184299Snwhitehorn
803184299Snwhitehorn	return (error);
804184299Snwhitehorn}
805184299Snwhitehorn
806184299Snwhitehornstatic int akbd_lock(keyboard_t *kbd, int lock)
807184299Snwhitehorn{
808184299Snwhitehorn	return (0);
809184299Snwhitehorn}
810184299Snwhitehorn
811184299Snwhitehornstatic void akbd_clear_state(keyboard_t *kbd)
812184299Snwhitehorn{
813186906Snwhitehorn	struct adb_kbd_softc *sc;
814186906Snwhitehorn
815186906Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
816186906Snwhitehorn
817186906Snwhitehorn	mtx_lock(&sc->sc_mutex);
818186906Snwhitehorn
819186906Snwhitehorn	sc->buffers = 0;
820186906Snwhitehorn	callout_stop(&sc->sc_repeater);
821186906Snwhitehorn
822186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD)
823186906Snwhitehorn	sc->at_buffered_char[0] = 0;
824186906Snwhitehorn	sc->at_buffered_char[1] = 0;
825186906Snwhitehorn#endif
826186906Snwhitehorn	mtx_unlock(&sc->sc_mutex);
827184299Snwhitehorn}
828184299Snwhitehorn
829184299Snwhitehornstatic int akbd_get_state(keyboard_t *kbd, void *buf, size_t len)
830184299Snwhitehorn{
831184299Snwhitehorn	return (0);
832184299Snwhitehorn}
833184299Snwhitehorn
834184299Snwhitehornstatic int akbd_set_state(keyboard_t *kbd, void *buf, size_t len)
835184299Snwhitehorn{
836184299Snwhitehorn	return (0);
837184299Snwhitehorn}
838184299Snwhitehorn
839184299Snwhitehornstatic int akbd_poll(keyboard_t *kbd, int on)
840184299Snwhitehorn{
841184299Snwhitehorn	return (0);
842184299Snwhitehorn}
843184299Snwhitehorn
844184299Snwhitehornstatic int
845184299Snwhitehornakbd_modevent(module_t mod, int type, void *data)
846184299Snwhitehorn{
847184299Snwhitehorn	switch (type) {
848184299Snwhitehorn	case MOD_LOAD:
849184299Snwhitehorn		kbd_add_driver(&akbd_kbd_driver);
850184299Snwhitehorn		break;
851184299Snwhitehorn
852184299Snwhitehorn	case MOD_UNLOAD:
853184299Snwhitehorn		kbd_delete_driver(&akbd_kbd_driver);
854184299Snwhitehorn		break;
855184299Snwhitehorn
856184299Snwhitehorn	default:
857184299Snwhitehorn		return (EOPNOTSUPP);
858184299Snwhitehorn	}
859184299Snwhitehorn
860184299Snwhitehorn	return (0);
861184299Snwhitehorn}
862184299Snwhitehorn
863226449Snwhitehornstatic int
864226449Snwhitehornadb_fn_keys(SYSCTL_HANDLER_ARGS)
865226449Snwhitehorn{
866226449Snwhitehorn	struct adb_kbd_softc *sc = arg1;
867226449Snwhitehorn	int error;
868226449Snwhitehorn	uint16_t is_fn_enabled;
869226449Snwhitehorn	unsigned int is_fn_enabled_sysctl;
870226449Snwhitehorn
871226449Snwhitehorn	adb_read_register(sc->sc_dev, 1, &is_fn_enabled);
872226449Snwhitehorn	is_fn_enabled &= 1;
873226449Snwhitehorn	is_fn_enabled_sysctl = is_fn_enabled;
874226449Snwhitehorn	error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req);
875226449Snwhitehorn
876226449Snwhitehorn	if (error || !req->newptr)
877226449Snwhitehorn		return (error);
878226449Snwhitehorn
879226449Snwhitehorn	is_fn_enabled = is_fn_enabled_sysctl;
880226449Snwhitehorn	if (is_fn_enabled != 1 && is_fn_enabled != 0)
881226449Snwhitehorn		return (EINVAL);
882226449Snwhitehorn
883226449Snwhitehorn	adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled);
884226449Snwhitehorn	return (0);
885226449Snwhitehorn}
886226449Snwhitehorn
887184299SnwhitehornDEV_MODULE(akbd, akbd_modevent, NULL);
888184299Snwhitehorn
889