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 51582434bdSNathan 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, u_char *reply); 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; 121582434bdSNathan Whitehorn sc->sync_packet = 0xffff; 122b4dbc599SNathan Whitehorn 123b4dbc599SNathan Whitehorn /* Initialize devinfo */ 124b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 125b4dbc599SNathan Whitehorn sc->devinfo[i].address = i; 126b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = 0; 127b4dbc599SNathan Whitehorn } 128b4dbc599SNathan Whitehorn 129b4dbc599SNathan Whitehorn /* Reset ADB bus */ 130582434bdSNathan Whitehorn adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL,NULL); 131b4dbc599SNathan Whitehorn DELAY(1500); 132b4dbc599SNathan Whitehorn 133b4dbc599SNathan Whitehorn /* Enumerate bus */ 134b4dbc599SNathan Whitehorn next_free = 8; 135b4dbc599SNathan Whitehorn 136669518d7SNathan Whitehorn for (i = 1; i <= 7; i++) { 137b4dbc599SNathan Whitehorn int8_t first_relocated = -1; 138b4dbc599SNathan Whitehorn int reply = 0; 139b4dbc599SNathan Whitehorn 140b4dbc599SNathan Whitehorn do { 141b4dbc599SNathan Whitehorn reply = adb_send_raw_packet_sync(dev,i, 142582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 143b4dbc599SNathan Whitehorn 144b4dbc599SNathan Whitehorn if (reply) { 145b4dbc599SNathan Whitehorn /* If we got a response, relocate to next_free */ 146b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 147b4dbc599SNathan Whitehorn r3 &= 0xf000; 148b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(next_free) & 0x000f) << 8; 149b4dbc599SNathan Whitehorn r3 |= 0x00fe; 150b4dbc599SNathan Whitehorn 151b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3, 152582434bdSNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3),NULL); 153b4dbc599SNathan Whitehorn 154b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,next_free, 155582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 156b4dbc599SNathan Whitehorn 157b4dbc599SNathan Whitehorn sc->devinfo[next_free].default_address = i; 158b4dbc599SNathan Whitehorn if (first_relocated < 0) 159b4dbc599SNathan Whitehorn first_relocated = next_free; 160b4dbc599SNathan Whitehorn 161b4dbc599SNathan Whitehorn next_free++; 162b4dbc599SNathan Whitehorn } else if (first_relocated > 0) { 163b4dbc599SNathan Whitehorn /* Collisions removed, relocate first device back */ 164b4dbc599SNathan Whitehorn 165b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 166b4dbc599SNathan Whitehorn r3 &= 0xf000; 167b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(i) & 0x000f) << 8; 168b4dbc599SNathan Whitehorn 169b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,first_relocated, 170b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN,3, 171582434bdSNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3),NULL); 172b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, 173582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 174b4dbc599SNathan Whitehorn 175b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = i; 176b4dbc599SNathan Whitehorn sc->devinfo[(int)(first_relocated)].default_address = 0; 177b4dbc599SNathan Whitehorn break; 178b4dbc599SNathan Whitehorn } 179b4dbc599SNathan Whitehorn } while (reply); 180b4dbc599SNathan Whitehorn } 181b4dbc599SNathan Whitehorn 182b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 183b4dbc599SNathan Whitehorn if (sc->devinfo[i].default_address) { 184b4dbc599SNathan Whitehorn sc->children[i] = device_add_child(dev, NULL, -1); 185b4dbc599SNathan Whitehorn device_set_ivars(sc->children[i], &sc->devinfo[i]); 186b4dbc599SNathan Whitehorn } 187b4dbc599SNathan Whitehorn } 188b4dbc599SNathan Whitehorn 18901418697SNathan Whitehorn bus_generic_attach(dev); 19001418697SNathan Whitehorn 19101418697SNathan Whitehorn config_intrhook_disestablish(&sc->enum_hook); 192b4dbc599SNathan Whitehorn } 193b4dbc599SNathan Whitehorn 194b4dbc599SNathan Whitehorn static int adb_bus_detach(device_t dev) 195b4dbc599SNathan Whitehorn { 196b4dbc599SNathan Whitehorn return (bus_generic_detach(dev)); 197b4dbc599SNathan Whitehorn } 198b4dbc599SNathan Whitehorn 199b4dbc599SNathan Whitehorn 200b4dbc599SNathan Whitehorn static void 201b4dbc599SNathan Whitehorn adb_probe_nomatch(device_t dev, device_t child) 202b4dbc599SNathan Whitehorn { 203b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 204b4dbc599SNathan Whitehorn 205b4dbc599SNathan Whitehorn if (bootverbose) { 206b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 207b4dbc599SNathan Whitehorn 208b4dbc599SNathan Whitehorn device_printf(dev,"ADB %s at device %d (no driver attached)\n", 209b4dbc599SNathan Whitehorn adb_device_string[dinfo->default_address],dinfo->address); 210b4dbc599SNathan Whitehorn } 211b4dbc599SNathan Whitehorn } 212b4dbc599SNathan Whitehorn 213b4dbc599SNathan Whitehorn u_int 214b4dbc599SNathan Whitehorn adb_receive_raw_packet(device_t dev, u_char status, u_char command, int len, 215b4dbc599SNathan Whitehorn u_char *data) 216b4dbc599SNathan Whitehorn { 217b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 218b4dbc599SNathan Whitehorn u_char addr = command >> 4; 219b4dbc599SNathan Whitehorn 220b4dbc599SNathan Whitehorn if (len > 0 && (command & 0x0f) == ((ADB_COMMAND_TALK << 2) | 3)) { 221b4dbc599SNathan Whitehorn memcpy(&sc->devinfo[addr].register3,data,2); 222b4dbc599SNathan Whitehorn sc->devinfo[addr].handler_id = data[1]; 223b4dbc599SNathan Whitehorn } 224b4dbc599SNathan Whitehorn 225b4dbc599SNathan Whitehorn if (sc->sync_packet == command) { 226b4dbc599SNathan Whitehorn memcpy(sc->syncreg,data,(len > 8) ? 8 : len); 227b4dbc599SNathan Whitehorn atomic_store_rel_int(&sc->packet_reply,len + 1); 228582434bdSNathan Whitehorn wakeup(sc); 229b4dbc599SNathan Whitehorn } 230b4dbc599SNathan Whitehorn 231b4dbc599SNathan Whitehorn if (sc->children[addr] != NULL) { 232b4dbc599SNathan Whitehorn ADB_RECEIVE_PACKET(sc->children[addr],status, 233b4dbc599SNathan Whitehorn (command & 0x0f) >> 2,command & 0x03,len,data); 234b4dbc599SNathan Whitehorn } 235b4dbc599SNathan Whitehorn 236b4dbc599SNathan Whitehorn return (0); 237b4dbc599SNathan Whitehorn } 238b4dbc599SNathan Whitehorn 239b4dbc599SNathan Whitehorn static int 240b4dbc599SNathan Whitehorn adb_print_child(device_t dev, device_t child) 241b4dbc599SNathan Whitehorn { 242b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 243b4dbc599SNathan Whitehorn int retval = 0; 244b4dbc599SNathan Whitehorn 245b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 246b4dbc599SNathan Whitehorn 247b4dbc599SNathan Whitehorn retval += bus_print_child_header(dev,child); 248b4dbc599SNathan Whitehorn printf(" at device %d",dinfo->address); 249b4dbc599SNathan Whitehorn retval += bus_print_child_footer(dev, child); 250b4dbc599SNathan Whitehorn 251b4dbc599SNathan Whitehorn return (retval); 252b4dbc599SNathan Whitehorn } 253b4dbc599SNathan Whitehorn 254b4dbc599SNathan Whitehorn u_int 255b4dbc599SNathan Whitehorn adb_send_packet(device_t dev, u_char command, u_char reg, int len, u_char *data) 256b4dbc599SNathan Whitehorn { 257b4dbc599SNathan Whitehorn u_char command_byte = 0; 258b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 259b4dbc599SNathan Whitehorn struct adb_softc *sc; 260b4dbc599SNathan Whitehorn 261b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 262b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 263b4dbc599SNathan Whitehorn 264b4dbc599SNathan Whitehorn command_byte |= dinfo->address << 4; 265b4dbc599SNathan Whitehorn command_byte |= command << 2; 266b4dbc599SNathan Whitehorn command_byte |= reg; 267b4dbc599SNathan Whitehorn 268b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 269b4dbc599SNathan Whitehorn 270b4dbc599SNathan Whitehorn return (0); 271b4dbc599SNathan Whitehorn } 272b4dbc599SNathan Whitehorn 273b4dbc599SNathan Whitehorn u_int 274b4dbc599SNathan Whitehorn adb_set_autopoll(device_t dev, u_char enable) 275b4dbc599SNathan Whitehorn { 276b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 277b4dbc599SNathan Whitehorn struct adb_softc *sc; 278b4dbc599SNathan Whitehorn uint16_t mod = 0; 279b4dbc599SNathan Whitehorn 280b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 281b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 282b4dbc599SNathan Whitehorn 283b4dbc599SNathan Whitehorn mod = enable << dinfo->address; 284b4dbc599SNathan Whitehorn if (enable) { 285b4dbc599SNathan Whitehorn sc->autopoll_mask |= mod; 286b4dbc599SNathan Whitehorn } else { 287b4dbc599SNathan Whitehorn mod = ~mod; 288b4dbc599SNathan Whitehorn sc->autopoll_mask &= mod; 289b4dbc599SNathan Whitehorn } 290b4dbc599SNathan Whitehorn 291b4dbc599SNathan Whitehorn ADB_HB_SET_AUTOPOLL_MASK(sc->parent,sc->autopoll_mask); 292b4dbc599SNathan Whitehorn 293b4dbc599SNathan Whitehorn return (0); 294b4dbc599SNathan Whitehorn } 295b4dbc599SNathan Whitehorn 296b4dbc599SNathan Whitehorn uint8_t 297b4dbc599SNathan Whitehorn adb_get_device_type(device_t dev) 298b4dbc599SNathan Whitehorn { 299b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 300b4dbc599SNathan Whitehorn 301b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 302b4dbc599SNathan Whitehorn return (dinfo->default_address); 303b4dbc599SNathan Whitehorn } 304b4dbc599SNathan Whitehorn 305b4dbc599SNathan Whitehorn uint8_t 306b4dbc599SNathan Whitehorn adb_get_device_handler(device_t dev) 307b4dbc599SNathan Whitehorn { 308b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 309b4dbc599SNathan Whitehorn 310b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 311b4dbc599SNathan Whitehorn return (dinfo->handler_id); 312b4dbc599SNathan Whitehorn } 313b4dbc599SNathan Whitehorn 314b4dbc599SNathan Whitehorn static int 315b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, 316582434bdSNathan Whitehorn uint8_t reg, int len, u_char *data, u_char *reply) 317b4dbc599SNathan Whitehorn { 318b4dbc599SNathan Whitehorn u_char command_byte = 0; 319b4dbc599SNathan Whitehorn struct adb_softc *sc; 320b4dbc599SNathan Whitehorn int result = -1; 321582434bdSNathan Whitehorn int i = 1; 322b4dbc599SNathan Whitehorn 323b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 324b4dbc599SNathan Whitehorn 325b4dbc599SNathan Whitehorn command_byte |= to << 4; 326b4dbc599SNathan Whitehorn command_byte |= command << 2; 327b4dbc599SNathan Whitehorn command_byte |= reg; 328b4dbc599SNathan Whitehorn 329b4dbc599SNathan Whitehorn /* Wait if someone else has a synchronous request pending */ 330582434bdSNathan Whitehorn while (!atomic_cmpset_int(&sc->sync_packet, 0xffff, command_byte)) 331582434bdSNathan Whitehorn tsleep(sc, 0, "ADB sync", hz/10); 332b4dbc599SNathan Whitehorn 333b4dbc599SNathan Whitehorn sc->packet_reply = 0; 334b4dbc599SNathan Whitehorn sc->sync_packet = command_byte; 335b4dbc599SNathan Whitehorn 336b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 337b4dbc599SNathan Whitehorn 338b4dbc599SNathan Whitehorn while (!atomic_fetchadd_int(&sc->packet_reply,0)) { 33901418697SNathan Whitehorn /* 34001418697SNathan Whitehorn * Maybe the command got lost? Try resending and polling the 34101418697SNathan Whitehorn * controller. 34201418697SNathan Whitehorn */ 343582434bdSNathan Whitehorn if (i % 40 == 0) 34401418697SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, 34501418697SNathan Whitehorn len, data, 1); 346b4dbc599SNathan Whitehorn 347582434bdSNathan Whitehorn tsleep(sc, 0, "ADB sync", hz/10); 348b4dbc599SNathan Whitehorn i++; 349b4dbc599SNathan Whitehorn } 350b4dbc599SNathan Whitehorn 351b4dbc599SNathan Whitehorn result = sc->packet_reply - 1; 352b4dbc599SNathan Whitehorn 353582434bdSNathan Whitehorn if (reply != NULL && result > 0) 354582434bdSNathan Whitehorn memcpy(reply,sc->syncreg,result); 355582434bdSNathan Whitehorn 356b4dbc599SNathan Whitehorn /* Clear packet sync */ 357b4dbc599SNathan Whitehorn sc->packet_reply = 0; 358b4dbc599SNathan Whitehorn 359582434bdSNathan Whitehorn /* 360582434bdSNathan Whitehorn * We can't match a value beyond 8 bits, so set sync_packet to 361582434bdSNathan Whitehorn * 0xffff to avoid collisions. 362582434bdSNathan Whitehorn */ 363582434bdSNathan Whitehorn atomic_set_int(&sc->sync_packet, 0xffff); 364b4dbc599SNathan Whitehorn 365b4dbc599SNathan Whitehorn return (result); 366b4dbc599SNathan Whitehorn } 367b4dbc599SNathan Whitehorn 368b4dbc599SNathan Whitehorn uint8_t 369b4dbc599SNathan Whitehorn adb_set_device_handler(device_t dev, uint8_t newhandler) 370b4dbc599SNathan Whitehorn { 371b4dbc599SNathan Whitehorn struct adb_softc *sc; 372b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 373b4dbc599SNathan Whitehorn uint16_t newr3; 374b4dbc599SNathan Whitehorn 375b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 376b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 377b4dbc599SNathan Whitehorn 378b4dbc599SNathan Whitehorn newr3 = dinfo->register3 & 0xff00; 379b4dbc599SNathan Whitehorn newr3 |= (uint16_t)(newhandler); 380b4dbc599SNathan Whitehorn 381582434bdSNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, ADB_COMMAND_LISTEN, 382582434bdSNathan Whitehorn 3, sizeof(uint16_t), (u_char *)(&newr3), NULL); 383b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 384582434bdSNathan Whitehorn ADB_COMMAND_TALK, 3, 0, NULL, NULL); 385b4dbc599SNathan Whitehorn 386b4dbc599SNathan Whitehorn return (dinfo->handler_id); 387b4dbc599SNathan Whitehorn } 388b4dbc599SNathan Whitehorn 389582434bdSNathan Whitehorn size_t 390582434bdSNathan Whitehorn adb_read_register(device_t dev, u_char reg, void *data) 391b4dbc599SNathan Whitehorn { 392b4dbc599SNathan Whitehorn struct adb_softc *sc; 393b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 394582434bdSNathan Whitehorn size_t result; 395b4dbc599SNathan Whitehorn 396b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 397b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 398b4dbc599SNathan Whitehorn 399582434bdSNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 400582434bdSNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL, data); 401b4dbc599SNathan Whitehorn 402582434bdSNathan Whitehorn return (result); 403b4dbc599SNathan Whitehorn } 404b4dbc599SNathan Whitehorn 405