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