Deleted Added
full compact
adb_bus.c (184890) adb_bus.c (185724)
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

--- 8 unchanged lines hidden (view full) ---

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 *
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

--- 8 unchanged lines hidden (view full) ---

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: head/sys/dev/adb/adb_bus.c 184890 2008-11-12 17:33:36Z nwhitehorn $
25 * $FreeBSD: head/sys/dev/adb/adb_bus.c 185724 2008-12-06 23:26:02Z nwhitehorn $
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>

--- 9 unchanged lines hidden (view full) ---

43
44static int adb_bus_probe(device_t dev);
45static int adb_bus_attach(device_t dev);
46static int adb_bus_detach(device_t dev);
47static void adb_bus_enumerate(void *xdev);
48static void adb_probe_nomatch(device_t dev, device_t child);
49static int adb_print_child(device_t dev, device_t child);
50
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>

--- 9 unchanged lines hidden (view full) ---

43
44static int adb_bus_probe(device_t dev);
45static int adb_bus_attach(device_t dev);
46static int adb_bus_detach(device_t dev);
47static void adb_bus_enumerate(void *xdev);
48static void adb_probe_nomatch(device_t dev, device_t child);
49static int adb_print_child(device_t dev, device_t child);
50
51static int adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command, uint8_t reg, int len, u_char *data);
51static 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
53static char *adb_device_string[] = {
54 "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc"
55};
56
57static device_method_t adb_bus_methods[] = {
58 /* Device interface */
59 DEVMETHOD(device_probe, adb_bus_probe),

--- 53 unchanged lines hidden (view full) ---

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;
52
53static char *adb_device_string[] = {
54 "HOST", "dongle", "keyboard", "mouse", "tablet", "modem", "RESERVED", "misc"
55};
56
57static device_method_t adb_bus_methods[] = {
58 /* Device interface */
59 DEVMETHOD(device_probe, adb_bus_probe),

--- 53 unchanged lines hidden (view full) ---

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;
121
122
122 mtx_init(&sc->sc_sync_mtx,"adbsyn",NULL,MTX_DEF | MTX_RECURSE);
123
124 /* Initialize devinfo */
125 for (i = 0; i < 16; i++) {
126 sc->devinfo[i].address = i;
127 sc->devinfo[i].default_address = 0;
128 }
129
130 /* Reset ADB bus */
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 */
131 adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL);
130 adb_send_raw_packet_sync(dev,0,ADB_COMMAND_BUS_RESET,0,0,NULL,NULL);
132 DELAY(1500);
133
134 /* Enumerate bus */
135 next_free = 8;
136
137 for (i = 1; i <= 7; i++) {
138 int8_t first_relocated = -1;
139 int reply = 0;
140
141 do {
142 reply = adb_send_raw_packet_sync(dev,i,
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,
143 ADB_COMMAND_TALK,3,0,NULL);
142 ADB_COMMAND_TALK,3,0,NULL,NULL);
144
145 if (reply) {
146 /* If we got a response, relocate to next_free */
147 r3 = sc->devinfo[i].register3;
148 r3 &= 0xf000;
149 r3 |= ((uint16_t)(next_free) & 0x000f) << 8;
150 r3 |= 0x00fe;
151
152 adb_send_raw_packet_sync(dev,i, ADB_COMMAND_LISTEN,3,
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,
153 sizeof(uint16_t),(u_char *)(&r3));
152 sizeof(uint16_t),(u_char *)(&r3),NULL);
154
155 adb_send_raw_packet_sync(dev,next_free,
153
154 adb_send_raw_packet_sync(dev,next_free,
156 ADB_COMMAND_TALK,3,0,NULL);
155 ADB_COMMAND_TALK,3,0,NULL,NULL);
157
158 sc->devinfo[next_free].default_address = i;
159 if (first_relocated < 0)
160 first_relocated = next_free;
161
162 next_free++;
163 } else if (first_relocated > 0) {
164 /* Collisions removed, relocate first device back */
165
166 r3 = sc->devinfo[i].register3;
167 r3 &= 0xf000;
168 r3 |= ((uint16_t)(i) & 0x000f) << 8;
169
170 adb_send_raw_packet_sync(dev,first_relocated,
171 ADB_COMMAND_LISTEN,3,
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,
172 sizeof(uint16_t),(u_char *)(&r3));
171 sizeof(uint16_t),(u_char *)(&r3),NULL);
173 adb_send_raw_packet_sync(dev,i,
172 adb_send_raw_packet_sync(dev,i,
174 ADB_COMMAND_TALK,3,0,NULL);
173 ADB_COMMAND_TALK,3,0,NULL,NULL);
175
176 sc->devinfo[i].default_address = i;
177 sc->devinfo[(int)(first_relocated)].default_address = 0;
178 break;
179 }
180 } while (reply);
181 }
182

--- 6 unchanged lines hidden (view full) ---

