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