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