1b4dbc599SNathan Whitehorn /*- 2b4dbc599SNathan Whitehorn * Copyright (C) 2008 Nathan Whitehorn 3b4dbc599SNathan Whitehorn * All rights reserved. 4b4dbc599SNathan Whitehorn * 5b4dbc599SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 6b4dbc599SNathan Whitehorn * modification, are permitted provided that the following conditions 7b4dbc599SNathan Whitehorn * are met: 8b4dbc599SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 9b4dbc599SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 10b4dbc599SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 11b4dbc599SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 12b4dbc599SNathan Whitehorn * documentation and/or other materials provided with the distribution. 13b4dbc599SNathan Whitehorn * 14b4dbc599SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15b4dbc599SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16b4dbc599SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17b4dbc599SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18b4dbc599SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19b4dbc599SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20b4dbc599SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21b4dbc599SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22b4dbc599SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23b4dbc599SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24b4dbc599SNathan Whitehorn * 25b4dbc599SNathan Whitehorn * $FreeBSD$ 26b4dbc599SNathan Whitehorn */ 27b4dbc599SNathan Whitehorn 28b4dbc599SNathan Whitehorn #include <sys/cdefs.h> 29b4dbc599SNathan Whitehorn #include <sys/param.h> 30b4dbc599SNathan Whitehorn #include <sys/systm.h> 31b4dbc599SNathan Whitehorn #include <sys/module.h> 32b4dbc599SNathan Whitehorn #include <sys/bus.h> 33b4dbc599SNathan Whitehorn #include <sys/conf.h> 34b4dbc599SNathan Whitehorn #include <sys/kernel.h> 35b4dbc599SNathan Whitehorn 36b4dbc599SNathan Whitehorn #include <machine/bus.h> 37b4dbc599SNathan Whitehorn 38b4dbc599SNathan Whitehorn #include <vm/vm.h> 39b4dbc599SNathan Whitehorn #include <vm/pmap.h> 40b4dbc599SNathan Whitehorn 41b4dbc599SNathan Whitehorn #include "adb.h" 42b4dbc599SNathan Whitehorn #include "adbvar.h" 43b4dbc599SNathan Whitehorn 44b4dbc599SNathan Whitehorn static int adb_bus_probe(device_t dev); 45b4dbc599SNathan Whitehorn static int adb_bus_attach(device_t dev); 46b4dbc599SNathan Whitehorn static int adb_bus_detach(device_t dev); 47b4dbc599SNathan Whitehorn static void adb_probe_nomatch(device_t dev, device_t child); 48b4dbc599SNathan Whitehorn static int adb_print_child(device_t dev, device_t child); 49b4dbc599SNathan Whitehorn 50b4dbc599SNathan Whitehorn static int adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, uint8_t reg, int len, u_char *data); 51b4dbc599SNathan Whitehorn 52b4dbc599SNathan Whitehorn static char *adb_device_string[] = { 53b4dbc599SNathan Whitehorn "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc" 54b4dbc599SNathan Whitehorn }; 55b4dbc599SNathan Whitehorn 56b4dbc599SNathan Whitehorn static device_method_t adb_bus_methods[] = { 57b4dbc599SNathan Whitehorn /* Device interface */ 58b4dbc599SNathan Whitehorn DEVMETHOD(device_probe, adb_bus_probe), 59b4dbc599SNathan Whitehorn DEVMETHOD(device_attach, adb_bus_attach), 60b4dbc599SNathan Whitehorn DEVMETHOD(device_detach, adb_bus_detach), 61b4dbc599SNathan Whitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 62b4dbc599SNathan Whitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 63b4dbc599SNathan Whitehorn DEVMETHOD(device_resume, bus_generic_resume), 64b4dbc599SNathan Whitehorn 65b4dbc599SNathan Whitehorn /* Bus Interface */ 66b4dbc599SNathan Whitehorn DEVMETHOD(bus_probe_nomatch, adb_probe_nomatch), 67b4dbc599SNathan Whitehorn DEVMETHOD(bus_print_child, adb_print_child), 68b4dbc599SNathan Whitehorn 69b4dbc599SNathan Whitehorn { 0, 0 }, 70b4dbc599SNathan Whitehorn }; 71b4dbc599SNathan Whitehorn 72b4dbc599SNathan Whitehorn driver_t adb_driver = { 73b4dbc599SNathan Whitehorn "adb", 74b4dbc599SNathan Whitehorn adb_bus_methods, 75b4dbc599SNathan Whitehorn sizeof(struct adb_softc), 76b4dbc599SNathan Whitehorn }; 77b4dbc599SNathan Whitehorn 78b4dbc599SNathan Whitehorn devclass_t adb_devclass; 79b4dbc599SNathan Whitehorn 80b4dbc599SNathan Whitehorn static int 81b4dbc599SNathan Whitehorn adb_bus_probe(device_t dev) 82b4dbc599SNathan Whitehorn { 83b4dbc599SNathan Whitehorn device_set_desc(dev, "Apple Desktop Bus"); 84b4dbc599SNathan Whitehorn return (0); 85b4dbc599SNathan Whitehorn } 86b4dbc599SNathan Whitehorn 87b4dbc599SNathan Whitehorn static int 88b4dbc599SNathan Whitehorn adb_bus_attach(device_t dev) 89b4dbc599SNathan Whitehorn { 90b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 91b4dbc599SNathan Whitehorn uint8_t i, next_free; 92b4dbc599SNathan Whitehorn uint16_t r3; 93b4dbc599SNathan Whitehorn 94b4dbc599SNathan Whitehorn sc->sc_dev = dev; 95b4dbc599SNathan Whitehorn sc->parent = device_get_parent(dev); 96b4dbc599SNathan Whitehorn 97b4dbc599SNathan Whitehorn sc->packet_reply = 0; 98b4dbc599SNathan Whitehorn sc->autopoll_mask = 0; 99b4dbc599SNathan Whitehorn 100b4dbc599SNathan Whitehorn mtx_init(&sc->sc_sync_mtx,"adbsyn",NULL,MTX_DEF | MTX_RECURSE); 101b4dbc599SNathan Whitehorn 102b4dbc599SNathan Whitehorn /* Initialize devinfo */ 103b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 104b4dbc599SNathan Whitehorn sc->devinfo[i].address = i; 105b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = 0; 106b4dbc599SNathan Whitehorn } 107b4dbc599SNathan Whitehorn 108b4dbc599SNathan Whitehorn /* Reset ADB bus */ 109b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL); 110b4dbc599SNathan Whitehorn DELAY(1500); 111b4dbc599SNathan Whitehorn 112b4dbc599SNathan Whitehorn /* Enumerate bus */ 113b4dbc599SNathan Whitehorn next_free = 8; 114b4dbc599SNathan Whitehorn 115b4dbc599SNathan Whitehorn for (i = 1; i < 7; i++) { 116b4dbc599SNathan Whitehorn int8_t first_relocated = -1; 117b4dbc599SNathan Whitehorn int reply = 0; 118b4dbc599SNathan Whitehorn 119b4dbc599SNathan Whitehorn do { 120b4dbc599SNathan Whitehorn reply = adb_send_raw_packet_sync(dev,i, 121b4dbc599SNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL); 122b4dbc599SNathan Whitehorn 123b4dbc599SNathan Whitehorn if (reply) { 124b4dbc599SNathan Whitehorn /* If we got a response, relocate to next_free */ 125b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 126b4dbc599SNathan Whitehorn r3 &= 0xf000; 127b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(next_free) & 0x000f) << 8; 128b4dbc599SNathan Whitehorn r3 |= 0x00fe; 129b4dbc599SNathan Whitehorn 130b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3, 131b4dbc599SNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3)); 132b4dbc599SNathan Whitehorn 133b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,next_free, 134b4dbc599SNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL); 135b4dbc599SNathan Whitehorn 136b4dbc599SNathan Whitehorn sc->devinfo[next_free].default_address = i; 137b4dbc599SNathan Whitehorn if (first_relocated < 0) 138b4dbc599SNathan Whitehorn first_relocated = next_free; 139b4dbc599SNathan Whitehorn 140b4dbc599SNathan Whitehorn next_free++; 141b4dbc599SNathan Whitehorn } else if (first_relocated > 0) { 142b4dbc599SNathan Whitehorn /* Collisions removed, relocate first device back */ 143b4dbc599SNathan Whitehorn 144b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 145b4dbc599SNathan Whitehorn r3 &= 0xf000; 146b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(i) & 0x000f) << 8; 147b4dbc599SNathan Whitehorn 148b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,first_relocated, 149b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN,3, 150b4dbc599SNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3)); 151b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, 152b4dbc599SNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL); 153b4dbc599SNathan Whitehorn 154b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = i; 155b4dbc599SNathan Whitehorn sc->devinfo[(int)(first_relocated)].default_address = 0; 156b4dbc599SNathan Whitehorn break; 157b4dbc599SNathan Whitehorn } 158b4dbc599SNathan Whitehorn } while (reply); 159b4dbc599SNathan Whitehorn } 160b4dbc599SNathan Whitehorn 161b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 162b4dbc599SNathan Whitehorn if (sc->devinfo[i].default_address) { 163b4dbc599SNathan Whitehorn sc->children[i] = device_add_child(dev, NULL, -1); 164b4dbc599SNathan Whitehorn device_set_ivars(sc->children[i], &sc->devinfo[i]); 165b4dbc599SNathan Whitehorn } 166b4dbc599SNathan Whitehorn } 167b4dbc599SNathan Whitehorn 168b4dbc599SNathan Whitehorn return (bus_generic_attach(dev)); 169b4dbc599SNathan Whitehorn } 170b4dbc599SNathan Whitehorn 171b4dbc599SNathan Whitehorn static int adb_bus_detach(device_t dev) 172b4dbc599SNathan Whitehorn { 173b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 174b4dbc599SNathan Whitehorn 175b4dbc599SNathan Whitehorn mtx_destroy(&sc->sc_sync_mtx); 176b4dbc599SNathan Whitehorn 177b4dbc599SNathan Whitehorn return (bus_generic_detach(dev)); 178b4dbc599SNathan Whitehorn } 179b4dbc599SNathan Whitehorn 180b4dbc599SNathan Whitehorn 181b4dbc599SNathan Whitehorn static void 182b4dbc599SNathan Whitehorn adb_probe_nomatch(device_t dev, device_t child) 183b4dbc599SNathan Whitehorn { 184b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 185b4dbc599SNathan Whitehorn 186b4dbc599SNathan Whitehorn if (bootverbose) { 187b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 188b4dbc599SNathan Whitehorn 189b4dbc599SNathan Whitehorn device_printf(dev,"ADB %s at device %d (no driver attached)\n", 190b4dbc599SNathan Whitehorn adb_device_string[dinfo->default_address],dinfo->address); 191b4dbc599SNathan Whitehorn } 192b4dbc599SNathan Whitehorn } 193b4dbc599SNathan Whitehorn 194b4dbc599SNathan Whitehorn u_int 195b4dbc599SNathan Whitehorn adb_receive_raw_packet(device_t dev, u_char status, u_char command, int len, 196b4dbc599SNathan Whitehorn u_char *data) 197b4dbc599SNathan Whitehorn { 198b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 199b4dbc599SNathan Whitehorn u_char addr = command >> 4; 200b4dbc599SNathan Whitehorn 201b4dbc599SNathan Whitehorn if (len > 0 && (command & 0x0f) == ((ADB_COMMAND_TALK << 2) | 3)) { 202b4dbc599SNathan Whitehorn memcpy(&sc->devinfo[addr].register3,data,2); 203b4dbc599SNathan Whitehorn sc->devinfo[addr].handler_id = data[1]; 204b4dbc599SNathan Whitehorn } 205b4dbc599SNathan Whitehorn 206b4dbc599SNathan Whitehorn if (sc->sync_packet == command) { 207b4dbc599SNathan Whitehorn memcpy(sc->syncreg,data,(len > 8) ? 8 : len); 208b4dbc599SNathan Whitehorn atomic_store_rel_int(&sc->packet_reply,len + 1); 209b4dbc599SNathan Whitehorn } 210b4dbc599SNathan Whitehorn 211b4dbc599SNathan Whitehorn if (sc->children[addr] != NULL) { 212b4dbc599SNathan Whitehorn ADB_RECEIVE_PACKET(sc->children[addr],status, 213b4dbc599SNathan Whitehorn (command & 0x0f) >> 2,command & 0x03,len,data); 214b4dbc599SNathan Whitehorn } 215b4dbc599SNathan Whitehorn 216b4dbc599SNathan Whitehorn return (0); 217b4dbc599SNathan Whitehorn } 218b4dbc599SNathan Whitehorn 219b4dbc599SNathan Whitehorn static int 220b4dbc599SNathan Whitehorn adb_print_child(device_t dev, device_t child) 221b4dbc599SNathan Whitehorn { 222b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 223b4dbc599SNathan Whitehorn int retval = 0; 224b4dbc599SNathan Whitehorn 225b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 226b4dbc599SNathan Whitehorn 227b4dbc599SNathan Whitehorn retval += bus_print_child_header(dev,child); 228b4dbc599SNathan Whitehorn printf(" at device %d",dinfo->address); 229b4dbc599SNathan Whitehorn retval += bus_print_child_footer(dev, child); 230b4dbc599SNathan Whitehorn 231b4dbc599SNathan Whitehorn return (retval); 232b4dbc599SNathan Whitehorn } 233b4dbc599SNathan Whitehorn 234b4dbc599SNathan Whitehorn u_int 235b4dbc599SNathan Whitehorn adb_send_packet(device_t dev, u_char command, u_char reg, int len, u_char *data) 236b4dbc599SNathan Whitehorn { 237b4dbc599SNathan Whitehorn u_char command_byte = 0; 238b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 239b4dbc599SNathan Whitehorn struct adb_softc *sc; 240b4dbc599SNathan Whitehorn 241b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 242b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 243b4dbc599SNathan Whitehorn 244b4dbc599SNathan Whitehorn command_byte |= dinfo->address << 4; 245b4dbc599SNathan Whitehorn command_byte |= command << 2; 246b4dbc599SNathan Whitehorn command_byte |= reg; 247b4dbc599SNathan Whitehorn 248b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 249b4dbc599SNathan Whitehorn 250b4dbc599SNathan Whitehorn return (0); 251b4dbc599SNathan Whitehorn } 252b4dbc599SNathan Whitehorn 253b4dbc599SNathan Whitehorn u_int 254b4dbc599SNathan Whitehorn adb_set_autopoll(device_t dev, u_char enable) 255b4dbc599SNathan Whitehorn { 256b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 257b4dbc599SNathan Whitehorn struct adb_softc *sc; 258b4dbc599SNathan Whitehorn uint16_t mod = 0; 259b4dbc599SNathan Whitehorn 260b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 261b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 262b4dbc599SNathan Whitehorn 263b4dbc599SNathan Whitehorn mod = enable << dinfo->address; 264b4dbc599SNathan Whitehorn if (enable) { 265b4dbc599SNathan Whitehorn sc->autopoll_mask |= mod; 266b4dbc599SNathan Whitehorn } else { 267b4dbc599SNathan Whitehorn mod = ~mod; 268b4dbc599SNathan Whitehorn sc->autopoll_mask &= mod; 269b4dbc599SNathan Whitehorn } 270b4dbc599SNathan Whitehorn 271b4dbc599SNathan Whitehorn ADB_HB_SET_AUTOPOLL_MASK(sc->parent,sc->autopoll_mask); 272b4dbc599SNathan Whitehorn 273b4dbc599SNathan Whitehorn return (0); 274b4dbc599SNathan Whitehorn } 275b4dbc599SNathan Whitehorn 276b4dbc599SNathan Whitehorn uint8_t 277b4dbc599SNathan Whitehorn adb_get_device_type(device_t dev) 278b4dbc599SNathan Whitehorn { 279b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 280b4dbc599SNathan Whitehorn 281b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 282b4dbc599SNathan Whitehorn return (dinfo->default_address); 283b4dbc599SNathan Whitehorn } 284b4dbc599SNathan Whitehorn 285b4dbc599SNathan Whitehorn uint8_t 286b4dbc599SNathan Whitehorn adb_get_device_handler(device_t dev) 287b4dbc599SNathan Whitehorn { 288b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 289b4dbc599SNathan Whitehorn 290b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 291b4dbc599SNathan Whitehorn return (dinfo->handler_id); 292b4dbc599SNathan Whitehorn } 293b4dbc599SNathan Whitehorn 294b4dbc599SNathan Whitehorn static int 295b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, 296b4dbc599SNathan Whitehorn uint8_t reg, int len, u_char *data) 297b4dbc599SNathan Whitehorn { 298b4dbc599SNathan Whitehorn u_char command_byte = 0; 299b4dbc599SNathan Whitehorn struct adb_softc *sc; 300b4dbc599SNathan Whitehorn int result = -1; 301b4dbc599SNathan Whitehorn int i = 0; 302b4dbc599SNathan Whitehorn 303b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 304b4dbc599SNathan Whitehorn 305b4dbc599SNathan Whitehorn command_byte |= to << 4; 306b4dbc599SNathan Whitehorn command_byte |= command << 2; 307b4dbc599SNathan Whitehorn command_byte |= reg; 308b4dbc599SNathan Whitehorn 309b4dbc599SNathan Whitehorn /* Wait if someone else has a synchronous request pending */ 310b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_sync_mtx); 311b4dbc599SNathan Whitehorn 312b4dbc599SNathan Whitehorn sc->packet_reply = 0; 313b4dbc599SNathan Whitehorn sc->sync_packet = command_byte; 314b4dbc599SNathan Whitehorn 315b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 316b4dbc599SNathan Whitehorn 317b4dbc599SNathan Whitehorn while (!atomic_fetchadd_int(&sc->packet_reply,0)) { 318b4dbc599SNathan Whitehorn /* Sometimes CUDA controllers hang up during cold boots. 319b4dbc599SNathan Whitehorn Try poking them. */ 320b4dbc599SNathan Whitehorn if (i > 10) 321b4dbc599SNathan Whitehorn ADB_HB_CONTROLLER_POLL(sc->parent); 322b4dbc599SNathan Whitehorn 323b4dbc599SNathan Whitehorn DELAY(100); 324b4dbc599SNathan Whitehorn i++; 325b4dbc599SNathan Whitehorn } 326b4dbc599SNathan Whitehorn 327b4dbc599SNathan Whitehorn result = sc->packet_reply - 1; 328b4dbc599SNathan Whitehorn 329b4dbc599SNathan Whitehorn /* Clear packet sync */ 330b4dbc599SNathan Whitehorn sc->packet_reply = 0; 331b4dbc599SNathan Whitehorn sc->sync_packet = 0xffff; /* We can't match a 16 bit value */ 332b4dbc599SNathan Whitehorn 333b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_sync_mtx); 334b4dbc599SNathan Whitehorn 335b4dbc599SNathan Whitehorn return (result); 336b4dbc599SNathan Whitehorn } 337b4dbc599SNathan Whitehorn 338b4dbc599SNathan Whitehorn uint8_t 339b4dbc599SNathan Whitehorn adb_set_device_handler(device_t dev, uint8_t newhandler) 340b4dbc599SNathan Whitehorn { 341b4dbc599SNathan Whitehorn struct adb_softc *sc; 342b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 343b4dbc599SNathan Whitehorn uint16_t newr3; 344b4dbc599SNathan Whitehorn 345b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 346b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 347b4dbc599SNathan Whitehorn 348b4dbc599SNathan Whitehorn newr3 = dinfo->register3 & 0xff00; 349b4dbc599SNathan Whitehorn newr3 |= (uint16_t)(newhandler); 350b4dbc599SNathan Whitehorn 351b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 352b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN, 3, sizeof(uint16_t), (u_char *)(&newr3)); 353b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 354b4dbc599SNathan Whitehorn ADB_COMMAND_TALK, 3, 0, NULL); 355b4dbc599SNathan Whitehorn 356b4dbc599SNathan Whitehorn return (dinfo->handler_id); 357b4dbc599SNathan Whitehorn } 358b4dbc599SNathan Whitehorn 359b4dbc599SNathan Whitehorn uint8_t 360b4dbc599SNathan Whitehorn adb_read_register(device_t dev, u_char reg, 361b4dbc599SNathan Whitehorn size_t *len, void *data) 362b4dbc599SNathan Whitehorn { 363b4dbc599SNathan Whitehorn struct adb_softc *sc; 364b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 365b4dbc599SNathan Whitehorn size_t orig_len; 366b4dbc599SNathan Whitehorn 367b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 368b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 369b4dbc599SNathan Whitehorn 370b4dbc599SNathan Whitehorn orig_len = *len; 371b4dbc599SNathan Whitehorn 372b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_sync_mtx); 373b4dbc599SNathan Whitehorn 374b4dbc599SNathan Whitehorn *len = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 375b4dbc599SNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL); 376b4dbc599SNathan Whitehorn 377b4dbc599SNathan Whitehorn if (*len > 0) 378b4dbc599SNathan Whitehorn memcpy(data,sc->syncreg,*len); 379b4dbc599SNathan Whitehorn 380b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_sync_mtx); 381b4dbc599SNathan Whitehorn 382b4dbc599SNathan Whitehorn return ((*len > 0) ? 0 : -1); 383b4dbc599SNathan Whitehorn } 384b4dbc599SNathan Whitehorn 385