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$
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>
38230751Sjhibbits#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>
45230751Sjhibbits#include <dev/ofw/openfirm.h>
46230751Sjhibbits#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);
61230751Sjhibbitsstatic 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;
289230751Sjhibbits	uint32_t fkeys;
290230751Sjhibbits	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
307262671Sjhibbits	mtx_init(&sc->sc_mutex, KBD_DRIVER_NAME, NULL, MTX_DEF);
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
342230751Sjhibbits	handle = OF_finddevice("mac-io/via-pmu/adb/keyboard");
343230751Sjhibbits	if (handle != -1 && OF_getprop(handle, "AAPL,has-embedded-fn-keys",
344230751Sjhibbits	    &fkeys, sizeof(fkeys)) != -1) {
345230751Sjhibbits		static const char *key_names[] = {"F1", "F2", "F3", "F4", "F5",
346230751Sjhibbits		    "F6", "F7", "F8", "F9", "F10", "F11", "F12"};
347230751Sjhibbits		struct sysctl_ctx_list *ctx;
348230751Sjhibbits		struct sysctl_oid *tree;
349230751Sjhibbits		int i;
350230751Sjhibbits
351230751Sjhibbits		if (bootverbose)
352230751Sjhibbits			device_printf(dev, "Keyboard has embedded Fn keys\n");
353230751Sjhibbits
354230751Sjhibbits		for (i = 0; i < 12; i++) {
355230751Sjhibbits			uint32_t keyval;
356230751Sjhibbits			char buf[3];
357230751Sjhibbits			if (OF_getprop(handle, key_names[i], &keyval,
358230751Sjhibbits			    sizeof(keyval)) < 0)
359230751Sjhibbits				continue;
360230751Sjhibbits			buf[0] = 1;
361230751Sjhibbits			buf[1] = i+1;
362230751Sjhibbits			buf[2] = keyval;
363230751Sjhibbits			adb_write_register(dev, 0, 3, buf);
364230751Sjhibbits		}
365230751Sjhibbits		adb_write_register(dev, 1, 2, &(uint16_t){0});
366230751Sjhibbits
367230751Sjhibbits		ctx = device_get_sysctl_ctx(dev);
368230751Sjhibbits		tree = device_get_sysctl_tree(dev);
369230751Sjhibbits
370230751Sjhibbits		SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
371230751Sjhibbits		    "fn_keys_function_as_primary", CTLTYPE_INT | CTLFLAG_RW, sc,
372230751Sjhibbits		    0, adb_fn_keys, "I",
373230751Sjhibbits		    "Set the Fn keys to be their F-key type as default");
374230751Sjhibbits	}
375230751Sjhibbits
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);
426230751Sjhibbits		/* 0x7f is always the power button */
427230751Sjhibbits		if (data[0] == 0x7f && devctl_process_running()) {
428230751Sjhibbits			devctl_notify("PMU", "Button", "pressed", NULL);
429237773Sjhibbits			mtx_unlock(&sc->sc_mutex);
430230751Sjhibbits			return (0);
431230751Sjhibbits		} else if (data[0] == 0xff) {
432237773Sjhibbits			mtx_unlock(&sc->sc_mutex);
433230751Sjhibbits			return (0);	/* Ignore power button release. */
434230751Sjhibbits		}
435184299Snwhitehorn		if ((data[0] & 0x7f) == 57 && sc->buffers < 7) {
436184299Snwhitehorn			/* Fake the down/up cycle for caps lock */
437184299Snwhitehorn			sc->buffer[sc->buffers++] = data[0] & 0x7f;
438184299Snwhitehorn			sc->buffer[sc->buffers++] = (data[0] & 0x7f) | (1 << 7);
439184299Snwhitehorn		} else {
440184299Snwhitehorn			sc->buffer[sc->buffers++] = data[0];
441184299Snwhitehorn		}
442184299Snwhitehorn		if (sc->buffer[sc->buffers-1] < 0xff)
443184299Snwhitehorn			sc->last_press = sc->buffer[sc->buffers-1];
444184299Snwhitehorn
445184299Snwhitehorn		if ((data[1] & 0x7f) == 57 && sc->buffers < 7) {
446184299Snwhitehorn			/* Fake the down/up cycle for caps lock */
447184299Snwhitehorn			sc->buffer[sc->buffers++] = data[1] & 0x7f;
448184299Snwhitehorn			sc->buffer[sc->buffers++] = (data[1] & 0x7f) | (1 << 7);
449184299Snwhitehorn		} else {
450184299Snwhitehorn			sc->buffer[sc->buffers++] = data[1];
451184299Snwhitehorn		}
452184299Snwhitehorn
453184299Snwhitehorn		if (sc->buffer[sc->buffers-1] < 0xff)
454184299Snwhitehorn			sc->last_press = sc->buffer[sc->buffers-1];
455184299Snwhitehorn
456184299Snwhitehorn		/* Stop any existing key repeating */
457184299Snwhitehorn		callout_stop(&sc->sc_repeater);
458184299Snwhitehorn
459184299Snwhitehorn		/* Schedule a repeat callback on keydown */
460184299Snwhitehorn		if (!(sc->last_press & (1 << 7))) {
461184299Snwhitehorn			callout_reset(&sc->sc_repeater,
462184299Snwhitehorn			    ms_to_ticks(sc->sc_kbd.kb_delay1), akbd_repeat, sc);
463184299Snwhitehorn		}
464184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
465184299Snwhitehorn
466184299Snwhitehorn	cv_broadcast(&sc->sc_cv);
467184299Snwhitehorn
468184299Snwhitehorn	if (KBD_IS_ACTIVE(&sc->sc_kbd) && KBD_IS_BUSY(&sc->sc_kbd)) {
469184299Snwhitehorn		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
470184299Snwhitehorn			 KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
471184299Snwhitehorn	}
472184299Snwhitehorn
473184299Snwhitehorn	return (0);
474184299Snwhitehorn}
475184299Snwhitehorn
476184299Snwhitehornstatic void
477184299Snwhitehornakbd_repeat(void *xsc) {
478184299Snwhitehorn	struct adb_kbd_softc *sc = xsc;
479184299Snwhitehorn	int notify_kbd = 0;
480184299Snwhitehorn
481184299Snwhitehorn	/* Fake an up/down key repeat so long as we have the
482184299Snwhitehorn	   free buffers */
483184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
484184299Snwhitehorn		if (sc->buffers < 7) {
485184299Snwhitehorn			sc->buffer[sc->buffers++] = sc->last_press | (1 << 7);
486184299Snwhitehorn			sc->buffer[sc->buffers++] = sc->last_press;
487184299Snwhitehorn
488184299Snwhitehorn			notify_kbd = 1;
489184299Snwhitehorn		}
490184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
491184299Snwhitehorn
492184299Snwhitehorn	if (notify_kbd && KBD_IS_ACTIVE(&sc->sc_kbd)
493184299Snwhitehorn	    && KBD_IS_BUSY(&sc->sc_kbd)) {
494184299Snwhitehorn		sc->sc_kbd.kb_callback.kc_func(&sc->sc_kbd,
495184299Snwhitehorn		    KBDIO_KEYINPUT, sc->sc_kbd.kb_callback.kc_arg);
496184299Snwhitehorn	}
497184299Snwhitehorn
498184299Snwhitehorn	/* Reschedule the callout */
499184299Snwhitehorn	callout_reset(&sc->sc_repeater, ms_to_ticks(sc->sc_kbd.kb_delay2),
500184299Snwhitehorn	    akbd_repeat, sc);
501184299Snwhitehorn}
502184299Snwhitehorn
503184299Snwhitehornstatic int
504184299Snwhitehornakbd_configure(int flags)
505184299Snwhitehorn{
506184299Snwhitehorn	return 0;
507184299Snwhitehorn}
508184299Snwhitehorn
509184299Snwhitehornstatic int
510184299Snwhitehornakbd_probe(int unit, void *arg, int flags)
511184299Snwhitehorn{
512184299Snwhitehorn	return 0;
513184299Snwhitehorn}
514184299Snwhitehorn
515184299Snwhitehornstatic int
516184299Snwhitehornakbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
517184299Snwhitehorn{
518184299Snwhitehorn	return 0;
519184299Snwhitehorn}
520184299Snwhitehorn
521184299Snwhitehornstatic int
522184299Snwhitehornakbd_term(keyboard_t *kbd)
523184299Snwhitehorn{
524184299Snwhitehorn	return 0;
525184299Snwhitehorn}
526184299Snwhitehorn
527184299Snwhitehornstatic int
528184299Snwhitehornakbd_interrupt(keyboard_t *kbd, void *arg)
529184299Snwhitehorn{
530184299Snwhitehorn	return 0;
531184299Snwhitehorn}
532184299Snwhitehorn
533184299Snwhitehornstatic int
534184299Snwhitehornakbd_test_if(keyboard_t *kbd)
535184299Snwhitehorn{
536184299Snwhitehorn	return 0;
537184299Snwhitehorn}
538184299Snwhitehorn
539184299Snwhitehornstatic int
540184299Snwhitehornakbd_enable(keyboard_t *kbd)
541184299Snwhitehorn{
542184299Snwhitehorn	KBD_ACTIVATE(kbd);
543184299Snwhitehorn	return (0);
544184299Snwhitehorn}
545184299Snwhitehorn
546184299Snwhitehornstatic int
547184299Snwhitehornakbd_disable(keyboard_t *kbd)
548184299Snwhitehorn{
549184299Snwhitehorn	struct adb_kbd_softc *sc;
550184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
551184299Snwhitehorn
552184299Snwhitehorn	callout_stop(&sc->sc_repeater);
553184299Snwhitehorn	KBD_DEACTIVATE(kbd);
554184299Snwhitehorn	return (0);
555184299Snwhitehorn}
556184299Snwhitehorn
557184299Snwhitehornstatic int
558184299Snwhitehornakbd_read(keyboard_t *kbd, int wait)
559184299Snwhitehorn{
560184299Snwhitehorn	return (0);
561184299Snwhitehorn}
562184299Snwhitehorn
563184299Snwhitehornstatic int
564184299Snwhitehornakbd_check(keyboard_t *kbd)
565184299Snwhitehorn{
566184299Snwhitehorn	struct adb_kbd_softc *sc;
567184299Snwhitehorn
568184299Snwhitehorn	if (!KBD_IS_ACTIVE(kbd))
569184299Snwhitehorn		return (FALSE);
570184299Snwhitehorn
571184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
572184299Snwhitehorn
573184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
574186906Snwhitehorn#ifdef AKBD_EMULATE_ATKBD
575186906Snwhitehorn		if (sc->at_buffered_char[0]) {
576186906Snwhitehorn			mtx_unlock(&sc->sc_mutex);
577186906Snwhitehorn			return (TRUE);
578186906Snwhitehorn		}
579186906Snwhitehorn#endif
580186906Snwhitehorn
581184299Snwhitehorn		if (sc->buffers > 0) {
582184299Snwhitehorn			mtx_unlock(&sc->sc_mutex);
583184299Snwhitehorn			return (TRUE);
584184299Snwhitehorn		}
585184299Snwhitehorn	mtx_unlock(&sc->sc_mutex);
586184299Snwhitehorn
587184299Snwhitehorn	return (FALSE);
588184299Snwhitehorn}
589184299Snwhitehorn
590184299Snwhitehornstatic u_int
591184299Snwhitehornakbd_read_char(keyboard_t *kbd, int wait)
592184299Snwhitehorn{
593184299Snwhitehorn	struct adb_kbd_softc *sc;
594186906Snwhitehorn	uint16_t key;
595186906Snwhitehorn	uint8_t adb_code;
596184299Snwhitehorn	int i;
597184299Snwhitehorn
598184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
599184299Snwhitehorn
600184299Snwhitehorn	mtx_lock(&sc->sc_mutex);
601184299Snwhitehorn
602186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD)
603186906Snwhitehorn	if (sc->sc_mode == K_RAW && sc->at_buffered_char[0]) {
604186906Snwhitehorn		key = sc->at_buffered_char[0];
605186906Snwhitehorn		if (key & SCAN_PREFIX) {
606186906Snwhitehorn			sc->at_buffered_char[0] = key & ~SCAN_PREFIX;
607186906Snwhitehorn			key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
608186906Snwhitehorn		} else {
609186906Snwhitehorn			sc->at_buffered_char[0] = sc->at_buffered_char[1];
610186906Snwhitehorn			sc->at_buffered_char[1] = 0;
611184299Snwhitehorn		}
612184299Snwhitehorn
613186906Snwhitehorn		mtx_unlock(&sc->sc_mutex);
614184299Snwhitehorn
615186906Snwhitehorn		return (key);
616186906Snwhitehorn	}
617186906Snwhitehorn#endif
618184299Snwhitehorn
619186906Snwhitehorn	if (!sc->buffers && wait)
620186906Snwhitehorn		cv_wait(&sc->sc_cv,&sc->sc_mutex);
621184299Snwhitehorn
622186906Snwhitehorn	if (!sc->buffers) {
623186906Snwhitehorn		mtx_unlock(&sc->sc_mutex);
624186906Snwhitehorn		return (0);
625186906Snwhitehorn	}
626186906Snwhitehorn
627186906Snwhitehorn	adb_code = sc->buffer[0];
628186906Snwhitehorn
629186906Snwhitehorn	for (i = 1; i < sc->buffers; i++)
630186906Snwhitehorn		sc->buffer[i-1] = sc->buffer[i];
631186906Snwhitehorn
632186906Snwhitehorn	sc->buffers--;
633186906Snwhitehorn
634184299Snwhitehorn	#ifdef AKBD_EMULATE_ATKBD
635186906Snwhitehorn		key = adb_to_at_scancode_map[adb_code & 0x7f];
636186906Snwhitehorn		if (sc->sc_mode == K_CODE) {
637186906Snwhitehorn			/* Add the key-release bit */
638186906Snwhitehorn			key |= adb_code & 0x80;
639186906Snwhitehorn		} else if (sc->sc_mode == K_RAW) {
640186906Snwhitehorn			/*
641186906Snwhitehorn			 * In the raw case, we have to emulate the gross
642186906Snwhitehorn			 * variable-length AT keyboard thing. Since this code
643186906Snwhitehorn			 * is copied from sunkbd, which is the same code
644186906Snwhitehorn			 * as ukbd, it might be nice to have this centralized.
645186906Snwhitehorn			 */
646186906Snwhitehorn
647186906Snwhitehorn			key = keycode2scancode(key,
648186906Snwhitehorn			    0, adb_code & 0x80);
649186906Snwhitehorn
650186906Snwhitehorn			if (key & SCAN_PREFIX) {
651186906Snwhitehorn				if (key & SCAN_PREFIX_CTL) {
652186906Snwhitehorn					sc->at_buffered_char[0] =
653186906Snwhitehorn					    0x1d | (key & SCAN_RELEASE);
654186906Snwhitehorn					sc->at_buffered_char[1] =
655186906Snwhitehorn					    key & ~SCAN_PREFIX;
656186906Snwhitehorn				} else if (key & SCAN_PREFIX_SHIFT) {
657186906Snwhitehorn					sc->at_buffered_char[0] =
658186906Snwhitehorn					    0x2a | (key & SCAN_RELEASE);
659186906Snwhitehorn					sc->at_buffered_char[1] =
660186906Snwhitehorn					    key & ~SCAN_PREFIX_SHIFT;
661186906Snwhitehorn				} else {
662186906Snwhitehorn					sc->at_buffered_char[0] =
663186906Snwhitehorn					    key & ~SCAN_PREFIX;
664186906Snwhitehorn					sc->at_buffered_char[1] = 0;
665186906Snwhitehorn				}
666186906Snwhitehorn
667186906Snwhitehorn				key = (key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1;
668186906Snwhitehorn			}
669186906Snwhitehorn		}
670184299Snwhitehorn	#else
671186906Snwhitehorn		key = adb_code;
672184299Snwhitehorn	#endif
673184299Snwhitehorn
674186906Snwhitehorn	mtx_unlock(&sc->sc_mutex);
675186906Snwhitehorn
676186906Snwhitehorn	return (key);
677184299Snwhitehorn}
678184299Snwhitehorn
679184299Snwhitehornstatic int
680184299Snwhitehornakbd_check_char(keyboard_t *kbd)
681184299Snwhitehorn{
682184299Snwhitehorn	if (!KBD_IS_ACTIVE(kbd))
683184299Snwhitehorn		return (FALSE);
684184299Snwhitehorn
685184299Snwhitehorn	return (akbd_check(kbd));
686184299Snwhitehorn}
687184299Snwhitehorn
688184299Snwhitehornstatic int
689184299Snwhitehornset_typematic(keyboard_t *kbd, int code)
690184299Snwhitehorn{
691184299Snwhitehorn	/* These numbers are in microseconds, so convert to ticks */
692184299Snwhitehorn
693184299Snwhitehorn	static int delays[] = { 250, 500, 750, 1000 };
694184299Snwhitehorn	static int rates[] = {  34,  38,  42,  46,  50,  55,  59,  63,
695184299Snwhitehorn				68,  76,  84,  92, 100, 110, 118, 126,
696184299Snwhitehorn				136, 152, 168, 184, 200, 220, 236, 252,
697184299Snwhitehorn				272, 304, 336, 368, 400, 440, 472, 504 };
698184299Snwhitehorn
699184299Snwhitehorn	if (code & ~0x7f)
700184299Snwhitehorn		return EINVAL;
701184299Snwhitehorn	kbd->kb_delay1 = delays[(code >> 5) & 3];
702184299Snwhitehorn	kbd->kb_delay2 = rates[code & 0x1f];
703184299Snwhitehorn	return 0;
704184299Snwhitehorn}
705184299Snwhitehorn
706184299Snwhitehornstatic int akbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
707184299Snwhitehorn{
708184299Snwhitehorn	struct adb_kbd_softc *sc;
709184299Snwhitehorn	uint16_t r2;
710184299Snwhitehorn	int error;
711184299Snwhitehorn
712184299Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
713184299Snwhitehorn	error = 0;
714184299Snwhitehorn
715184299Snwhitehorn	switch (cmd) {
716184299Snwhitehorn	case KDGKBMODE:
717184299Snwhitehorn		*(int *)data = sc->sc_mode;
718184299Snwhitehorn		break;
719184299Snwhitehorn	case KDSKBMODE:
720184299Snwhitehorn		switch (*(int *)data) {
721184299Snwhitehorn		case K_XLATE:
722184299Snwhitehorn			if (sc->sc_mode != K_XLATE) {
723184299Snwhitehorn				/* make lock key state and LED state match */
724184299Snwhitehorn				sc->sc_state &= ~LOCK_MASK;
725184299Snwhitehorn				sc->sc_state |= KBD_LED_VAL(kbd);
726184299Snwhitehorn			}
727184299Snwhitehorn			/* FALLTHROUGH */
728184299Snwhitehorn		case K_RAW:
729184299Snwhitehorn		case K_CODE:
730184299Snwhitehorn			if (sc->sc_mode != *(int *)data)
731184299Snwhitehorn				sc->sc_mode = *(int *)data;
732184299Snwhitehorn			break;
733184299Snwhitehorn		default:
734184299Snwhitehorn			error = EINVAL;
735184299Snwhitehorn			break;
736184299Snwhitehorn		}
737184299Snwhitehorn
738184299Snwhitehorn		break;
739184299Snwhitehorn
740184299Snwhitehorn	case KDGETLED:
741184299Snwhitehorn		*(int *)data = KBD_LED_VAL(kbd);
742184299Snwhitehorn		break;
743184299Snwhitehorn
744184299Snwhitehorn	case KDSKBSTATE:
745184299Snwhitehorn		if (*(int *)data & ~LOCK_MASK) {
746184299Snwhitehorn			error = EINVAL;
747184299Snwhitehorn			break;
748184299Snwhitehorn		}
749184299Snwhitehorn		sc->sc_state &= ~LOCK_MASK;
750184299Snwhitehorn		sc->sc_state |= *(int *)data;
751184299Snwhitehorn
752184299Snwhitehorn		/* FALLTHROUGH */
753184299Snwhitehorn
754184299Snwhitehorn	case KDSETLED:
755184299Snwhitehorn		KBD_LED_VAL(kbd) = *(int *)data;
756184299Snwhitehorn
757184299Snwhitehorn		if (!sc->have_led_control)
758184299Snwhitehorn			break;
759184299Snwhitehorn
760184299Snwhitehorn		r2 = (~0 & 0x04) | 3;
761184299Snwhitehorn
762184299Snwhitehorn		if (*(int *)data & NLKED)
763184299Snwhitehorn			r2 &= ~1;
764184299Snwhitehorn		if (*(int *)data & CLKED)
765184299Snwhitehorn			r2 &= ~2;
766184299Snwhitehorn		if (*(int *)data & SLKED)
767184299Snwhitehorn			r2 &= ~4;
768184299Snwhitehorn
769184299Snwhitehorn		adb_send_packet(sc->sc_dev,ADB_COMMAND_LISTEN,2,
770184299Snwhitehorn			sizeof(uint16_t),(u_char *)&r2);
771184299Snwhitehorn
772184299Snwhitehorn		break;
773184299Snwhitehorn
774184299Snwhitehorn	case KDGKBSTATE:
775184299Snwhitehorn		*(int *)data = sc->sc_state & LOCK_MASK;
776184299Snwhitehorn		break;
777184299Snwhitehorn
778184299Snwhitehorn	case KDSETREPEAT:
779184299Snwhitehorn		if (!KBD_HAS_DEVICE(kbd))
780184299Snwhitehorn			return 0;
781184299Snwhitehorn		if (((int *)data)[1] < 0)
782184299Snwhitehorn			return EINVAL;
783184299Snwhitehorn		if (((int *)data)[0] < 0)
784184299Snwhitehorn			return EINVAL;
785184299Snwhitehorn		else if (((int *)data)[0] == 0)  /* fastest possible value */
786184299Snwhitehorn			kbd->kb_delay1 = 200;
787184299Snwhitehorn		else
788184299Snwhitehorn			kbd->kb_delay1 = ((int *)data)[0];
789184299Snwhitehorn		kbd->kb_delay2 = ((int *)data)[1];
790184299Snwhitehorn
791184299Snwhitehorn		break;
792184299Snwhitehorn
793184299Snwhitehorn	case KDSETRAD:
794184299Snwhitehorn		error = set_typematic(kbd, *(int *)data);
795184299Snwhitehorn		break;
796184299Snwhitehorn
797184299Snwhitehorn	case PIO_KEYMAP:
798224126Sed	case OPIO_KEYMAP:
799184299Snwhitehorn	case PIO_KEYMAPENT:
800184299Snwhitehorn	case PIO_DEADKEYMAP:
801184299Snwhitehorn	default:
802184299Snwhitehorn		return (genkbd_commonioctl(kbd, cmd, data));
803184299Snwhitehorn	}
804184299Snwhitehorn
805184299Snwhitehorn	return (error);
806184299Snwhitehorn}
807184299Snwhitehorn
808184299Snwhitehornstatic int akbd_lock(keyboard_t *kbd, int lock)
809184299Snwhitehorn{
810184299Snwhitehorn	return (0);
811184299Snwhitehorn}
812184299Snwhitehorn
813184299Snwhitehornstatic void akbd_clear_state(keyboard_t *kbd)
814184299Snwhitehorn{
815186906Snwhitehorn	struct adb_kbd_softc *sc;
816186906Snwhitehorn
817186906Snwhitehorn	sc = (struct adb_kbd_softc *)(kbd);
818186906Snwhitehorn
819186906Snwhitehorn	mtx_lock(&sc->sc_mutex);
820186906Snwhitehorn
821186906Snwhitehorn	sc->buffers = 0;
822186906Snwhitehorn	callout_stop(&sc->sc_repeater);
823186906Snwhitehorn
824186906Snwhitehorn#if defined(AKBD_EMULATE_ATKBD)
825186906Snwhitehorn	sc->at_buffered_char[0] = 0;
826186906Snwhitehorn	sc->at_buffered_char[1] = 0;
827186906Snwhitehorn#endif
828186906Snwhitehorn	mtx_unlock(&sc->sc_mutex);
829184299Snwhitehorn}
830184299Snwhitehorn
831184299Snwhitehornstatic int akbd_get_state(keyboard_t *kbd, void *buf, size_t len)
832184299Snwhitehorn{
833184299Snwhitehorn	return (0);
834184299Snwhitehorn}
835184299Snwhitehorn
836184299Snwhitehornstatic int akbd_set_state(keyboard_t *kbd, void *buf, size_t len)
837184299Snwhitehorn{
838184299Snwhitehorn	return (0);
839184299Snwhitehorn}
840184299Snwhitehorn
841184299Snwhitehornstatic int akbd_poll(keyboard_t *kbd, int on)
842184299Snwhitehorn{
843184299Snwhitehorn	return (0);
844184299Snwhitehorn}
845184299Snwhitehorn
846184299Snwhitehornstatic int
847184299Snwhitehornakbd_modevent(module_t mod, int type, void *data)
848184299Snwhitehorn{
849184299Snwhitehorn	switch (type) {
850184299Snwhitehorn	case MOD_LOAD:
851184299Snwhitehorn		kbd_add_driver(&akbd_kbd_driver);
852184299Snwhitehorn		break;
853184299Snwhitehorn
854184299Snwhitehorn	case MOD_UNLOAD:
855184299Snwhitehorn		kbd_delete_driver(&akbd_kbd_driver);
856184299Snwhitehorn		break;
857184299Snwhitehorn
858184299Snwhitehorn	default:
859184299Snwhitehorn		return (EOPNOTSUPP);
860184299Snwhitehorn	}
861184299Snwhitehorn
862184299Snwhitehorn	return (0);
863184299Snwhitehorn}
864184299Snwhitehorn
865230751Sjhibbitsstatic int
866230751Sjhibbitsadb_fn_keys(SYSCTL_HANDLER_ARGS)
867230751Sjhibbits{
868230751Sjhibbits	struct adb_kbd_softc *sc = arg1;
869230751Sjhibbits	int error;
870230751Sjhibbits	uint16_t is_fn_enabled;
871230751Sjhibbits	unsigned int is_fn_enabled_sysctl;
872230751Sjhibbits
873230751Sjhibbits	adb_read_register(sc->sc_dev, 1, &is_fn_enabled);
874230751Sjhibbits	is_fn_enabled &= 1;
875230751Sjhibbits	is_fn_enabled_sysctl = is_fn_enabled;
876230751Sjhibbits	error = sysctl_handle_int(oidp, &is_fn_enabled_sysctl, 0, req);
877230751Sjhibbits
878230751Sjhibbits	if (error || !req->newptr)
879230751Sjhibbits		return (error);
880230751Sjhibbits
881230751Sjhibbits	is_fn_enabled = is_fn_enabled_sysctl;
882230751Sjhibbits	if (is_fn_enabled != 1 && is_fn_enabled != 0)
883230751Sjhibbits		return (EINVAL);
884230751Sjhibbits
885230751Sjhibbits	adb_write_register(sc->sc_dev, 1, 2, &is_fn_enabled);
886230751Sjhibbits	return (0);
887230751Sjhibbits}
888230751Sjhibbits
889184299SnwhitehornDEV_MODULE(akbd, akbd_modevent, NULL);
890184299Snwhitehorn
891