This commit is contained in:
bjh21 2004-01-17 21:14:46 +00:00
parent 8e0990aadd
commit b727d5da17

View File

@ -1,4 +1,4 @@
/* $NetBSD: rpckbd.c,v 1.7 2004/01/17 21:05:40 bjh21 Exp $ */ /* $NetBSD: rpckbd.c,v 1.8 2004/01/17 21:14:46 bjh21 Exp $ */
/*- /*-
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -45,7 +45,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rpckbd.c,v 1.7 2004/01/17 21:05:40 bjh21 Exp $"); __KERNEL_RCSID(0, "$NetBSD: rpckbd.c,v 1.8 2004/01/17 21:14:46 bjh21 Exp $");
#include "opt_ddb.h" #include "opt_ddb.h"
#include "opt_pmap_debug.h" #include "opt_pmap_debug.h"
@ -79,7 +79,8 @@ __KERNEL_RCSID(0, "$NetBSD: rpckbd.c,v 1.7 2004/01/17 21:05:40 bjh21 Exp $");
#define KBC_RESEND 0xFE /* request the keyboard resend the last byte */ #define KBC_RESEND 0xFE /* request the keyboard resend the last byte */
#define KBC_SET_TMB 0xFA /* What is this one ? */ #define KBC_SET_TMB 0xFA /* What is this one ? */
#define KBC_SETDEFAULT 0xF6 /* resets keyboard to its power-on defaults */ #define KBC_SETDEFAULT 0xF6 /* resets keyboard to its power-on defaults */
#define KBC_DISABLE 0xF5 /* as per KBC_SETDEFAULT, but also disable key scanning */ #define KBC_DISABLE 0xF5 /* as per KBC_SETDEFAULT, but also disable key
scanning */
#define KBC_ENABLE 0xF4 /* enable key scanning */ #define KBC_ENABLE 0xF4 /* enable key scanning */
#define KBC_TYPEMATIC 0xF3 /* set typematic rate and delay */ #define KBC_TYPEMATIC 0xF3 /* set typematic rate and delay */
#define KBD_READID 0xF2 /* Read keyboard ID */ #define KBD_READID 0xF2 /* Read keyboard ID */
@ -186,17 +187,17 @@ rpckbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
/* check if we're allready in this state */ /* check if we're allready in this state */
new_ledstate = rpckbd_led_encode(*(int *)data); new_ledstate = rpckbd_led_encode(*(int *)data);
if (new_ledstate == sc->sc_ledstate) if (new_ledstate == sc->sc_ledstate)
return (0); return 0;
sc->sc_ledstate = new_ledstate; sc->sc_ledstate = new_ledstate;
res = kbdcmd(sc, KBC_SETLEDS, 0); res = kbdcmd(sc, KBC_SETLEDS, 0);
res = kbdcmd(sc, sc->sc_ledstate, 0); res = kbdcmd(sc, sc->sc_ledstate, 0);
if (res == KBR_ACK) if (res == KBR_ACK)
return (0); return 0;
return (EIO); return EIO;
case WSKBDIO_GETLEDS: case WSKBDIO_GETLEDS:
*(int *)data = rpckbd_led_decode(sc->sc_ledstate); *(int *)data = rpckbd_led_decode(sc->sc_ledstate);
return (0); return 0;
case WSKBDIO_COMPLEXBELL: case WSKBDIO_COMPLEXBELL:
#define d ((struct wskbd_bell_data *)data) #define d ((struct wskbd_bell_data *)data)
/* /*
@ -205,11 +206,11 @@ rpckbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
*/ */
rpckbd_bell(d->pitch, d->period, d->volume); rpckbd_bell(d->pitch, d->period, d->volume);
#undef d #undef d
return (0); return 0;
#ifdef WSDISPLAY_COMPAT_RAWKBD #ifdef WSDISPLAY_COMPAT_RAWKBD
case WSKBDIO_SETMODE: case WSKBDIO_SETMODE:
sc->rawkbd = (*(int *)data == WSKBD_RAW); sc->rawkbd = (*(int *)data == WSKBD_RAW);
return (0); return 0;
#endif #endif
} }
return EPASSTHROUGH; return EPASSTHROUGH;
@ -226,24 +227,26 @@ rpckbd_enable(void *v, int on)
if (on) { if (on) {
if (sc->sc_enabled) if (sc->sc_enabled)
return (EBUSY); return EBUSY;
res = kbdcmd(sc, KBC_ENABLE, 0); res = kbdcmd(sc, KBC_ENABLE, 0);
if (res != KBR_ACK) { if (res != KBR_ACK) {
printf("rpckbd_enable: command error; got response %d\n", res); printf("rpckbd_enable: command error; "
return (EIO); "got response %d\n", res);
}; return EIO;
}
sc->sc_enabled = 1; sc->sc_enabled = 1;
} else { } else {
if (sc->t_isconsole) if (sc->t_isconsole)
return (EBUSY); return EBUSY;
res = kbdcmd(sc, KBC_DISABLE, 0); res = kbdcmd(sc, KBC_DISABLE, 0);
if (res != KBR_ACK) { if (res != KBR_ACK) {
printf("rpckbd_disable: command error; got response %d\n", res); printf("rpckbd_disable: command error; "
return (EIO); "got response %d\n", res);
}; return EIO;
}
sc->sc_enabled = 0; sc->sc_enabled = 0;
}; }
return (0); return 0;
} }
@ -282,10 +285,10 @@ rpckbd_reset(struct rpckbd_softc *sc)
(KBD_CR_KDATAO | KBD_CR_KCLKO)); (KBD_CR_KDATAO | KBD_CR_KCLKO));
delay(200); delay(200);
bus_space_write_1(sc->sc_iot, sc->sc_ioh, KBD_CR, KBD_CR_ENABLE); bus_space_write_1(sc->sc_iot, sc->sc_ioh, KBD_CR, KBD_CR_ENABLE);
}; }
if (i == 0 || (bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_STATUS) if (i == 0 || (bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_STATUS)
& KBD_ST_ENABLE) == 0) & KBD_ST_ENABLE) == 0)
return(1); return 1;
kbd_flush_input(sc); kbd_flush_input(sc);
kbdcmd(sc, KBC_DISABLE, 0); kbdcmd(sc, KBC_DISABLE, 0);
@ -302,22 +305,22 @@ retry:
printf(" [retry]"); printf(" [retry]");
goto retry; goto retry;
} }
}; }
if (i == 0) if (i == 0)
return(2); return 2;
kbdcmd(sc, KBC_SETSCANTBL, 0); kbdcmd(sc, KBC_SETSCANTBL, 0);
kbdcmd(sc, KBD_SETSCAN_2, 0); kbdcmd(sc, KBD_SETSCAN_2, 0);
kbdcmd(sc, KBC_ENABLE, 0); kbdcmd(sc, KBC_ENABLE, 0);
return (0); return 0;
#if 0 #if 0
res = kbdcmd(sc, KBC_RESET, 1); res = kbdcmd(sc, KBC_RESET, 1);
if (res != KBR_RSTDONE) { if (res != KBR_RSTDONE) {
printf(" : reset error, got 0x%02x ", res); printf(" : reset error, got 0x%02x ", res);
return 1; return 1;
}; }
return 0; /* flag success */ return 0; /* flag success */
#endif #endif
} }
@ -329,7 +332,6 @@ rpckbd_set_leds(void *context, int leds)
struct rpckbd_softc *sc = (struct rpckbd_softc *) context; struct rpckbd_softc *sc = (struct rpckbd_softc *) context;
int res, new_ledstate; int res, new_ledstate;
/* check if we're allready in this state */ /* check if we're allready in this state */
new_ledstate = rpckbd_led_encode(leds); new_ledstate = rpckbd_led_encode(leds);
if (new_ledstate == sc->sc_ledstate) if (new_ledstate == sc->sc_ledstate)
@ -354,24 +356,25 @@ rpckbd_intr(void *context)
/* read the key code */ /* read the key code */
data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_DATA); data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_DATA);
if (data == 0) return (1); if (data == 0) return 1;
#ifdef WSDISPLAY_COMPAT_RAWKBD #ifdef WSDISPLAY_COMPAT_RAWKBD
if (sc->rawkbd) { if (sc->rawkbd) {
wskbd_rawinput(sc->sc_wskbddev, (u_char *) &data, 1); wskbd_rawinput(sc->sc_wskbddev, (u_char *) &data, 1);
return (1); /* claim interrupt */ return 1; /* claim interrupt */
} }
#endif #endif
if (rpckbd_decode(sc, data, &type, &key)) if (rpckbd_decode(sc, data, &type, &key))
wskbd_input(sc->sc_wskbddev, type, key); wskbd_input(sc->sc_wskbddev, type, key);
return (1); /* claim interrupt */ return 1; /* claim interrupt */
} }
/* should really be renamed to attach using the normal attachment stuff */ /* should really be renamed to attach using the normal attachment stuff */
int int
rpckbd_init(struct device *self, int isconsole, vaddr_t data_port, vaddr_t cmd_port) rpckbd_init(struct device *self, int isconsole, vaddr_t data_port,
vaddr_t cmd_port)
{ {
struct rpckbd_softc *sc = (struct rpckbd_softc *) self; struct rpckbd_softc *sc = (struct rpckbd_softc *) self;
struct wskbddev_attach_args a; struct wskbddev_attach_args a;
@ -407,10 +410,13 @@ rpckbd_cnattach(struct device *self)
{ {
struct rpckbd_softc *sc = (struct rpckbd_softc *) self; struct rpckbd_softc *sc = (struct rpckbd_softc *) self;
/* attach to wskbd ; the 2nd. arg. is a information pointer passed on to us */ /*
* attach to wskbd ; the 2nd. arg. is a information pointer
* passed on to us
*/
wskbd_cnattach(&rpckbd_consops, sc, &rpckbd_keymapdata); wskbd_cnattach(&rpckbd_consops, sc, &rpckbd_keymapdata);
return (0); /* flag success */ return 0; /* flag success */
} }
@ -422,10 +428,14 @@ rpckbd_cngetc(void *v, u_int *type, int *data)
for (;;) { for (;;) {
/* wait for a receive event */ /* wait for a receive event */
while ((bus_space_read_1(console_kbd.sc_iot, console_kbd.sc_ioh, KBD_STATUS) & KBD_ST_RXF) == 0) ; while ((bus_space_read_1(console_kbd.sc_iot,
console_kbd.sc_ioh, KBD_STATUS) &
KBD_ST_RXF) == 0)
continue;
delay(10); delay(10);
val = bus_space_read_1(console_kbd.sc_iot, console_kbd.sc_ioh, KBD_DATA); val = bus_space_read_1(console_kbd.sc_iot, console_kbd.sc_ioh,
KBD_DATA);
if (rpckbd_decode(sc, val, type, data)) if (rpckbd_decode(sc, val, type, data))
return; return;
} }
@ -435,6 +445,7 @@ rpckbd_cngetc(void *v, u_int *type, int *data)
void void
rpckbd_cnpollc(void *v, int on) rpckbd_cnpollc(void *v, int on)
{ {
/* switched on/off polling ... what to do ? */ /* switched on/off polling ... what to do ? */
} }
@ -442,18 +453,20 @@ rpckbd_cnpollc(void *v, int on)
void void
rpckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) rpckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
{ {
/* dunno yet */ /* dunno yet */
}; }
void void
rpckbd_bell(int pitch, int period, int volume) rpckbd_bell(int pitch, int period, int volume)
{ {
/* dunno yet */ /* dunno yet */
#if NBEEP>0 #if NBEEP > 0
sysbeep(pitch, period); sysbeep(pitch, period);
#endif #endif
}; }
/* Code derived from the standard pckbd_decode driver */ /* Code derived from the standard pckbd_decode driver */
@ -469,35 +482,35 @@ rpckbd_decode(struct rpckbd_softc *id, int datain, u_int *type, int *dataout)
/* mark keyup flag */ /* mark keyup flag */
if (datain == 0xf0) { if (datain == 0xf0) {
id->t_flags |= FLAG_KEYUP; id->t_flags |= FLAG_KEYUP;
return (0); return 0;
}; }
/* special code -> ignore */ /* special code -> ignore */
if ((datain == 0xff) || (datain == 0x00)) { if ((datain == 0xff) || (datain == 0x00)) {
id->t_flags = 0; id->t_flags = 0;
return (0); return 0;
}; }
/* just note resend ... */ /* just note resend ... */
if (datain == KBR_RESEND) { if (datain == KBR_RESEND) {
/* printf("rpckbd:resend\n"); */ /* printf("rpckbd:resend\n"); */
id->t_resend = 1; id->t_resend = 1;
return (0); return 0;
}; }
/* just note ack code */ /* just note ack code */
if (datain == KBR_ACK) { if (datain == KBR_ACK) {
/* printf("rpckbd:ack\n"); */ /* printf("rpckbd:ack\n"); */
id->t_ack = 1; id->t_ack = 1;
return (0); return 0;
}; }
if (datain == KBR_EXTENDED0) { if (datain == KBR_EXTENDED0) {
id->t_flags |= FLAG_E0; id->t_flags |= FLAG_E0;
return(0); return 0;
} else if (datain == KBR_EXTENDED1) { } else if (datain == KBR_EXTENDED1) {
id->t_flags |= FLAG_E1; id->t_flags |= FLAG_E1;
return(0); return 0;
} }
key = datain; key = datain;
@ -507,10 +520,10 @@ rpckbd_decode(struct rpckbd_softc *id, int datain, u_int *type, int *dataout)
id->t_flags &= ~FLAG_E0; id->t_flags &= ~FLAG_E0;
if (datain == 0x12) { if (datain == 0x12) {
id->t_flags &= ~FLAG_KEYUP; id->t_flags &= ~FLAG_KEYUP;
return (0); return 0;
}; }
key |= 0x100; key |= 0x100;
}; }
/* /*
* process BREAK key (EXT1 0x14 0x77): * process BREAK key (EXT1 0x14 0x77):
@ -518,7 +531,7 @@ rpckbd_decode(struct rpckbd_softc *id, int datain, u_int *type, int *dataout)
*/ */
if ((id->t_flags & FLAG_E1) && (datain == 0x14)) { if ((id->t_flags & FLAG_E1) && (datain == 0x14)) {
id->t_flags |= FLAG_BREAKPRELUDE; id->t_flags |= FLAG_BREAKPRELUDE;
return(0); return 0;
} else if ((id->t_flags & FLAG_BREAKPRELUDE) && } else if ((id->t_flags & FLAG_BREAKPRELUDE) &&
(datain == 0x77)) { (datain == 0x77)) {
id->t_flags &= ~(FLAG_E1 | FLAG_BREAKPRELUDE); id->t_flags &= ~(FLAG_E1 | FLAG_BREAKPRELUDE);
@ -538,7 +551,7 @@ rpckbd_decode(struct rpckbd_softc *id, int datain, u_int *type, int *dataout)
} else { } else {
/* Always ignore typematic keys */ /* Always ignore typematic keys */
if (key == id->t_lastchar) if (key == id->t_lastchar)
return(0); return 0;
id->t_lastchar = key; id->t_lastchar = key;
*type = WSCONS_EVENT_KEY_DOWN; *type = WSCONS_EVENT_KEY_DOWN;
#if 0 #if 0
@ -546,7 +559,7 @@ rpckbd_decode(struct rpckbd_softc *id, int datain, u_int *type, int *dataout)
#endif #endif
} }
*dataout = key; *dataout = key;
return(1); return 1;
} }
@ -560,8 +573,9 @@ rpckbd_led_decode(int code)
num = (code & 2) ? 1:0; num = (code & 2) ? 1:0;
caps = (code & 4) ? 1:0; caps = (code & 4) ? 1:0;
return (scroll*WSKBD_LED_SCROLL) | (num*WSKBD_LED_NUM) | (caps*WSKBD_LED_CAPS); return (scroll * WSKBD_LED_SCROLL) |
}; (num * WSKBD_LED_NUM) | (caps * WSKBD_LED_CAPS);
}
/* return kbd led byte for this wscons keyboard leds code */ /* return kbd led byte for this wscons keyboard leds code */
@ -575,7 +589,7 @@ rpckbd_led_encode(int code)
caps = (code & WSKBD_LED_CAPS) ? 1:0; caps = (code & WSKBD_LED_CAPS) ? 1:0;
/* cant do compose :( */ /* cant do compose :( */
return (caps<<2) | (num<<1) | (scroll<<0); return (caps << 2) | (num << 1) | (scroll << 0);
} }
@ -587,7 +601,8 @@ kbd_flush_input(struct rpckbd_softc *sc)
/* Loop round reading bytes while the receive buffer is not empty */ /* Loop round reading bytes while the receive buffer is not empty */
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {
if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_STATUS) & KBD_ST_RXF) == 0) if ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_STATUS) &
KBD_ST_RXF) == 0)
break; break;
delay(100); delay(100);
(void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_DATA); (void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_DATA);
@ -608,12 +623,14 @@ kbdcmd(struct rpckbd_softc *sc, u_char cmd, int eat_acks)
/* Wait for empty kbd transmit register */ /* Wait for empty kbd transmit register */
for (i = 1000; i; i--) { for (i = 1000; i; i--) {
if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_STATUS) & KBD_ST_TXE) if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
KBD_STATUS) & KBD_ST_TXE)
break; break;
delay(200); delay(200);
} }
if (i == 0) if (i == 0)
printf("%s: transmit not ready\n", sc->sc_device.dv_xname); printf("%s: transmit not ready\n",
sc->sc_device.dv_xname);
bus_space_write_1(sc->sc_iot, sc->sc_ioh, KBD_DATA, cmd); bus_space_write_1(sc->sc_iot, sc->sc_ioh, KBD_DATA, cmd);
@ -622,7 +639,8 @@ kbdcmd(struct rpckbd_softc *sc, u_char cmd, int eat_acks)
/* Wait for full kbd receive register */ /* Wait for full kbd receive register */
for (i = 0; i < 1000; i++) { for (i = 0; i < 1000; i++) {
c = bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_STATUS); c = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
KBD_STATUS);
if ((c & KBD_ST_RXF) == KBD_ST_RXF) if ((c & KBD_ST_RXF) == KBD_ST_RXF)
break; break;
delay(100); delay(100);
@ -633,21 +651,21 @@ kbdcmd(struct rpckbd_softc *sc, u_char cmd, int eat_acks)
/* Get byte from kbd receive register */ /* Get byte from kbd receive register */
c = bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_DATA); c = bus_space_read_1(sc->sc_iot, sc->sc_ioh, KBD_DATA);
if ((c == KBR_ECHO) || (c == KBR_RSTDONE)) if ((c == KBR_ECHO) || (c == KBR_RSTDONE))
return (c); return c;
} while ((c==KBR_ACK) && eat_acks); } while ((c==KBR_ACK) && eat_acks);
if (c == KBR_ACK) if (c == KBR_ACK)
return (c); return c;
/* Failed if we have more reties to go flush kbd */ /* Failed if we have more reties to go flush kbd */
if (retry) { if (retry) {
kbd_flush_input(sc); kbd_flush_input(sc);
printf(" [retry] "); printf(" [retry] ");
}; }
} }
printf("%s: command failed, cmd = %02x, status = %02x\n", sc->sc_device.dv_xname, cmd, c); printf("%s: command failed, cmd = %02x, status = %02x\n",
return (1); sc->sc_device.dv_xname, cmd, c);
return 1;
} }
/* end of rpckbd.c */ /* end of rpckbd.c */