]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/pc98/cbus/pckbd.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / pc98 / cbus / pckbd.c
1 /*-
2  * Copyright (c) 1999 FreeBSD(98) port team.
3  * All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer as
10  *    the first lines of this file unmodified.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #include "opt_compat.h"
32 #include "opt_kbd.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/bus.h>
39 #include <machine/bus.h>
40 #include <sys/rman.h>
41 #include <sys/kbio.h>
42
43 #include <machine/resource.h>
44
45 #include <dev/kbd/kbdreg.h>
46
47 #include <pc98/cbus/cbus.h>
48 #include <isa/isavar.h>
49
50 #define DRIVER_NAME             "pckbd"
51
52 /* device configuration flags */
53 #define KB_CONF_FAIL_IF_NO_KBD  (1 << 0) /* don't install if no kbd is found */
54
55 static devclass_t       pckbd_devclass;
56
57 static int              pckbdprobe(device_t dev);
58 static int              pckbdattach(device_t dev);
59 static int              pckbdresume(device_t dev);
60 static void             pckbd_isa_intr(void *arg);
61
62 static device_method_t pckbd_methods[] = {
63         /* Device interface */
64         DEVMETHOD(device_probe,         pckbdprobe),
65         DEVMETHOD(device_attach,        pckbdattach),
66         DEVMETHOD(device_resume,        pckbdresume),
67         { 0, 0 }
68 };
69
70 static driver_t pckbd_driver = {
71         DRIVER_NAME,
72         pckbd_methods,
73         1,
74 };
75
76 DRIVER_MODULE(pckbd, isa, pckbd_driver, pckbd_devclass, 0, 0);
77
78 static bus_addr_t pckbd_iat[] = {0, 2};
79
80 static int              pckbd_probe_unit(int unit, int port, int irq,
81                                          int flags);
82 static int              pckbd_attach_unit(int unit, keyboard_t **kbd,
83                                           int port, int irq, int flags);
84 static timeout_t        pckbd_timeout;
85
86
87 static int
88 pckbdprobe(device_t dev)
89 {
90         struct resource *res;
91         int error, rid;
92
93         /* Check isapnp ids */
94         if (isa_get_vendorid(dev))
95                 return (ENXIO);
96
97         device_set_desc(dev, "PC-98 Keyboard");
98
99         rid = 0;
100         res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2,
101                                   RF_ACTIVE);
102         if (res == NULL)
103                 return ENXIO;
104         isa_load_resourcev(res, pckbd_iat, 2);
105
106         error = pckbd_probe_unit(device_get_unit(dev),
107                                  isa_get_port(dev),
108                                  (1 << isa_get_irq(dev)),
109                                  device_get_flags(dev));
110
111         bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
112
113         return (error);
114 }
115
116 static int
117 pckbdattach(device_t dev)
118 {
119         keyboard_t      *kbd;
120         void            *ih;
121         struct resource *res;
122         int             error, rid;
123
124         rid = 0;
125         res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, pckbd_iat, 2,
126                                   RF_ACTIVE);
127         if (res == NULL)
128                 return ENXIO;
129         isa_load_resourcev(res, pckbd_iat, 2);
130
131         error = pckbd_attach_unit(device_get_unit(dev), &kbd,
132                                   isa_get_port(dev),
133                                   (1 << isa_get_irq(dev)),
134                                   device_get_flags(dev));
135
136         rid = 0;
137         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
138         if (res == NULL)
139                 return ENXIO;
140         bus_setup_intr(dev, res, INTR_TYPE_TTY, NULL, pckbd_isa_intr, kbd, &ih);
141
142         return 0;
143 }
144
145 static int
146 pckbdresume(device_t dev)
147 {
148         keyboard_t *kbd;
149
150         kbd = kbd_get_keyboard(kbd_find_keyboard(DRIVER_NAME,
151                                                  device_get_unit(dev)));
152         if (kbd)
153                 kbdd_clear_state(kbd);
154
155         return (0);
156 }
157
158 static void
159 pckbd_isa_intr(void *arg)
160 {
161         keyboard_t      *kbd = arg;
162
163         kbdd_intr(kbd, NULL);
164 }
165
166 static int
167 pckbd_probe_unit(int unit, int port, int irq, int flags)
168 {
169         keyboard_switch_t *sw;
170         int args[2];
171         int error;
172
173         sw = kbd_get_switch(DRIVER_NAME);
174         if (sw == NULL)
175                 return ENXIO;
176
177         args[0] = port;
178         args[1] = irq;
179         error = (*sw->probe)(unit, args, flags);
180         if (error)
181                 return error;
182         return 0;
183 }
184
185 static int
186 pckbd_attach_unit(int unit, keyboard_t **kbd, int port, int irq, int flags)
187 {
188         keyboard_switch_t *sw;
189         int args[2];
190         int error;
191
192         sw = kbd_get_switch(DRIVER_NAME);
193         if (sw == NULL)
194                 return ENXIO;
195
196         /* reset, initialize and enable the device */
197         args[0] = port;
198         args[1] = irq;
199         *kbd = NULL;
200         error = (*sw->probe)(unit, args, flags);
201         if (error)
202                 return error;
203         error = (*sw->init)(unit, kbd, args, flags);
204         if (error)
205                 return error;
206         (*sw->enable)(*kbd);
207
208 #ifdef KBD_INSTALL_CDEV
209         /* attach a virtual keyboard cdev */
210         error = kbd_attach(*kbd);
211         if (error)
212                 return error;
213 #endif /* KBD_INSTALL_CDEV */
214
215         /*
216          * This is a kludge to compensate for lost keyboard interrupts.
217          * A similar code used to be in syscons. See below. XXX
218          */
219         pckbd_timeout(*kbd);
220
221         if (bootverbose)
222                 (*sw->diag)(*kbd, bootverbose);
223
224         return 0;
225 }
226
227 static void
228 pckbd_timeout(void *arg)
229 {
230         keyboard_t *kbd;
231         int s;
232
233         /* The following comments are extracted from syscons.c (1.287) */
234         /* 
235          * With release 2.1 of the Xaccel server, the keyboard is left
236          * hanging pretty often. Apparently an interrupt from the
237          * keyboard is lost, and I don't know why (yet).
238          * This ugly hack calls scintr if input is ready for the keyboard
239          * and conveniently hides the problem.                  XXX
240          */
241         /*
242          * Try removing anything stuck in the keyboard controller; whether
243          * it's a keyboard scan code or mouse data. `scintr()' doesn't
244          * read the mouse data directly, but `kbdio' routines will, as a
245          * side effect.
246          */
247         s = spltty();
248         kbd = (keyboard_t *)arg;
249         if (kbdd_lock(kbd, TRUE)) {
250                 /*
251                  * We have seen the lock flag is not set. Let's reset
252                  * the flag early, otherwise the LED update routine fails
253                  * which may want the lock during the interrupt routine.
254                  */
255                 kbdd_lock(kbd, FALSE);
256                 if (kbdd_check_char(kbd))
257                         kbdd_intr(kbd, NULL);
258         }
259         splx(s);
260         timeout(pckbd_timeout, arg, hz/10);
261 }
262
263 /* LOW-LEVEL */
264
265 #include <sys/limits.h>
266
267 #define PC98KBD_DEFAULT 0
268
269 typedef caddr_t         KBDC;
270
271 typedef struct pckbd_state {
272         KBDC            kbdc;           /* keyboard controller */
273         int             ks_mode;        /* input mode (K_XLATE,K_RAW,K_CODE) */
274         int             ks_flags;       /* flags */
275 #define COMPOSE         (1 << 0)
276         int             ks_state;       /* shift/lock key state */
277         int             ks_accents;     /* accent key index (> 0) */
278         u_int           ks_composed_char; /* composed char code (> 0) */
279 } pckbd_state_t;
280
281 /* keyboard driver declaration */
282 static int              pckbd_configure(int flags);
283 static kbd_probe_t      pckbd_probe;
284 static kbd_init_t       pckbd_init;
285 static kbd_term_t       pckbd_term;
286 static kbd_intr_t       pckbd_intr;
287 static kbd_test_if_t    pckbd_test_if;
288 static kbd_enable_t     pckbd_enable;
289 static kbd_disable_t    pckbd_disable;
290 static kbd_read_t       pckbd_read;
291 static kbd_check_t      pckbd_check;
292 static kbd_read_char_t  pckbd_read_char;
293 static kbd_check_char_t pckbd_check_char;
294 static kbd_ioctl_t      pckbd_ioctl;
295 static kbd_lock_t       pckbd_lock;
296 static kbd_clear_state_t pckbd_clear_state;
297 static kbd_get_state_t  pckbd_get_state;
298 static kbd_set_state_t  pckbd_set_state;
299 static kbd_poll_mode_t  pckbd_poll;
300
301 keyboard_switch_t pckbdsw = {
302         pckbd_probe,
303         pckbd_init,
304         pckbd_term,
305         pckbd_intr,
306         pckbd_test_if,
307         pckbd_enable,
308         pckbd_disable,
309         pckbd_read,
310         pckbd_check,
311         pckbd_read_char,
312         pckbd_check_char,
313         pckbd_ioctl,
314         pckbd_lock,
315         pckbd_clear_state,
316         pckbd_get_state,
317         pckbd_set_state,
318         genkbd_get_fkeystr,
319         pckbd_poll,
320         genkbd_diag,
321 };
322
323 KEYBOARD_DRIVER(pckbd, pckbdsw, pckbd_configure);
324
325 struct kbdc_softc {
326     int port;                   /* base port address */
327     int lock;                   /* FIXME: XXX not quite a semaphore... */
328 }; 
329
330 /* local functions */
331 static int              probe_keyboard(KBDC kbdc, int flags);
332 static int              init_keyboard(KBDC kbdc, int *type, int flags);
333 static KBDC             kbdc_open(int port);
334 static int              kbdc_lock(KBDC kbdc, int lock);
335 static int              kbdc_data_ready(KBDC kbdc);
336 static int              read_kbd_data(KBDC kbdc);
337 static int              read_kbd_data_no_wait(KBDC kbdc);
338 static int              wait_for_kbd_data(struct kbdc_softc *kbdc);
339
340 /* local variables */
341
342 /* the initial key map, accent map and fkey strings */
343 #include <pc98/cbus/pckbdtables.h>
344
345 /* structures for the default keyboard */
346 static keyboard_t       default_kbd;
347 static pckbd_state_t    default_kbd_state;
348 static keymap_t         default_keymap;
349 static accentmap_t      default_accentmap;
350 static fkeytab_t        default_fkeytab[NUM_FKEYS];
351
352 /* 
353  * The back door to the keyboard driver!
354  * This function is called by the console driver, via the kbdio module,
355  * to tickle keyboard drivers when the low-level console is being initialized.
356  * Almost nothing in the kernel has been initialied yet.  Try to probe
357  * keyboards if possible.
358  * NOTE: because of the way the low-level conole is initialized, this routine
359  * may be called more than once!!
360  */
361 static int
362 pckbd_configure(int flags)
363 {
364         keyboard_t *kbd;
365         int arg[2];
366         int i;
367
368         /* XXX: a kludge to obtain the device configuration flags */
369         if (resource_int_value(DRIVER_NAME, 0, "flags", &i) == 0) {
370                 flags |= i;
371                 /* if the driver is disabled, unregister the keyboard if any */
372                 if (resource_disabled(DRIVER_NAME, 0)) {
373                         i = kbd_find_keyboard(DRIVER_NAME, PC98KBD_DEFAULT);
374                         if (i >= 0) {
375                                 kbd = kbd_get_keyboard(i);
376                                 kbd_unregister(kbd);
377                                 kbd->kb_flags &= ~KB_REGISTERED;
378                                 return 0;
379                         }
380                 }
381         }
382
383         /* probe the default keyboard */
384         arg[0] = -1;
385         arg[1] = -1;
386         kbd = NULL;
387         if (pckbd_probe(PC98KBD_DEFAULT, arg, flags))
388                 return 0;
389         if (pckbd_init(PC98KBD_DEFAULT, &kbd, arg, flags))
390                 return 0;
391
392         /* return the number of found keyboards */
393         return 1;
394 }
395
396 /* low-level functions */
397
398 /* detect a keyboard */
399 static int
400 pckbd_probe(int unit, void *arg, int flags)
401 {
402         KBDC kbdc;
403         int *data = (int *)arg;
404
405         if (unit != PC98KBD_DEFAULT)
406                 return ENXIO;
407         if (KBD_IS_PROBED(&default_kbd))
408                 return 0;
409
410         kbdc = kbdc_open(data[0]);
411         if (kbdc == NULL)
412                 return ENXIO;
413         if (probe_keyboard(kbdc, flags)) {
414                 if (flags & KB_CONF_FAIL_IF_NO_KBD)
415                         return ENXIO;
416         }
417         return 0;
418 }
419
420 /* reset and initialize the device */
421 static int
422 pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
423 {
424         keyboard_t *kbd;
425         pckbd_state_t *state;
426         keymap_t *keymap;
427         accentmap_t *accmap;
428         fkeytab_t *fkeymap;
429         int fkeymap_size;
430         int *data = (int *)arg;
431
432         if (unit != PC98KBD_DEFAULT)                    /* shouldn't happen */
433                 return ENXIO;
434
435         *kbdp = kbd = &default_kbd;
436         state = &default_kbd_state;
437         if (!KBD_IS_PROBED(kbd)) {
438                 keymap = &default_keymap;
439                 accmap = &default_accentmap;
440                 fkeymap = default_fkeytab;
441                 fkeymap_size =
442                         sizeof(default_fkeytab)/sizeof(default_fkeytab[0]);
443
444                 state->kbdc = kbdc_open(data[0]);
445                 if (state->kbdc == NULL)
446                         return ENXIO;
447                 kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags,
448                                 data[0], IO_KBDSIZE);
449                 bcopy(&key_map, keymap, sizeof(key_map));
450                 bcopy(&accent_map, accmap, sizeof(accent_map));
451                 bcopy(fkey_tab, fkeymap,
452                       imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
453                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
454                 kbd->kb_data = (void *)state;
455
456                 if (probe_keyboard(state->kbdc, flags)) {/* shouldn't happen */
457                         if (flags & KB_CONF_FAIL_IF_NO_KBD)
458                                 return ENXIO;
459                 } else {
460                         KBD_FOUND_DEVICE(kbd);
461                 }
462                 pckbd_clear_state(kbd);
463                 state->ks_mode = K_XLATE;
464                 KBD_PROBE_DONE(kbd);
465         }
466         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
467                 if (KBD_HAS_DEVICE(kbd)
468                     && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config)
469                     && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
470                         return ENXIO;
471                 pckbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
472                 KBD_INIT_DONE(kbd);
473         }
474         if (!KBD_IS_CONFIGURED(kbd)) {
475                 if (kbd_register(kbd) < 0)
476                         return ENXIO;
477                 KBD_CONFIG_DONE(kbd);
478         }
479
480         return 0;
481 }
482
483 /* finish using this keyboard */
484 static int
485 pckbd_term(keyboard_t *kbd)
486 {
487         kbd_unregister(kbd);
488         return 0;
489 }
490
491 /* keyboard interrupt routine */
492 static int
493 pckbd_intr(keyboard_t *kbd, void *arg)
494 {
495         int c;
496
497         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
498                 /* let the callback function to process the input */
499                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
500                                             kbd->kb_callback.kc_arg);
501         } else {
502                 /* read and discard the input; no one is waiting for input */
503                 do {
504                         c = pckbd_read_char(kbd, FALSE);
505                 } while (c != NOKEY);
506         }
507         return 0;
508 }
509
510 /* test the interface to the device */
511 static int
512 pckbd_test_if(keyboard_t *kbd)
513 {
514         return 0;
515 }
516
517 /* 
518  * Enable the access to the device; until this function is called,
519  * the client cannot read from the keyboard.
520  */
521 static int
522 pckbd_enable(keyboard_t *kbd)
523 {
524         int s;
525
526         s = spltty();
527         KBD_ACTIVATE(kbd);
528         splx(s);
529         return 0;
530 }
531
532 /* disallow the access to the device */
533 static int
534 pckbd_disable(keyboard_t *kbd)
535 {
536         int s;
537
538         s = spltty();
539         KBD_DEACTIVATE(kbd);
540         splx(s);
541         return 0;
542 }
543
544 /* read one byte from the keyboard if it's allowed */
545 static int
546 pckbd_read(keyboard_t *kbd, int wait)
547 {
548         int c;
549
550         if (wait)
551                 c = read_kbd_data(((pckbd_state_t *)kbd->kb_data)->kbdc);
552         else
553                 c = read_kbd_data_no_wait(((pckbd_state_t *)kbd->kb_data)->kbdc);
554         if (c != -1)
555                 ++kbd->kb_count;
556         return (KBD_IS_ACTIVE(kbd) ? c : -1);
557 }
558
559 /* check if data is waiting */
560 static int
561 pckbd_check(keyboard_t *kbd)
562 {
563         if (!KBD_IS_ACTIVE(kbd))
564                 return FALSE;
565         return kbdc_data_ready(((pckbd_state_t *)kbd->kb_data)->kbdc);
566 }
567
568 /* read char from the keyboard */
569 static u_int
570 pckbd_read_char(keyboard_t *kbd, int wait)
571 {
572         pckbd_state_t *state;
573         u_int action;
574         int scancode;
575         int keycode;
576
577         state = (pckbd_state_t *)kbd->kb_data;
578 next_code:
579         /* do we have a composed char to return? */
580         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
581                 action = state->ks_composed_char;
582                 state->ks_composed_char = 0;
583                 if (action > UCHAR_MAX)
584                         return ERRKEY;
585                 return action;
586         }
587
588         /* see if there is something in the keyboard port */
589         if (wait) {
590                 do {
591                         scancode = read_kbd_data(state->kbdc);
592                 } while (scancode == -1);
593         } else {
594                 scancode = read_kbd_data_no_wait(state->kbdc);
595                 if (scancode == -1)
596                         return NOKEY;
597         }
598         ++kbd->kb_count;
599
600 #if 0
601         printf("pckbd_read_char(): scancode:0x%x\n", scancode);
602 #endif
603
604         /* return the byte as is for the K_RAW mode */
605         if (state->ks_mode == K_RAW)
606                 return scancode;
607
608         /* translate the scan code into a keycode */
609         keycode = scancode & 0x7F;
610         switch(scancode) {
611         case 0xF3:      /* GRPH (compose key) released */
612                 if (state->ks_flags & COMPOSE) {
613                         state->ks_flags &= ~COMPOSE;
614                         if (state->ks_composed_char > UCHAR_MAX)
615                                 state->ks_composed_char = 0;
616                 }
617                 break;
618         case 0x73:      /* GRPH (compose key) pressed */
619                 if (!(state->ks_flags & COMPOSE)) {
620                         state->ks_flags |= COMPOSE;
621                         state->ks_composed_char = 0;
622                 }
623                 break;
624         }
625
626         /* return the key code in the K_CODE mode */
627         if (state->ks_mode == K_CODE)
628                 return (keycode | (scancode & 0x80));
629
630         /* compose a character code */
631         if (state->ks_flags & COMPOSE) {
632                 switch (scancode) {
633                 /* key pressed, process it */
634                 case 0x42: case 0x43: case 0x44:        /* keypad 7,8,9 */
635                         state->ks_composed_char *= 10;
636                         state->ks_composed_char += scancode - 0x3B;
637                         if (state->ks_composed_char > UCHAR_MAX)
638                                 return ERRKEY;
639                         goto next_code;
640                 case 0x46: case 0x47: case 0x48:        /* keypad 4,5,6 */
641                         state->ks_composed_char *= 10;
642                         state->ks_composed_char += scancode - 0x42;
643                         if (state->ks_composed_char > UCHAR_MAX)
644                                 return ERRKEY;
645                         goto next_code;
646                 case 0x4A: case 0x4B: case 0x4C:        /* keypad 1,2,3 */
647                         state->ks_composed_char *= 10;
648                         state->ks_composed_char += scancode - 0x49;
649                         if (state->ks_composed_char > UCHAR_MAX)
650                                 return ERRKEY;
651                         goto next_code;
652                 case 0x4E:                              /* keypad 0 */
653                         state->ks_composed_char *= 10;
654                         if (state->ks_composed_char > UCHAR_MAX)
655                                 return ERRKEY;
656                         goto next_code;
657
658                 /* key released, no interest here */
659                 case 0xC2: case 0xC3: case 0xC4:        /* keypad 7,8,9 */
660                 case 0xC6: case 0xC7: case 0xC8:        /* keypad 4,5,6 */
661                 case 0xCA: case 0xCB: case 0xCC:        /* keypad 1,2,3 */
662                 case 0xCE:                              /* keypad 0 */
663                         goto next_code;
664
665                 case 0x73:                              /* GRPH key */
666                         break;
667
668                 default:
669                         if (state->ks_composed_char > 0) {
670                                 state->ks_flags &= ~COMPOSE;
671                                 state->ks_composed_char = 0;
672                                 return ERRKEY;
673                         }
674                         break;
675                 }
676         }
677
678         /* keycode to key action */
679         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
680                                   &state->ks_state, &state->ks_accents);
681         if (action == NOKEY)
682                 goto next_code;
683         else
684                 return action;
685 }
686
687 /* check if char is waiting */
688 static int
689 pckbd_check_char(keyboard_t *kbd)
690 {
691         pckbd_state_t *state;
692
693         if (!KBD_IS_ACTIVE(kbd))
694                 return FALSE;
695         state = (pckbd_state_t *)kbd->kb_data;
696         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0))
697                 return TRUE;
698         return kbdc_data_ready(state->kbdc);
699 }
700
701 /* some useful control functions */
702 static int
703 pckbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
704 {
705         pckbd_state_t *state = kbd->kb_data;
706         int s;
707         int i;
708 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
709     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
710         int ival;
711 #endif
712
713         s = spltty();
714         switch (cmd) {
715
716         case KDGKBMODE:         /* get keyboard mode */
717                 *(int *)arg = state->ks_mode;
718                 break;
719 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
720     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
721         case _IO('K', 7):
722                 ival = IOCPARM_IVAL(arg);
723                 arg = (caddr_t)&ival;
724                 /* FALLTHROUGH */
725 #endif
726         case KDSKBMODE:         /* set keyboard mode */
727                 switch (*(int *)arg) {
728                 case K_XLATE:
729                         if (state->ks_mode != K_XLATE) {
730                                 /* make lock key state and LED state match */
731                                 state->ks_state &= ~LOCK_MASK;
732                                 state->ks_state |= KBD_LED_VAL(kbd);
733                         }
734                         /* FALLTHROUGH */
735                 case K_RAW:
736                 case K_CODE:
737                         if (state->ks_mode != *(int *)arg) {
738                                 pckbd_clear_state(kbd);
739                                 state->ks_mode = *(int *)arg;
740                         }
741                         break;
742                 default:
743                         splx(s);
744                         return EINVAL;
745                 }
746                 break;
747
748         case KDGETLED:          /* get keyboard LED */
749                 *(int *)arg = KBD_LED_VAL(kbd);
750                 break;
751 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
752     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
753         case _IO('K', 66):
754                 ival = IOCPARM_IVAL(arg);
755                 arg = (caddr_t)&ival;
756                 /* FALLTHROUGH */
757 #endif
758         case KDSETLED:          /* set keyboard LED */
759                 /* NOTE: lock key state in ks_state won't be changed */
760                 if (*(int *)arg & ~LOCK_MASK) {
761                         splx(s);
762                         return EINVAL;
763                 }
764                 i = *(int *)arg;
765                 /* replace CAPS LED with ALTGR LED for ALTGR keyboards */
766                 if (kbd->kb_keymap->n_keys > ALTGR_OFFSET) {
767                         if (i & ALKED)
768                                 i |= CLKED;
769                         else
770                                 i &= ~CLKED;
771                 }
772                 KBD_LED_VAL(kbd) = *(int *)arg;
773                 break;
774
775         case KDGKBSTATE:        /* get lock key state */
776                 *(int *)arg = state->ks_state & LOCK_MASK;
777                 break;
778 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
779     defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
780         case _IO('K', 20):
781                 ival = IOCPARM_IVAL(arg);
782                 arg = (caddr_t)&ival;
783                 /* FALLTHROUGH */
784 #endif
785         case KDSKBSTATE:        /* set lock key state */
786                 if (*(int *)arg & ~LOCK_MASK) {
787                         splx(s);
788                         return EINVAL;
789                 }
790                 state->ks_state &= ~LOCK_MASK;
791                 state->ks_state |= *(int *)arg;
792                 splx(s);
793                 /* set LEDs and quit */
794                 return pckbd_ioctl(kbd, KDSETLED, arg);
795
796         case KDSETRAD:          /* set keyboard repeat rate (old interface)*/
797                 break;
798         case KDSETREPEAT:       /* set keyboard repeat rate (new interface) */
799                 break;
800
801         case PIO_KEYMAP:        /* set keyboard translation table */
802         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
803         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
804         case PIO_DEADKEYMAP:    /* set accent key translation table */
805                 state->ks_accents = 0;
806                 /* FALLTHROUGH */
807         default:
808                 splx(s);
809                 return genkbd_commonioctl(kbd, cmd, arg);
810         }
811
812         splx(s);
813         return 0;
814 }
815
816 /* lock the access to the keyboard */
817 static int
818 pckbd_lock(keyboard_t *kbd, int lock)
819 {
820         return kbdc_lock(((pckbd_state_t *)kbd->kb_data)->kbdc, lock);
821 }
822
823 /* clear the internal state of the keyboard */
824 static void
825 pckbd_clear_state(keyboard_t *kbd)
826 {
827         pckbd_state_t *state;
828
829         state = (pckbd_state_t *)kbd->kb_data;
830         state->ks_flags = 0;
831         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
832         state->ks_accents = 0;
833         state->ks_composed_char = 0;
834 }
835
836 /* save the internal state */
837 static int
838 pckbd_get_state(keyboard_t *kbd, void *buf, size_t len)
839 {
840         if (len == 0)
841                 return sizeof(pckbd_state_t);
842         if (len < sizeof(pckbd_state_t))
843                 return -1;
844         bcopy(kbd->kb_data, buf, sizeof(pckbd_state_t));
845         return 0;
846 }
847
848 /* set the internal state */
849 static int
850 pckbd_set_state(keyboard_t *kbd, void *buf, size_t len)
851 {
852         if (len < sizeof(pckbd_state_t))
853                 return ENOMEM;
854         if (((pckbd_state_t *)kbd->kb_data)->kbdc
855                 != ((pckbd_state_t *)buf)->kbdc)
856                 return ENOMEM;
857         bcopy(buf, kbd->kb_data, sizeof(pckbd_state_t));
858         return 0;
859 }
860
861 /* set polling mode */
862 static int
863 pckbd_poll(keyboard_t *kbd, int on)
864 {
865         return 0;
866 }
867
868 /* local functions */
869
870 static int
871 probe_keyboard(KBDC kbdc, int flags)
872 {
873         return 0;
874 }
875
876 static int
877 init_keyboard(KBDC kbdc, int *type, int flags)
878 {
879         *type = KB_OTHER;
880         return 0;
881 }
882
883 /* keyboard I/O routines */
884
885 /* retry count */
886 #ifndef KBD_MAXRETRY
887 #define KBD_MAXRETRY    3
888 #endif
889
890 /* timing parameters */
891 #ifndef KBD_RESETDELAY
892 #define KBD_RESETDELAY  200     /* wait 200msec after kbd/mouse reset */
893 #endif
894 #ifndef KBD_MAXWAIT
895 #define KBD_MAXWAIT     5       /* wait 5 times at most after reset */
896 #endif
897
898 /* I/O recovery time */
899 #define KBDC_DELAYTIME  37
900 #define KBDD_DELAYTIME  37
901
902 /* I/O ports */
903 #define KBD_STATUS_PORT         2       /* status port, read */
904 #define KBD_DATA_PORT           0       /* data port, read */
905
906 /* status bits (KBD_STATUS_PORT) */
907 #define KBDS_BUFFER_FULL        0x0002
908
909 /* macros */
910
911 #define kbdcp(p)                ((struct kbdc_softc *)(p))
912
913 /* local variables */
914
915 static struct kbdc_softc kbdc_softc[1] = { { 0 }, };
916
917 /* associate a port number with a KBDC */
918
919 static KBDC
920 kbdc_open(int port)
921 {
922         if (port <= 0)
923                 port = IO_KBD;
924
925         /* PC-98 has only one keyboard I/F */
926         kbdc_softc[0].port = port;
927         kbdc_softc[0].lock = FALSE;
928         return (KBDC)&kbdc_softc[0];
929 }
930
931 /* set/reset polling lock */
932 static int 
933 kbdc_lock(KBDC p, int lock)
934 {
935     int prevlock;
936
937     prevlock = kbdcp(p)->lock;
938     kbdcp(p)->lock = lock;
939
940     return (prevlock != lock);
941 }
942
943 /* check if any data is waiting to be processed */
944 static int
945 kbdc_data_ready(KBDC p)
946 {
947         return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL);
948 }
949
950 /* wait for data from the keyboard */
951 static int
952 wait_for_kbd_data(struct kbdc_softc *kbdc)
953 {
954     /* CPU will stay inside the loop for 200msec at most */
955     int retry = 10000;
956     int port = kbdc->port;
957
958     while (!(inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)) {
959         DELAY(KBDD_DELAYTIME);
960         DELAY(KBDC_DELAYTIME);
961         if (--retry < 0)
962             return 0;
963     }
964     DELAY(KBDD_DELAYTIME);
965     return 1;
966 }
967
968 /* read one byte from the keyboard */
969 static int
970 read_kbd_data(KBDC p)
971 {
972     if (!wait_for_kbd_data(kbdcp(p)))
973         return -1;              /* timeout */
974     DELAY(KBDC_DELAYTIME);
975     return inb(kbdcp(p)->port + KBD_DATA_PORT);
976 }
977
978 /* read one byte from the keyboard, but return immediately if 
979  * no data is waiting
980  */
981 static int
982 read_kbd_data_no_wait(KBDC p)
983 {
984     if (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL) {
985         DELAY(KBDD_DELAYTIME);
986         return inb(kbdcp(p)->port + KBD_DATA_PORT);
987     }
988     return -1;          /* no data */
989 }