189
190 bus_generic_attach(dev);
191
192 config_intrhook_disestablish(&sc->enum_hook);
193}
194
195static int adb_bus_detach(device_t dev)
196{
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

--- 6 unchanged lines hidden (view full) ---

188
189 bus_generic_attach(dev);
190
191 config_intrhook_disestablish(&sc->enum_hook);
192}
193
194static int adb_bus_detach(device_t dev)
195{
197 struct adb_softc *sc = device_get_softc(dev);
198
199 mtx_destroy(&sc->sc_sync_mtx);
200
201 return (bus_generic_detach(dev));
202}
203
204
205static void
206adb_probe_nomatch(device_t dev, device_t child)
207{
208 struct adb_devinfo *dinfo;

--- 16 unchanged lines hidden (view full) ---

225 if (len > 0 && (command & 0x0f) == ((ADB_COMMAND_TALK << 2) | 3)) {
226 memcpy(&sc->devinfo[addr].register3,data,2);
227 sc->devinfo[addr].handler_id = data[1];
228 }
229
230 if (sc->sync_packet == command) {
231 memcpy(sc->syncreg,data,(len > 8) ? 8 : len);
232 atomic_store_rel_int(&sc->packet_reply,len + 1);
196 return (bus_generic_detach(dev));
197}
198
199
200static void
201adb_probe_nomatch(device_t dev, device_t child)
202{
203 struct adb_devinfo *dinfo;

--- 16 unchanged lines hidden (view full) ---

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);
233 }
234
235 if (sc->children[addr] != NULL) {
236 ADB_RECEIVE_PACKET(sc->children[addr],status,
237 (command & 0x0f) >> 2,command & 0x03,len,data);
238 }
239
240 return (0);

--- 71 unchanged lines hidden (view full) ---

312 struct adb_devinfo *dinfo;
313
314 dinfo = device_get_ivars(dev);
315 return (dinfo->handler_id);
316}
317
318static int
319adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command,
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);

--- 71 unchanged lines hidden (view full) ---

308 struct adb_devinfo *dinfo;
309
310 dinfo = device_get_ivars(dev);
311 return (dinfo->handler_id);
312}
313
314static int
315adb_send_raw_packet_sync(device_t dev, uint8_t to, uint8_t command,
320 uint8_t reg, int len, u_char *data)
316 uint8_t reg, int len, u_char *data, u_char *reply)
321{
322 u_char command_byte = 0;
323 struct adb_softc *sc;
324 int result = -1;
317{
318 u_char command_byte = 0;
319 struct adb_softc *sc;
320 int result = -1;
325 int i = 0;
321 int i = 1;
326
327 sc = device_get_softc(dev);
328
329 command_byte |= to << 4;
330 command_byte |= command << 2;
331 command_byte |= reg;
332
333 /* Wait if someone else has a synchronous request pending */
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 */
334 mtx_lock(&sc->sc_sync_mtx);
330 while (!atomic_cmpset_int(&sc->sync_packet, 0xffff, command_byte))
331 tsleep(sc, 0, "ADB sync", hz/10);
335
336 sc->packet_reply = 0;
337 sc->sync_packet = command_byte;
338
339 ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1);
340
341 while (!atomic_fetchadd_int(&sc->packet_reply,0)) {
342 /*
343 * Maybe the command got lost? Try resending and polling the
344 * controller.
345 */
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 */
346 if (i > 40)
343 if (i % 40 == 0)
347 ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte,
348 len, data, 1);
349
344 ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte,
345 len, data, 1);
346
350 DELAY(100);
347 tsleep(sc, 0, "ADB sync", hz/10);
351 i++;
352 }
353
354 result = sc->packet_reply - 1;
355
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;
356 /* Clear packet sync */
357 sc->packet_reply = 0;
358 sc->sync_packet = 0xffff; /* We can't match a 16 bit value */
359
358
360 mtx_unlock(&sc->sc_sync_mtx);
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);
361
362 return (result);
363}
364
365uint8_t
366adb_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
364
365 return (result);
366}
367
368uint8_t
369adb_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);
378 adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
383 adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
379 ADB_COMMAND_LISTEN, 3, sizeof(uint16_t), (u_char *)(&newr3));
380 adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
381 ADB_COMMAND_TALK, 3, 0, NULL);
384 ADB_COMMAND_TALK, 3, 0, NULL, NULL);
382
383 return (dinfo->handler_id);
384}
385
385
386 return (dinfo->handler_id);
387}
388
386uint8_t
387adb_read_register(device_t dev, u_char reg,
388 size_t *len, void *data)
389size_t
390adb_read_register(device_t dev, u_char reg, void *data)
389{
390 struct adb_softc *sc;
391 struct adb_devinfo *dinfo;
391{
392 struct adb_softc *sc;
393 struct adb_devinfo *dinfo;
392 size_t orig_len;
394 size_t result;
393
394 dinfo = device_get_ivars(dev);
395 sc = device_get_softc(device_get_parent(dev));
396
395
396 dinfo = device_get_ivars(dev);
397 sc = device_get_softc(device_get_parent(dev));
398
397 orig_len = *len;
399 result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
400 ADB_COMMAND_TALK, reg, 0, NULL, data);
398
401
399 mtx_lock(&sc->sc_sync_mtx);
400
401 *len = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
402 ADB_COMMAND_TALK, reg, 0, NULL);
403
404 if (*len > 0)
405 memcpy(data,sc->syncreg,*len);
406
407 mtx_unlock(&sc->sc_sync_mtx);
408
409 return ((*len > 0) ? 0 : -1);
402 return (result);
410}
411
403}
404