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