1b4dbc599SNathan Whitehorn /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*718cf2ccSPedro F. Giffuni * 4b4dbc599SNathan Whitehorn * Copyright (C) 2008 Nathan Whitehorn 5b4dbc599SNathan Whitehorn * All rights reserved. 6b4dbc599SNathan Whitehorn * 7b4dbc599SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 8b4dbc599SNathan Whitehorn * modification, are permitted provided that the following conditions 9b4dbc599SNathan Whitehorn * are met: 10b4dbc599SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 11b4dbc599SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 12b4dbc599SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 13b4dbc599SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 14b4dbc599SNathan Whitehorn * documentation and/or other materials provided with the distribution. 15b4dbc599SNathan Whitehorn * 16b4dbc599SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17b4dbc599SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18b4dbc599SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19b4dbc599SNathan Whitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20b4dbc599SNathan Whitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21b4dbc599SNathan Whitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22b4dbc599SNathan Whitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23b4dbc599SNathan Whitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24b4dbc599SNathan Whitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25b4dbc599SNathan Whitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b4dbc599SNathan Whitehorn * 27b4dbc599SNathan Whitehorn * $FreeBSD$ 28b4dbc599SNathan Whitehorn */ 29b4dbc599SNathan Whitehorn 30b4dbc599SNathan Whitehorn #include <sys/cdefs.h> 31b4dbc599SNathan Whitehorn #include <sys/param.h> 32b4dbc599SNathan Whitehorn #include <sys/systm.h> 33b4dbc599SNathan Whitehorn #include <sys/module.h> 34b4dbc599SNathan Whitehorn #include <sys/bus.h> 35b4dbc599SNathan Whitehorn #include <sys/conf.h> 36b4dbc599SNathan Whitehorn #include <sys/kernel.h> 37b4dbc599SNathan Whitehorn 38b4dbc599SNathan Whitehorn #include <machine/bus.h> 39b4dbc599SNathan Whitehorn 40b4dbc599SNathan Whitehorn #include <vm/vm.h> 41b4dbc599SNathan Whitehorn #include <vm/pmap.h> 42b4dbc599SNathan Whitehorn 43b4dbc599SNathan Whitehorn #include "adb.h" 44b4dbc599SNathan Whitehorn #include "adbvar.h" 45b4dbc599SNathan Whitehorn 46b4dbc599SNathan Whitehorn static int adb_bus_probe(device_t dev); 47b4dbc599SNathan Whitehorn static int adb_bus_attach(device_t dev); 48b4dbc599SNathan Whitehorn static int adb_bus_detach(device_t dev); 4901418697SNathan Whitehorn static void adb_bus_enumerate(void *xdev); 50b4dbc599SNathan Whitehorn static void adb_probe_nomatch(device_t dev, device_t child); 51b4dbc599SNathan Whitehorn static int adb_print_child(device_t dev, device_t child); 52b4dbc599SNathan Whitehorn 53582434bdSNathan 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); 54b4dbc599SNathan Whitehorn 55b4dbc599SNathan Whitehorn static char *adb_device_string[] = { 56b4dbc599SNathan Whitehorn "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc" 57b4dbc599SNathan Whitehorn }; 58b4dbc599SNathan Whitehorn 59b4dbc599SNathan Whitehorn static device_method_t adb_bus_methods[] = { 60b4dbc599SNathan Whitehorn /* Device interface */ 61b4dbc599SNathan Whitehorn DEVMETHOD(device_probe, adb_bus_probe), 62b4dbc599SNathan Whitehorn DEVMETHOD(device_attach, adb_bus_attach), 63b4dbc599SNathan Whitehorn DEVMETHOD(device_detach, adb_bus_detach), 64b4dbc599SNathan Whitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 65b4dbc599SNathan Whitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 66b4dbc599SNathan Whitehorn DEVMETHOD(device_resume, bus_generic_resume), 67b4dbc599SNathan Whitehorn 68b4dbc599SNathan Whitehorn /* Bus Interface */ 69b4dbc599SNathan Whitehorn DEVMETHOD(bus_probe_nomatch, adb_probe_nomatch), 70b4dbc599SNathan Whitehorn DEVMETHOD(bus_print_child, adb_print_child), 71b4dbc599SNathan Whitehorn 72b4dbc599SNathan Whitehorn { 0, 0 }, 73b4dbc599SNathan Whitehorn }; 74b4dbc599SNathan Whitehorn 75b4dbc599SNathan Whitehorn driver_t adb_driver = { 76b4dbc599SNathan Whitehorn "adb", 77b4dbc599SNathan Whitehorn adb_bus_methods, 78b4dbc599SNathan Whitehorn sizeof(struct adb_softc), 79b4dbc599SNathan Whitehorn }; 80b4dbc599SNathan Whitehorn 81b4dbc599SNathan Whitehorn devclass_t adb_devclass; 82b4dbc599SNathan Whitehorn 83b4dbc599SNathan Whitehorn static int 84b4dbc599SNathan Whitehorn adb_bus_probe(device_t dev) 85b4dbc599SNathan Whitehorn { 86b4dbc599SNathan Whitehorn device_set_desc(dev, "Apple Desktop Bus"); 87b4dbc599SNathan Whitehorn return (0); 88b4dbc599SNathan Whitehorn } 89b4dbc599SNathan Whitehorn 90b4dbc599SNathan Whitehorn static int 91b4dbc599SNathan Whitehorn adb_bus_attach(device_t dev) 92b4dbc599SNathan Whitehorn { 93b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 9401418697SNathan Whitehorn sc->enum_hook.ich_func = adb_bus_enumerate; 9501418697SNathan Whitehorn sc->enum_hook.ich_arg = dev; 9601418697SNathan Whitehorn 9701418697SNathan Whitehorn /* 9801418697SNathan Whitehorn * We should wait until interrupts are enabled to try to probe 9901418697SNathan Whitehorn * the bus. Enumerating the ADB involves receiving packets, 10001418697SNathan Whitehorn * which works best with interrupts enabled. 10101418697SNathan Whitehorn */ 10201418697SNathan Whitehorn 10301418697SNathan Whitehorn if (config_intrhook_establish(&sc->enum_hook) != 0) 10401418697SNathan Whitehorn return (ENOMEM); 10501418697SNathan Whitehorn 10601418697SNathan Whitehorn return (0); 10701418697SNathan Whitehorn } 10801418697SNathan Whitehorn 10901418697SNathan Whitehorn static void 11001418697SNathan Whitehorn adb_bus_enumerate(void *xdev) 11101418697SNathan Whitehorn { 11201418697SNathan Whitehorn device_t dev = (device_t)xdev; 11301418697SNathan Whitehorn 11401418697SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 115b4dbc599SNathan Whitehorn uint8_t i, next_free; 116b4dbc599SNathan Whitehorn uint16_t r3; 117b4dbc599SNathan Whitehorn 118b4dbc599SNathan Whitehorn sc->sc_dev = dev; 119b4dbc599SNathan Whitehorn sc->parent = device_get_parent(dev); 120b4dbc599SNathan Whitehorn 121b4dbc599SNathan Whitehorn sc->packet_reply = 0; 122b4dbc599SNathan Whitehorn sc->autopoll_mask = 0; 123582434bdSNathan Whitehorn sc->sync_packet = 0xffff; 124b4dbc599SNathan Whitehorn 125b4dbc599SNathan Whitehorn /* Initialize devinfo */ 126b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 127b4dbc599SNathan Whitehorn sc->devinfo[i].address = i; 128b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = 0; 129b4dbc599SNathan Whitehorn } 130b4dbc599SNathan Whitehorn 131b4dbc599SNathan Whitehorn /* Reset ADB bus */ 132582434bdSNathan Whitehorn adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL,NULL); 133b4dbc599SNathan Whitehorn DELAY(1500); 134b4dbc599SNathan Whitehorn 135b4dbc599SNathan Whitehorn /* Enumerate bus */ 136b4dbc599SNathan Whitehorn next_free = 8; 137b4dbc599SNathan Whitehorn 138669518d7SNathan Whitehorn for (i = 1; i <= 7; i++) { 139b4dbc599SNathan Whitehorn int8_t first_relocated = -1; 140b4dbc599SNathan Whitehorn int reply = 0; 141b4dbc599SNathan Whitehorn 142b4dbc599SNathan Whitehorn do { 143b4dbc599SNathan Whitehorn reply = adb_send_raw_packet_sync(dev,i, 144582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 145b4dbc599SNathan Whitehorn 146b4dbc599SNathan Whitehorn if (reply) { 147b4dbc599SNathan Whitehorn /* If we got a response, relocate to next_free */ 148b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 149b4dbc599SNathan Whitehorn r3 &= 0xf000; 150b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(next_free) & 0x000f) << 8; 151b4dbc599SNathan Whitehorn r3 |= 0x00fe; 152b4dbc599SNathan Whitehorn 153b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3, 154582434bdSNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3),NULL); 155b4dbc599SNathan Whitehorn 156b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,next_free, 157582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 158b4dbc599SNathan Whitehorn 159b4dbc599SNathan Whitehorn sc->devinfo[next_free].default_address = i; 160b4dbc599SNathan Whitehorn if (first_relocated < 0) 161b4dbc599SNathan Whitehorn first_relocated = next_free; 162b4dbc599SNathan Whitehorn 163b4dbc599SNathan Whitehorn next_free++; 164b4dbc599SNathan Whitehorn } else if (first_relocated > 0) { 165b4dbc599SNathan Whitehorn /* Collisions removed, relocate first device back */ 166b4dbc599SNathan Whitehorn 167b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 168b4dbc599SNathan Whitehorn r3 &= 0xf000; 169b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(i) & 0x000f) << 8; 170b4dbc599SNathan Whitehorn 171b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,first_relocated, 172b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN,3, 173582434bdSNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3),NULL); 174b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, 175582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 176b4dbc599SNathan Whitehorn 177b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = i; 178b4dbc599SNathan Whitehorn sc->devinfo[(int)(first_relocated)].default_address = 0; 179b4dbc599SNathan Whitehorn break; 180b4dbc599SNathan Whitehorn } 181b4dbc599SNathan Whitehorn } while (reply); 182b4dbc599SNathan Whitehorn } 183b4dbc599SNathan Whitehorn 184b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 185b4dbc599SNathan Whitehorn if (sc->devinfo[i].default_address) { 186b4dbc599SNathan Whitehorn sc->children[i] = device_add_child(dev, NULL, -1); 187b4dbc599SNathan Whitehorn device_set_ivars(sc->children[i], &sc->devinfo[i]); 188b4dbc599SNathan Whitehorn } 189b4dbc599SNathan Whitehorn } 190b4dbc599SNathan Whitehorn 19101418697SNathan Whitehorn bus_generic_attach(dev); 19201418697SNathan Whitehorn 19301418697SNathan Whitehorn config_intrhook_disestablish(&sc->enum_hook); 194b4dbc599SNathan Whitehorn } 195b4dbc599SNathan Whitehorn 196b4dbc599SNathan Whitehorn static int adb_bus_detach(device_t dev) 197b4dbc599SNathan Whitehorn { 198b4dbc599SNathan Whitehorn return (bus_generic_detach(dev)); 199b4dbc599SNathan Whitehorn } 200b4dbc599SNathan Whitehorn 201b4dbc599SNathan Whitehorn 202b4dbc599SNathan Whitehorn static void 203b4dbc599SNathan Whitehorn adb_probe_nomatch(device_t dev, device_t child) 204b4dbc599SNathan Whitehorn { 205b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 206b4dbc599SNathan Whitehorn 207b4dbc599SNathan Whitehorn if (bootverbose) { 208b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 209b4dbc599SNathan Whitehorn 210b4dbc599SNathan Whitehorn device_printf(dev,"ADB %s at device %d (no driver attached)\n", 211b4dbc599SNathan Whitehorn adb_device_string[dinfo->default_address],dinfo->address); 212b4dbc599SNathan Whitehorn } 213b4dbc599SNathan Whitehorn } 214b4dbc599SNathan Whitehorn 215b4dbc599SNathan Whitehorn u_int 216b4dbc599SNathan Whitehorn adb_receive_raw_packet(device_t dev, u_char status, u_char command, int len, 217b4dbc599SNathan Whitehorn u_char *data) 218b4dbc599SNathan Whitehorn { 219b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 220b4dbc599SNathan Whitehorn u_char addr = command >> 4; 221b4dbc599SNathan Whitehorn 222b4dbc599SNathan Whitehorn if (len > 0 && (command & 0x0f) == ((ADB_COMMAND_TALK << 2) | 3)) { 223b4dbc599SNathan Whitehorn memcpy(&sc->devinfo[addr].register3,data,2); 224b4dbc599SNathan Whitehorn sc->devinfo[addr].handler_id = data[1]; 225b4dbc599SNathan Whitehorn } 226b4dbc599SNathan Whitehorn 227b4dbc599SNathan Whitehorn if (sc->sync_packet == command) { 228b4dbc599SNathan Whitehorn memcpy(sc->syncreg,data,(len > 8) ? 8 : len); 229b4dbc599SNathan Whitehorn atomic_store_rel_int(&sc->packet_reply,len + 1); 230582434bdSNathan Whitehorn wakeup(sc); 231b4dbc599SNathan Whitehorn } 232b4dbc599SNathan Whitehorn 233b4dbc599SNathan Whitehorn if (sc->children[addr] != NULL) { 234b4dbc599SNathan Whitehorn ADB_RECEIVE_PACKET(sc->children[addr],status, 235b4dbc599SNathan Whitehorn (command & 0x0f) >> 2,command & 0x03,len,data); 236b4dbc599SNathan Whitehorn } 237b4dbc599SNathan Whitehorn 238b4dbc599SNathan Whitehorn return (0); 239b4dbc599SNathan Whitehorn } 240b4dbc599SNathan Whitehorn 241b4dbc599SNathan Whitehorn static int 242b4dbc599SNathan Whitehorn adb_print_child(device_t dev, device_t child) 243b4dbc599SNathan Whitehorn { 244b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 245b4dbc599SNathan Whitehorn int retval = 0; 246b4dbc599SNathan Whitehorn 247b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 248b4dbc599SNathan Whitehorn 249b4dbc599SNathan Whitehorn retval += bus_print_child_header(dev,child); 250b4dbc599SNathan Whitehorn printf(" at device %d",dinfo->address); 251b4dbc599SNathan Whitehorn retval += bus_print_child_footer(dev, child); 252b4dbc599SNathan Whitehorn 253b4dbc599SNathan Whitehorn return (retval); 254b4dbc599SNathan Whitehorn } 255b4dbc599SNathan Whitehorn 256b4dbc599SNathan Whitehorn u_int 257b4dbc599SNathan Whitehorn adb_send_packet(device_t dev, u_char command, u_char reg, int len, u_char *data) 258b4dbc599SNathan Whitehorn { 259b4dbc599SNathan Whitehorn u_char command_byte = 0; 260b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 261b4dbc599SNathan Whitehorn struct adb_softc *sc; 262b4dbc599SNathan Whitehorn 263b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 264b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 265b4dbc599SNathan Whitehorn 266b4dbc599SNathan Whitehorn command_byte |= dinfo->address << 4; 267b4dbc599SNathan Whitehorn command_byte |= command << 2; 268b4dbc599SNathan Whitehorn command_byte |= reg; 269b4dbc599SNathan Whitehorn 270b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 271b4dbc599SNathan Whitehorn 272b4dbc599SNathan Whitehorn return (0); 273b4dbc599SNathan Whitehorn } 274b4dbc599SNathan Whitehorn 275b4dbc599SNathan Whitehorn u_int 276b4dbc599SNathan Whitehorn adb_set_autopoll(device_t dev, u_char enable) 277b4dbc599SNathan Whitehorn { 278b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 279b4dbc599SNathan Whitehorn struct adb_softc *sc; 280b4dbc599SNathan Whitehorn uint16_t mod = 0; 281b4dbc599SNathan Whitehorn 282b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 283b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 284b4dbc599SNathan Whitehorn 285b4dbc599SNathan Whitehorn mod = enable << dinfo->address; 286b4dbc599SNathan Whitehorn if (enable) { 287b4dbc599SNathan Whitehorn sc->autopoll_mask |= mod; 288b4dbc599SNathan Whitehorn } else { 289b4dbc599SNathan Whitehorn mod = ~mod; 290b4dbc599SNathan Whitehorn sc->autopoll_mask &= mod; 291b4dbc599SNathan Whitehorn } 292b4dbc599SNathan Whitehorn 293b4dbc599SNathan Whitehorn ADB_HB_SET_AUTOPOLL_MASK(sc->parent,sc->autopoll_mask); 294b4dbc599SNathan Whitehorn 295b4dbc599SNathan Whitehorn return (0); 296b4dbc599SNathan Whitehorn } 297b4dbc599SNathan Whitehorn 298b4dbc599SNathan Whitehorn uint8_t 299b4dbc599SNathan Whitehorn adb_get_device_type(device_t dev) 300b4dbc599SNathan Whitehorn { 301b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 302b4dbc599SNathan Whitehorn 303b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 304b4dbc599SNathan Whitehorn return (dinfo->default_address); 305b4dbc599SNathan Whitehorn } 306b4dbc599SNathan Whitehorn 307b4dbc599SNathan Whitehorn uint8_t 308b4dbc599SNathan Whitehorn adb_get_device_handler(device_t dev) 309b4dbc599SNathan Whitehorn { 310b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 311b4dbc599SNathan Whitehorn 312b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 313b4dbc599SNathan Whitehorn return (dinfo->handler_id); 314b4dbc599SNathan Whitehorn } 315b4dbc599SNathan Whitehorn 316b4dbc599SNathan Whitehorn static int 317b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, 318582434bdSNathan Whitehorn uint8_t reg, int len, u_char *data, u_char *reply) 319b4dbc599SNathan Whitehorn { 320b4dbc599SNathan Whitehorn u_char command_byte = 0; 321b4dbc599SNathan Whitehorn struct adb_softc *sc; 322b4dbc599SNathan Whitehorn int result = -1; 323582434bdSNathan Whitehorn int i = 1; 324b4dbc599SNathan Whitehorn 325b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 326b4dbc599SNathan Whitehorn 327b4dbc599SNathan Whitehorn command_byte |= to << 4; 328b4dbc599SNathan Whitehorn command_byte |= command << 2; 329b4dbc599SNathan Whitehorn command_byte |= reg; 330b4dbc599SNathan Whitehorn 331b4dbc599SNathan Whitehorn /* Wait if someone else has a synchronous request pending */ 332582434bdSNathan Whitehorn while (!atomic_cmpset_int(&sc->sync_packet, 0xffff, command_byte)) 333582434bdSNathan Whitehorn tsleep(sc, 0, "ADB sync", hz/10); 334b4dbc599SNathan Whitehorn 335b4dbc599SNathan Whitehorn sc->packet_reply = 0; 336b4dbc599SNathan Whitehorn sc->sync_packet = command_byte; 337b4dbc599SNathan Whitehorn 338b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 339b4dbc599SNathan Whitehorn 340b4dbc599SNathan Whitehorn while (!atomic_fetchadd_int(&sc->packet_reply,0)) { 34101418697SNathan Whitehorn /* 34201418697SNathan Whitehorn * Maybe the command got lost? Try resending and polling the 34301418697SNathan Whitehorn * controller. 34401418697SNathan Whitehorn */ 345582434bdSNathan Whitehorn if (i % 40 == 0) 34601418697SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, 34701418697SNathan Whitehorn len, data, 1); 348b4dbc599SNathan Whitehorn 349582434bdSNathan Whitehorn tsleep(sc, 0, "ADB sync", hz/10); 350b4dbc599SNathan Whitehorn i++; 351b4dbc599SNathan Whitehorn } 352b4dbc599SNathan Whitehorn 353b4dbc599SNathan Whitehorn result = sc->packet_reply - 1; 354b4dbc599SNathan Whitehorn 355582434bdSNathan Whitehorn if (reply != NULL && result > 0) 356582434bdSNathan Whitehorn memcpy(reply,sc->syncreg,result); 357582434bdSNathan Whitehorn 358b4dbc599SNathan Whitehorn /* Clear packet sync */ 359b4dbc599SNathan Whitehorn sc->packet_reply = 0; 360b4dbc599SNathan Whitehorn 361582434bdSNathan Whitehorn /* 362582434bdSNathan Whitehorn * We can't match a value beyond 8 bits, so set sync_packet to 363582434bdSNathan Whitehorn * 0xffff to avoid collisions. 364582434bdSNathan Whitehorn */ 365582434bdSNathan Whitehorn atomic_set_int(&sc->sync_packet, 0xffff); 366b4dbc599SNathan Whitehorn 367b4dbc599SNathan Whitehorn return (result); 368b4dbc599SNathan Whitehorn } 369b4dbc599SNathan Whitehorn 370b4dbc599SNathan Whitehorn uint8_t 371b4dbc599SNathan Whitehorn adb_set_device_handler(device_t dev, uint8_t newhandler) 372b4dbc599SNathan Whitehorn { 373b4dbc599SNathan Whitehorn struct adb_softc *sc; 374b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 375b4dbc599SNathan Whitehorn uint16_t newr3; 376b4dbc599SNathan Whitehorn 377b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 378b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 379b4dbc599SNathan Whitehorn 380b4dbc599SNathan Whitehorn newr3 = dinfo->register3 & 0xff00; 381b4dbc599SNathan Whitehorn newr3 |= (uint16_t)(newhandler); 382b4dbc599SNathan Whitehorn 383582434bdSNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, ADB_COMMAND_LISTEN, 384582434bdSNathan Whitehorn 3, sizeof(uint16_t), (u_char *)(&newr3), NULL); 385b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 386582434bdSNathan Whitehorn ADB_COMMAND_TALK, 3, 0, NULL, NULL); 387b4dbc599SNathan Whitehorn 388b4dbc599SNathan Whitehorn return (dinfo->handler_id); 389b4dbc599SNathan Whitehorn } 390b4dbc599SNathan Whitehorn 391582434bdSNathan Whitehorn size_t 392582434bdSNathan Whitehorn adb_read_register(device_t dev, u_char reg, void *data) 393b4dbc599SNathan Whitehorn { 394b4dbc599SNathan Whitehorn struct adb_softc *sc; 395b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 396582434bdSNathan Whitehorn size_t result; 397b4dbc599SNathan Whitehorn 398b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 399b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 400b4dbc599SNathan Whitehorn 401582434bdSNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 402582434bdSNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL, data); 403b4dbc599SNathan Whitehorn 404582434bdSNathan Whitehorn return (result); 405b4dbc599SNathan Whitehorn } 406b4dbc599SNathan Whitehorn 407f697a802SNathan Whitehorn size_t 408f697a802SNathan Whitehorn adb_write_register(device_t dev, u_char reg, size_t len, void *data) 409f697a802SNathan Whitehorn { 410f697a802SNathan Whitehorn struct adb_softc *sc; 411f697a802SNathan Whitehorn struct adb_devinfo *dinfo; 412f697a802SNathan Whitehorn size_t result; 413f697a802SNathan Whitehorn 414f697a802SNathan Whitehorn dinfo = device_get_ivars(dev); 415f697a802SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 416f697a802SNathan Whitehorn 417f697a802SNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 418f697a802SNathan Whitehorn ADB_COMMAND_LISTEN, reg, len, (u_char *)data, NULL); 419f697a802SNathan Whitehorn 420f697a802SNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 421f697a802SNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL, NULL); 422f697a802SNathan Whitehorn 423f697a802SNathan Whitehorn return (result); 424f697a802SNathan Whitehorn } 425