1b4dbc599SNathan Whitehorn /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro 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 28b4dbc599SNathan Whitehorn #include <sys/param.h> 29b4dbc599SNathan Whitehorn #include <sys/systm.h> 30b4dbc599SNathan Whitehorn #include <sys/module.h> 31b4dbc599SNathan Whitehorn #include <sys/bus.h> 32b4dbc599SNathan Whitehorn #include <sys/conf.h> 33b4dbc599SNathan Whitehorn #include <sys/kernel.h> 34b4dbc599SNathan Whitehorn 35b4dbc599SNathan Whitehorn #include <machine/bus.h> 36b4dbc599SNathan Whitehorn 37b4dbc599SNathan Whitehorn #include <vm/vm.h> 38b4dbc599SNathan Whitehorn #include <vm/pmap.h> 39b4dbc599SNathan Whitehorn 40b4dbc599SNathan Whitehorn #include "adb.h" 41b4dbc599SNathan Whitehorn #include "adbvar.h" 42b4dbc599SNathan Whitehorn 43b4dbc599SNathan Whitehorn static int adb_bus_probe(device_t dev); 44b4dbc599SNathan Whitehorn static int adb_bus_attach(device_t dev); 4501418697SNathan Whitehorn static void adb_bus_enumerate(void *xdev); 46b4dbc599SNathan Whitehorn static void adb_probe_nomatch(device_t dev, device_t child); 47b4dbc599SNathan Whitehorn static int adb_print_child(device_t dev, device_t child); 48b4dbc599SNathan Whitehorn 49582434bdSNathan 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); 50b4dbc599SNathan Whitehorn 51b4dbc599SNathan Whitehorn static char *adb_device_string[] = { 52b4dbc599SNathan Whitehorn "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc" 53b4dbc599SNathan Whitehorn }; 54b4dbc599SNathan Whitehorn 55b4dbc599SNathan Whitehorn static device_method_t adb_bus_methods[] = { 56b4dbc599SNathan Whitehorn /* Device interface */ 57b4dbc599SNathan Whitehorn DEVMETHOD(device_probe, adb_bus_probe), 58b4dbc599SNathan Whitehorn DEVMETHOD(device_attach, adb_bus_attach), 59d62d10ebSJohn Baldwin DEVMETHOD(device_detach, bus_generic_detach), 60b4dbc599SNathan Whitehorn DEVMETHOD(device_shutdown, bus_generic_shutdown), 61b4dbc599SNathan Whitehorn DEVMETHOD(device_suspend, bus_generic_suspend), 62b4dbc599SNathan Whitehorn DEVMETHOD(device_resume, bus_generic_resume), 63b4dbc599SNathan Whitehorn 64b4dbc599SNathan Whitehorn /* Bus Interface */ 65b4dbc599SNathan Whitehorn DEVMETHOD(bus_probe_nomatch, adb_probe_nomatch), 66b4dbc599SNathan Whitehorn DEVMETHOD(bus_print_child, adb_print_child), 67b4dbc599SNathan Whitehorn 68b4dbc599SNathan Whitehorn { 0, 0 }, 69b4dbc599SNathan Whitehorn }; 70b4dbc599SNathan Whitehorn 71b4dbc599SNathan Whitehorn driver_t adb_driver = { 72b4dbc599SNathan Whitehorn "adb", 73b4dbc599SNathan Whitehorn adb_bus_methods, 74b4dbc599SNathan Whitehorn sizeof(struct adb_softc), 75b4dbc599SNathan Whitehorn }; 76b4dbc599SNathan Whitehorn 77b4dbc599SNathan Whitehorn static int 78b4dbc599SNathan Whitehorn adb_bus_probe(device_t dev) 79b4dbc599SNathan Whitehorn { 80b4dbc599SNathan Whitehorn device_set_desc(dev, "Apple Desktop Bus"); 81b4dbc599SNathan Whitehorn return (0); 82b4dbc599SNathan Whitehorn } 83b4dbc599SNathan Whitehorn 84b4dbc599SNathan Whitehorn static int 85b4dbc599SNathan Whitehorn adb_bus_attach(device_t dev) 86b4dbc599SNathan Whitehorn { 87b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 8801418697SNathan Whitehorn sc->enum_hook.ich_func = adb_bus_enumerate; 8901418697SNathan Whitehorn sc->enum_hook.ich_arg = dev; 9001418697SNathan Whitehorn 9101418697SNathan Whitehorn /* 9201418697SNathan Whitehorn * We should wait until interrupts are enabled to try to probe 9301418697SNathan Whitehorn * the bus. Enumerating the ADB involves receiving packets, 9401418697SNathan Whitehorn * which works best with interrupts enabled. 9501418697SNathan Whitehorn */ 9601418697SNathan Whitehorn 9701418697SNathan Whitehorn if (config_intrhook_establish(&sc->enum_hook) != 0) 9801418697SNathan Whitehorn return (ENOMEM); 9901418697SNathan Whitehorn 10001418697SNathan Whitehorn return (0); 10101418697SNathan Whitehorn } 10201418697SNathan Whitehorn 10301418697SNathan Whitehorn static void 10401418697SNathan Whitehorn adb_bus_enumerate(void *xdev) 10501418697SNathan Whitehorn { 10601418697SNathan Whitehorn device_t dev = (device_t)xdev; 10701418697SNathan Whitehorn 10801418697SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 109b4dbc599SNathan Whitehorn uint8_t i, next_free; 110b4dbc599SNathan Whitehorn uint16_t r3; 111b4dbc599SNathan Whitehorn 112b4dbc599SNathan Whitehorn sc->sc_dev = dev; 113b4dbc599SNathan Whitehorn sc->parent = device_get_parent(dev); 114b4dbc599SNathan Whitehorn 115b4dbc599SNathan Whitehorn sc->packet_reply = 0; 116b4dbc599SNathan Whitehorn sc->autopoll_mask = 0; 117582434bdSNathan Whitehorn sc->sync_packet = 0xffff; 118b4dbc599SNathan Whitehorn 119b4dbc599SNathan Whitehorn /* Initialize devinfo */ 120b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 121b4dbc599SNathan Whitehorn sc->devinfo[i].address = i; 122b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = 0; 123b4dbc599SNathan Whitehorn } 124b4dbc599SNathan Whitehorn 125b4dbc599SNathan Whitehorn /* Reset ADB bus */ 126582434bdSNathan Whitehorn adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL,NULL); 127b4dbc599SNathan Whitehorn DELAY(1500); 128b4dbc599SNathan Whitehorn 129b4dbc599SNathan Whitehorn /* Enumerate bus */ 130b4dbc599SNathan Whitehorn next_free = 8; 131b4dbc599SNathan Whitehorn 132669518d7SNathan Whitehorn for (i = 1; i <= 7; i++) { 133b4dbc599SNathan Whitehorn int8_t first_relocated = -1; 134b4dbc599SNathan Whitehorn int reply = 0; 135b4dbc599SNathan Whitehorn 136b4dbc599SNathan Whitehorn do { 137b4dbc599SNathan Whitehorn reply = adb_send_raw_packet_sync(dev,i, 138582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 139b4dbc599SNathan Whitehorn 140b4dbc599SNathan Whitehorn if (reply) { 141b4dbc599SNathan Whitehorn /* If we got a response, relocate to next_free */ 142b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 143b4dbc599SNathan Whitehorn r3 &= 0xf000; 144b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(next_free) & 0x000f) << 8; 145b4dbc599SNathan Whitehorn r3 |= 0x00fe; 146b4dbc599SNathan Whitehorn 147b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3, 148582434bdSNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3),NULL); 149b4dbc599SNathan Whitehorn 150b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,next_free, 151582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 152b4dbc599SNathan Whitehorn 153b4dbc599SNathan Whitehorn sc->devinfo[next_free].default_address = i; 154b4dbc599SNathan Whitehorn if (first_relocated < 0) 155b4dbc599SNathan Whitehorn first_relocated = next_free; 156b4dbc599SNathan Whitehorn 157b4dbc599SNathan Whitehorn next_free++; 158b4dbc599SNathan Whitehorn } else if (first_relocated > 0) { 159b4dbc599SNathan Whitehorn /* Collisions removed, relocate first device back */ 160b4dbc599SNathan Whitehorn 161b4dbc599SNathan Whitehorn r3 = sc->devinfo[i].register3; 162b4dbc599SNathan Whitehorn r3 &= 0xf000; 163b4dbc599SNathan Whitehorn r3 |= ((uint16_t)(i) & 0x000f) << 8; 164b4dbc599SNathan Whitehorn 165b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,first_relocated, 166b4dbc599SNathan Whitehorn ADB_COMMAND_LISTEN,3, 167582434bdSNathan Whitehorn sizeof(uint16_t),(u_char *)(&r3),NULL); 168b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(dev,i, 169582434bdSNathan Whitehorn ADB_COMMAND_TALK,3,0,NULL,NULL); 170b4dbc599SNathan Whitehorn 171b4dbc599SNathan Whitehorn sc->devinfo[i].default_address = i; 172b4dbc599SNathan Whitehorn sc->devinfo[(int)(first_relocated)].default_address = 0; 173b4dbc599SNathan Whitehorn break; 174b4dbc599SNathan Whitehorn } 175b4dbc599SNathan Whitehorn } while (reply); 176b4dbc599SNathan Whitehorn } 177b4dbc599SNathan Whitehorn 178b4dbc599SNathan Whitehorn for (i = 0; i < 16; i++) { 179b4dbc599SNathan Whitehorn if (sc->devinfo[i].default_address) { 1805b56413dSWarner Losh sc->children[i] = device_add_child(dev, NULL, DEVICE_UNIT_ANY); 181b4dbc599SNathan Whitehorn device_set_ivars(sc->children[i], &sc->devinfo[i]); 182b4dbc599SNathan Whitehorn } 183b4dbc599SNathan Whitehorn } 184b4dbc599SNathan Whitehorn 185*18250ec6SJohn Baldwin bus_attach_children(dev); 18601418697SNathan Whitehorn 18701418697SNathan Whitehorn config_intrhook_disestablish(&sc->enum_hook); 188b4dbc599SNathan Whitehorn } 189b4dbc599SNathan Whitehorn 190b4dbc599SNathan Whitehorn static void 191b4dbc599SNathan Whitehorn adb_probe_nomatch(device_t dev, device_t child) 192b4dbc599SNathan Whitehorn { 193b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 194b4dbc599SNathan Whitehorn 195b4dbc599SNathan Whitehorn if (bootverbose) { 196b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 197b4dbc599SNathan Whitehorn 198b4dbc599SNathan Whitehorn device_printf(dev,"ADB %s at device %d (no driver attached)\n", 199b4dbc599SNathan Whitehorn adb_device_string[dinfo->default_address],dinfo->address); 200b4dbc599SNathan Whitehorn } 201b4dbc599SNathan Whitehorn } 202b4dbc599SNathan Whitehorn 203b4dbc599SNathan Whitehorn u_int 204b4dbc599SNathan Whitehorn adb_receive_raw_packet(device_t dev, u_char status, u_char command, int len, 205b4dbc599SNathan Whitehorn u_char *data) 206b4dbc599SNathan Whitehorn { 207b4dbc599SNathan Whitehorn struct adb_softc *sc = device_get_softc(dev); 208b4dbc599SNathan Whitehorn u_char addr = command >> 4; 209b4dbc599SNathan Whitehorn 210b4dbc599SNathan Whitehorn if (len > 0 && (command & 0x0f) == ((ADB_COMMAND_TALK << 2) | 3)) { 211b4dbc599SNathan Whitehorn memcpy(&sc->devinfo[addr].register3,data,2); 212b4dbc599SNathan Whitehorn sc->devinfo[addr].handler_id = data[1]; 213b4dbc599SNathan Whitehorn } 214b4dbc599SNathan Whitehorn 215b4dbc599SNathan Whitehorn if (sc->sync_packet == command) { 216b4dbc599SNathan Whitehorn memcpy(sc->syncreg,data,(len > 8) ? 8 : len); 217b4dbc599SNathan Whitehorn atomic_store_rel_int(&sc->packet_reply,len + 1); 218582434bdSNathan Whitehorn wakeup(sc); 219b4dbc599SNathan Whitehorn } 220b4dbc599SNathan Whitehorn 221b4dbc599SNathan Whitehorn if (sc->children[addr] != NULL) { 222b4dbc599SNathan Whitehorn ADB_RECEIVE_PACKET(sc->children[addr],status, 223b4dbc599SNathan Whitehorn (command & 0x0f) >> 2,command & 0x03,len,data); 224b4dbc599SNathan Whitehorn } 225b4dbc599SNathan Whitehorn 226b4dbc599SNathan Whitehorn return (0); 227b4dbc599SNathan Whitehorn } 228b4dbc599SNathan Whitehorn 229b4dbc599SNathan Whitehorn static int 230b4dbc599SNathan Whitehorn adb_print_child(device_t dev, device_t child) 231b4dbc599SNathan Whitehorn { 232b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 233b4dbc599SNathan Whitehorn int retval = 0; 234b4dbc599SNathan Whitehorn 235b4dbc599SNathan Whitehorn dinfo = device_get_ivars(child); 236b4dbc599SNathan Whitehorn 237b4dbc599SNathan Whitehorn retval += bus_print_child_header(dev,child); 238b4dbc599SNathan Whitehorn printf(" at device %d",dinfo->address); 239b4dbc599SNathan Whitehorn retval += bus_print_child_footer(dev, child); 240b4dbc599SNathan Whitehorn 241b4dbc599SNathan Whitehorn return (retval); 242b4dbc599SNathan Whitehorn } 243b4dbc599SNathan Whitehorn 244b4dbc599SNathan Whitehorn u_int 245b4dbc599SNathan Whitehorn adb_send_packet(device_t dev, u_char command, u_char reg, int len, u_char *data) 246b4dbc599SNathan Whitehorn { 247b4dbc599SNathan Whitehorn u_char command_byte = 0; 248b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 249b4dbc599SNathan Whitehorn struct adb_softc *sc; 250b4dbc599SNathan Whitehorn 251b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 252b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 253b4dbc599SNathan Whitehorn 254b4dbc599SNathan Whitehorn command_byte |= dinfo->address << 4; 255b4dbc599SNathan Whitehorn command_byte |= command << 2; 256b4dbc599SNathan Whitehorn command_byte |= reg; 257b4dbc599SNathan Whitehorn 258b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 259b4dbc599SNathan Whitehorn 260b4dbc599SNathan Whitehorn return (0); 261b4dbc599SNathan Whitehorn } 262b4dbc599SNathan Whitehorn 263b4dbc599SNathan Whitehorn u_int 264b4dbc599SNathan Whitehorn adb_set_autopoll(device_t dev, u_char enable) 265b4dbc599SNathan Whitehorn { 266b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 267b4dbc599SNathan Whitehorn struct adb_softc *sc; 268b4dbc599SNathan Whitehorn uint16_t mod = 0; 269b4dbc599SNathan Whitehorn 270b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 271b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 272b4dbc599SNathan Whitehorn 273b4dbc599SNathan Whitehorn mod = enable << dinfo->address; 274b4dbc599SNathan Whitehorn if (enable) { 275b4dbc599SNathan Whitehorn sc->autopoll_mask |= mod; 276b4dbc599SNathan Whitehorn } else { 277b4dbc599SNathan Whitehorn mod = ~mod; 278b4dbc599SNathan Whitehorn sc->autopoll_mask &= mod; 279b4dbc599SNathan Whitehorn } 280b4dbc599SNathan Whitehorn 281b4dbc599SNathan Whitehorn ADB_HB_SET_AUTOPOLL_MASK(sc->parent,sc->autopoll_mask); 282b4dbc599SNathan Whitehorn 283b4dbc599SNathan Whitehorn return (0); 284b4dbc599SNathan Whitehorn } 285b4dbc599SNathan Whitehorn 286b4dbc599SNathan Whitehorn uint8_t 287b4dbc599SNathan Whitehorn adb_get_device_type(device_t dev) 288b4dbc599SNathan Whitehorn { 289b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 290b4dbc599SNathan Whitehorn 291b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 292b4dbc599SNathan Whitehorn return (dinfo->default_address); 293b4dbc599SNathan Whitehorn } 294b4dbc599SNathan Whitehorn 295b4dbc599SNathan Whitehorn uint8_t 296b4dbc599SNathan Whitehorn adb_get_device_handler(device_t dev) 297b4dbc599SNathan Whitehorn { 298b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 299b4dbc599SNathan Whitehorn 300b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 301b4dbc599SNathan Whitehorn return (dinfo->handler_id); 302b4dbc599SNathan Whitehorn } 303b4dbc599SNathan Whitehorn 304b4dbc599SNathan Whitehorn static int 305b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, 306582434bdSNathan Whitehorn uint8_t reg, int len, u_char *data, u_char *reply) 307b4dbc599SNathan Whitehorn { 308b4dbc599SNathan Whitehorn u_char command_byte = 0; 309b4dbc599SNathan Whitehorn struct adb_softc *sc; 310b4dbc599SNathan Whitehorn int result = -1; 311582434bdSNathan Whitehorn int i = 1; 312b4dbc599SNathan Whitehorn 313b4dbc599SNathan Whitehorn sc = device_get_softc(dev); 314b4dbc599SNathan Whitehorn 315b4dbc599SNathan Whitehorn command_byte |= to << 4; 316b4dbc599SNathan Whitehorn command_byte |= command << 2; 317b4dbc599SNathan Whitehorn command_byte |= reg; 318b4dbc599SNathan Whitehorn 319b4dbc599SNathan Whitehorn /* Wait if someone else has a synchronous request pending */ 320582434bdSNathan Whitehorn while (!atomic_cmpset_int(&sc->sync_packet, 0xffff, command_byte)) 321582434bdSNathan Whitehorn tsleep(sc, 0, "ADB sync", hz/10); 322b4dbc599SNathan Whitehorn 323b4dbc599SNathan Whitehorn sc->packet_reply = 0; 324b4dbc599SNathan Whitehorn sc->sync_packet = command_byte; 325b4dbc599SNathan Whitehorn 326b4dbc599SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1); 327b4dbc599SNathan Whitehorn 328b4dbc599SNathan Whitehorn while (!atomic_fetchadd_int(&sc->packet_reply,0)) { 32901418697SNathan Whitehorn /* 33001418697SNathan Whitehorn * Maybe the command got lost? Try resending and polling the 33101418697SNathan Whitehorn * controller. 33201418697SNathan Whitehorn */ 333582434bdSNathan Whitehorn if (i % 40 == 0) 33401418697SNathan Whitehorn ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, 33501418697SNathan Whitehorn len, data, 1); 336b4dbc599SNathan Whitehorn 337582434bdSNathan Whitehorn tsleep(sc, 0, "ADB sync", hz/10); 338b4dbc599SNathan Whitehorn i++; 339b4dbc599SNathan Whitehorn } 340b4dbc599SNathan Whitehorn 341b4dbc599SNathan Whitehorn result = sc->packet_reply - 1; 342b4dbc599SNathan Whitehorn 343582434bdSNathan Whitehorn if (reply != NULL && result > 0) 344582434bdSNathan Whitehorn memcpy(reply,sc->syncreg,result); 345582434bdSNathan Whitehorn 346b4dbc599SNathan Whitehorn /* Clear packet sync */ 347b4dbc599SNathan Whitehorn sc->packet_reply = 0; 348b4dbc599SNathan Whitehorn 349582434bdSNathan Whitehorn /* 350582434bdSNathan Whitehorn * We can't match a value beyond 8 bits, so set sync_packet to 351582434bdSNathan Whitehorn * 0xffff to avoid collisions. 352582434bdSNathan Whitehorn */ 353582434bdSNathan Whitehorn atomic_set_int(&sc->sync_packet, 0xffff); 354b4dbc599SNathan Whitehorn 355b4dbc599SNathan Whitehorn return (result); 356b4dbc599SNathan Whitehorn } 357b4dbc599SNathan Whitehorn 358b4dbc599SNathan Whitehorn uint8_t 359b4dbc599SNathan Whitehorn adb_set_device_handler(device_t dev, uint8_t newhandler) 360b4dbc599SNathan Whitehorn { 361b4dbc599SNathan Whitehorn struct adb_softc *sc; 362b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 363b4dbc599SNathan Whitehorn uint16_t newr3; 364b4dbc599SNathan Whitehorn 365b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 366b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 367b4dbc599SNathan Whitehorn 368b4dbc599SNathan Whitehorn newr3 = dinfo->register3 & 0xff00; 369b4dbc599SNathan Whitehorn newr3 |= (uint16_t)(newhandler); 370b4dbc599SNathan Whitehorn 371582434bdSNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, ADB_COMMAND_LISTEN, 372582434bdSNathan Whitehorn 3, sizeof(uint16_t), (u_char *)(&newr3), NULL); 373b4dbc599SNathan Whitehorn adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 374582434bdSNathan Whitehorn ADB_COMMAND_TALK, 3, 0, NULL, NULL); 375b4dbc599SNathan Whitehorn 376b4dbc599SNathan Whitehorn return (dinfo->handler_id); 377b4dbc599SNathan Whitehorn } 378b4dbc599SNathan Whitehorn 379582434bdSNathan Whitehorn size_t 380582434bdSNathan Whitehorn adb_read_register(device_t dev, u_char reg, void *data) 381b4dbc599SNathan Whitehorn { 382b4dbc599SNathan Whitehorn struct adb_softc *sc; 383b4dbc599SNathan Whitehorn struct adb_devinfo *dinfo; 384582434bdSNathan Whitehorn size_t result; 385b4dbc599SNathan Whitehorn 386b4dbc599SNathan Whitehorn dinfo = device_get_ivars(dev); 387b4dbc599SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 388b4dbc599SNathan Whitehorn 389582434bdSNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 390582434bdSNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL, data); 391b4dbc599SNathan Whitehorn 392582434bdSNathan Whitehorn return (result); 393b4dbc599SNathan Whitehorn } 394b4dbc599SNathan Whitehorn 395f697a802SNathan Whitehorn size_t 396f697a802SNathan Whitehorn adb_write_register(device_t dev, u_char reg, size_t len, void *data) 397f697a802SNathan Whitehorn { 398f697a802SNathan Whitehorn struct adb_softc *sc; 399f697a802SNathan Whitehorn struct adb_devinfo *dinfo; 400f697a802SNathan Whitehorn size_t result; 401f697a802SNathan Whitehorn 402f697a802SNathan Whitehorn dinfo = device_get_ivars(dev); 403f697a802SNathan Whitehorn sc = device_get_softc(device_get_parent(dev)); 404f697a802SNathan Whitehorn 405f697a802SNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 406f697a802SNathan Whitehorn ADB_COMMAND_LISTEN, reg, len, (u_char *)data, NULL); 407f697a802SNathan Whitehorn 408f697a802SNathan Whitehorn result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address, 409f697a802SNathan Whitehorn ADB_COMMAND_TALK, reg, 0, NULL, NULL); 410f697a802SNathan Whitehorn 411f697a802SNathan Whitehorn return (result); 412f697a802SNathan Whitehorn } 413