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