diff options
Diffstat (limited to 'drivers/sh/maple/maple.c')
-rw-r--r-- | drivers/sh/maple/maple.c | 302 |
1 files changed, 211 insertions, 91 deletions
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 617efb1640b1..d1812d32f47d 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Core maple bus functionality | 2 | * Core maple bus functionality |
3 | * | 3 | * |
4 | * Copyright (C) 2007, 2008 Adrian McMenamin | 4 | * Copyright (C) 2007, 2008 Adrian McMenamin |
5 | * Copyright (C) 2001 - 2008 Paul Mundt | ||
5 | * | 6 | * |
6 | * Based on 2.4 code by: | 7 | * Based on 2.4 code by: |
7 | * | 8 | * |
@@ -24,15 +25,14 @@ | |||
24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
25 | #include <linux/maple.h> | 26 | #include <linux/maple.h> |
26 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
28 | #include <linux/delay.h> | ||
27 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
28 | #include <asm/dma.h> | 30 | #include <asm/dma.h> |
29 | #include <asm/io.h> | 31 | #include <asm/io.h> |
30 | #include <asm/mach/dma.h> | 32 | #include <mach/dma.h> |
31 | #include <asm/mach/sysasic.h> | 33 | #include <mach/sysasic.h> |
32 | #include <asm/mach/maple.h> | ||
33 | #include <linux/delay.h> | ||
34 | 34 | ||
35 | MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin"); | 35 | MODULE_AUTHOR("Yaegashi Takeshi, Paul Mundt, M. R. Brown, Adrian McMenamin"); |
36 | MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); | 36 | MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); |
37 | MODULE_LICENSE("GPL v2"); | 37 | MODULE_LICENSE("GPL v2"); |
38 | MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); | 38 | MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); |
@@ -46,14 +46,15 @@ static DECLARE_WORK(maple_vblank_process, maple_vblank_handler); | |||
46 | static LIST_HEAD(maple_waitq); | 46 | static LIST_HEAD(maple_waitq); |
47 | static LIST_HEAD(maple_sentq); | 47 | static LIST_HEAD(maple_sentq); |
48 | 48 | ||
49 | static DEFINE_MUTEX(maple_list_lock); | 49 | /* mutex to protect queue of waiting packets */ |
50 | static DEFINE_MUTEX(maple_wlist_lock); | ||
50 | 51 | ||
51 | static struct maple_driver maple_dummy_driver; | 52 | static struct maple_driver maple_dummy_driver; |
52 | static struct device maple_bus; | 53 | static struct device maple_bus; |
53 | static int subdevice_map[MAPLE_PORTS]; | 54 | static int subdevice_map[MAPLE_PORTS]; |
54 | static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; | 55 | static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; |
55 | static unsigned long maple_pnp_time; | 56 | static unsigned long maple_pnp_time; |
56 | static int started, scanning, liststatus, fullscan; | 57 | static int started, scanning, fullscan; |
57 | static struct kmem_cache *maple_queue_cache; | 58 | static struct kmem_cache *maple_queue_cache; |
58 | 59 | ||
59 | struct maple_device_specify { | 60 | struct maple_device_specify { |
@@ -65,19 +66,36 @@ static bool checked[4]; | |||
65 | static struct maple_device *baseunits[4]; | 66 | static struct maple_device *baseunits[4]; |
66 | 67 | ||
67 | /** | 68 | /** |
68 | * maple_driver_register - register a device driver | 69 | * maple_driver_register - register a maple driver |
69 | * automatically makes the driver bus a maple bus | 70 | * @drv: maple driver to be registered. |
70 | * @drv: the driver to be registered | 71 | * |
72 | * Registers the passed in @drv, while updating the bus type. | ||
73 | * Devices with matching function IDs will be automatically probed. | ||
71 | */ | 74 | */ |
72 | int maple_driver_register(struct device_driver *drv) | 75 | int maple_driver_register(struct maple_driver *drv) |
73 | { | 76 | { |
74 | if (!drv) | 77 | if (!drv) |
75 | return -EINVAL; | 78 | return -EINVAL; |
76 | drv->bus = &maple_bus_type; | 79 | |
77 | return driver_register(drv); | 80 | drv->drv.bus = &maple_bus_type; |
81 | |||
82 | return driver_register(&drv->drv); | ||
78 | } | 83 | } |
79 | EXPORT_SYMBOL_GPL(maple_driver_register); | 84 | EXPORT_SYMBOL_GPL(maple_driver_register); |
80 | 85 | ||
86 | /** | ||
87 | * maple_driver_unregister - unregister a maple driver. | ||
88 | * @drv: maple driver to unregister. | ||
89 | * | ||
90 | * Cleans up after maple_driver_register(). To be invoked in the exit | ||
91 | * path of any module drivers. | ||
92 | */ | ||
93 | void maple_driver_unregister(struct maple_driver *drv) | ||
94 | { | ||
95 | driver_unregister(&drv->drv); | ||
96 | } | ||
97 | EXPORT_SYMBOL_GPL(maple_driver_unregister); | ||
98 | |||
81 | /* set hardware registers to enable next round of dma */ | 99 | /* set hardware registers to enable next round of dma */ |
82 | static void maplebus_dma_reset(void) | 100 | static void maplebus_dma_reset(void) |
83 | { | 101 | { |
@@ -131,33 +149,123 @@ static void maple_release_device(struct device *dev) | |||
131 | 149 | ||
132 | /** | 150 | /** |
133 | * maple_add_packet - add a single instruction to the queue | 151 | * maple_add_packet - add a single instruction to the queue |
134 | * @mq: instruction to add to waiting queue | 152 | * @mdev: maple device |
153 | * @function: function on device being queried | ||
154 | * @command: maple command to add | ||
155 | * @length: length of command string (in 32 bit words) | ||
156 | * @data: remainder of command string | ||
135 | */ | 157 | */ |
136 | void maple_add_packet(struct mapleq *mq) | 158 | int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, |
159 | size_t length, void *data) | ||
137 | { | 160 | { |
138 | mutex_lock(&maple_list_lock); | 161 | int locking, ret = 0; |
139 | list_add(&mq->list, &maple_waitq); | 162 | void *sendbuf = NULL; |
140 | mutex_unlock(&maple_list_lock); | 163 | |
164 | mutex_lock(&maple_wlist_lock); | ||
165 | /* bounce if device already locked */ | ||
166 | locking = mutex_is_locked(&mdev->mq->mutex); | ||
167 | if (locking) { | ||
168 | ret = -EBUSY; | ||
169 | goto out; | ||
170 | } | ||
171 | |||
172 | mutex_lock(&mdev->mq->mutex); | ||
173 | |||
174 | if (length) { | ||
175 | sendbuf = kmalloc(length * 4, GFP_KERNEL); | ||
176 | if (!sendbuf) { | ||
177 | mutex_unlock(&mdev->mq->mutex); | ||
178 | ret = -ENOMEM; | ||
179 | goto out; | ||
180 | } | ||
181 | ((__be32 *)sendbuf)[0] = cpu_to_be32(function); | ||
182 | } | ||
183 | |||
184 | mdev->mq->command = command; | ||
185 | mdev->mq->length = length; | ||
186 | if (length > 1) | ||
187 | memcpy(sendbuf + 4, data, (length - 1) * 4); | ||
188 | mdev->mq->sendbuf = sendbuf; | ||
189 | |||
190 | list_add(&mdev->mq->list, &maple_waitq); | ||
191 | out: | ||
192 | mutex_unlock(&maple_wlist_lock); | ||
193 | return ret; | ||
141 | } | 194 | } |
142 | EXPORT_SYMBOL_GPL(maple_add_packet); | 195 | EXPORT_SYMBOL_GPL(maple_add_packet); |
143 | 196 | ||
197 | /** | ||
198 | * maple_add_packet_sleeps - add a single instruction to the queue | ||
199 | * @mdev: maple device | ||
200 | * @function: function on device being queried | ||
201 | * @command: maple command to add | ||
202 | * @length: length of command string (in 32 bit words) | ||
203 | * @data: remainder of command string | ||
204 | * | ||
205 | * Same as maple_add_packet(), but waits for the lock to become free. | ||
206 | */ | ||
207 | int maple_add_packet_sleeps(struct maple_device *mdev, u32 function, | ||
208 | u32 command, size_t length, void *data) | ||
209 | { | ||
210 | int locking, ret = 0; | ||
211 | void *sendbuf = NULL; | ||
212 | |||
213 | locking = mutex_lock_interruptible(&mdev->mq->mutex); | ||
214 | if (locking) { | ||
215 | ret = -EIO; | ||
216 | goto out; | ||
217 | } | ||
218 | |||
219 | if (length) { | ||
220 | sendbuf = kmalloc(length * 4, GFP_KERNEL); | ||
221 | if (!sendbuf) { | ||
222 | mutex_unlock(&mdev->mq->mutex); | ||
223 | ret = -ENOMEM; | ||
224 | goto out; | ||
225 | } | ||
226 | ((__be32 *)sendbuf)[0] = cpu_to_be32(function); | ||
227 | } | ||
228 | |||
229 | mdev->mq->command = command; | ||
230 | mdev->mq->length = length; | ||
231 | if (length > 1) | ||
232 | memcpy(sendbuf + 4, data, (length - 1) * 4); | ||
233 | mdev->mq->sendbuf = sendbuf; | ||
234 | |||
235 | mutex_lock(&maple_wlist_lock); | ||
236 | list_add(&mdev->mq->list, &maple_waitq); | ||
237 | mutex_unlock(&maple_wlist_lock); | ||
238 | out: | ||
239 | return ret; | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(maple_add_packet_sleeps); | ||
242 | |||
144 | static struct mapleq *maple_allocq(struct maple_device *mdev) | 243 | static struct mapleq *maple_allocq(struct maple_device *mdev) |
145 | { | 244 | { |
146 | struct mapleq *mq; | 245 | struct mapleq *mq; |
147 | 246 | ||
148 | mq = kmalloc(sizeof(*mq), GFP_KERNEL); | 247 | mq = kmalloc(sizeof(*mq), GFP_KERNEL); |
149 | if (!mq) | 248 | if (!mq) |
150 | return NULL; | 249 | goto failed_nomem; |
151 | 250 | ||
152 | mq->dev = mdev; | 251 | mq->dev = mdev; |
153 | mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); | 252 | mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); |
154 | mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp); | 253 | mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp); |
155 | if (!mq->recvbuf) { | 254 | if (!mq->recvbuf) |
156 | kfree(mq); | 255 | goto failed_p2; |
157 | return NULL; | 256 | /* |
158 | } | 257 | * most devices do not need the mutex - but |
258 | * anything that injects block reads or writes | ||
259 | * will rely on it | ||
260 | */ | ||
261 | mutex_init(&mq->mutex); | ||
159 | 262 | ||
160 | return mq; | 263 | return mq; |
264 | |||
265 | failed_p2: | ||
266 | kfree(mq); | ||
267 | failed_nomem: | ||
268 | return NULL; | ||
161 | } | 269 | } |
162 | 270 | ||
163 | static struct maple_device *maple_alloc_dev(int port, int unit) | 271 | static struct maple_device *maple_alloc_dev(int port, int unit) |
@@ -178,7 +286,6 @@ static struct maple_device *maple_alloc_dev(int port, int unit) | |||
178 | } | 286 | } |
179 | mdev->dev.bus = &maple_bus_type; | 287 | mdev->dev.bus = &maple_bus_type; |
180 | mdev->dev.parent = &maple_bus; | 288 | mdev->dev.parent = &maple_bus; |
181 | mdev->function = 0; | ||
182 | return mdev; | 289 | return mdev; |
183 | } | 290 | } |
184 | 291 | ||
@@ -216,7 +323,6 @@ static void maple_build_block(struct mapleq *mq) | |||
216 | *maple_sendptr++ = PHYSADDR(mq->recvbuf); | 323 | *maple_sendptr++ = PHYSADDR(mq->recvbuf); |
217 | *maple_sendptr++ = | 324 | *maple_sendptr++ = |
218 | mq->command | (to << 8) | (from << 16) | (len << 24); | 325 | mq->command | (to << 8) | (from << 16) | (len << 24); |
219 | |||
220 | while (len-- > 0) | 326 | while (len-- > 0) |
221 | *maple_sendptr++ = *lsendbuf++; | 327 | *maple_sendptr++ = *lsendbuf++; |
222 | } | 328 | } |
@@ -224,22 +330,27 @@ static void maple_build_block(struct mapleq *mq) | |||
224 | /* build up command queue */ | 330 | /* build up command queue */ |
225 | static void maple_send(void) | 331 | static void maple_send(void) |
226 | { | 332 | { |
227 | int i; | 333 | int i, maple_packets = 0; |
228 | int maple_packets; | ||
229 | struct mapleq *mq, *nmq; | 334 | struct mapleq *mq, *nmq; |
230 | 335 | ||
231 | if (!list_empty(&maple_sentq)) | 336 | if (!list_empty(&maple_sentq)) |
232 | return; | 337 | return; |
233 | if (list_empty(&maple_waitq) || !maple_dma_done()) | 338 | mutex_lock(&maple_wlist_lock); |
339 | if (list_empty(&maple_waitq) || !maple_dma_done()) { | ||
340 | mutex_unlock(&maple_wlist_lock); | ||
234 | return; | 341 | return; |
235 | maple_packets = 0; | 342 | } |
236 | maple_sendptr = maple_lastptr = maple_sendbuf; | 343 | mutex_unlock(&maple_wlist_lock); |
344 | maple_lastptr = maple_sendbuf; | ||
345 | maple_sendptr = maple_sendbuf; | ||
346 | mutex_lock(&maple_wlist_lock); | ||
237 | list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { | 347 | list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { |
238 | maple_build_block(mq); | 348 | maple_build_block(mq); |
239 | list_move(&mq->list, &maple_sentq); | 349 | list_move(&mq->list, &maple_sentq); |
240 | if (maple_packets++ > MAPLE_MAXPACKETS) | 350 | if (maple_packets++ > MAPLE_MAXPACKETS) |
241 | break; | 351 | break; |
242 | } | 352 | } |
353 | mutex_unlock(&maple_wlist_lock); | ||
243 | if (maple_packets > 0) { | 354 | if (maple_packets > 0) { |
244 | for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) | 355 | for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) |
245 | dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, | 356 | dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, |
@@ -247,7 +358,8 @@ static void maple_send(void) | |||
247 | } | 358 | } |
248 | } | 359 | } |
249 | 360 | ||
250 | static int attach_matching_maple_driver(struct device_driver *driver, | 361 | /* check if there is a driver registered likely to match this device */ |
362 | static int check_matching_maple_driver(struct device_driver *driver, | ||
251 | void *devptr) | 363 | void *devptr) |
252 | { | 364 | { |
253 | struct maple_driver *maple_drv; | 365 | struct maple_driver *maple_drv; |
@@ -255,12 +367,8 @@ static int attach_matching_maple_driver(struct device_driver *driver, | |||
255 | 367 | ||
256 | mdev = devptr; | 368 | mdev = devptr; |
257 | maple_drv = to_maple_driver(driver); | 369 | maple_drv = to_maple_driver(driver); |
258 | if (mdev->devinfo.function & be32_to_cpu(maple_drv->function)) { | 370 | if (mdev->devinfo.function & cpu_to_be32(maple_drv->function)) |
259 | if (maple_drv->connect(mdev) == 0) { | 371 | return 1; |
260 | mdev->driver = maple_drv; | ||
261 | return 1; | ||
262 | } | ||
263 | } | ||
264 | return 0; | 372 | return 0; |
265 | } | 373 | } |
266 | 374 | ||
@@ -268,11 +376,6 @@ static void maple_detach_driver(struct maple_device *mdev) | |||
268 | { | 376 | { |
269 | if (!mdev) | 377 | if (!mdev) |
270 | return; | 378 | return; |
271 | if (mdev->driver) { | ||
272 | if (mdev->driver->disconnect) | ||
273 | mdev->driver->disconnect(mdev); | ||
274 | } | ||
275 | mdev->driver = NULL; | ||
276 | device_unregister(&mdev->dev); | 379 | device_unregister(&mdev->dev); |
277 | mdev = NULL; | 380 | mdev = NULL; |
278 | } | 381 | } |
@@ -328,8 +431,8 @@ static void maple_attach_driver(struct maple_device *mdev) | |||
328 | mdev->port, mdev->unit, function); | 431 | mdev->port, mdev->unit, function); |
329 | 432 | ||
330 | matched = | 433 | matched = |
331 | bus_for_each_drv(&maple_bus_type, NULL, mdev, | 434 | bus_for_each_drv(&maple_bus_type, NULL, mdev, |
332 | attach_matching_maple_driver); | 435 | check_matching_maple_driver); |
333 | 436 | ||
334 | if (matched == 0) { | 437 | if (matched == 0) { |
335 | /* Driver does not exist yet */ | 438 | /* Driver does not exist yet */ |
@@ -373,45 +476,48 @@ static int detach_maple_device(struct device *device, void *portptr) | |||
373 | 476 | ||
374 | static int setup_maple_commands(struct device *device, void *ignored) | 477 | static int setup_maple_commands(struct device *device, void *ignored) |
375 | { | 478 | { |
479 | int add; | ||
376 | struct maple_device *maple_dev = to_maple_dev(device); | 480 | struct maple_device *maple_dev = to_maple_dev(device); |
377 | 481 | ||
378 | if ((maple_dev->interval > 0) | 482 | if ((maple_dev->interval > 0) |
379 | && time_after(jiffies, maple_dev->when)) { | 483 | && time_after(jiffies, maple_dev->when)) { |
380 | maple_dev->when = jiffies + maple_dev->interval; | 484 | /* bounce if we cannot lock */ |
381 | maple_dev->mq->command = MAPLE_COMMAND_GETCOND; | 485 | add = maple_add_packet(maple_dev, |
382 | maple_dev->mq->sendbuf = &maple_dev->function; | 486 | be32_to_cpu(maple_dev->devinfo.function), |
383 | maple_dev->mq->length = 1; | 487 | MAPLE_COMMAND_GETCOND, 1, NULL); |
384 | maple_add_packet(maple_dev->mq); | 488 | if (!add) |
385 | liststatus++; | 489 | maple_dev->when = jiffies + maple_dev->interval; |
386 | } else { | 490 | } else { |
387 | if (time_after(jiffies, maple_pnp_time)) { | 491 | if (time_after(jiffies, maple_pnp_time)) |
388 | maple_dev->mq->command = MAPLE_COMMAND_DEVINFO; | 492 | /* This will also bounce */ |
389 | maple_dev->mq->length = 0; | 493 | maple_add_packet(maple_dev, 0, |
390 | maple_add_packet(maple_dev->mq); | 494 | MAPLE_COMMAND_DEVINFO, 0, NULL); |
391 | liststatus++; | ||
392 | } | ||
393 | } | 495 | } |
394 | |||
395 | return 0; | 496 | return 0; |
396 | } | 497 | } |
397 | 498 | ||
398 | /* VBLANK bottom half - implemented via workqueue */ | 499 | /* VBLANK bottom half - implemented via workqueue */ |
399 | static void maple_vblank_handler(struct work_struct *work) | 500 | static void maple_vblank_handler(struct work_struct *work) |
400 | { | 501 | { |
401 | if (!maple_dma_done()) | 502 | if (!list_empty(&maple_sentq) || !maple_dma_done()) |
402 | return; | ||
403 | if (!list_empty(&maple_sentq)) | ||
404 | return; | 503 | return; |
504 | |||
405 | ctrl_outl(0, MAPLE_ENABLE); | 505 | ctrl_outl(0, MAPLE_ENABLE); |
406 | liststatus = 0; | 506 | |
407 | bus_for_each_dev(&maple_bus_type, NULL, NULL, | 507 | bus_for_each_dev(&maple_bus_type, NULL, NULL, |
408 | setup_maple_commands); | 508 | setup_maple_commands); |
509 | |||
409 | if (time_after(jiffies, maple_pnp_time)) | 510 | if (time_after(jiffies, maple_pnp_time)) |
410 | maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; | 511 | maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; |
411 | if (liststatus && list_empty(&maple_sentq)) { | 512 | |
412 | INIT_LIST_HEAD(&maple_sentq); | 513 | mutex_lock(&maple_wlist_lock); |
514 | if (!list_empty(&maple_waitq) && list_empty(&maple_sentq)) { | ||
515 | mutex_unlock(&maple_wlist_lock); | ||
413 | maple_send(); | 516 | maple_send(); |
517 | } else { | ||
518 | mutex_unlock(&maple_wlist_lock); | ||
414 | } | 519 | } |
520 | |||
415 | maplebus_dma_reset(); | 521 | maplebus_dma_reset(); |
416 | } | 522 | } |
417 | 523 | ||
@@ -422,8 +528,8 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) | |||
422 | struct maple_device *mdev_add; | 528 | struct maple_device *mdev_add; |
423 | struct maple_device_specify ds; | 529 | struct maple_device_specify ds; |
424 | 530 | ||
531 | ds.port = mdev->port; | ||
425 | for (k = 0; k < 5; k++) { | 532 | for (k = 0; k < 5; k++) { |
426 | ds.port = mdev->port; | ||
427 | ds.unit = k + 1; | 533 | ds.unit = k + 1; |
428 | retval = | 534 | retval = |
429 | bus_for_each_dev(&maple_bus_type, NULL, &ds, | 535 | bus_for_each_dev(&maple_bus_type, NULL, &ds, |
@@ -437,9 +543,9 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) | |||
437 | mdev_add = maple_alloc_dev(mdev->port, k + 1); | 543 | mdev_add = maple_alloc_dev(mdev->port, k + 1); |
438 | if (!mdev_add) | 544 | if (!mdev_add) |
439 | return; | 545 | return; |
440 | mdev_add->mq->command = MAPLE_COMMAND_DEVINFO; | 546 | maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, |
441 | mdev_add->mq->length = 0; | 547 | 0, NULL); |
442 | maple_add_packet(mdev_add->mq); | 548 | /* mark that we are checking sub devices */ |
443 | scanning = 1; | 549 | scanning = 1; |
444 | } | 550 | } |
445 | submask = submask >> 1; | 551 | submask = submask >> 1; |
@@ -505,6 +611,28 @@ static void maple_response_devinfo(struct maple_device *mdev, | |||
505 | } | 611 | } |
506 | } | 612 | } |
507 | 613 | ||
614 | static void maple_port_rescan(void) | ||
615 | { | ||
616 | int i; | ||
617 | struct maple_device *mdev; | ||
618 | |||
619 | fullscan = 1; | ||
620 | for (i = 0; i < MAPLE_PORTS; i++) { | ||
621 | if (checked[i] == false) { | ||
622 | fullscan = 0; | ||
623 | mdev = baseunits[i]; | ||
624 | /* | ||
625 | * test lock in case scan has failed | ||
626 | * but device is still locked | ||
627 | */ | ||
628 | if (mutex_is_locked(&mdev->mq->mutex)) | ||
629 | mutex_unlock(&mdev->mq->mutex); | ||
630 | maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO, | ||
631 | 0, NULL); | ||
632 | } | ||
633 | } | ||
634 | } | ||
635 | |||
508 | /* maple dma end bottom half - implemented via workqueue */ | 636 | /* maple dma end bottom half - implemented via workqueue */ |
509 | static void maple_dma_handler(struct work_struct *work) | 637 | static void maple_dma_handler(struct work_struct *work) |
510 | { | 638 | { |
@@ -512,7 +640,6 @@ static void maple_dma_handler(struct work_struct *work) | |||
512 | struct maple_device *dev; | 640 | struct maple_device *dev; |
513 | char *recvbuf; | 641 | char *recvbuf; |
514 | enum maple_code code; | 642 | enum maple_code code; |
515 | int i; | ||
516 | 643 | ||
517 | if (!maple_dma_done()) | 644 | if (!maple_dma_done()) |
518 | return; | 645 | return; |
@@ -522,6 +649,10 @@ static void maple_dma_handler(struct work_struct *work) | |||
522 | recvbuf = mq->recvbuf; | 649 | recvbuf = mq->recvbuf; |
523 | code = recvbuf[0]; | 650 | code = recvbuf[0]; |
524 | dev = mq->dev; | 651 | dev = mq->dev; |
652 | kfree(mq->sendbuf); | ||
653 | mutex_unlock(&mq->mutex); | ||
654 | list_del_init(&mq->list); | ||
655 | |||
525 | switch (code) { | 656 | switch (code) { |
526 | case MAPLE_RESPONSE_NONE: | 657 | case MAPLE_RESPONSE_NONE: |
527 | maple_response_none(dev, mq); | 658 | maple_response_none(dev, mq); |
@@ -558,26 +689,16 @@ static void maple_dma_handler(struct work_struct *work) | |||
558 | break; | 689 | break; |
559 | } | 690 | } |
560 | } | 691 | } |
561 | INIT_LIST_HEAD(&maple_sentq); | 692 | /* if scanning is 1 then we have subdevices to check */ |
562 | if (scanning == 1) { | 693 | if (scanning == 1) { |
563 | maple_send(); | 694 | maple_send(); |
564 | scanning = 2; | 695 | scanning = 2; |
565 | } else | 696 | } else |
566 | scanning = 0; | 697 | scanning = 0; |
567 | 698 | /*check if we have actually tested all ports yet */ | |
568 | if (!fullscan) { | 699 | if (!fullscan) |
569 | fullscan = 1; | 700 | maple_port_rescan(); |
570 | for (i = 0; i < MAPLE_PORTS; i++) { | 701 | /* mark that we have been through the first scan */ |
571 | if (checked[i] == false) { | ||
572 | fullscan = 0; | ||
573 | dev = baseunits[i]; | ||
574 | dev->mq->command = | ||
575 | MAPLE_COMMAND_DEVINFO; | ||
576 | dev->mq->length = 0; | ||
577 | maple_add_packet(dev->mq); | ||
578 | } | ||
579 | } | ||
580 | } | ||
581 | if (started == 0) | 702 | if (started == 0) |
582 | started = 1; | 703 | started = 1; |
583 | } | 704 | } |
@@ -622,16 +743,14 @@ static int maple_get_dma_buffer(void) | |||
622 | static int match_maple_bus_driver(struct device *devptr, | 743 | static int match_maple_bus_driver(struct device *devptr, |
623 | struct device_driver *drvptr) | 744 | struct device_driver *drvptr) |
624 | { | 745 | { |
625 | struct maple_driver *maple_drv; | 746 | struct maple_driver *maple_drv = to_maple_driver(drvptr); |
626 | struct maple_device *maple_dev; | 747 | struct maple_device *maple_dev = to_maple_dev(devptr); |
627 | 748 | ||
628 | maple_drv = container_of(drvptr, struct maple_driver, drv); | ||
629 | maple_dev = container_of(devptr, struct maple_device, dev); | ||
630 | /* Trap empty port case */ | 749 | /* Trap empty port case */ |
631 | if (maple_dev->devinfo.function == 0xFFFFFFFF) | 750 | if (maple_dev->devinfo.function == 0xFFFFFFFF) |
632 | return 0; | 751 | return 0; |
633 | else if (maple_dev->devinfo.function & | 752 | else if (maple_dev->devinfo.function & |
634 | be32_to_cpu(maple_drv->function)) | 753 | cpu_to_be32(maple_drv->function)) |
635 | return 1; | 754 | return 1; |
636 | return 0; | 755 | return 0; |
637 | } | 756 | } |
@@ -713,6 +832,9 @@ static int __init maple_bus_init(void) | |||
713 | if (!maple_queue_cache) | 832 | if (!maple_queue_cache) |
714 | goto cleanup_bothirqs; | 833 | goto cleanup_bothirqs; |
715 | 834 | ||
835 | INIT_LIST_HEAD(&maple_waitq); | ||
836 | INIT_LIST_HEAD(&maple_sentq); | ||
837 | |||
716 | /* setup maple ports */ | 838 | /* setup maple ports */ |
717 | for (i = 0; i < MAPLE_PORTS; i++) { | 839 | for (i = 0; i < MAPLE_PORTS; i++) { |
718 | checked[i] = false; | 840 | checked[i] = false; |
@@ -723,9 +845,7 @@ static int __init maple_bus_init(void) | |||
723 | maple_free_dev(mdev[i]); | 845 | maple_free_dev(mdev[i]); |
724 | goto cleanup_cache; | 846 | goto cleanup_cache; |
725 | } | 847 | } |
726 | mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO; | 848 | maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); |
727 | mdev[i]->mq->length = 0; | ||
728 | maple_add_packet(mdev[i]->mq); | ||
729 | subdevice_map[i] = 0; | 849 | subdevice_map[i] = 0; |
730 | } | 850 | } |
731 | 851 | ||