diff options
Diffstat (limited to 'drivers/sh')
-rw-r--r-- | drivers/sh/intc.c | 47 | ||||
-rw-r--r-- | drivers/sh/maple/maple.c | 463 |
2 files changed, 281 insertions, 229 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 58d24c5a76ce..2269fbcaa182 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
@@ -568,6 +568,10 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
568 | if (!data[0] && data[1]) | 568 | if (!data[0] && data[1]) |
569 | primary = 1; | 569 | primary = 1; |
570 | 570 | ||
571 | if (!data[0] && !data[1]) | ||
572 | pr_warning("intc: missing unique irq mask for " | ||
573 | "irq %d (vect 0x%04x)\n", irq, irq2evt(irq)); | ||
574 | |||
571 | data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); | 575 | data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); |
572 | data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); | 576 | data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); |
573 | 577 | ||
@@ -641,6 +645,17 @@ static unsigned int __init save_reg(struct intc_desc_int *d, | |||
641 | return 0; | 645 | return 0; |
642 | } | 646 | } |
643 | 647 | ||
648 | static unsigned char *intc_evt2irq_table; | ||
649 | |||
650 | unsigned int intc_evt2irq(unsigned int vector) | ||
651 | { | ||
652 | unsigned int irq = evt2irq(vector); | ||
653 | |||
654 | if (intc_evt2irq_table && intc_evt2irq_table[irq]) | ||
655 | irq = intc_evt2irq_table[irq]; | ||
656 | |||
657 | return irq; | ||
658 | } | ||
644 | 659 | ||
645 | void __init register_intc_controller(struct intc_desc *desc) | 660 | void __init register_intc_controller(struct intc_desc *desc) |
646 | { | 661 | { |
@@ -705,9 +720,41 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
705 | 720 | ||
706 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ | 721 | BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ |
707 | 722 | ||
723 | /* keep the first vector only if same enum is used multiple times */ | ||
724 | for (i = 0; i < desc->nr_vectors; i++) { | ||
725 | struct intc_vect *vect = desc->vectors + i; | ||
726 | int first_irq = evt2irq(vect->vect); | ||
727 | |||
728 | if (!vect->enum_id) | ||
729 | continue; | ||
730 | |||
731 | for (k = i + 1; k < desc->nr_vectors; k++) { | ||
732 | struct intc_vect *vect2 = desc->vectors + k; | ||
733 | |||
734 | if (vect->enum_id != vect2->enum_id) | ||
735 | continue; | ||
736 | |||
737 | vect2->enum_id = 0; | ||
738 | |||
739 | if (!intc_evt2irq_table) | ||
740 | intc_evt2irq_table = alloc_bootmem(NR_IRQS); | ||
741 | |||
742 | if (!intc_evt2irq_table) { | ||
743 | pr_warning("intc: cannot allocate evt2irq!\n"); | ||
744 | continue; | ||
745 | } | ||
746 | |||
747 | intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; | ||
748 | } | ||
749 | } | ||
750 | |||
751 | /* register the vectors one by one */ | ||
708 | for (i = 0; i < desc->nr_vectors; i++) { | 752 | for (i = 0; i < desc->nr_vectors; i++) { |
709 | struct intc_vect *vect = desc->vectors + i; | 753 | struct intc_vect *vect = desc->vectors + i; |
710 | 754 | ||
755 | if (!vect->enum_id) | ||
756 | continue; | ||
757 | |||
711 | intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); | 758 | intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); |
712 | } | 759 | } |
713 | } | 760 | } |
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 7e1257af3d41..cab1ab7cfb78 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; | 160 | void *sendbuf = NULL; |
163 | 161 | ||
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) { | 162 | if (length) { |
175 | sendbuf = kmalloc(length * 4, GFP_KERNEL); | 163 | sendbuf = kzalloc(length * 4, GFP_KERNEL); |
176 | if (!sendbuf) { | 164 | 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; | ||
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; | 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,39 @@ 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 | dev_set_name(&mdev->dev, "%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 | dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, | 382 | dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, |
444 | mdev->unit, function); | 383 | mdev->unit, function); |
445 | } | 384 | } |
385 | |||
446 | mdev->function = function; | 386 | mdev->function = function; |
447 | mdev->dev.release = &maple_release_device; | 387 | mdev->dev.release = &maple_release_device; |
448 | retval = device_register(&mdev->dev); | 388 | |
449 | if (retval) { | 389 | atomic_set(&mdev->busy, 0); |
450 | printk(KERN_INFO | 390 | error = device_register(&mdev->dev); |
451 | "Maple bus: Attempt to register device" | 391 | if (error) { |
452 | " (%x, %x) failed.\n", | 392 | dev_warn(&mdev->dev, "could not register device at" |
453 | mdev->port, mdev->unit); | 393 | " (%d, %d), with error 0x%X\n", mdev->unit, |
394 | mdev->port, error); | ||
454 | maple_free_dev(mdev); | 395 | maple_free_dev(mdev); |
455 | mdev = NULL; | 396 | mdev = NULL; |
456 | return; | 397 | return; |
@@ -462,7 +403,7 @@ static void maple_attach_driver(struct maple_device *mdev) | |||
462 | * port and unit then return 1 - allows identification | 403 | * port and unit then return 1 - allows identification |
463 | * of which devices need to be attached or detached | 404 | * of which devices need to be attached or detached |
464 | */ | 405 | */ |
465 | static int detach_maple_device(struct device *device, void *portptr) | 406 | static int check_maple_device(struct device *device, void *portptr) |
466 | { | 407 | { |
467 | struct maple_device_specify *ds; | 408 | struct maple_device_specify *ds; |
468 | struct maple_device *mdev; | 409 | struct maple_device *mdev; |
@@ -477,21 +418,25 @@ static int detach_maple_device(struct device *device, void *portptr) | |||
477 | static int setup_maple_commands(struct device *device, void *ignored) | 418 | static int setup_maple_commands(struct device *device, void *ignored) |
478 | { | 419 | { |
479 | int add; | 420 | int add; |
480 | struct maple_device *maple_dev = to_maple_dev(device); | 421 | struct maple_device *mdev = to_maple_dev(device); |
481 | 422 | if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 && | |
482 | if ((maple_dev->interval > 0) | 423 | time_after(jiffies, mdev->when)) { |
483 | && time_after(jiffies, maple_dev->when)) { | 424 | /* bounce if we cannot add */ |
484 | /* bounce if we cannot lock */ | 425 | add = maple_add_packet(mdev, |
485 | add = maple_add_packet(maple_dev, | 426 | be32_to_cpu(mdev->devinfo.function), |
486 | be32_to_cpu(maple_dev->devinfo.function), | ||
487 | MAPLE_COMMAND_GETCOND, 1, NULL); | 427 | MAPLE_COMMAND_GETCOND, 1, NULL); |
488 | if (!add) | 428 | if (!add) |
489 | maple_dev->when = jiffies + maple_dev->interval; | 429 | mdev->when = jiffies + mdev->interval; |
490 | } else { | 430 | } else { |
491 | if (time_after(jiffies, maple_pnp_time)) | 431 | if (time_after(jiffies, maple_pnp_time)) |
492 | /* This will also bounce */ | 432 | /* Ensure we don't have block reads and devinfo |
493 | maple_add_packet(maple_dev, 0, | 433 | * calls interfering with one another - so flag the |
494 | MAPLE_COMMAND_DEVINFO, 0, NULL); | 434 | * device as busy */ |
435 | if (atomic_read(&mdev->busy) == 0) { | ||
436 | atomic_set(&mdev->busy, 1); | ||
437 | maple_add_packet(mdev, 0, | ||
438 | MAPLE_COMMAND_DEVINFO, 0, NULL); | ||
439 | } | ||
495 | } | 440 | } |
496 | return 0; | 441 | return 0; |
497 | } | 442 | } |
@@ -499,29 +444,50 @@ static int setup_maple_commands(struct device *device, void *ignored) | |||
499 | /* VBLANK bottom half - implemented via workqueue */ | 444 | /* VBLANK bottom half - implemented via workqueue */ |
500 | static void maple_vblank_handler(struct work_struct *work) | 445 | static void maple_vblank_handler(struct work_struct *work) |
501 | { | 446 | { |
502 | if (!list_empty(&maple_sentq) || !maple_dma_done()) | 447 | int x, locking; |
448 | struct maple_device *mdev; | ||
449 | |||
450 | if (!maple_dma_done()) | ||
503 | return; | 451 | return; |
504 | 452 | ||
505 | ctrl_outl(0, MAPLE_ENABLE); | 453 | ctrl_outl(0, MAPLE_ENABLE); |
506 | 454 | ||
455 | if (!list_empty(&maple_sentq)) | ||
456 | goto finish; | ||
457 | |||
458 | /* | ||
459 | * Set up essential commands - to fetch data and | ||
460 | * check devices are still present | ||
461 | */ | ||
507 | bus_for_each_dev(&maple_bus_type, NULL, NULL, | 462 | bus_for_each_dev(&maple_bus_type, NULL, NULL, |
508 | setup_maple_commands); | 463 | setup_maple_commands); |
464 | |||
465 | if (time_after(jiffies, maple_pnp_time)) { | ||
466 | /* | ||
467 | * Scan the empty ports - bus is flakey and may have | ||
468 | * mis-reported emptyness | ||
469 | */ | ||
470 | for (x = 0; x < MAPLE_PORTS; x++) { | ||
471 | if (checked[x] && empty[x]) { | ||
472 | mdev = baseunits[x]; | ||
473 | if (!mdev) | ||
474 | break; | ||
475 | atomic_set(&mdev->busy, 1); | ||
476 | locking = maple_add_packet(mdev, 0, | ||
477 | MAPLE_COMMAND_DEVINFO, 0, NULL); | ||
478 | if (!locking) | ||
479 | break; | ||
480 | } | ||
481 | } | ||
509 | 482 | ||
510 | if (time_after(jiffies, maple_pnp_time)) | ||
511 | maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; | 483 | 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 | } | 484 | } |
520 | 485 | ||
521 | maplebus_dma_reset(); | 486 | finish: |
487 | maple_send(); | ||
522 | } | 488 | } |
523 | 489 | ||
524 | /* handle devices added via hotplugs - placing them on queue for DEVINFO*/ | 490 | /* handle devices added via hotplugs - placing them on queue for DEVINFO */ |
525 | static void maple_map_subunits(struct maple_device *mdev, int submask) | 491 | static void maple_map_subunits(struct maple_device *mdev, int submask) |
526 | { | 492 | { |
527 | int retval, k, devcheck; | 493 | int retval, k, devcheck; |
@@ -533,7 +499,7 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) | |||
533 | ds.unit = k + 1; | 499 | ds.unit = k + 1; |
534 | retval = | 500 | retval = |
535 | bus_for_each_dev(&maple_bus_type, NULL, &ds, | 501 | bus_for_each_dev(&maple_bus_type, NULL, &ds, |
536 | detach_maple_device); | 502 | check_maple_device); |
537 | if (retval) { | 503 | if (retval) { |
538 | submask = submask >> 1; | 504 | submask = submask >> 1; |
539 | continue; | 505 | continue; |
@@ -543,6 +509,7 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) | |||
543 | mdev_add = maple_alloc_dev(mdev->port, k + 1); | 509 | mdev_add = maple_alloc_dev(mdev->port, k + 1); |
544 | if (!mdev_add) | 510 | if (!mdev_add) |
545 | return; | 511 | return; |
512 | atomic_set(&mdev_add->busy, 1); | ||
546 | maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, | 513 | maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, |
547 | 0, NULL); | 514 | 0, NULL); |
548 | /* mark that we are checking sub devices */ | 515 | /* mark that we are checking sub devices */ |
@@ -564,27 +531,45 @@ static void maple_clean_submap(struct maple_device *mdev) | |||
564 | } | 531 | } |
565 | 532 | ||
566 | /* handle empty port or hotplug removal */ | 533 | /* handle empty port or hotplug removal */ |
567 | static void maple_response_none(struct maple_device *mdev, | 534 | static void maple_response_none(struct maple_device *mdev) |
568 | struct mapleq *mq) | 535 | { |
569 | { | 536 | maple_clean_submap(mdev); |
570 | if (mdev->unit != 0) { | 537 | |
571 | list_del(&mq->list); | 538 | if (likely(mdev->unit != 0)) { |
572 | maple_clean_submap(mdev); | 539 | /* |
573 | printk(KERN_INFO | 540 | * Block devices play up |
574 | "Maple bus device detaching at (%d, %d)\n", | 541 | * and give the impression they have |
575 | mdev->port, mdev->unit); | 542 | * been removed even when still in place or |
543 | * trip the mtd layer when they have | ||
544 | * really gone - this code traps that eventuality | ||
545 | * and ensures we aren't overloaded with useless | ||
546 | * error messages | ||
547 | */ | ||
548 | if (mdev->can_unload) { | ||
549 | if (!mdev->can_unload(mdev)) { | ||
550 | atomic_set(&mdev->busy, 2); | ||
551 | wake_up(&mdev->maple_wait); | ||
552 | return; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | dev_info(&mdev->dev, "detaching device at (%d, %d)\n", | ||
557 | mdev->port, mdev->unit); | ||
576 | maple_detach_driver(mdev); | 558 | maple_detach_driver(mdev); |
577 | return; | 559 | return; |
578 | } | 560 | } else { |
579 | if (!started || !fullscan) { | 561 | if (!started || !fullscan) { |
580 | if (checked[mdev->port] == false) { | 562 | if (checked[mdev->port] == false) { |
581 | checked[mdev->port] = true; | 563 | checked[mdev->port] = true; |
582 | printk(KERN_INFO "No maple devices attached" | 564 | empty[mdev->port] = true; |
583 | " to port %d\n", mdev->port); | 565 | dev_info(&mdev->dev, "no devices" |
566 | " to port %d\n", mdev->port); | ||
567 | } | ||
568 | return; | ||
584 | } | 569 | } |
585 | return; | ||
586 | } | 570 | } |
587 | maple_clean_submap(mdev); | 571 | /* Some hardware devices generate false detach messages on unit 0 */ |
572 | atomic_set(&mdev->busy, 0); | ||
588 | } | 573 | } |
589 | 574 | ||
590 | /* preprocess hotplugs or scans */ | 575 | /* preprocess hotplugs or scans */ |
@@ -599,8 +584,11 @@ static void maple_response_devinfo(struct maple_device *mdev, | |||
599 | } else { | 584 | } else { |
600 | if (mdev->unit != 0) | 585 | if (mdev->unit != 0) |
601 | maple_attach_driver(mdev); | 586 | maple_attach_driver(mdev); |
587 | if (mdev->unit == 0) { | ||
588 | empty[mdev->port] = false; | ||
589 | maple_attach_driver(mdev); | ||
590 | } | ||
602 | } | 591 | } |
603 | return; | ||
604 | } | 592 | } |
605 | if (mdev->unit == 0) { | 593 | if (mdev->unit == 0) { |
606 | submask = recvbuf[2] & 0x1F; | 594 | submask = recvbuf[2] & 0x1F; |
@@ -611,6 +599,17 @@ static void maple_response_devinfo(struct maple_device *mdev, | |||
611 | } | 599 | } |
612 | } | 600 | } |
613 | 601 | ||
602 | static void maple_response_fileerr(struct maple_device *mdev, void *recvbuf) | ||
603 | { | ||
604 | if (mdev->fileerr_handler) { | ||
605 | mdev->fileerr_handler(mdev, recvbuf); | ||
606 | return; | ||
607 | } else | ||
608 | dev_warn(&mdev->dev, "device at (%d, %d) reports" | ||
609 | "file error 0x%X\n", mdev->port, mdev->unit, | ||
610 | ((int *)recvbuf)[1]); | ||
611 | } | ||
612 | |||
614 | static void maple_port_rescan(void) | 613 | static void maple_port_rescan(void) |
615 | { | 614 | { |
616 | int i; | 615 | int i; |
@@ -621,12 +620,6 @@ static void maple_port_rescan(void) | |||
621 | if (checked[i] == false) { | 620 | if (checked[i] == false) { |
622 | fullscan = 0; | 621 | fullscan = 0; |
623 | mdev = baseunits[i]; | 622 | 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, | 623 | maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO, |
631 | 0, NULL); | 624 | 0, NULL); |
632 | } | 625 | } |
@@ -637,7 +630,7 @@ static void maple_port_rescan(void) | |||
637 | static void maple_dma_handler(struct work_struct *work) | 630 | static void maple_dma_handler(struct work_struct *work) |
638 | { | 631 | { |
639 | struct mapleq *mq, *nmq; | 632 | struct mapleq *mq, *nmq; |
640 | struct maple_device *dev; | 633 | struct maple_device *mdev; |
641 | char *recvbuf; | 634 | char *recvbuf; |
642 | enum maple_code code; | 635 | enum maple_code code; |
643 | 636 | ||
@@ -646,43 +639,56 @@ static void maple_dma_handler(struct work_struct *work) | |||
646 | ctrl_outl(0, MAPLE_ENABLE); | 639 | ctrl_outl(0, MAPLE_ENABLE); |
647 | if (!list_empty(&maple_sentq)) { | 640 | if (!list_empty(&maple_sentq)) { |
648 | list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { | 641 | list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { |
649 | recvbuf = mq->recvbuf; | 642 | mdev = mq->dev; |
643 | recvbuf = mq->recvbuf->buf; | ||
644 | dma_cache_sync(&mdev->dev, recvbuf, 0x400, | ||
645 | DMA_FROM_DEVICE); | ||
650 | code = recvbuf[0]; | 646 | code = recvbuf[0]; |
651 | dev = mq->dev; | ||
652 | kfree(mq->sendbuf); | 647 | kfree(mq->sendbuf); |
653 | mutex_unlock(&mq->mutex); | ||
654 | list_del_init(&mq->list); | 648 | list_del_init(&mq->list); |
655 | |||
656 | switch (code) { | 649 | switch (code) { |
657 | case MAPLE_RESPONSE_NONE: | 650 | case MAPLE_RESPONSE_NONE: |
658 | maple_response_none(dev, mq); | 651 | maple_response_none(mdev); |
659 | break; | 652 | break; |
660 | 653 | ||
661 | case MAPLE_RESPONSE_DEVINFO: | 654 | case MAPLE_RESPONSE_DEVINFO: |
662 | maple_response_devinfo(dev, recvbuf); | 655 | maple_response_devinfo(mdev, recvbuf); |
656 | atomic_set(&mdev->busy, 0); | ||
663 | break; | 657 | break; |
664 | 658 | ||
665 | case MAPLE_RESPONSE_DATATRF: | 659 | case MAPLE_RESPONSE_DATATRF: |
666 | if (dev->callback) | 660 | if (mdev->callback) |
667 | dev->callback(mq); | 661 | mdev->callback(mq); |
662 | atomic_set(&mdev->busy, 0); | ||
663 | wake_up(&mdev->maple_wait); | ||
668 | break; | 664 | break; |
669 | 665 | ||
670 | case MAPLE_RESPONSE_FILEERR: | 666 | case MAPLE_RESPONSE_FILEERR: |
667 | maple_response_fileerr(mdev, recvbuf); | ||
668 | atomic_set(&mdev->busy, 0); | ||
669 | wake_up(&mdev->maple_wait); | ||
670 | break; | ||
671 | |||
671 | case MAPLE_RESPONSE_AGAIN: | 672 | case MAPLE_RESPONSE_AGAIN: |
672 | case MAPLE_RESPONSE_BADCMD: | 673 | case MAPLE_RESPONSE_BADCMD: |
673 | case MAPLE_RESPONSE_BADFUNC: | 674 | case MAPLE_RESPONSE_BADFUNC: |
674 | printk(KERN_DEBUG | 675 | dev_warn(&mdev->dev, "non-fatal error" |
675 | "Maple non-fatal error 0x%X\n", | 676 | " 0x%X at (%d, %d)\n", code, |
676 | code); | 677 | mdev->port, mdev->unit); |
678 | atomic_set(&mdev->busy, 0); | ||
677 | break; | 679 | break; |
678 | 680 | ||
679 | case MAPLE_RESPONSE_ALLINFO: | 681 | case MAPLE_RESPONSE_ALLINFO: |
680 | printk(KERN_DEBUG | 682 | dev_notice(&mdev->dev, "extended" |
681 | "Maple - extended device information" | 683 | " device information request for (%d, %d)" |
682 | " not supported\n"); | 684 | " but call is not supported\n", mdev->port, |
685 | mdev->unit); | ||
686 | atomic_set(&mdev->busy, 0); | ||
683 | break; | 687 | break; |
684 | 688 | ||
685 | case MAPLE_RESPONSE_OK: | 689 | case MAPLE_RESPONSE_OK: |
690 | atomic_set(&mdev->busy, 0); | ||
691 | wake_up(&mdev->maple_wait); | ||
686 | break; | 692 | break; |
687 | 693 | ||
688 | default: | 694 | default: |
@@ -699,20 +705,19 @@ static void maple_dma_handler(struct work_struct *work) | |||
699 | if (!fullscan) | 705 | if (!fullscan) |
700 | maple_port_rescan(); | 706 | maple_port_rescan(); |
701 | /* mark that we have been through the first scan */ | 707 | /* mark that we have been through the first scan */ |
702 | if (started == 0) | 708 | started = 1; |
703 | started = 1; | ||
704 | } | 709 | } |
705 | maplebus_dma_reset(); | 710 | maple_send(); |
706 | } | 711 | } |
707 | 712 | ||
708 | static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id) | 713 | static irqreturn_t maple_dma_interrupt(int irq, void *dev_id) |
709 | { | 714 | { |
710 | /* Load everything into the bottom half */ | 715 | /* Load everything into the bottom half */ |
711 | schedule_work(&maple_dma_process); | 716 | schedule_work(&maple_dma_process); |
712 | return IRQ_HANDLED; | 717 | return IRQ_HANDLED; |
713 | } | 718 | } |
714 | 719 | ||
715 | static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) | 720 | static irqreturn_t maple_vblank_interrupt(int irq, void *dev_id) |
716 | { | 721 | { |
717 | schedule_work(&maple_vblank_process); | 722 | schedule_work(&maple_vblank_process); |
718 | return IRQ_HANDLED; | 723 | return IRQ_HANDLED; |
@@ -720,14 +725,14 @@ static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) | |||
720 | 725 | ||
721 | static int maple_set_dma_interrupt_handler(void) | 726 | static int maple_set_dma_interrupt_handler(void) |
722 | { | 727 | { |
723 | return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt, | 728 | return request_irq(HW_EVENT_MAPLE_DMA, maple_dma_interrupt, |
724 | IRQF_SHARED, "maple bus DMA", &maple_dummy_driver); | 729 | IRQF_SHARED, "maple bus DMA", &maple_unsupported_device); |
725 | } | 730 | } |
726 | 731 | ||
727 | static int maple_set_vblank_interrupt_handler(void) | 732 | static int maple_set_vblank_interrupt_handler(void) |
728 | { | 733 | { |
729 | return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt, | 734 | return request_irq(HW_EVENT_VSYNC, maple_vblank_interrupt, |
730 | IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver); | 735 | IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device); |
731 | } | 736 | } |
732 | 737 | ||
733 | static int maple_get_dma_buffer(void) | 738 | static int maple_get_dma_buffer(void) |
@@ -740,7 +745,7 @@ static int maple_get_dma_buffer(void) | |||
740 | return 0; | 745 | return 0; |
741 | } | 746 | } |
742 | 747 | ||
743 | static int match_maple_bus_driver(struct device *devptr, | 748 | static int maple_match_bus_driver(struct device *devptr, |
744 | struct device_driver *drvptr) | 749 | struct device_driver *drvptr) |
745 | { | 750 | { |
746 | struct maple_driver *maple_drv = to_maple_driver(drvptr); | 751 | struct maple_driver *maple_drv = to_maple_driver(drvptr); |
@@ -765,16 +770,18 @@ static void maple_bus_release(struct device *dev) | |||
765 | { | 770 | { |
766 | } | 771 | } |
767 | 772 | ||
768 | static struct maple_driver maple_dummy_driver = { | 773 | static struct maple_driver maple_unsupported_device = { |
769 | .drv = { | 774 | .drv = { |
770 | .name = "maple_dummy_driver", | 775 | .name = "maple_unsupported_device", |
771 | .bus = &maple_bus_type, | 776 | .bus = &maple_bus_type, |
772 | }, | 777 | }, |
773 | }; | 778 | }; |
774 | 779 | /** | |
780 | * maple_bus_type - core maple bus structure | ||
781 | */ | ||
775 | struct bus_type maple_bus_type = { | 782 | struct bus_type maple_bus_type = { |
776 | .name = "maple", | 783 | .name = "maple", |
777 | .match = match_maple_bus_driver, | 784 | .match = maple_match_bus_driver, |
778 | .uevent = maple_bus_uevent, | 785 | .uevent = maple_bus_uevent, |
779 | }; | 786 | }; |
780 | EXPORT_SYMBOL_GPL(maple_bus_type); | 787 | EXPORT_SYMBOL_GPL(maple_bus_type); |
@@ -788,7 +795,8 @@ static int __init maple_bus_init(void) | |||
788 | { | 795 | { |
789 | int retval, i; | 796 | int retval, i; |
790 | struct maple_device *mdev[MAPLE_PORTS]; | 797 | struct maple_device *mdev[MAPLE_PORTS]; |
791 | ctrl_outl(0, MAPLE_STATE); | 798 | |
799 | ctrl_outl(0, MAPLE_ENABLE); | ||
792 | 800 | ||
793 | retval = device_register(&maple_bus); | 801 | retval = device_register(&maple_bus); |
794 | if (retval) | 802 | if (retval) |
@@ -798,36 +806,33 @@ static int __init maple_bus_init(void) | |||
798 | if (retval) | 806 | if (retval) |
799 | goto cleanup_device; | 807 | goto cleanup_device; |
800 | 808 | ||
801 | retval = driver_register(&maple_dummy_driver.drv); | 809 | retval = driver_register(&maple_unsupported_device.drv); |
802 | if (retval) | 810 | if (retval) |
803 | goto cleanup_bus; | 811 | goto cleanup_bus; |
804 | 812 | ||
805 | /* allocate memory for maple bus dma */ | 813 | /* allocate memory for maple bus dma */ |
806 | retval = maple_get_dma_buffer(); | 814 | retval = maple_get_dma_buffer(); |
807 | if (retval) { | 815 | if (retval) { |
808 | printk(KERN_INFO | 816 | dev_err(&maple_bus, "failed to allocate DMA buffers\n"); |
809 | "Maple bus: Failed to allocate Maple DMA buffers\n"); | ||
810 | goto cleanup_basic; | 817 | goto cleanup_basic; |
811 | } | 818 | } |
812 | 819 | ||
813 | /* set up DMA interrupt handler */ | 820 | /* set up DMA interrupt handler */ |
814 | retval = maple_set_dma_interrupt_handler(); | 821 | retval = maple_set_dma_interrupt_handler(); |
815 | if (retval) { | 822 | if (retval) { |
816 | printk(KERN_INFO | 823 | dev_err(&maple_bus, "bus failed to grab maple " |
817 | "Maple bus: Failed to grab maple DMA IRQ\n"); | 824 | "DMA IRQ\n"); |
818 | goto cleanup_dma; | 825 | goto cleanup_dma; |
819 | } | 826 | } |
820 | 827 | ||
821 | /* set up VBLANK interrupt handler */ | 828 | /* set up VBLANK interrupt handler */ |
822 | retval = maple_set_vblank_interrupt_handler(); | 829 | retval = maple_set_vblank_interrupt_handler(); |
823 | if (retval) { | 830 | if (retval) { |
824 | printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); | 831 | dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n"); |
825 | goto cleanup_irq; | 832 | goto cleanup_irq; |
826 | } | 833 | } |
827 | 834 | ||
828 | maple_queue_cache = | 835 | 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 | 836 | ||
832 | if (!maple_queue_cache) | 837 | if (!maple_queue_cache) |
833 | goto cleanup_bothirqs; | 838 | goto cleanup_bothirqs; |
@@ -838,23 +843,23 @@ static int __init maple_bus_init(void) | |||
838 | /* setup maple ports */ | 843 | /* setup maple ports */ |
839 | for (i = 0; i < MAPLE_PORTS; i++) { | 844 | for (i = 0; i < MAPLE_PORTS; i++) { |
840 | checked[i] = false; | 845 | checked[i] = false; |
846 | empty[i] = false; | ||
841 | mdev[i] = maple_alloc_dev(i, 0); | 847 | mdev[i] = maple_alloc_dev(i, 0); |
842 | baseunits[i] = mdev[i]; | ||
843 | if (!mdev[i]) { | 848 | if (!mdev[i]) { |
844 | while (i-- > 0) | 849 | while (i-- > 0) |
845 | maple_free_dev(mdev[i]); | 850 | maple_free_dev(mdev[i]); |
846 | goto cleanup_cache; | 851 | goto cleanup_cache; |
847 | } | 852 | } |
853 | baseunits[i] = mdev[i]; | ||
854 | atomic_set(&mdev[i]->busy, 1); | ||
848 | maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); | 855 | maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); |
849 | subdevice_map[i] = 0; | 856 | subdevice_map[i] = 0; |
850 | } | 857 | } |
851 | 858 | ||
852 | /* setup maplebus hardware */ | 859 | maple_pnp_time = jiffies + HZ; |
853 | maplebus_dma_reset(); | 860 | /* prepare initial queue */ |
854 | /* initial detection */ | ||
855 | maple_send(); | 861 | maple_send(); |
856 | maple_pnp_time = jiffies; | 862 | dev_info(&maple_bus, "bus core now registered\n"); |
857 | printk(KERN_INFO "Maple bus core now registered.\n"); | ||
858 | 863 | ||
859 | return 0; | 864 | return 0; |
860 | 865 | ||
@@ -871,7 +876,7 @@ cleanup_dma: | |||
871 | free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); | 876 | free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); |
872 | 877 | ||
873 | cleanup_basic: | 878 | cleanup_basic: |
874 | driver_unregister(&maple_dummy_driver.drv); | 879 | driver_unregister(&maple_unsupported_device.drv); |
875 | 880 | ||
876 | cleanup_bus: | 881 | cleanup_bus: |
877 | bus_unregister(&maple_bus_type); | 882 | bus_unregister(&maple_bus_type); |
@@ -880,7 +885,7 @@ cleanup_device: | |||
880 | device_unregister(&maple_bus); | 885 | device_unregister(&maple_bus); |
881 | 886 | ||
882 | cleanup: | 887 | cleanup: |
883 | printk(KERN_INFO "Maple bus registration failed\n"); | 888 | printk(KERN_ERR "Maple bus registration failed\n"); |
884 | return retval; | 889 | return retval; |
885 | } | 890 | } |
886 | /* Push init to later to ensure hardware gets detected */ | 891 | /* Push init to later to ensure hardware gets detected */ |