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