diff options
Diffstat (limited to 'sys/dev/adb')
-rw-r--r-- | sys/dev/adb/adb.h | 2 | ||||
-rw-r--r-- | sys/dev/adb/adb_bus.c | 71 | ||||
-rw-r--r-- | sys/dev/adb/adb_kbd.c | 14 | ||||
-rw-r--r-- | sys/dev/adb/adb_mouse.c | 2 | ||||
-rw-r--r-- | sys/dev/adb/adbvar.h | 1 |
5 files changed, 39 insertions, 51 deletions
diff --git a/sys/dev/adb/adb.h b/sys/dev/adb/adb.h index 8d68a87..10c3db2 100644 --- a/sys/dev/adb/adb.h +++ b/sys/dev/adb/adb.h @@ -68,7 +68,7 @@ uint8_t adb_get_device_type(device_t dev); uint8_t adb_get_device_handler(device_t dev); uint8_t adb_set_device_handler(device_t dev, uint8_t newhandler); -uint8_t adb_read_register(device_t dev, u_char reg, size_t *len, void *data); +size_t adb_read_register(device_t dev, u_char reg, void *data); /* Bits for implementing ADB host bus adapters */ extern devclass_t adb_devclass; diff --git a/sys/dev/adb/adb_bus.c b/sys/dev/adb/adb_bus.c index 9c00144..faab048 100644 --- a/sys/dev/adb/adb_bus.c +++ b/sys/dev/adb/adb_bus.c @@ -48,7 +48,7 @@ static void adb_bus_enumerate(void *xdev); static void adb_probe_nomatch(device_t dev, device_t child); static int adb_print_child(device_t dev, device_t child); -static int adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, uint8_t reg, int len, u_char *data); +static int adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, uint8_t reg, int len, u_char *data, u_char *reply); static char *adb_device_string[] = { "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc" @@ -118,8 +118,7 @@ adb_bus_enumerate(void *xdev) sc->packet_reply = 0; sc->autopoll_mask = 0; - - mtx_init(&sc->sc_sync_mtx,"adbsyn",NULL,MTX_DEF | MTX_RECURSE); + sc->sync_packet = 0xffff; /* Initialize devinfo */ for (i = 0; i < 16; i++) { @@ -128,7 +127,7 @@ adb_bus_enumerate(void *xdev) } /* Reset ADB bus */ - adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL); + adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL,NULL); DELAY(1500); /* Enumerate bus */ @@ -140,7 +139,7 @@ adb_bus_enumerate(void *xdev) do { reply = adb_send_raw_packet_sync(dev,i, - ADB_COMMAND_TALK,3,0,NULL); + ADB_COMMAND_TALK,3,0,NULL,NULL); if (reply) { /* If we got a response, relocate to next_free */ @@ -150,10 +149,10 @@ adb_bus_enumerate(void *xdev) r3 |= 0x00fe; adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3, - sizeof(uint16_t),(u_char *)(&r3)); + sizeof(uint16_t),(u_char *)(&r3),NULL); adb_send_raw_packet_sync(dev,next_free, - ADB_COMMAND_TALK,3,0,NULL); + ADB_COMMAND_TALK,3,0,NULL,NULL); sc->devinfo[next_free].default_address = i; if (first_relocated < 0) @@ -169,9 +168,9 @@ adb_bus_enumerate(void *xdev) adb_send_raw_packet_sync(dev,first_relocated, ADB_COMMAND_LISTEN,3, - sizeof(uint16_t),(u_char *)(&r3)); + sizeof(uint16_t),(u_char *)(&r3),NULL); adb_send_raw_packet_sync(dev,i, - ADB_COMMAND_TALK,3,0,NULL); + ADB_COMMAND_TALK,3,0,NULL,NULL); sc->devinfo[i].default_address = i; sc->devinfo[(int)(first_relocated)].default_address = 0; @@ -194,10 +193,6 @@ adb_bus_enumerate(void *xdev) static int adb_bus_detach(device_t dev) { - struct adb_softc *sc = device_get_softc(dev); - - mtx_destroy(&sc->sc_sync_mtx); - return (bus_generic_detach(dev)); } @@ -230,6 +225,7 @@ adb_receive_raw_packet(device_t dev, u_char status, u_char command, int len, if (sc->sync_packet == command) { memcpy(sc->syncreg,data,(len > 8) ? 8 : len); atomic_store_rel_int(&sc->packet_reply,len + 1); + wakeup(sc); } if (sc->children[addr] != NULL) { @@ -317,12 +313,12 @@ adb_get_device_handler(device_t dev) static int adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, - uint8_t reg, int len, u_char *data) + uint8_t reg, int len, u_char *data, u_char *reply) { u_char command_byte = 0; struct adb_softc *sc; int result = -1; - int i = 0; + int i = 1; sc = device_get_softc(dev); @@ -331,7 +327,8 @@ adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, command_byte |= reg; /* Wait if someone else has a synchronous request pending */ - mtx_lock(&sc->sc_sync_mtx); + while (!atomic_cmpset_int(&sc->sync_packet, 0xffff, command_byte)) + tsleep(sc, 0, "ADB sync", hz/10); sc->packet_reply = 0; sc->sync_packet = command_byte; @@ -343,21 +340,27 @@ adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, * Maybe the command got lost? Try resending and polling the * controller. */ - if (i > 40) + if (i % 40 == 0) ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); - DELAY(100); + tsleep(sc, 0, "ADB sync", hz/10); i++; } result = sc->packet_reply - 1; + if (reply != NULL && result > 0) + memcpy(reply,sc->syncreg,result); + /* Clear packet sync */ sc->packet_reply = 0; - sc->sync_packet = 0xffff; /* We can't match a 16 bit value */ - mtx_unlock(&sc->sc_sync_mtx); + /* + * We can't match a value beyond 8 bits, so set sync_packet to + * 0xffff to avoid collisions. + */ + atomic_set_int(&sc->sync_packet, 0xffff); return (result); } @@ -375,37 +378,27 @@ adb_set_device_handler(device_t dev, uint8_t newhandler) newr3 = dinfo->register3 & 0xff00; newr3 |= (uint16_t)(newhandler); + adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, ADB_COMMAND_LISTEN, + 3, sizeof(uint16_t), (u_char *)(&newr3), NULL); adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, - ADB_COMMAND_LISTEN, 3, sizeof(uint16_t), (u_char *)(&newr3)); - adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, - ADB_COMMAND_TALK, 3, 0, NULL); + ADB_COMMAND_TALK, 3, 0, NULL, NULL); return (dinfo->handler_id); } -uint8_t -adb_read_register(device_t dev, u_char reg, - size_t *len, void *data) +size_t +adb_read_register(device_t dev, u_char reg, void *data) { struct adb_softc *sc; struct adb_devinfo *dinfo; - size_t orig_len; + size_t result; dinfo = device_get_ivars(dev); sc = device_get_softc(device_get_parent(dev)); - orig_len = *len; - - mtx_lock(&sc->sc_sync_mtx); - - *len = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, - ADB_COMMAND_TALK, reg, 0, NULL); + result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, + ADB_COMMAND_TALK, reg, 0, NULL, data); - if (*len > 0) - memcpy(data,sc->syncreg,*len); - - mtx_unlock(&sc->sc_sync_mtx); - - return ((*len > 0) ? 0 : -1); + return (result); } diff --git a/sys/dev/adb/adb_kbd.c b/sys/dev/adb/adb_kbd.c index db95cfe..115b35d 100644 --- a/sys/dev/adb/adb_kbd.c +++ b/sys/dev/adb/adb_kbd.c @@ -271,11 +271,12 @@ adb_kbd_attach(device_t dev) } #endif - adb_set_autopoll(dev,1); - - /* Check (asynchronously) if we can read out the LED state from + /* Check if we can read out the LED state from this keyboard by reading the key state register */ - adb_send_packet(dev,ADB_COMMAND_TALK,2,0,NULL); + if (adb_read_register(dev, 2, NULL) == 2) + sc->have_led_control = 1; + + adb_set_autopoll(dev,1); return (0); } @@ -323,11 +324,6 @@ adb_kbd_receive_packet(device_t dev, u_char status, if (command != ADB_COMMAND_TALK) return 0; - if (reg == 2 && len == 2) { - sc->have_led_control = 1; - return 0; - } - if (reg != 0 || len != 2) return (0); diff --git a/sys/dev/adb/adb_mouse.c b/sys/dev/adb/adb_mouse.c index 26edbc5..bba38c2 100644 --- a/sys/dev/adb/adb_mouse.c +++ b/sys/dev/adb/adb_mouse.c @@ -181,7 +181,7 @@ adb_mouse_attach(device_t dev) sc->mode.resolution = 200; break; case 4: - adb_read_register(dev,1,&r1_len,r1); + r1_len = adb_read_register(dev,1,r1); if (r1_len < 8) break; diff --git a/sys/dev/adb/adbvar.h b/sys/dev/adb/adbvar.h index e70aa75..47afb35 100644 --- a/sys/dev/adb/adbvar.h +++ b/sys/dev/adb/adbvar.h @@ -40,7 +40,6 @@ struct adb_softc { device_t parent; struct intr_config_hook enum_hook; - struct mtx sc_sync_mtx; volatile int sync_packet; volatile int packet_reply; |