diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 14:11:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 14:11:23 -0400 |
commit | 928a726b0e12184729900c076e13dbf1c511c96c (patch) | |
tree | f31a7f23c1b511ebb486598cc746786e1821d48c /drivers/sh/maple/maple.c | |
parent | 8ff64b539bfd998792614481ccb67139b97075ef (diff) | |
parent | eaeed5d31d8ded02fa0a4b608f57418cc0e65b07 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (96 commits)
sh: add support for SMSC Polaris platform
sh: fix the HD64461 level-triggered interrupts handling
sh: sh-rtc wakeup support
sh: sh-rtc invalid time rework
sh: sh-rtc carry interrupt rework
sh: disallow kexec virtual entry
sh: kexec jump: fix for ftrace.
sh: kexec: Drop SR.BL bit toggling.
sh: add kexec jump support
sh: rework kexec segment code
sh: simplify kexec vbr code
sh: Flush only the needed range when unmapping a VMA.
sh: Update debugfs ASID dumping for 16-bit ASID support.
sh: tlb-pteaex: Kill off legacy PTEA updates.
sh: Support for extended ASIDs on PTEAEX-capable SH-X3 cores.
sh: sh7763rdp: Change IRQ number for sh_eth of sh7763rdp
sh: espt-giga board support
sh: dma: Make G2 DMA configurable.
sh: dma: Make PVR2 DMA configurable.
sh: Move IRQ multi definition of DMAC to defconfig
...
Diffstat (limited to 'drivers/sh/maple/maple.c')
-rw-r--r-- | drivers/sh/maple/maple.c | 472 |
1 files changed, 239 insertions, 233 deletions
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 63f0de29aa14..c71bb4b4ce84 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c | |||
@@ -1,16 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * Core maple bus functionality | 2 | * Core maple bus functionality |
3 | * | 3 | * |
4 | * Copyright (C) 2007, 2008 Adrian McMenamin | 4 | * Copyright (C) 2007 - 2009 Adrian McMenamin |
5 | * Copyright (C) 2001 - 2008 Paul Mundt | 5 | * Copyright (C) 2001 - 2008 Paul Mundt |
6 | * | 6 | * Copyright (C) 2000 - 2001 YAEGASHI Takeshi |
7 | * Based on 2.4 code by: | ||
8 | * | ||
9 | * Copyright (C) 2000-2001 YAEGASHI Takeshi | ||
10 | * Copyright (C) 2001 M. R. Brown | 7 | * Copyright (C) 2001 M. R. Brown |
11 | * Copyright (C) 2001 Paul Mundt | ||
12 | * | ||
13 | * and others. | ||
14 | * | 8 | * |
15 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
16 | * License. See the file "COPYING" in the main directory of this archive | 10 | * License. See the file "COPYING" in the main directory of this archive |
@@ -32,7 +26,7 @@ | |||
32 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
33 | #include <mach/sysasic.h> | 27 | #include <mach/sysasic.h> |
34 | 28 | ||
35 | MODULE_AUTHOR("Yaegashi Takeshi, Paul Mundt, M. R. Brown, Adrian McMenamin"); | 29 | MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); |
36 | MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); | 30 | MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); |
37 | MODULE_LICENSE("GPL v2"); | 31 | MODULE_LICENSE("GPL v2"); |
38 | MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); | 32 | MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); |
@@ -49,7 +43,7 @@ static LIST_HEAD(maple_sentq); | |||
49 | /* mutex to protect queue of waiting packets */ | 43 | /* mutex to protect queue of waiting packets */ |
50 | static DEFINE_MUTEX(maple_wlist_lock); | 44 | static DEFINE_MUTEX(maple_wlist_lock); |
51 | 45 | ||
52 | static struct maple_driver maple_dummy_driver; | 46 | static struct maple_driver maple_unsupported_device; |
53 | static struct device maple_bus; | 47 | static struct device maple_bus; |
54 | static int subdevice_map[MAPLE_PORTS]; | 48 | static int subdevice_map[MAPLE_PORTS]; |
55 | static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; | 49 | static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; |
@@ -62,8 +56,9 @@ struct maple_device_specify { | |||
62 | int unit; | 56 | int unit; |
63 | }; | 57 | }; |
64 | 58 | ||
65 | static bool checked[4]; | 59 | static bool checked[MAPLE_PORTS]; |
66 | static struct maple_device *baseunits[4]; | 60 | static bool empty[MAPLE_PORTS]; |
61 | static struct maple_device *baseunits[MAPLE_PORTS]; | ||
67 | 62 | ||
68 | /** | 63 | /** |
69 | * maple_driver_register - register a maple driver | 64 | * maple_driver_register - register a maple driver |
@@ -97,12 +92,20 @@ void maple_driver_unregister(struct maple_driver *drv) | |||
97 | EXPORT_SYMBOL_GPL(maple_driver_unregister); | 92 | EXPORT_SYMBOL_GPL(maple_driver_unregister); |
98 | 93 | ||
99 | /* set hardware registers to enable next round of dma */ | 94 | /* set hardware registers to enable next round of dma */ |
100 | static void maplebus_dma_reset(void) | 95 | static void maple_dma_reset(void) |
101 | { | 96 | { |
102 | ctrl_outl(MAPLE_MAGIC, MAPLE_RESET); | 97 | ctrl_outl(MAPLE_MAGIC, MAPLE_RESET); |
103 | /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ | 98 | /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ |
104 | ctrl_outl(1, MAPLE_TRIGTYPE); | 99 | ctrl_outl(1, MAPLE_TRIGTYPE); |
105 | ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED); | 100 | /* |
101 | * Maple system register | ||
102 | * bits 31 - 16 timeout in units of 20nsec | ||
103 | * bit 12 hard trigger - set 0 to keep responding to VBLANK | ||
104 | * bits 9 - 8 set 00 for 2 Mbps, 01 for 1 Mbps | ||
105 | * bits 3 - 0 delay (in 1.3ms) between VBLANK and start of DMA | ||
106 | * max delay is 11 | ||
107 | */ | ||
108 | ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED); | ||
106 | ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); | 109 | ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); |
107 | ctrl_outl(1, MAPLE_ENABLE); | 110 | ctrl_outl(1, MAPLE_ENABLE); |
108 | } | 111 | } |
@@ -134,21 +137,16 @@ static void maple_release_device(struct device *dev) | |||
134 | { | 137 | { |
135 | struct maple_device *mdev; | 138 | struct maple_device *mdev; |
136 | struct mapleq *mq; | 139 | struct mapleq *mq; |
137 | if (!dev) | 140 | |
138 | return; | ||
139 | mdev = to_maple_dev(dev); | 141 | mdev = to_maple_dev(dev); |
140 | mq = mdev->mq; | 142 | mq = mdev->mq; |
141 | if (mq) { | 143 | kmem_cache_free(maple_queue_cache, mq->recvbuf); |
142 | if (mq->recvbufdcsp) | 144 | kfree(mq); |
143 | kmem_cache_free(maple_queue_cache, mq->recvbufdcsp); | ||
144 | kfree(mq); | ||
145 | mq = NULL; | ||
146 | } | ||
147 | kfree(mdev); | 145 | kfree(mdev); |
148 | } | 146 | } |
149 | 147 | ||
150 | /** | 148 | /** |
151 | * maple_add_packet - add a single instruction to the queue | 149 | * maple_add_packet - add a single instruction to the maple bus queue |
152 | * @mdev: maple device | 150 | * @mdev: maple device |
153 | * @function: function on device being queried | 151 | * @function: function on device being queried |
154 | * @command: maple command to add | 152 | * @command: maple command to add |
@@ -158,68 +156,12 @@ static void maple_release_device(struct device *dev) | |||
158 | int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, | 156 | int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, |
159 | size_t length, void *data) | 157 | size_t length, void *data) |
160 | { | 158 | { |
161 | int locking, ret = 0; | 159 | int ret = 0; |
162 | void *sendbuf = NULL; | ||
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; | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(maple_add_packet); | ||
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; | 160 | void *sendbuf = NULL; |
212 | 161 | ||
213 | locking = mutex_lock_interruptible(&mdev->mq->mutex); | ||
214 | if (locking) { | ||
215 | ret = -EIO; | ||
216 | goto out; | ||
217 | } | ||
218 | |||
219 | if (length) { | 162 | if (length) { |
220 | sendbuf = kmalloc(length * 4, GFP_KERNEL); | 163 | sendbuf = kzalloc(length * 4, GFP_KERNEL); |
221 | if (!sendbuf) { | 164 | if (!sendbuf) { |
222 | mutex_unlock(&mdev->mq->mutex); | ||
223 | ret = -ENOMEM; | 165 | ret = -ENOMEM; |
224 | goto out; | 166 | goto out; |
225 | } | 167 | } |
@@ -233,38 +175,35 @@ int maple_add_packet_sleeps(struct maple_device *mdev, u32 function, | |||
233 | mdev->mq->sendbuf = sendbuf; | 175 | mdev->mq->sendbuf = sendbuf; |
234 | 176 | ||
235 | mutex_lock(&maple_wlist_lock); | 177 | mutex_lock(&maple_wlist_lock); |
236 | list_add(&mdev->mq->list, &maple_waitq); | 178 | list_add_tail(&mdev->mq->list, &maple_waitq); |
237 | mutex_unlock(&maple_wlist_lock); | 179 | mutex_unlock(&maple_wlist_lock); |
238 | out: | 180 | out: |
239 | return ret; | 181 | return ret; |
240 | } | 182 | } |
241 | EXPORT_SYMBOL_GPL(maple_add_packet_sleeps); | 183 | EXPORT_SYMBOL_GPL(maple_add_packet); |
242 | 184 | ||
243 | static struct mapleq *maple_allocq(struct maple_device *mdev) | 185 | static struct mapleq *maple_allocq(struct maple_device *mdev) |
244 | { | 186 | { |
245 | struct mapleq *mq; | 187 | struct mapleq *mq; |
246 | 188 | ||
247 | mq = kmalloc(sizeof(*mq), GFP_KERNEL); | 189 | mq = kzalloc(sizeof(*mq), GFP_KERNEL); |
248 | if (!mq) | 190 | if (!mq) |
249 | goto failed_nomem; | 191 | goto failed_nomem; |
250 | 192 | ||
193 | INIT_LIST_HEAD(&mq->list); | ||
251 | mq->dev = mdev; | 194 | mq->dev = mdev; |
252 | mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); | 195 | mq->recvbuf = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); |
253 | mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp); | ||
254 | if (!mq->recvbuf) | 196 | if (!mq->recvbuf) |
255 | goto failed_p2; | 197 | goto failed_p2; |
256 | /* | 198 | mq->recvbuf->buf = &((mq->recvbuf->bufx)[0]); |
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); | ||
262 | 199 | ||
263 | return mq; | 200 | return mq; |
264 | 201 | ||
265 | failed_p2: | 202 | failed_p2: |
266 | kfree(mq); | 203 | kfree(mq); |
267 | failed_nomem: | 204 | failed_nomem: |
205 | dev_err(&mdev->dev, "could not allocate memory for device (%d, %d)\n", | ||
206 | mdev->port, mdev->unit); | ||
268 | return NULL; | 207 | return NULL; |
269 | } | 208 | } |
270 | 209 | ||
@@ -272,12 +211,16 @@ static struct maple_device *maple_alloc_dev(int port, int unit) | |||
272 | { | 211 | { |
273 | struct maple_device *mdev; | 212 | struct maple_device *mdev; |
274 | 213 | ||
214 | /* zero this out to avoid kobj subsystem | ||
215 | * thinking it has already been registered */ | ||
216 | |||
275 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); | 217 | mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); |
276 | if (!mdev) | 218 | if (!mdev) |
277 | return NULL; | 219 | return NULL; |
278 | 220 | ||
279 | mdev->port = port; | 221 | mdev->port = port; |
280 | mdev->unit = unit; | 222 | mdev->unit = unit; |
223 | |||
281 | mdev->mq = maple_allocq(mdev); | 224 | mdev->mq = maple_allocq(mdev); |
282 | 225 | ||
283 | if (!mdev->mq) { | 226 | if (!mdev->mq) { |
@@ -286,19 +229,14 @@ static struct maple_device *maple_alloc_dev(int port, int unit) | |||
286 | } | 229 | } |
287 | mdev->dev.bus = &maple_bus_type; | 230 | mdev->dev.bus = &maple_bus_type; |
288 | mdev->dev.parent = &maple_bus; | 231 | mdev->dev.parent = &maple_bus; |
232 | init_waitqueue_head(&mdev->maple_wait); | ||
289 | return mdev; | 233 | return mdev; |
290 | } | 234 | } |
291 | 235 | ||
292 | static void maple_free_dev(struct maple_device *mdev) | 236 | static void maple_free_dev(struct maple_device *mdev) |
293 | { | 237 | { |
294 | if (!mdev) | 238 | kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf); |
295 | return; | 239 | kfree(mdev->mq); |
296 | if (mdev->mq) { | ||
297 | if (mdev->mq->recvbufdcsp) | ||
298 | kmem_cache_free(maple_queue_cache, | ||
299 | mdev->mq->recvbufdcsp); | ||
300 | kfree(mdev->mq); | ||
301 | } | ||
302 | kfree(mdev); | 240 | kfree(mdev); |
303 | } | 241 | } |
304 | 242 | ||
@@ -320,7 +258,7 @@ static void maple_build_block(struct mapleq *mq) | |||
320 | maple_lastptr = maple_sendptr; | 258 | maple_lastptr = maple_sendptr; |
321 | 259 | ||
322 | *maple_sendptr++ = (port << 16) | len | 0x80000000; | 260 | *maple_sendptr++ = (port << 16) | len | 0x80000000; |
323 | *maple_sendptr++ = PHYSADDR(mq->recvbuf); | 261 | *maple_sendptr++ = PHYSADDR(mq->recvbuf->buf); |
324 | *maple_sendptr++ = | 262 | *maple_sendptr++ = |
325 | mq->command | (to << 8) | (from << 16) | (len << 24); | 263 | mq->command | (to << 8) | (from << 16) | (len << 24); |
326 | while (len-- > 0) | 264 | while (len-- > 0) |
@@ -333,20 +271,28 @@ static void maple_send(void) | |||
333 | int i, maple_packets = 0; | 271 | int i, maple_packets = 0; |
334 | struct mapleq *mq, *nmq; | 272 | struct mapleq *mq, *nmq; |
335 | 273 | ||
336 | if (!list_empty(&maple_sentq)) | 274 | if (!maple_dma_done()) |
337 | return; | 275 | return; |
276 | |||
277 | /* disable DMA */ | ||
278 | ctrl_outl(0, MAPLE_ENABLE); | ||
279 | |||
280 | if (!list_empty(&maple_sentq)) | ||
281 | goto finish; | ||
282 | |||
338 | mutex_lock(&maple_wlist_lock); | 283 | mutex_lock(&maple_wlist_lock); |
339 | if (list_empty(&maple_waitq) || !maple_dma_done()) { | 284 | if (list_empty(&maple_waitq)) { |
340 | mutex_unlock(&maple_wlist_lock); | 285 | mutex_unlock(&maple_wlist_lock); |
341 | return; | 286 | goto finish; |
342 | } | 287 | } |
343 | mutex_unlock(&maple_wlist_lock); | 288 | |
344 | maple_lastptr = maple_sendbuf; | 289 | maple_lastptr = maple_sendbuf; |
345 | maple_sendptr = maple_sendbuf; | 290 | maple_sendptr = maple_sendbuf; |
346 | mutex_lock(&maple_wlist_lock); | 291 | |
347 | list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { | 292 | list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { |
348 | maple_build_block(mq); | 293 | maple_build_block(mq); |
349 | list_move(&mq->list, &maple_sentq); | 294 | list_del_init(&mq->list); |
295 | list_add_tail(&mq->list, &maple_sentq); | ||
350 | if (maple_packets++ > MAPLE_MAXPACKETS) | 296 | if (maple_packets++ > MAPLE_MAXPACKETS) |
351 | break; | 297 | break; |
352 | } | 298 | } |
@@ -356,10 +302,13 @@ static void maple_send(void) | |||
356 | dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, | 302 | dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, |
357 | PAGE_SIZE, DMA_BIDIRECTIONAL); | 303 | PAGE_SIZE, DMA_BIDIRECTIONAL); |
358 | } | 304 | } |
305 | |||
306 | finish: | ||
307 | maple_dma_reset(); | ||
359 | } | 308 | } |
360 | 309 | ||
361 | /* check if there is a driver registered likely to match this device */ | 310 | /* check if there is a driver registered likely to match this device */ |
362 | static int check_matching_maple_driver(struct device_driver *driver, | 311 | static int maple_check_matching_driver(struct device_driver *driver, |
363 | void *devptr) | 312 | void *devptr) |
364 | { | 313 | { |
365 | struct maple_driver *maple_drv; | 314 | struct maple_driver *maple_drv; |
@@ -374,10 +323,7 @@ static int check_matching_maple_driver(struct device_driver *driver, | |||
374 | 323 | ||
375 | static void maple_detach_driver(struct maple_device *mdev) | 324 | static void maple_detach_driver(struct maple_device *mdev) |
376 | { | 325 | { |
377 | if (!mdev) | ||
378 | return; | ||
379 | device_unregister(&mdev->dev); | 326 | device_unregister(&mdev->dev); |
380 | mdev = NULL; | ||
381 | } | 327 | } |
382 | 328 | ||
383 | /* process initial MAPLE_COMMAND_DEVINFO for each device or port */ | 329 | /* process initial MAPLE_COMMAND_DEVINFO for each device or port */ |
@@ -385,9 +331,9 @@ static void maple_attach_driver(struct maple_device *mdev) | |||
385 | { | 331 | { |
386 | char *p, *recvbuf; | 332 | char *p, *recvbuf; |
387 | unsigned long function; | 333 | unsigned long function; |
388 | int matched, retval; | 334 | int matched, error; |
389 | 335 | ||
390 | recvbuf = mdev->mq->recvbuf; | 336 | recvbuf = mdev->mq->recvbuf->buf; |
391 | /* copy the data as individual elements in | 337 | /* copy the data as individual elements in |
392 | * case of memory optimisation */ | 338 | * case of memory optimisation */ |
393 | memcpy(&mdev->devinfo.function, recvbuf + 4, 4); | 339 | memcpy(&mdev->devinfo.function, recvbuf + 4, 4); |
@@ -395,7 +341,6 @@ static void maple_attach_driver(struct maple_device *mdev) | |||
395 | memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); | 341 | memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); |
396 | memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); | 342 | memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); |
397 | memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); | 343 | memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); |
398 | memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60); | ||
399 | memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); | 344 | memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); |
400 | memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); | 345 | memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); |
401 | memcpy(mdev->product_name, mdev->devinfo.product_name, 30); | 346 | memcpy(mdev->product_name, mdev->devinfo.product_name, 30); |
@@ -414,43 +359,40 @@ static void maple_attach_driver(struct maple_device *mdev) | |||
414 | else | 359 | else |
415 | break; | 360 | break; |
416 | 361 | ||
417 | printk(KERN_INFO "Maple device detected: %s\n", | ||
418 | mdev->product_name); | ||
419 | printk(KERN_INFO "Maple device: %s\n", mdev->product_licence); | ||
420 | |||
421 | function = be32_to_cpu(mdev->devinfo.function); | 362 | function = be32_to_cpu(mdev->devinfo.function); |
422 | 363 | ||
364 | dev_info(&mdev->dev, "detected %s: function 0x%lX: at (%d, %d)\n", | ||
365 | mdev->product_name, function, mdev->port, mdev->unit); | ||
366 | |||
423 | if (function > 0x200) { | 367 | if (function > 0x200) { |
424 | /* Do this silently - as not a real device */ | 368 | /* Do this silently - as not a real device */ |
425 | function = 0; | 369 | function = 0; |
426 | mdev->driver = &maple_dummy_driver; | 370 | mdev->driver = &maple_unsupported_device; |
427 | sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port); | 371 | dev_set_name(&mdev->dev, "%d:0.port", mdev->port); |
428 | } else { | 372 | } else { |
429 | printk(KERN_INFO | ||
430 | "Maple bus at (%d, %d): Function 0x%lX\n", | ||
431 | mdev->port, mdev->unit, function); | ||
432 | |||
433 | matched = | 373 | matched = |
434 | bus_for_each_drv(&maple_bus_type, NULL, mdev, | 374 | bus_for_each_drv(&maple_bus_type, NULL, mdev, |
435 | check_matching_maple_driver); | 375 | maple_check_matching_driver); |
436 | 376 | ||
437 | if (matched == 0) { | 377 | if (matched == 0) { |
438 | /* Driver does not exist yet */ | 378 | /* Driver does not exist yet */ |
439 | printk(KERN_INFO | 379 | dev_info(&mdev->dev, "no driver found\n"); |
440 | "No maple driver found.\n"); | 380 | mdev->driver = &maple_unsupported_device; |
441 | mdev->driver = &maple_dummy_driver; | ||
442 | } | 381 | } |
443 | sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port, | 382 | |
444 | mdev->unit, function); | 383 | dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, |
384 | mdev->unit, function); | ||
445 | } | 385 | } |
386 | |||
446 | mdev->function = function; | 387 | mdev->function = function; |
447 | mdev->dev.release = &maple_release_device; | 388 | mdev->dev.release = &maple_release_device; |
448 | retval = device_register(&mdev->dev); | 389 | |
449 | if (retval) { | 390 | atomic_set(&mdev->busy, 0); |
450 | printk(KERN_INFO | 391 | error = device_register(&mdev->dev); |
451 | "Maple bus: Attempt to register device" | 392 | if (error) { |
452 | " (%x, %x) failed.\n", | 393 | dev_warn(&mdev->dev, "could not register device at" |
453 | mdev->port, mdev->unit); | 394 | " (%d, %d), with error 0x%X\n", mdev->unit, |
395 | mdev->port, error); | ||
454 | maple_free_dev(mdev); | 396 | maple_free_dev(mdev); |
455 | mdev = NULL; | 397 | mdev = NULL; |
456 | return; | 398 | return; |
@@ -462,7 +404,7 @@ static void maple_attach_driver(struct maple_device *mdev) | |||
462 | * port and unit then return 1 - allows identification | 404 | * port and unit then return 1 - allows identification |
463 | * of which devices need to be attached or detached | 405 | * of which devices need to be attached or detached |
464 | */ | 406 | */ |
465 | static int detach_maple_device(struct device *device, void *portptr) | 407 | static int check_maple_device(struct device *device, void *portptr) |
466 | { | 408 | { |
467 | struct maple_device_specify *ds; | 409 | struct maple_device_specify *ds; |
468 | struct maple_device *mdev; | 410 | struct maple_device *mdev; |
@@ -477,21 +419,25 @@ static int detach_maple_device(struct device *device, void *portptr) | |||
477 | static int setup_maple_commands(struct device *device, void *ignored) | 419 | static int setup_maple_commands(struct device *device, void *ignored) |
478 | { | 420 | { |
479 | int add; | 421 | int add; |
480 | struct maple_device *maple_dev = to_maple_dev(device); | 422 | struct maple_device *mdev = to_maple_dev(device); |
481 | 423 | if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 && | |
482 | if ((maple_dev->interval > 0) | 424 | time_after(jiffies, mdev->when)) { |
483 | && time_after(jiffies, maple_dev->when)) { | 425 | /* bounce if we cannot add */ |
484 | /* bounce if we cannot lock */ | 426 | add = maple_add_packet(mdev, |
485 | add = maple_add_packet(maple_dev, | 427 | be32_to_cpu(mdev->devinfo.function), |
486 | be32_to_cpu(maple_dev->devinfo.function), | ||
487 | MAPLE_COMMAND_GETCOND, 1, NULL); | 428 | MAPLE_COMMAND_GETCOND, 1, NULL); |
488 | if (!add) | 429 | if (!add) |
489 | maple_dev->when = jiffies + maple_dev->interval; | 430 | mdev->when = jiffies + mdev->interval; |
490 | } else { | 431 | } else { |
491 | if (time_after(jiffies, maple_pnp_time)) | 432 | if (time_after(jiffies, maple_pnp_time)) |
492 | /* This will also bounce */ | 433 | /* Ensure we don't have block reads and devinfo |
493 | maple_add_packet(maple_dev, 0, | 434 | * calls interfering with one another - so flag the |
494 | MAPLE_COMMAND_DEVINFO, 0, NULL); | 435 | * device as busy */ |
436 | if (atomic_read(&mdev->busy) == 0) { | ||
437 | atomic_set(&mdev->busy, 1); | ||
438 | maple_add_packet(mdev, 0, | ||
439 | MAPLE_COMMAND_DEVINFO, 0, NULL); | ||
440 | } | ||
495 | } | 441 | } |
496 | return 0; | 442 | return 0; |
497 | } | 443 | } |
@@ -499,29 +445,50 @@ static int setup_maple_commands(struct device *device, void *ignored) | |||
499 | /* VBLANK bottom half - implemented via workqueue */ | 445 | /* VBLANK bottom half - implemented via workqueue */ |
500 | static void maple_vblank_handler(struct work_struct *work) | 446 | static void maple_vblank_handler(struct work_struct *work) |
501 | { | 447 | { |
502 | if (!list_empty(&maple_sentq) || !maple_dma_done()) | 448 | int x, locking; |
449 | struct maple_device *mdev; | ||
450 | |||
451 | if (!maple_dma_done()) | ||
503 | return; | 452 | return; |
504 | 453 | ||
505 | ctrl_outl(0, MAPLE_ENABLE); | 454 | ctrl_outl(0, MAPLE_ENABLE); |
506 | 455 | ||
456 | if (!list_empty(&maple_sentq)) | ||
457 | goto finish; | ||
458 | |||
459 | /* | ||
460 | * Set up essential commands - to fetch data and | ||
461 | * check devices are still present | ||
462 | */ | ||
507 | bus_for_each_dev(&maple_bus_type, NULL, NULL, | 463 | bus_for_each_dev(&maple_bus_type, NULL, NULL, |
508 | setup_maple_commands); | 464 | setup_maple_commands); |
465 | |||
466 | if (time_after(jiffies, maple_pnp_time)) { | ||
467 | /* | ||
468 | * Scan the empty ports - bus is flakey and may have | ||
469 | * mis-reported emptyness | ||
470 | */ | ||
471 | for (x = 0; x < MAPLE_PORTS; x++) { | ||
472 | if (checked[x] && empty[x]) { | ||
473 | mdev = baseunits[x]; | ||
474 | if (!mdev) | ||
475 | break; | ||
476 | atomic_set(&mdev->busy, 1); | ||
477 | locking = maple_add_packet(mdev, 0, | ||
478 | MAPLE_COMMAND_DEVINFO, 0, NULL); | ||
479 | if (!locking) | ||
480 | break; | ||
481 | } | ||
482 | } | ||
509 | 483 | ||
510 | if (time_after(jiffies, maple_pnp_time)) | ||
511 | maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; | 484 | maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; |
512 | |||
513 | mutex_lock(&maple_wlist_lock); | ||
514 | if (!list_empty(&maple_waitq) && list_empty(&maple_sentq)) { | ||
515 | mutex_unlock(&maple_wlist_lock); | ||
516 | maple_send(); | ||
517 | } else { | ||
518 | mutex_unlock(&maple_wlist_lock); | ||
519 | } | 485 | } |
520 | 486 | ||
521 | maplebus_dma_reset(); | 487 | finish: |
488 | maple_send(); | ||
522 | } | 489 | } |
523 | 490 | ||
524 | /* handle devices added via hotplugs - placing them on queue for DEVINFO*/ | 491 | /* handle devices added via hotplugs - placing them on queue for DEVINFO */ |
525 | static void maple_map_subunits(struct maple_device *mdev, int submask) | 492 | static void maple_map_subunits(struct maple_device *mdev, int submask) |
526 | { | 493 | { |
527 | int retval, k, devcheck; | 494 | int retval, k, devcheck; |
@@ -533,7 +500,7 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) | |||
533 | ds.unit = k + 1; | 500 | ds.unit = k + 1; |
534 | retval = | 501 | retval = |
535 | bus_for_each_dev(&maple_bus_type, NULL, &ds, | 502 | bus_for_each_dev(&maple_bus_type, NULL, &ds, |
536 | detach_maple_device); | 503 | check_maple_device); |
537 | if (retval) { | 504 | if (retval) { |
538 | submask = submask >> 1; | 505 | submask = submask >> 1; |
539 | continue; | 506 | continue; |
@@ -543,6 +510,7 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) | |||
543 | mdev_add = maple_alloc_dev(mdev->port, k + 1); | 510 | mdev_add = maple_alloc_dev(mdev->port, k + 1); |
544 | if (!mdev_add) | 511 | if (!mdev_add) |
545 | return; | 512 | return; |
513 | atomic_set(&mdev_add->busy, 1); | ||
546 | maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, | 514 | maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, |
547 | 0, NULL); | 515 | 0, NULL); |
548 | /* mark that we are checking sub devices */ | 516 | /* mark that we are checking sub devices */ |
@@ -564,27 +532,45 @@ static void maple_clean_submap(struct maple_device *mdev) | |||
564 | } | 532 | } |
565 | 533 | ||
566 | /* handle empty port or hotplug removal */ | 534 | /* handle empty port or hotplug removal */ |
567 | static void maple_response_none(struct maple_device *mdev, | 535 | static void maple_response_none(struct maple_device *mdev) |
568 | struct mapleq *mq) | 536 | { |
569 | { | 537 | maple_clean_submap(mdev); |
570 | if (mdev->unit != 0) { | 538 | |
571 | list_del(&mq->list); | 539 | if (likely(mdev->unit != 0)) { |
572 | maple_clean_submap(mdev); | 540 | /* |
573 | printk(KERN_INFO | 541 | * Block devices play up |
574 | "Maple bus device detaching at (%d, %d)\n", | 542 | * and give the impression they have |
575 | mdev->port, mdev->unit); | 543 | * been removed even when still in place or |
544 | * trip the mtd layer when they have | ||
545 | * really gone - this code traps that eventuality | ||
546 | * and ensures we aren't overloaded with useless | ||
547 | * error messages | ||
548 | */ | ||
549 | if (mdev->can_unload) { | ||
550 | if (!mdev->can_unload(mdev)) { | ||
551 | atomic_set(&mdev->busy, 2); | ||
552 | wake_up(&mdev->maple_wait); | ||
553 | return; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | dev_info(&mdev->dev, "detaching device at (%d, %d)\n", | ||
558 | mdev->port, mdev->unit); | ||
576 | maple_detach_driver(mdev); | 559 | maple_detach_driver(mdev); |
577 | return; | 560 | return; |
578 | } | 561 | } else { |
579 | if (!started || !fullscan) { | 562 | if (!started || !fullscan) { |
580 | if (checked[mdev->port] == false) { | 563 | if (checked[mdev->port] == false) { |
581 | checked[mdev->port] = true; | 564 | checked[mdev->port] = true; |
582 | printk(KERN_INFO "No maple devices attached" | 565 | empty[mdev->port] = true; |
583 | " to port %d\n", mdev->port); | 566 | dev_info(&mdev->dev, "no devices" |
567 | " to port %d\n", mdev->port); | ||
568 | } | ||
569 | return; | ||
584 | } | 570 | } |
585 | return; | ||
586 | } | 571 | } |
587 | maple_clean_submap(mdev); | 572 | /* Some hardware devices generate false detach messages on unit 0 */ |
573 | atomic_set(&mdev->busy, 0); | ||
588 | } | 574 | } |
589 | 575 | ||
590 | /* preprocess hotplugs or scans */ | 576 | /* preprocess hotplugs or scans */ |
@@ -599,8 +585,11 @@ static void maple_response_devinfo(struct maple_device *mdev, | |||
599 | } else { | 585 | } else { |
600 | if (mdev->unit != 0) | 586 | if (mdev->unit != 0) |
601 | maple_attach_driver(mdev); | 587 | maple_attach_driver(mdev); |
588 | if (mdev->unit == 0) { | ||
589 | empty[mdev->port] = false; | ||
590 | maple_attach_driver(mdev); | ||
591 | } | ||
602 | } | 592 | } |
603 | return; | ||
604 | } | 593 | } |
605 | if (mdev->unit == 0) { | 594 | if (mdev->unit == 0) { |
606 | submask = recvbuf[2] & 0x1F; | 595 | submask = recvbuf[2] & 0x1F; |
@@ -611,6 +600,17 @@ static void maple_response_devinfo(struct maple_device *mdev, | |||
611 | } | 600 | } |
612 | } | 601 | } |
613 | 602 | ||
603 | static void maple_response_fileerr(struct maple_device *mdev, void *recvbuf) | ||
604 | { | ||
605 | if (mdev->fileerr_handler) { | ||
606 | mdev->fileerr_handler(mdev, recvbuf); | ||
607 | return; | ||
608 | } else | ||
609 | dev_warn(&mdev->dev, "device at (%d, %d) reports" | ||
610 | "file error 0x%X\n", mdev->port, mdev->unit, | ||
611 | ((int *)recvbuf)[1]); | ||
612 | } | ||
613 | |||
614 | static void maple_port_rescan(void) | 614 | static void maple_port_rescan(void) |
615 | { | 615 | { |
616 | int i; | 616 | int i; |
@@ -621,12 +621,6 @@ static void maple_port_rescan(void) | |||
621 | if (checked[i] == false) { | 621 | if (checked[i] == false) { |
622 | fullscan = 0; | 622 | fullscan = 0; |
623 | mdev = baseunits[i]; | 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, | 624 | maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO, |
631 | 0, NULL); | 625 | 0, NULL); |
632 | } | 626 | } |
@@ -637,7 +631,7 @@ static void maple_port_rescan(void) | |||
637 | static void maple_dma_handler(struct work_struct *work) | 631 | static void maple_dma_handler(struct work_struct *work) |
638 | { | 632 | { |
639 | struct mapleq *mq, *nmq; | 633 | struct mapleq *mq, *nmq; |
640 | struct maple_device *dev; | 634 | struct maple_device *mdev; |
641 | char *recvbuf; | 635 | char *recvbuf; |
642 | enum maple_code code; | 636 | enum maple_code code; |
643 | 637 | ||
@@ -646,43 +640,56 @@ static void maple_dma_handler(struct work_struct *work) | |||
646 | ctrl_outl(0, MAPLE_ENABLE); | 640 | ctrl_outl(0, MAPLE_ENABLE); |
647 | if (!list_empty(&maple_sentq)) { | 641 | if (!list_empty(&maple_sentq)) { |
648 | list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { | 642 | list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { |
649 | recvbuf = mq->recvbuf; | 643 | mdev = mq->dev; |
644 | recvbuf = mq->recvbuf->buf; | ||
645 | dma_cache_sync(&mdev->dev, recvbuf, 0x400, | ||
646 | DMA_FROM_DEVICE); | ||
650 | code = recvbuf[0]; | 647 | code = recvbuf[0]; |
651 | dev = mq->dev; | ||
652 | kfree(mq->sendbuf); | 648 | kfree(mq->sendbuf); |
653 | mutex_unlock(&mq->mutex); | ||
654 | list_del_init(&mq->list); | 649 | list_del_init(&mq->list); |
655 | |||
656 | switch (code) { | 650 | switch (code) { |
657 | case MAPLE_RESPONSE_NONE: | 651 | case MAPLE_RESPONSE_NONE: |
658 | maple_response_none(dev, mq); | 652 | maple_response_none(mdev); |
659 | break; | 653 | break; |
660 | 654 | ||
661 | case MAPLE_RESPONSE_DEVINFO: | 655 | case MAPLE_RESPONSE_DEVINFO: |
662 | maple_response_devinfo(dev, recvbuf); | 656 | maple_response_devinfo(mdev, recvbuf); |
657 | atomic_set(&mdev->busy, 0); | ||
663 | break; | 658 | break; |
664 | 659 | ||
665 | case MAPLE_RESPONSE_DATATRF: | 660 | case MAPLE_RESPONSE_DATATRF: |
666 | if (dev->callback) | 661 | if (mdev->callback) |
667 | dev->callback(mq); | 662 | mdev->callback(mq); |
663 | atomic_set(&mdev->busy, 0); | ||
664 | wake_up(&mdev->maple_wait); | ||
668 | break; | 665 | break; |
669 | 666 | ||
670 | case MAPLE_RESPONSE_FILEERR: | 667 | case MAPLE_RESPONSE_FILEERR: |
668 | maple_response_fileerr(mdev, recvbuf); | ||
669 | atomic_set(&mdev->busy, 0); | ||
670 | wake_up(&mdev->maple_wait); | ||
671 | break; | ||
672 | |||
671 | case MAPLE_RESPONSE_AGAIN: | 673 | case MAPLE_RESPONSE_AGAIN: |
672 | case MAPLE_RESPONSE_BADCMD: | 674 | case MAPLE_RESPONSE_BADCMD: |
673 | case MAPLE_RESPONSE_BADFUNC: | 675 | case MAPLE_RESPONSE_BADFUNC: |
674 | printk(KERN_DEBUG | 676 | dev_warn(&mdev->dev, "non-fatal error" |
675 | "Maple non-fatal error 0x%X\n", | 677 | " 0x%X at (%d, %d)\n", code, |
676 | code); | 678 | mdev->port, mdev->unit); |
679 | atomic_set(&mdev->busy, 0); | ||
677 | break; | 680 | break; |
678 | 681 | ||
679 | case MAPLE_RESPONSE_ALLINFO: | 682 | case MAPLE_RESPONSE_ALLINFO: |
680 | printk(KERN_DEBUG | 683 | dev_notice(&mdev->dev, "extended" |
681 | "Maple - extended device information" | 684 | " device information request for (%d, %d)" |
682 | " not supported\n"); | 685 | " but call is not supported\n", mdev->port, |
686 | mdev->unit); | ||
687 | atomic_set(&mdev->busy, 0); | ||
683 | break; | 688 | break; |
684 | 689 | ||
685 | case MAPLE_RESPONSE_OK: | 690 | case MAPLE_RESPONSE_OK: |
691 | atomic_set(&mdev->busy, 0); | ||
692 | wake_up(&mdev->maple_wait); | ||
686 | break; | 693 | break; |
687 | 694 | ||
688 | default: | 695 | default: |
@@ -699,20 +706,19 @@ static void maple_dma_handler(struct work_struct *work) | |||
699 | if (!fullscan) | 706 | if (!fullscan) |
700 | maple_port_rescan(); | 707 | maple_port_rescan(); |
701 | /* mark that we have been through the first scan */ | 708 | /* mark that we have been through the first scan */ |
702 | if (started == 0) | 709 | started = 1; |
703 | started = 1; | ||
704 | } | 710 | } |
705 | maplebus_dma_reset(); | 711 | maple_send(); |
706 | } | 712 | } |
707 | 713 | ||
708 | static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id) | 714 | static irqreturn_t maple_dma_interrupt(int irq, void *dev_id) |
709 | { | 715 | { |
710 | /* Load everything into the bottom half */ | 716 | /* Load everything into the bottom half */ |
711 | schedule_work(&maple_dma_process); | 717 | schedule_work(&maple_dma_process); |
712 | return IRQ_HANDLED; | 718 | return IRQ_HANDLED; |
713 | } | 719 | } |
714 | 720 | ||
715 | static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) | 721 | static irqreturn_t maple_vblank_interrupt(int irq, void *dev_id) |
716 | { | 722 | { |
717 | schedule_work(&maple_vblank_process); | 723 | schedule_work(&maple_vblank_process); |
718 | return IRQ_HANDLED; | 724 | return IRQ_HANDLED; |
@@ -720,14 +726,14 @@ static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) | |||
720 | 726 | ||
721 | static int maple_set_dma_interrupt_handler(void) | 727 | static int maple_set_dma_interrupt_handler(void) |
722 | { | 728 | { |
723 | return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt, | 729 | return request_irq(HW_EVENT_MAPLE_DMA, maple_dma_interrupt, |
724 | IRQF_SHARED, "maple bus DMA", &maple_dummy_driver); | 730 | IRQF_SHARED, "maple bus DMA", &maple_unsupported_device); |
725 | } | 731 | } |
726 | 732 | ||
727 | static int maple_set_vblank_interrupt_handler(void) | 733 | static int maple_set_vblank_interrupt_handler(void) |
728 | { | 734 | { |
729 | return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt, | 735 | return request_irq(HW_EVENT_VSYNC, maple_vblank_interrupt, |
730 | IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver); | 736 | IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device); |
731 | } | 737 | } |
732 | 738 | ||
733 | static int maple_get_dma_buffer(void) | 739 | static int maple_get_dma_buffer(void) |
@@ -740,7 +746,7 @@ static int maple_get_dma_buffer(void) | |||
740 | return 0; | 746 | return 0; |
741 | } | 747 | } |
742 | 748 | ||
743 | static int match_maple_bus_driver(struct device *devptr, | 749 | static int maple_match_bus_driver(struct device *devptr, |
744 | struct device_driver *drvptr) | 750 | struct device_driver *drvptr) |
745 | { | 751 | { |
746 | struct maple_driver *maple_drv = to_maple_driver(drvptr); | 752 | struct maple_driver *maple_drv = to_maple_driver(drvptr); |
@@ -765,22 +771,24 @@ static void maple_bus_release(struct device *dev) | |||
765 | { | 771 | { |
766 | } | 772 | } |
767 | 773 | ||
768 | static struct maple_driver maple_dummy_driver = { | 774 | static struct maple_driver maple_unsupported_device = { |
769 | .drv = { | 775 | .drv = { |
770 | .name = "maple_dummy_driver", | 776 | .name = "maple_unsupported_device", |
771 | .bus = &maple_bus_type, | 777 | .bus = &maple_bus_type, |
772 | }, | 778 | }, |
773 | }; | 779 | }; |
774 | 780 | /** | |
781 | * maple_bus_type - core maple bus structure | ||
782 | */ | ||
775 | struct bus_type maple_bus_type = { | 783 | struct bus_type maple_bus_type = { |
776 | .name = "maple", | 784 | .name = "maple", |
777 | .match = match_maple_bus_driver, | 785 | .match = maple_match_bus_driver, |
778 | .uevent = maple_bus_uevent, | 786 | .uevent = maple_bus_uevent, |
779 | }; | 787 | }; |
780 | EXPORT_SYMBOL_GPL(maple_bus_type); | 788 | EXPORT_SYMBOL_GPL(maple_bus_type); |
781 | 789 | ||
782 | static struct device maple_bus = { | 790 | static struct device maple_bus = { |
783 | .bus_id = "maple", | 791 | .init_name = "maple", |
784 | .release = maple_bus_release, | 792 | .release = maple_bus_release, |
785 | }; | 793 | }; |
786 | 794 | ||
@@ -788,7 +796,8 @@ static int __init maple_bus_init(void) | |||
788 | { | 796 | { |
789 | int retval, i; | 797 | int retval, i; |
790 | struct maple_device *mdev[MAPLE_PORTS]; | 798 | struct maple_device *mdev[MAPLE_PORTS]; |
791 | ctrl_outl(0, MAPLE_STATE); | 799 | |
800 | ctrl_outl(0, MAPLE_ENABLE); | ||
792 | 801 | ||
793 | retval = device_register(&maple_bus); | 802 | retval = device_register(&maple_bus); |
794 | if (retval) | 803 | if (retval) |
@@ -798,36 +807,33 @@ static int __init maple_bus_init(void) | |||
798 | if (retval) | 807 | if (retval) |
799 | goto cleanup_device; | 808 | goto cleanup_device; |
800 | 809 | ||
801 | retval = driver_register(&maple_dummy_driver.drv); | 810 | retval = driver_register(&maple_unsupported_device.drv); |
802 | if (retval) | 811 | if (retval) |
803 | goto cleanup_bus; | 812 | goto cleanup_bus; |
804 | 813 | ||
805 | /* allocate memory for maple bus dma */ | 814 | /* allocate memory for maple bus dma */ |
806 | retval = maple_get_dma_buffer(); | 815 | retval = maple_get_dma_buffer(); |
807 | if (retval) { | 816 | if (retval) { |
808 | printk(KERN_INFO | 817 | dev_err(&maple_bus, "failed to allocate DMA buffers\n"); |
809 | "Maple bus: Failed to allocate Maple DMA buffers\n"); | ||
810 | goto cleanup_basic; | 818 | goto cleanup_basic; |
811 | } | 819 | } |
812 | 820 | ||
813 | /* set up DMA interrupt handler */ | 821 | /* set up DMA interrupt handler */ |
814 | retval = maple_set_dma_interrupt_handler(); | 822 | retval = maple_set_dma_interrupt_handler(); |
815 | if (retval) { | 823 | if (retval) { |
816 | printk(KERN_INFO | 824 | dev_err(&maple_bus, "bus failed to grab maple " |
817 | "Maple bus: Failed to grab maple DMA IRQ\n"); | 825 | "DMA IRQ\n"); |
818 | goto cleanup_dma; | 826 | goto cleanup_dma; |
819 | } | 827 | } |
820 | 828 | ||
821 | /* set up VBLANK interrupt handler */ | 829 | /* set up VBLANK interrupt handler */ |
822 | retval = maple_set_vblank_interrupt_handler(); | 830 | retval = maple_set_vblank_interrupt_handler(); |
823 | if (retval) { | 831 | if (retval) { |
824 | printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); | 832 | dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n"); |
825 | goto cleanup_irq; | 833 | goto cleanup_irq; |
826 | } | 834 | } |
827 | 835 | ||
828 | maple_queue_cache = | 836 | maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN); |
829 | kmem_cache_create("maple_queue_cache", 0x400, 0, | ||
830 | SLAB_HWCACHE_ALIGN, NULL); | ||
831 | 837 | ||
832 | if (!maple_queue_cache) | 838 | if (!maple_queue_cache) |
833 | goto cleanup_bothirqs; | 839 | goto cleanup_bothirqs; |
@@ -838,23 +844,23 @@ static int __init maple_bus_init(void) | |||
838 | /* setup maple ports */ | 844 | /* setup maple ports */ |
839 | for (i = 0; i < MAPLE_PORTS; i++) { | 845 | for (i = 0; i < MAPLE_PORTS; i++) { |
840 | checked[i] = false; | 846 | checked[i] = false; |
847 | empty[i] = false; | ||
841 | mdev[i] = maple_alloc_dev(i, 0); | 848 | mdev[i] = maple_alloc_dev(i, 0); |
842 | baseunits[i] = mdev[i]; | ||
843 | if (!mdev[i]) { | 849 | if (!mdev[i]) { |
844 | while (i-- > 0) | 850 | while (i-- > 0) |
845 | maple_free_dev(mdev[i]); | 851 | maple_free_dev(mdev[i]); |
846 | goto cleanup_cache; | 852 | goto cleanup_cache; |
847 | } | 853 | } |
854 | baseunits[i] = mdev[i]; | ||
855 | atomic_set(&mdev[i]->busy, 1); | ||
848 | maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); | 856 | maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); |
849 | subdevice_map[i] = 0; | 857 | subdevice_map[i] = 0; |
850 | } | 858 | } |
851 | 859 | ||
852 | /* setup maplebus hardware */ | 860 | maple_pnp_time = jiffies + HZ; |
853 | maplebus_dma_reset(); | 861 | /* prepare initial queue */ |
854 | /* initial detection */ | ||
855 | maple_send(); | 862 | maple_send(); |
856 | maple_pnp_time = jiffies; | 863 | dev_info(&maple_bus, "bus core now registered\n"); |
857 | printk(KERN_INFO "Maple bus core now registered.\n"); | ||
858 | 864 | ||
859 | return 0; | 865 | return 0; |
860 | 866 | ||
@@ -871,7 +877,7 @@ cleanup_dma: | |||
871 | free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); | 877 | free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); |
872 | 878 | ||
873 | cleanup_basic: | 879 | cleanup_basic: |
874 | driver_unregister(&maple_dummy_driver.drv); | 880 | driver_unregister(&maple_unsupported_device.drv); |
875 | 881 | ||
876 | cleanup_bus: | 882 | cleanup_bus: |
877 | bus_unregister(&maple_bus_type); | 883 | bus_unregister(&maple_bus_type); |
@@ -880,7 +886,7 @@ cleanup_device: | |||
880 | device_unregister(&maple_bus); | 886 | device_unregister(&maple_bus); |
881 | 887 | ||
882 | cleanup: | 888 | cleanup: |
883 | printk(KERN_INFO "Maple bus registration failed\n"); | 889 | printk(KERN_ERR "Maple bus registration failed\n"); |
884 | return retval; | 890 | return retval; |
885 | } | 891 | } |
886 | /* Push init to later to ensure hardware gets detected */ | 892 | /* Push init to later to ensure hardware gets detected */ |