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); 4701418697SNathan Whitehorn static void adb_bus_enumerate(void *xdev); 48b4dbc599SNathan Whitehorn static void adb_probe_nomatch(device_t dev, device_t child); 49b4dbc599SNathan Whitehorn static int adb_print_child(device_t dev, device_t child); 50b4dbc599SNathan Whitehorn 51b4dbc599SNathan 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); 52b4dbc599SNathan Whitehorn 53b4dbc599SNathan Whitehorn static char *adb_device_string[] = { 54b4dbc599SNathan Whitehorn "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc" 55b4dbc599SNathan Whitehorn }; 56b4dbc599SNathan Whitehorn 57b4dbc599SNathan Whitehorn static device_method_t adb_bus_methods[] = { 58b4dbc599SNathan Whitehorn /* Device interface */ 59b4dbc599SNathan Whitehorn DEVMETHOD(device_probe, adb_bus_probe), 60b4dbc599SNathan Whitehorn DEVMETHOD(device_attach, adb_bus_attach), 61b4dbc599SNathan Whitehorn DEVMETHOD(device_detach, adb_bus_detach), 62b4dbc599SNathan Whitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 63b4dbc599SNathan Whitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 64b4dbc599SNathan Whitehorn DEVMETHOD(device_resume, bus_generic_resume), 65b4dbc599SNathan Whitehorn 66b4dbc599SNathan Whitehorn /* Bus Interface */ 67b4dbc599SNathan Whitehorn DEVMETHOD(bus_probe_nomatch, adb_probe_nomatch), 68b4dbc599SNathan Whitehorn DEVMETHOD(bus_print_child, adb_print_child), 69b4dbc599SNathan Whitehorn 70b4dbc599SNathan Whitehorn { 0, 0 }, 71b4dbc599SNathan Whitehorn }; 72b4dbc599SNathan Whitehorn 73b4dbc599SNathan Whitehorn driver_t adb_driver = { 74b4dbc599SNathan Whitehorn "adb", 75b4dbc599SNathan Whitehorn adb_bus_methods, 76b4dbc599SNathan Whitehorn sizeof(struct adb_softc), 77b4dbc599SNathan Whitehorn }; 78b4dbc599SNathan Whitehorn 79b4dbc599SNathan Whitehorn devclass_t adb_devclass; 80b4dbc599SNathan Whitehorn 81b4dbc599SNathan Whitehorn static int 82b4dbc599SNathan Whitehorn adb_bus_probe(device_t dev) 83b4dbc599SNathan Whitehorn { 84b4dbc599SNathan Whitehorn device_set_desc(dev, "Apple Desktop Bus"); 85b4dbc599SNathan Whitehorn return (0); 86b4dbc599SNathan Whitehorn } 87b4dbc599SNathan Whitehorn 88b4dbc599SNathan Whitehorn static int 89b4dbc599SNathan Whitehorn adb_bus_attach(device_t dev) 90b4dbc599SNathan Whitehorn { 91b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 9201418697SNathan Whitehorn sc->enum_hook.ich_func = adb_bus_enumerate; 9301418697SNathan Whitehorn sc->enum_hook.ich_arg = dev; 9401418697SNathan Whitehorn 9501418697SNathan Whitehorn /* 9601418697SNathan Whitehorn * We should wait until interrupts are enabled to try to probe 9701418697SNathan Whitehorn * the bus. Enumerating the ADB involves receiving packets, 9801418697SNathan Whitehorn * which works best with interrupts enabled. 9901418697SNathan Whitehorn */ 10001418697SNathan Whitehorn 10101418697SNathan Whitehorn if (config_intrhook_establish(&sc->enum_hook) != 0) 10201418697SNathan Whitehorn return (ENOMEM); 10301418697SNathan Whitehorn 10401418697SNathan Whitehorn return (0); 10501418697SNathan Whitehorn } 10601418697SNathan Whitehorn 10701418697SNathan Whitehorn static void 10801418697SNathan Whitehorn adb_bus_enumerate(void *xdev) 10901418697SNathan Whitehorn { 11001418697SNathan Whitehorn device_t dev = (device_t)xdev; 11101418697SNathan Whitehorn 11201418697SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 113b4dbc599SNathan Whitehorn uint8_t i, next_free; 114b4dbc599SNathan Whitehorn uint16_t r3; 115b4dbc599SNathan Whitehorn 116b4dbc599SNathan Whitehorn sc->sc_dev = dev; 117b4dbc599SNathan Whitehorn sc->parent = device_get_parent(dev); 118b4dbc599SNathan Whitehorn 119b4dbc599SNathan Whitehorn sc->packet_reply = 0; 120b4dbc599SNathan Whitehorn sc->autopoll_mask = 0; 121b4dbc599SNathan Whitehorn 122b4dbc599SNathan Whitehorn mtx_init(&sc->sc_sync_mtx,"adbsyn",NULL,MTX_DEF | MTX_RECURSE); 123b4dbc599SNathan Whitehorn 124b4dbc599SNathan Whitehorn /* Initialize devinfo */ 125b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 126b4dbc599SNathan Whitehorn sc->devinfo[i].address = i; 127b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = 0; 128b4dbc599SNathan Whitehorn } 129b4dbc599SNathan Whitehorn 130b4dbc599SNathan Whitehorn /* Reset ADB bus */ 131b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL); 132b4dbc599SNathan Whitehorn DELAY(1500); 133b4dbc599SNathan Whitehorn 134b4dbc599SNathan Whitehorn /* Enumerate bus */ 135b4dbc599SNathan Whitehorn next_free = 8; 136b4dbc599SNathan Whitehorn 137669518d7SNathan Whitehorn for (i = 1; i <= 7; i++) { 138b4dbc599SNathan Whitehorn int8_t first_relocated = -1; 139b4dbc599SNathan Whitehorn int reply = 0; 140b4dbc599SNathan Whitehorn 141b4dbc599SNathan Whitehorn do { 142b4dbc599SNathan Whitehorn reply = adb_send_raw_packet_sync(dev,i, 143b4dbc599SNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL); 144b4dbc599SNathan Whitehorn 145b4dbc599SNathan Whitehorn if (reply) { 146b4dbc599SNathan Whitehorn /* If we got a response, relocate to next_free */ 147b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 148b4dbc599SNathan Whitehorn r3 &= 0xf000; 149b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(next_free) & 0x000f) << 8; 150b4dbc599SNathan Whitehorn r3 |= 0x00fe; 151b4dbc599SNathan Whitehorn 152b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3, 153b4dbc599SNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3)); 154b4dbc599SNathan Whitehorn 155b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,next_free, 156b4dbc599SNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL); 157b4dbc599SNathan Whitehorn 158b4dbc599SNathan Whitehorn sc->devinfo[next_free].default_address = i; 159b4dbc599SNathan Whitehorn if (first_relocated < 0) 160b4dbc599SNathan Whitehorn first_relocated = next_free; 161b4dbc599SNathan Whitehorn 162b4dbc599SNathan Whitehorn next_free++; 163b4dbc599SNathan Whitehorn } else if (first_relocated > 0) { 164b4dbc599SNathan Whitehorn /* Collisions removed, relocate first device back */ 165b4dbc599SNathan Whitehorn 166b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 167b4dbc599SNathan Whitehorn r3 &= 0xf000; 168b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(i) & 0x000f) << 8; 169b4dbc599SNathan Whitehorn 170b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,first_relocated, 171b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN,3, 172b4dbc599SNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3)); 173b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, 174b4dbc599SNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL); 175b4dbc599SNathan Whitehorn 176b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = i; 177b4dbc599SNathan Whitehorn sc->devinfo[(int)(first_relocated)].default_address = 0; 178b4dbc599SNathan Whitehorn break; 179b4dbc599SNathan Whitehorn } 180b4dbc599SNathan Whitehorn } while (reply); 181b4dbc599SNathan Whitehorn } 182b4dbc599SNathan Whitehorn 183b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 184b4dbc599SNathan Whitehorn if (sc->devinfo[i].default_address) { 185b4dbc599SNathan Whitehorn sc->children[i] = device_add_child(dev, NULL, -1); 186b4dbc599SNathan Whitehorn device_set_ivars(sc->children[i], &sc->devinfo[i]); 187b4dbc599SNathan Whitehorn } 188b4dbc599SNathan Whitehorn } 189b4dbc599SNathan Whitehorn 19001418697SNathan Whitehorn bus_generic_attach(dev); 19101418697SNathan Whitehorn 19201418697SNathan Whitehorn config_intrhook_disestablish(&sc->enum_hook); 193b4dbc599SNathan Whitehorn } 194b4dbc599SNathan Whitehorn 195b4dbc599SNathan Whitehorn static int adb_bus_detach(device_t dev) 196b4dbc599SNathan Whitehorn { 197b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 198b4dbc599SNathan Whitehorn 199b4dbc599SNathan Whitehorn mtx_destroy(&sc->sc_sync_mtx); 200b4dbc599SNathan Whitehorn 201b4dbc599SNathan Whitehorn return (bus_generic_detach(dev)); 202b4dbc599SNathan Whitehorn } 203b4dbc599SNathan Whitehorn 204b4dbc599SNathan Whitehorn 205b4dbc599SNathan Whitehorn static void 206b4dbc599SNathan Whitehorn adb_probe_nomatch(device_t dev, device_t child) 207b4dbc599SNathan Whitehorn { 208b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 209b4dbc599SNathan Whitehorn 210b4dbc599SNathan Whitehorn if (bootverbose) { 211b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 212b4dbc599SNathan Whitehorn 213b4dbc599SNathan Whitehorn device_printf(dev,"ADB %s at device %d (no driver attached)\n", 214b4dbc599SNathan Whitehorn adb_device_string[dinfo->default_address],dinfo->address); 215b4dbc599SNathan Whitehorn } 216b4dbc599SNathan Whitehorn } 217b4dbc599SNathan Whitehorn 218b4dbc599SNathan Whitehorn u_int 219b4dbc599SNathan Whitehorn adb_receive_raw_packet(device_t dev, u_char status, u_char command, int len, 220b4dbc599SNathan Whitehorn u_char *data) 221b4dbc599SNathan Whitehorn { 222b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 223b4dbc599SNathan Whitehorn u_char addr = command >> 4; 224b4dbc599SNathan Whitehorn 225b4dbc599SNathan Whitehorn if (len > 0 && (command & 0x0f) == ((ADB_COMMAND_TALK << 2) | 3)) { 226b4dbc599SNathan Whitehorn memcpy(&sc->devinfo[addr].register3,data,2); 227b4dbc599SNathan Whitehorn sc->devinfo[addr].handler_id = data[1]; 228b4dbc599SNathan Whitehorn } 229b4dbc599SNathan Whitehorn 230b4dbc599SNathan Whitehorn if (sc->sync_packet == command) { 231b4dbc599SNathan Whitehorn memcpy(sc->syncreg,data,(len > 8) ? 8 : len); 232b4dbc599SNathan Whitehorn atomic_store_rel_int(&sc->packet_reply,len + 1); 233b4dbc599SNathan Whitehorn } 234b4dbc599SNathan Whitehorn 235b4dbc599SNathan Whitehorn if (sc->children[addr] != NULL) { 236b4dbc599SNathan Whitehorn ADB_RECEIVE_PACKET(sc->children[addr],status, 237b4dbc599SNathan Whitehorn (command & 0x0f) >> 2,command & 0x03,len,data); 238b4dbc599SNathan Whitehorn } 239b4dbc599SNathan Whitehorn 240b4dbc599SNathan Whitehorn return (0); 241b4dbc599SNathan Whitehorn } 242b4dbc599SNathan Whitehorn 243b4dbc599SNathan Whitehorn static int 244b4dbc599SNathan Whitehorn adb_print_child(device_t dev, device_t child) 245b4dbc599SNathan Whitehorn { 246b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 247b4dbc599SNathan Whitehorn int retval = 0; 248b4dbc599SNathan Whitehorn 249b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 250b4dbc599SNathan Whitehorn 251b4dbc599SNathan Whitehorn retval += bus_print_child_header(dev,child); 252b4dbc599SNathan Whitehorn printf(" at device %d",dinfo->address); 253b4dbc599SNathan Whitehorn retval += bus_print_child_footer(dev, child); 254b4dbc599SNathan Whitehorn 255b4dbc599SNathan Whitehorn return (retval); 256b4dbc599SNathan Whitehorn } 257b4dbc599SNathan Whitehorn 258b4dbc599SNathan Whitehorn u_int 259b4dbc599SNathan Whitehorn adb_send_packet(device_t dev, u_char command, u_char reg, int len, u_char *data) 260b4dbc599SNathan Whitehorn { 261b4dbc599SNathan Whitehorn u_char command_byte = 0; 262b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 263b4dbc599SNathan Whitehorn struct adb_softc *sc; 264b4dbc599SNathan Whitehorn 265b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 266b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 267b4dbc599SNathan Whitehorn 268b4dbc599SNathan Whitehorn command_byte |= dinfo->address << 4; 269b4dbc599SNathan Whitehorn command_byte |= command << 2; 270b4dbc599SNathan Whitehorn command_byte |= reg; 271b4dbc599SNathan Whitehorn 272b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 273b4dbc599SNathan Whitehorn 274b4dbc599SNathan Whitehorn return (0); 275b4dbc599SNathan Whitehorn } 276b4dbc599SNathan Whitehorn 277b4dbc599SNathan Whitehorn u_int 278b4dbc599SNathan Whitehorn adb_set_autopoll(device_t dev, u_char enable) 279b4dbc599SNathan Whitehorn { 280b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 281b4dbc599SNathan Whitehorn struct adb_softc *sc; 282b4dbc599SNathan Whitehorn uint16_t mod = 0; 283b4dbc599SNathan Whitehorn 284b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 285b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 286b4dbc599SNathan Whitehorn 287b4dbc599SNathan Whitehorn mod = enable << dinfo->address; 288b4dbc599SNathan Whitehorn if (enable) { 289b4dbc599SNathan Whitehorn sc->autopoll_mask |= mod; 290b4dbc599SNathan Whitehorn } else { 291b4dbc599SNathan Whitehorn mod = ~mod; 292b4dbc599SNathan Whitehorn sc->autopoll_mask &= mod; 293b4dbc599SNathan Whitehorn } 294b4dbc599SNathan Whitehorn 295b4dbc599SNathan Whitehorn ADB_HB_SET_AUTOPOLL_MASK(sc->parent,sc->autopoll_mask); 296b4dbc599SNathan Whitehorn 297b4dbc599SNathan Whitehorn return (0); 298b4dbc599SNathan Whitehorn } 299b4dbc599SNathan Whitehorn 300b4dbc599SNathan Whitehorn uint8_t 301b4dbc599SNathan Whitehorn adb_get_device_type(device_t dev) 302b4dbc599SNathan Whitehorn { 303b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 304b4dbc599SNathan Whitehorn 305b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 306b4dbc599SNathan Whitehorn return (dinfo->default_address); 307b4dbc599SNathan Whitehorn } 308b4dbc599SNathan Whitehorn 309b4dbc599SNathan Whitehorn uint8_t 310b4dbc599SNathan Whitehorn adb_get_device_handler(device_t dev) 311b4dbc599SNathan Whitehorn { 312b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 313b4dbc599SNathan Whitehorn 314b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 315b4dbc599SNathan Whitehorn return (dinfo->handler_id); 316b4dbc599SNathan Whitehorn } 317b4dbc599SNathan Whitehorn 318b4dbc599SNathan Whitehorn static int 319b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, 320b4dbc599SNathan Whitehorn uint8_t reg, int len, u_char *data) 321b4dbc599SNathan Whitehorn { 322b4dbc599SNathan Whitehorn u_char command_byte = 0; 323b4dbc599SNathan Whitehorn struct adb_softc *sc; 324b4dbc599SNathan Whitehorn int result = -1; 325b4dbc599SNathan Whitehorn int i = 0; 326b4dbc599SNathan Whitehorn 327b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 328b4dbc599SNathan Whitehorn 329b4dbc599SNathan Whitehorn command_byte |= to << 4; 330b4dbc599SNathan Whitehorn command_byte |= command << 2; 331b4dbc599SNathan Whitehorn command_byte |= reg; 332b4dbc599SNathan Whitehorn 333b4dbc599SNathan Whitehorn /* Wait if someone else has a synchronous request pending */ 334b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_sync_mtx); 335b4dbc599SNathan Whitehorn 336b4dbc599SNathan Whitehorn sc->packet_reply = 0; 337b4dbc599SNathan Whitehorn sc->sync_packet = command_byte; 338b4dbc599SNathan Whitehorn 339b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 340b4dbc599SNathan Whitehorn 341b4dbc599SNathan Whitehorn while (!atomic_fetchadd_int(&sc->packet_reply,0)) { 34201418697SNathan Whitehorn /* 34301418697SNathan Whitehorn * Maybe the command got lost? Try resending and polling the 34401418697SNathan Whitehorn * controller. 34501418697SNathan Whitehorn */ 34601418697SNathan Whitehorn if (i > 40) 34701418697SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, 34801418697SNathan Whitehorn len, data, 1); 349b4dbc599SNathan Whitehorn 350b4dbc599SNathan Whitehorn DELAY(100); 351b4dbc599SNathan Whitehorn i++; 352b4dbc599SNathan Whitehorn } 353b4dbc599SNathan Whitehorn 354b4dbc599SNathan Whitehorn result = sc->packet_reply - 1; 355b4dbc599SNathan Whitehorn 356b4dbc599SNathan Whitehorn /* Clear packet sync */ 357b4dbc599SNathan Whitehorn sc->packet_reply = 0; 358b4dbc599SNathan Whitehorn sc->sync_packet = 0xffff; /* We can't match a 16 bit value */ 359b4dbc599SNathan Whitehorn 360b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_sync_mtx); 361b4dbc599SNathan Whitehorn 362b4dbc599SNathan Whitehorn return (result); 363b4dbc599SNathan Whitehorn } 364b4dbc599SNathan Whitehorn 365b4dbc599SNathan Whitehorn uint8_t 366b4dbc599SNathan Whitehorn adb_set_device_handler(device_t dev, uint8_t newhandler) 367b4dbc599SNathan Whitehorn { 368b4dbc599SNathan Whitehorn struct adb_softc *sc; 369b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 370b4dbc599SNathan Whitehorn uint16_t newr3; 371b4dbc599SNathan Whitehorn 372b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 373b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 374b4dbc599SNathan Whitehorn 375b4dbc599SNathan Whitehorn newr3 = dinfo->register3 & 0xff00; 376b4dbc599SNathan Whitehorn newr3 |= (uint16_t)(newhandler); 377b4dbc599SNathan Whitehorn 378b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 379b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN, 3, sizeof(uint16_t), (u_char *)(&newr3)); 380b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 381b4dbc599SNathan Whitehorn ADB_COMMAND_TALK, 3, 0, NULL); 382b4dbc599SNathan Whitehorn 383b4dbc599SNathan Whitehorn return (dinfo->handler_id); 384b4dbc599SNathan Whitehorn } 385b4dbc599SNathan Whitehorn 386b4dbc599SNathan Whitehorn uint8_t 387b4dbc599SNathan Whitehorn adb_read_register(device_t dev, u_char reg, 388b4dbc599SNathan Whitehorn size_t *len, void *data) 389b4dbc599SNathan Whitehorn { 390b4dbc599SNathan Whitehorn struct adb_softc *sc; 391b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 392b4dbc599SNathan Whitehorn size_t orig_len; 393b4dbc599SNathan Whitehorn 394b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 395b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 396b4dbc599SNathan Whitehorn 397b4dbc599SNathan Whitehorn orig_len = *len; 398b4dbc599SNathan Whitehorn 399b4dbc599SNathan Whitehorn mtx_lock(&sc->sc_sync_mtx); 400b4dbc599SNathan Whitehorn 401b4dbc599SNathan Whitehorn *len = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 402b4dbc599SNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL); 403b4dbc599SNathan Whitehorn 404b4dbc599SNathan Whitehorn if (*len > 0) 405b4dbc599SNathan Whitehorn memcpy(data,sc->syncreg,*len); 406b4dbc599SNathan Whitehorn 407b4dbc599SNathan Whitehorn mtx_unlock(&sc->sc_sync_mtx); 408b4dbc599SNathan Whitehorn 409b4dbc599SNathan Whitehorn return ((*len > 0) ? 0 : -1); 410b4dbc599SNathan Whitehorn } 411b4dbc599SNathan Whitehorn 412