Index: sys/dev/atkbdc/atkbd.c =================================================================== --- sys/dev/atkbdc/atkbd.c +++ sys/dev/atkbdc/atkbd.c @@ -161,7 +161,6 @@ { atkbd_state_t *state; keyboard_t *kbd; - int s; /* * The original text of the following comments are extracted @@ -188,19 +187,9 @@ * * The keyboard apparently unwedges the irq in most cases. */ - s = spltty(); kbd = (keyboard_t *)arg; - if (kbdd_lock(kbd, TRUE)) { - /* - * We have seen the lock flag is not set. Let's reset - * the flag early, otherwise the LED update routine fails - * which may want the lock during the interrupt routine. - */ - kbdd_lock(kbd, FALSE); - if (kbdd_check_char(kbd)) - kbdd_intr(kbd, NULL); - } - splx(s); + if (kbdd_check_char(kbd)) + kbdd_intr(kbd, NULL); state = (atkbd_state_t *)kbd->kb_data; callout_reset(&state->ks_timer, hz / 10, atkbd_timeout, arg); } @@ -572,16 +561,15 @@ atkbd_test_if(keyboard_t *kbd) { int error; - int s; error = 0; + kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc); empty_both_buffers(((atkbd_state_t *)kbd->kb_data)->kbdc, 10); - s = spltty(); if (!test_controller(((atkbd_state_t *)kbd->kb_data)->kbdc)) error = EIO; else if (test_kbd_port(((atkbd_state_t *)kbd->kb_data)->kbdc) != 0) error = EIO; - splx(s); + kbdc_unlock(((atkbd_state_t *)kbd->kb_data)->kbdc); return error; } @@ -619,10 +607,12 @@ { int c; + kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc); if (wait) c = read_kbd_data(((atkbd_state_t *)kbd->kb_data)->kbdc); else c = read_kbd_data_no_wait(((atkbd_state_t *)kbd->kb_data)->kbdc); + kbdc_unlock(((atkbd_state_t *)kbd->kb_data)->kbdc); if (c != -1) ++kbd->kb_count; return (KBD_IS_ACTIVE(kbd) ? c : -1); @@ -658,15 +648,19 @@ } /* see if there is something in the keyboard port */ + kbdc_lock(state->kbdc); if (wait) { do { scancode = read_kbd_data(state->kbdc); } while (scancode == -1); } else { scancode = read_kbd_data_no_wait(state->kbdc); - if (scancode == -1) + if (scancode == -1) { + kbdc_unlock(state->kbdc); return NOKEY; + } } + kbdc_unlock(state->kbdc); ++kbd->kb_count; #if KBDIO_DEBUG >= 10 @@ -1086,7 +1080,7 @@ static int atkbd_lock(keyboard_t *kbd, int lock) { - return kbdc_lock(((atkbd_state_t *)kbd->kb_data)->kbdc, lock); + return (1); } /* clear the internal state of the keyboard */ @@ -1163,17 +1157,21 @@ * disabling the interrupts doesn't cause real problems but the * responsiveness is a bit better when they are turned off. */ + kbdc_lock(kbdc); send_kbd_command(kbdc, KBDC_DISABLE_KBD); set_controller_command_byte(kbdc, KBD_AUX_CONTROL_BITS | KBD_KBD_CONTROL_BITS | KBD_TRANSLATION, KBD_DISABLE_AUX_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_KBD_PORT); send_kbd_command(kbdc, KBDC_ENABLE_KBD); + kbdc_unlock(kbdc); #endif } static int atkbd_reset(KBDC kbdc, int flags, int c) { + kbdc_lock_assert(kbdc); + /* reset keyboard hardware */ if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) { /* @@ -1225,6 +1223,8 @@ static int setup_kbd_port(KBDC kbdc, int port, int intr) { + kbdc_lock_assert(kbdc); + if (!set_controller_command_byte(kbdc, KBD_KBD_CONTROL_BITS, ((port) ? KBD_ENABLE_KBD_PORT : KBD_DISABLE_KBD_PORT) @@ -1236,6 +1236,8 @@ static int get_kbd_echo(KBDC kbdc) { + kbdc_lock_assert(kbdc); + /* enable the keyboard port, but disable the keyboard intr. */ if (setup_kbd_port(kbdc, TRUE, FALSE)) /* CONTROLLER ERROR: there is very little we can do... */ @@ -1273,10 +1275,7 @@ int c; int m; - if (!kbdc_lock(kbdc, TRUE)) { - /* driver error? */ - return ENXIO; - } + kbdc_lock(kbdc); /* temporarily block data transmission from the keyboard */ write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); @@ -1290,7 +1289,7 @@ if (c == -1) { /* CONTROLLER ERROR */ kbdc_set_device_mask(kbdc, m); - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return ENXIO; } @@ -1327,7 +1326,7 @@ } #endif - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return (HAS_QUIRK(kbdc, KBDC_QUIRK_IGNORE_PROBE_RESULT) ? 0 : err); } @@ -1338,10 +1337,7 @@ int id; int c; - if (!kbdc_lock(kbdc, TRUE)) { - /* driver error? */ - return EIO; - } + kbdc_lock(kbdc); /* temporarily block data transmission from the keyboard */ write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT); @@ -1351,7 +1347,7 @@ c = get_controller_command_byte(kbdc); if (c == -1) { /* CONTROLLER ERROR */ - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); printf("atkbd: unable to get the current command byte value.\n"); return EIO; } @@ -1367,13 +1363,13 @@ if (setup_kbd_port(kbdc, TRUE, FALSE)) { /* CONTROLLER ERROR: there is very little we can do... */ printf("atkbd: unable to set the command byte.\n"); - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return EIO; } if (HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) && atkbd_reset(kbdc, flags, c)) { - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return EIO; } @@ -1423,7 +1419,7 @@ if (!HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) && atkbd_reset(kbdc, flags, c)) { - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return EIO; } @@ -1445,7 +1441,7 @@ */ set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc) ? 0xff : KBD_KBD_CONTROL_BITS, c); - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); printf("atkbd: unable to set the XT keyboard mode.\n"); return EIO; } @@ -1483,26 +1479,20 @@ set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc) ? 0xff : (KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK), c); - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); printf("atkbd: unable to enable the keyboard port and intr.\n"); return EIO; } - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return 0; } static int write_kbd(KBDC kbdc, int command, int data) { - int s; - /* prevent the timeout routine from polling the keyboard */ - if (!kbdc_lock(kbdc, TRUE)) - return EBUSY; - - /* disable the keyboard and mouse interrupt */ - s = spltty(); + kbdc_lock(kbdc); #if 0 c = get_controller_command_byte(kbdc); if ((c == -1) @@ -1511,18 +1501,9 @@ KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { /* CONTROLLER ERROR */ - kbdc_lock(kbdc, FALSE); - splx(s); + kbdc_unlock(kbdc); return EIO; } - /* - * Now that the keyboard controller is told not to generate - * the keyboard and mouse interrupts, call `splx()' to allow - * the other tty interrupts. The clock interrupt may also occur, - * but the timeout routine (`scrn_timer()') will be blocked - * by the lock flag set via `kbdc_lock()' - */ - splx(s); #endif if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK) send_kbd_command(kbdc, KBDC_ENABLE_KBD); @@ -1532,10 +1513,8 @@ c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { /* CONTROLLER ERROR */ } -#else - splx(s); #endif - kbdc_lock(kbdc, FALSE); + kbdc_unlock(kbdc); return 0; } @@ -1545,6 +1524,8 @@ { int id1, id2; + kbdc_lock_assert(kbdc); + empty_both_buffers(kbdc, 10); id1 = id2 = -1; if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) != KBD_ACK) Index: sys/dev/atkbdc/atkbdc.c =================================================================== --- sys/dev/atkbdc/atkbdc.c +++ sys/dev/atkbdc/atkbdc.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #if defined(__amd64__) #include @@ -291,7 +293,7 @@ if (sc->ioh0 == 0) { /* XXX */ sc->command_byte = -1; sc->command_mask = 0; - sc->lock = FALSE; + mtx_init(&sc->lock, "atkbdc lock", NULL, MTX_DEF); sc->kbd.head = sc->kbd.tail = 0; sc->aux.head = sc->aux.tail = 0; #if KBDIO_DEBUG >= 2 @@ -349,56 +351,6 @@ return NULL; } -/* - * I/O access arbitration in `kbdio' - * - * The `kbdio' module uses a simplistic convention to arbitrate - * I/O access to the controller/keyboard/mouse. The convention requires - * close cooperation of the calling device driver. - * - * The device drivers which utilize the `kbdio' module are assumed to - * have the following set of routines. - * a. An interrupt handler (the bottom half of the driver). - * b. Timeout routines which may briefly poll the keyboard controller. - * c. Routines outside interrupt context (the top half of the driver). - * They should follow the rules below: - * 1. The interrupt handler may assume that it always has full access - * to the controller/keyboard/mouse. - * 2. The other routines must issue `spltty()' if they wish to - * prevent the interrupt handler from accessing - * the controller/keyboard/mouse. - * 3. The timeout routines and the top half routines of the device driver - * arbitrate I/O access by observing the lock flag in `kbdio'. - * The flag is manipulated via `kbdc_lock()'; when one wants to - * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if - * the call returns with TRUE. Otherwise the caller must back off. - * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion - * is finished. This mechanism does not prevent the interrupt - * handler from being invoked at any time and carrying out I/O. - * Therefore, `spltty()' must be strategically placed in the device - * driver code. Also note that the timeout routine may interrupt - * `kbdc_lock()' called by the top half of the driver, but this - * interruption is OK so long as the timeout routine observes - * rule 4 below. - * 4. The interrupt and timeout routines should not extend I/O operation - * across more than one interrupt or timeout; they must complete any - * necessary I/O operation within one invocation of the routine. - * This means that if the timeout routine acquires the lock flag, - * it must reset the flag to FALSE before it returns. - */ - -/* set/reset polling lock */ -int -kbdc_lock(KBDC p, int lock) -{ - int prevlock; - - prevlock = kbdcp(p)->lock; - kbdcp(p)->lock = lock; - - return (prevlock != lock); -} - /* check if any data is waiting to be processed */ int kbdc_data_ready(KBDC p) @@ -607,6 +559,8 @@ int write_controller_command(KBDC p, int c) { + kbdc_lock_assert(p); + if (!wait_while_controller_busy(kbdcp(p))) return FALSE; write_command(kbdcp(p), c); @@ -617,6 +571,8 @@ int write_controller_data(KBDC p, int c) { + kbdc_lock_assert(p); + if (!wait_while_controller_busy(kbdcp(p))) return FALSE; write_data(kbdcp(p), c); @@ -627,6 +583,8 @@ int write_kbd_command(KBDC p, int c) { + kbdc_lock_assert(p); + if (!wait_while_controller_busy(kbdcp(p))) return FALSE; write_data(kbdcp(p), c); @@ -637,6 +595,8 @@ int write_aux_command(KBDC p, int c) { + kbdc_lock_assert(p); + if (!write_controller_command(p, KBDC_WRITE_TO_AUX)) return FALSE; return write_controller_data(p, c); @@ -649,6 +609,8 @@ int retry = KBD_MAXRETRY; int res = -1; + kbdc_lock_assert(p); + while (retry-- > 0) { if (!write_kbd_command(p, c)) continue; @@ -666,6 +628,8 @@ int retry = KBD_MAXRETRY; int res = -1; + kbdc_lock_assert(p); + while (retry-- > 0) { if (!write_aux_command(p, c)) continue; @@ -693,6 +657,8 @@ int retry; int res = -1; + kbdc_lock_assert(p); + for (retry = KBD_MAXRETRY; retry > 0; --retry) { if (!write_kbd_command(p, c)) continue; @@ -722,6 +688,8 @@ int retry; int res = -1; + kbdc_lock_assert(p); + for (retry = KBD_MAXRETRY; retry > 0; --retry) { if (!write_aux_command(p, c)) continue; @@ -752,6 +720,8 @@ int read_controller_data(KBDC p) { + kbdc_lock_assert(p); + if (availq(&kbdcp(p)->kbd)) return removeq(&kbdcp(p)->kbd); if (availq(&kbdcp(p)->aux)) @@ -779,6 +749,8 @@ } #endif + kbdc_lock_assert(p); + if (availq(&kbdcp(p)->kbd)) return removeq(&kbdcp(p)->kbd); if (!wait_for_kbd_data(kbdcp(p))) @@ -804,6 +776,8 @@ } #endif + kbdc_lock_assert(p); + if (availq(&kbdcp(p)->kbd)) return removeq(&kbdcp(p)->kbd); f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; @@ -823,6 +797,8 @@ int read_aux_data(KBDC p) { + kbdc_lock_assert(p); + if (availq(&kbdcp(p)->aux)) return removeq(&kbdcp(p)->aux); if (!wait_for_aux_data(kbdcp(p))) @@ -838,6 +814,8 @@ { int f; + kbdc_lock_assert(p); + if (availq(&kbdcp(p)->aux)) return removeq(&kbdcp(p)->aux); f = read_status(kbdcp(p)) & KBDS_BUFFER_FULL; @@ -866,6 +844,8 @@ #endif int delta = 2; + kbdc_lock_assert(p); + for (t = wait; t > 0; ) { if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); @@ -905,6 +885,8 @@ #endif int delta = 2; + kbdc_lock_assert(p); + for (t = wait; t > 0; ) { if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); @@ -944,6 +926,8 @@ #endif int delta = 2; + kbdc_lock_assert(p); + for (t = wait; t > 0; ) { if ((f = read_status(kbdcp(p))) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); @@ -991,6 +975,8 @@ int again = KBD_MAXWAIT; int c = KBD_RESEND; /* keep the compiler happy */ + kbdc_lock_assert(p); + while (retry-- > 0) { empty_both_buffers(p, 10); if (!write_kbd_command(p, KBDC_RESET_KBD)) @@ -1029,6 +1015,8 @@ int again = KBD_MAXWAIT; int c = PSM_RESEND; /* keep the compiler happy */ + kbdc_lock_assert(p); + while (retry-- > 0) { empty_both_buffers(p, 10); if (!write_aux_command(p, PSMC_RESET_DEV)) @@ -1077,6 +1065,8 @@ int again = KBD_MAXWAIT; int c = KBD_DIAG_FAIL; + kbdc_lock_assert(p); + while (retry-- > 0) { empty_both_buffers(p, 10); if (write_controller_command(p, KBDC_DIAGNOSE)) @@ -1105,6 +1095,8 @@ int again = KBD_MAXWAIT; int c = -1; + kbdc_lock_assert(p); + while (retry-- > 0) { empty_both_buffers(p, 10); if (write_controller_command(p, KBDC_TEST_KBD_PORT)) @@ -1131,6 +1123,8 @@ int again = KBD_MAXWAIT; int c = -1; + kbdc_lock_assert(p); + while (retry-- > 0) { empty_both_buffers(p, 10); if (write_controller_command(p, KBDC_TEST_AUX_PORT)) @@ -1167,6 +1161,8 @@ int get_controller_command_byte(KBDC p) { + kbdc_lock_assert(p); + if (kbdcp(p)->command_byte != -1) return kbdcp(p)->command_byte; if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE)) @@ -1179,6 +1175,8 @@ int set_controller_command_byte(KBDC p, int mask, int command) { + kbdc_lock_assert(p); + if (get_controller_command_byte(p) == -1) return FALSE; Index: sys/dev/atkbdc/atkbdcreg.h =================================================================== --- sys/dev/atkbdc/atkbdcreg.h +++ sys/dev/atkbdc/atkbdcreg.h @@ -198,7 +198,7 @@ bus_space_handle_t ioh1; int command_byte; /* current command byte value */ int command_mask; /* command byte mask bits for kbd/aux devices */ - int lock; /* FIXME: XXX not quite a semaphore... */ + struct mtx lock; kqueue kbd; /* keyboard data queue */ kqueue aux; /* auxiliary data queue */ int retry; @@ -221,6 +221,28 @@ #define KBDC_RID_KBD 0 #define KBDC_RID_AUX 1 +/* inlined functions */ +static __inline void +kbdc_lock(KBDC kbdc) +{ + + mtx_lock(&((atkbdc_softc_t *)kbdc)->lock); +} + +static __inline void +kbdc_unlock(KBDC kbdc) +{ + + mtx_unlock(&((atkbdc_softc_t *)kbdc)->lock); +} + +static __inline void +kbdc_lock_assert(KBDC kbdc) +{ + + mtx_assert(&((atkbdc_softc_t *)kbdc)->lock, MA_OWNED); +} + /* function prototypes */ atkbdc_softc_t *atkbdc_get_softc(int unit); @@ -230,7 +252,6 @@ int atkbdc_configure(void); KBDC atkbdc_open(int unit); -int kbdc_lock(KBDC kbdc, int lock); int kbdc_data_ready(KBDC kbdc); int write_controller_command(KBDC kbdc,int c); Index: sys/dev/atkbdc/psm.c =================================================================== --- sys/dev/atkbdc/psm.c +++ sys/dev/atkbdc/psm.c @@ -681,6 +681,8 @@ { int res; + kbdc_lock_assert(kbdc); + res = send_aux_command(kbdc, PSMC_ENABLE_DEV); VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res)); @@ -692,6 +694,8 @@ { int res; + kbdc_lock_assert(kbdc); + res = send_aux_command(kbdc, PSMC_DISABLE_DEV); VLOG(2, (LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res)); @@ -705,6 +709,8 @@ int res; int i; + kbdc_lock_assert(kbdc); + switch (flag) { case 0: default: @@ -739,6 +745,8 @@ int res; int id; + kbdc_lock_assert(kbdc); + empty_aux_buffer(kbdc, 5); res = send_aux_command(kbdc, PSMC_SEND_DEV_ID); VLOG(2, (LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res)); @@ -759,6 +767,8 @@ { int res; + kbdc_lock_assert(kbdc); + res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate); VLOG(2, (LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res)); @@ -770,6 +780,8 @@ { int res; + kbdc_lock_assert(kbdc); + switch (scale) { case 1: default: @@ -792,6 +804,8 @@ { int res; + kbdc_lock_assert(kbdc); + res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val); VLOG(2, (LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res)); @@ -807,6 +821,8 @@ { int res; + kbdc_lock_assert(kbdc); + res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE); VLOG(2, (LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res)); @@ -819,6 +835,8 @@ int c = 2; /* assume two buttons by default */ int status[3]; + kbdc_lock_assert(kbdc); + /* * NOTE: a special sequence to obtain Logitech Mouse specific * information: set resolution to 25 ppi, set scaling to 1:1, set @@ -896,6 +914,8 @@ static void recover_from_error(KBDC kbdc) { + kbdc_lock_assert(kbdc); + /* discard anything left in the output buffer */ empty_both_buffers(kbdc, 10); @@ -921,6 +941,8 @@ static int restore_controller(KBDC kbdc, int command_byte) { + kbdc_lock_assert(kbdc); + empty_both_buffers(kbdc, 10); if (!set_controller_command_byte(kbdc, 0xff, command_byte)) { @@ -948,6 +970,8 @@ int stat[3]; int i; + kbdc_lock_assert(kbdc); + switch((i = test_aux_port(kbdc))) { case 1: /* ignore these errors */ case 2: @@ -1031,6 +1055,8 @@ { int stat[3]; + kbdc_lock_assert(sc->kbdc); + /* * FIXME: Synaptics TouchPad seems to go back to Relative Mode with * no obvious reason. Thus we check the current mode and restore the @@ -1136,8 +1162,7 @@ int s; /* don't let anybody mess with the aux device */ - if (!kbdc_lock(sc->kbdc, TRUE)) - return (EIO); + kbdc_lock(sc->kbdc); s = spltty(); /* block our watchdog timer */ @@ -1158,7 +1183,7 @@ KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { /* CONTROLLER ERROR */ splx(s); - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); log(LOG_ERR, "psm%d: unable to set the command byte (reinitialize).\n", sc->unit); @@ -1214,7 +1239,7 @@ } } - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); return (err); } @@ -1259,7 +1284,7 @@ if (bootverbose) \ --verbose; \ kbdc_set_device_mask(sc->kbdc, mask); \ - kbdc_lock(sc->kbdc, FALSE); \ + kbdc_unlock(sc->kbdc); \ return (v); \ } while (0) @@ -1306,12 +1331,7 @@ device_set_desc(dev, "PS/2 Mouse"); - if (!kbdc_lock(sc->kbdc, TRUE)) { - printf("psm%d: unable to lock the controller.\n", unit); - if (bootverbose) - --verbose; - return (ENXIO); - } + kbdc_lock(sc->kbdc); /* * NOTE: two bits in the command byte controls the operation of the @@ -1572,7 +1592,7 @@ /* done */ kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS); - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); return (0); } @@ -1674,7 +1694,6 @@ struct psm_softc *sc; int command_byte; int err; - int s; /* Get device data */ sc = dev->si_drv1; @@ -1715,11 +1734,9 @@ sc->pkterrors = 0; /* don't let timeout routines in the keyboard driver to poll the kbdc */ - if (!kbdc_lock(sc->kbdc, TRUE)) - return (EIO); + kbdc_lock(sc->kbdc); /* save the current controller command byte */ - s = spltty(); command_byte = get_controller_command_byte(sc->kbdc); /* enable the aux port and temporalily disable the keyboard */ @@ -1728,21 +1745,12 @@ KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { /* CONTROLLER ERROR; do you know how to get out of this? */ - kbdc_lock(sc->kbdc, FALSE); - splx(s); + kbdc_unlock(sc->kbdc); log(LOG_ERR, "psm%d: unable to set the command byte (psmopen).\n", sc->unit); return (EIO); } - /* - * Now that the keyboard controller is told not to generate - * the keyboard and mouse interrupts, call `splx()' to allow - * the other tty interrupts. The clock interrupt may also occur, - * but timeout routines will be blocked by the poll flag set - * via `kbdc_lock()' - */ - splx(s); /* enable the mouse device */ err = doopen(sc, command_byte); @@ -1750,7 +1758,7 @@ /* done */ if (err == 0) sc->state |= PSM_OPEN; - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); return (err); } @@ -1760,18 +1768,14 @@ struct psm_softc *sc = dev->si_drv1; int stat[3]; int command_byte; - int s; /* don't let timeout routines in the keyboard driver to poll the kbdc */ - if (!kbdc_lock(sc->kbdc, TRUE)) - return (EIO); + kbdc_lock(sc->kbdc); /* save the current controller command byte */ - s = spltty(); command_byte = get_controller_command_byte(sc->kbdc); if (command_byte == -1) { - kbdc_lock(sc->kbdc, FALSE); - splx(s); + kbdc_unlock(sc->kbdc); return (EIO); } @@ -1790,7 +1794,6 @@ * so long as the mouse will accept the DISABLE command. */ } - splx(s); /* stop the watchdog timer */ callout_stop(&sc->callout); @@ -1842,7 +1845,7 @@ /* close is almost always successful */ sc->state &= ~PSM_OPEN; - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); device_unbusy(devclass_get_device(psm_devclass, sc->unit)); return (0); } @@ -1972,8 +1975,7 @@ { int s; - if (!kbdc_lock(sc->kbdc, TRUE)) - return (EIO); + kbdc_lock(sc->kbdc); s = spltty(); *c = get_controller_command_byte(sc->kbdc); @@ -1983,7 +1985,7 @@ KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { /* this is CONTROLLER ERROR */ splx(s); - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); return (EIO); } @@ -1996,8 +1998,8 @@ * output buffer; throw it away. Note that the second argument * to `empty_aux_buffer()' is zero, so that the call will just * flush the internal queue. - * `psmintr()' will be invoked after `splx()' if an interrupt is - * pending; it will see no data and returns immediately. + * `psmintr()' will be invoked after `kbdc_unlock()' if an interrupt + * is pending; it will see no data and returns immediately. */ empty_aux_buffer(sc->kbdc, 0); /* flush the queue */ read_aux_data_no_wait(sc->kbdc); /* throw away data if any */ @@ -2052,7 +2054,7 @@ error = EIO; } - kbdc_lock(sc->kbdc, FALSE); + kbdc_unlock(sc->kbdc); return (error); } @@ -2075,14 +2077,17 @@ error = uiomove(buf, l, uio); if (error) break; + kbdc_lock(sc->kbdc); for (i = 0; i < l; i++) { VLOG(4, (LOG_DEBUG, "psm: cmd 0x%x\n", buf[i])); if (!write_aux_command(sc->kbdc, buf[i])) { + kbdc_unlock(sc->kbdc); VLOG(2, (LOG_DEBUG, "psm: cmd 0x%x failed.\n", buf[i])); return (reinitialize(sc, FALSE)); } } + kbdc_unlock(sc->kbdc); } return (error); @@ -2425,10 +2430,9 @@ sc = (struct psm_softc *)arg; s = spltty(); - if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) { + if (sc->watchdog) { VLOG(4, (LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit)); psmintr(sc); - kbdc_lock(sc->kbdc, FALSE); } sc->watchdog = TRUE; splx(s); @@ -2480,6 +2484,17 @@ SYSCTL_INT(_hw_psm, OID_AUTO, elantech_support, CTLFLAG_RDTUN, &elantech_support, 0, "Enable support for Elantech touchpads"); +static int +psm_read_aux_data(KBDC kbdc) +{ + int c; + + kbdc_lock(kbdc); + c = read_aux_data_no_wait(kbdc); + kbdc_unlock(kbdc); + return (c); +} + static void psmintr(void *arg) { @@ -2490,7 +2505,7 @@ /* read until there is nothing to read */ - while((c = read_aux_data_no_wait(sc->kbdc)) != -1) { + while((c = psm_read_aux_data(sc->kbdc)) != -1) { pb = &sc->pqueue[sc->pqueue_end]; /* discard the byte if the device is not open */ @@ -2574,8 +2589,10 @@ VLOG(3, (LOG_DEBUG, "psmintr: re-enable the mouse.\n")); pb->inputbytes = 0; + kbdc_lock(sc->kbdc); disable_aux_dev(sc->kbdc); enable_aux_dev(sc->kbdc); + kbdc_unlock(sc->kbdc); } else { VLOG(3, (LOG_DEBUG, "psmintr: discard a byte (%d)\n", @@ -5717,8 +5734,10 @@ if (arg == PROBE) { /* Create sysctl tree. */ + kbdc_unlock(sc->kbdc); synaptics_sysctl_create_tree(sc, "synaptics", "Synaptics TouchPad"); + kbdc_lock(sc->kbdc); sc->hw.buttons = buttons; } @@ -5991,7 +6010,9 @@ synaptics_passthrough_off(sc); if (arg == PROBE) { + kbdc_unlock(sc->kbdc); trackpoint_sysctl_create_tree(sc); + kbdc_lock(sc->kbdc); /* * Don't overwrite hwid and buttons when we are * a guest device. @@ -6360,7 +6381,9 @@ sc->hw.buttons = 3; /* Initialize synaptics movement smoother */ + kbdc_unlock(sc->kbdc); elantech_init_synaptics(sc); + kbdc_lock(sc->kbdc); for (id = 0; id < ELANTECH_MAX_FINGERS; id++) PSM_FINGER_RESET(sc->elanaction.fingers[id]);