Lines Matching +full:half +full:- +full:bus
2 * Core maple bus functionality
4 * Copyright (C) 2007 - 2009 Adrian McMenamin
5 * Copyright (C) 2001 - 2008 Paul Mundt
6 * Copyright (C) 2000 - 2001 YAEGASHI Takeshi
21 #include <linux/dma-mapping.h>
31 MODULE_DESCRIPTION("Maple bus driver for Dreamcast");
65 * maple_driver_register - register a maple driver
68 * Registers the passed in @drv, while updating the bus type.
74 return -EINVAL; in maple_driver_register()
76 drv->drv.bus = &maple_bus_type; in maple_driver_register()
78 return driver_register(&drv->drv); in maple_driver_register()
83 * maple_driver_unregister - unregister a maple driver.
91 driver_unregister(&drv->drv); in maple_driver_unregister()
103 * bits 31 - 16 timeout in units of 20nsec in maple_dma_reset()
104 * bit 12 hard trigger - set 0 to keep responding to VBLANK in maple_dma_reset()
105 * bits 9 - 8 set 00 for 2 Mbps, 01 for 1 Mbps in maple_dma_reset()
106 * bits 3 - 0 delay (in 1.3ms) between VBLANK and start of DMA in maple_dma_reset()
115 * maple_getcond_callback - setup handling MAPLE_COMMAND_GETCOND
125 dev->callback = callback; in maple_getcond_callback()
126 dev->interval = interval; in maple_getcond_callback()
127 dev->function = cpu_to_be32(function); in maple_getcond_callback()
128 dev->when = jiffies; in maple_getcond_callback()
143 mq = mdev->mq; in maple_release_device()
144 kmem_cache_free(maple_queue_cache, mq->recvbuf); in maple_release_device()
150 * maple_add_packet - add a single instruction to the maple bus queue
166 ret = -ENOMEM; in maple_add_packet()
172 mdev->mq->command = command; in maple_add_packet()
173 mdev->mq->length = length; in maple_add_packet()
175 memcpy(sendbuf + 4, data, (length - 1) * 4); in maple_add_packet()
176 mdev->mq->sendbuf = sendbuf; in maple_add_packet()
179 list_add_tail(&mdev->mq->list, &maple_waitq); in maple_add_packet()
194 INIT_LIST_HEAD(&mq->list); in maple_allocq()
195 mq->dev = mdev; in maple_allocq()
196 mq->recvbuf = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); in maple_allocq()
197 if (!mq->recvbuf) in maple_allocq()
199 mq->recvbuf->buf = &((mq->recvbuf->bufx)[0]); in maple_allocq()
206 dev_err(&mdev->dev, "could not allocate memory for device (%d, %d)\n", in maple_allocq()
207 mdev->port, mdev->unit); in maple_allocq()
222 mdev->port = port; in maple_alloc_dev()
223 mdev->unit = unit; in maple_alloc_dev()
225 mdev->mq = maple_allocq(mdev); in maple_alloc_dev()
227 if (!mdev->mq) { in maple_alloc_dev()
231 mdev->dev.bus = &maple_bus_type; in maple_alloc_dev()
232 mdev->dev.parent = &maple_bus; in maple_alloc_dev()
233 init_waitqueue_head(&mdev->maple_wait); in maple_alloc_dev()
239 kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf); in maple_free_dev()
240 kfree(mdev->mq); in maple_free_dev()
250 unsigned long *lsendbuf = mq->sendbuf; in maple_build_block()
252 port = mq->dev->port & 3; in maple_build_block()
253 unit = mq->dev->unit; in maple_build_block()
254 len = mq->length; in maple_build_block()
256 to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20); in maple_build_block()
262 *maple_sendptr++ = virt_to_phys(mq->recvbuf->buf); in maple_build_block()
264 mq->command | (to << 8) | (from << 16) | (len << 24); in maple_build_block()
265 while (len-- > 0) in maple_build_block()
295 list_del_init(&mq->list); in maple_send()
296 list_add_tail(&mq->list, &maple_sentq); in maple_send()
320 if (mdev->devinfo.function & cpu_to_be32(maple_drv->function)) in maple_check_matching_driver()
327 device_unregister(&mdev->dev); in maple_detach_driver()
337 recvbuf = mdev->mq->recvbuf->buf; in maple_attach_driver()
340 memcpy(&mdev->devinfo.function, recvbuf + 4, 4); in maple_attach_driver()
341 memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12); in maple_attach_driver()
342 memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); in maple_attach_driver()
343 memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); in maple_attach_driver()
344 memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); in maple_attach_driver()
345 memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); in maple_attach_driver()
346 memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); in maple_attach_driver()
347 memcpy(mdev->product_name, mdev->devinfo.product_name, 30); in maple_attach_driver()
348 mdev->product_name[30] = '\0'; in maple_attach_driver()
349 memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60); in maple_attach_driver()
350 mdev->product_licence[60] = '\0'; in maple_attach_driver()
352 for (p = mdev->product_name + 29; mdev->product_name <= p; p--) in maple_attach_driver()
357 for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--) in maple_attach_driver()
363 function = be32_to_cpu(mdev->devinfo.function); in maple_attach_driver()
365 dev_info(&mdev->dev, "detected %s: function 0x%lX: at (%d, %d)\n", in maple_attach_driver()
366 mdev->product_name, function, mdev->port, mdev->unit); in maple_attach_driver()
369 /* Do this silently - as not a real device */ in maple_attach_driver()
371 mdev->driver = &maple_unsupported_device; in maple_attach_driver()
372 dev_set_name(&mdev->dev, "%d:0.port", mdev->port); in maple_attach_driver()
380 dev_info(&mdev->dev, "no driver found\n"); in maple_attach_driver()
381 mdev->driver = &maple_unsupported_device; in maple_attach_driver()
383 dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, in maple_attach_driver()
384 mdev->unit, function); in maple_attach_driver()
387 mdev->function = function; in maple_attach_driver()
388 mdev->dev.release = &maple_release_device; in maple_attach_driver()
390 atomic_set(&mdev->busy, 0); in maple_attach_driver()
391 error = device_register(&mdev->dev); in maple_attach_driver()
393 dev_warn(&mdev->dev, "could not register device at" in maple_attach_driver()
394 " (%d, %d), with error 0x%X\n", mdev->unit, in maple_attach_driver()
395 mdev->port, error); in maple_attach_driver()
404 * port and unit then return 1 - allows identification
414 if (mdev->port == ds->port && mdev->unit == ds->unit) in check_maple_device()
423 if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 && in setup_maple_commands()
424 time_after(jiffies, mdev->when)) { in setup_maple_commands()
427 be32_to_cpu(mdev->devinfo.function), in setup_maple_commands()
430 mdev->when = jiffies + mdev->interval; in setup_maple_commands()
434 * calls interfering with one another - so flag the in setup_maple_commands()
436 if (atomic_read(&mdev->busy) == 0) { in setup_maple_commands()
437 atomic_set(&mdev->busy, 1); in setup_maple_commands()
445 /* VBLANK bottom half - implemented via workqueue */
460 * Set up essential commands - to fetch data and in maple_vblank_handler()
468 * Scan the empty ports - bus is flakey and may have in maple_vblank_handler()
469 * mis-reported emptyness in maple_vblank_handler()
476 atomic_set(&mdev->busy, 1); in maple_vblank_handler()
491 /* handle devices added via hotplugs - placing them on queue for DEVINFO */
498 ds.port = mdev->port; in maple_map_subunits()
510 mdev_add = maple_alloc_dev(mdev->port, k + 1); in maple_map_subunits()
513 atomic_set(&mdev_add->busy, 1); in maple_map_subunits()
528 killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20); in maple_clean_submap()
531 subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit; in maple_clean_submap()
539 if (likely(mdev->unit != 0)) { in maple_response_none()
545 * really gone - this code traps that eventuality in maple_response_none()
549 if (mdev->can_unload) { in maple_response_none()
550 if (!mdev->can_unload(mdev)) { in maple_response_none()
551 atomic_set(&mdev->busy, 2); in maple_response_none()
552 wake_up(&mdev->maple_wait); in maple_response_none()
557 dev_info(&mdev->dev, "detaching device at (%d, %d)\n", in maple_response_none()
558 mdev->port, mdev->unit); in maple_response_none()
563 if (checked[mdev->port] == false) { in maple_response_none()
564 checked[mdev->port] = true; in maple_response_none()
565 empty[mdev->port] = true; in maple_response_none()
566 dev_info(&mdev->dev, "no devices" in maple_response_none()
567 " to port %d\n", mdev->port); in maple_response_none()
573 atomic_set(&mdev->busy, 0); in maple_response_none()
582 if ((mdev->unit == 0) && (checked[mdev->port] == false)) { in maple_response_devinfo()
583 checked[mdev->port] = true; in maple_response_devinfo()
586 if (mdev->unit != 0) in maple_response_devinfo()
588 if (mdev->unit == 0) { in maple_response_devinfo()
589 empty[mdev->port] = false; in maple_response_devinfo()
594 if (mdev->unit == 0) { in maple_response_devinfo()
596 if (submask ^ subdevice_map[mdev->port]) { in maple_response_devinfo()
598 subdevice_map[mdev->port] = submask; in maple_response_devinfo()
605 if (mdev->fileerr_handler) { in maple_response_fileerr()
606 mdev->fileerr_handler(mdev, recvbuf); in maple_response_fileerr()
609 dev_warn(&mdev->dev, "device at (%d, %d) reports" in maple_response_fileerr()
610 "file error 0x%X\n", mdev->port, mdev->unit, in maple_response_fileerr()
630 /* maple dma end bottom half - implemented via workqueue */
643 mdev = mq->dev; in maple_dma_handler()
644 recvbuf = mq->recvbuf->buf; in maple_dma_handler()
648 kfree(mq->sendbuf); in maple_dma_handler()
649 list_del_init(&mq->list); in maple_dma_handler()
657 atomic_set(&mdev->busy, 0); in maple_dma_handler()
661 if (mdev->callback) in maple_dma_handler()
662 mdev->callback(mq); in maple_dma_handler()
663 atomic_set(&mdev->busy, 0); in maple_dma_handler()
664 wake_up(&mdev->maple_wait); in maple_dma_handler()
669 atomic_set(&mdev->busy, 0); in maple_dma_handler()
670 wake_up(&mdev->maple_wait); in maple_dma_handler()
676 dev_warn(&mdev->dev, "non-fatal error" in maple_dma_handler()
678 mdev->port, mdev->unit); in maple_dma_handler()
679 atomic_set(&mdev->busy, 0); in maple_dma_handler()
683 dev_notice(&mdev->dev, "extended" in maple_dma_handler()
685 " but call is not supported\n", mdev->port, in maple_dma_handler()
686 mdev->unit); in maple_dma_handler()
687 atomic_set(&mdev->busy, 0); in maple_dma_handler()
691 atomic_set(&mdev->busy, 0); in maple_dma_handler()
692 wake_up(&mdev->maple_wait); in maple_dma_handler()
716 /* Load everything into the bottom half */ in maple_dma_interrupt()
730 IRQF_SHARED, "maple bus DMA", &maple_unsupported_device); in maple_set_dma_interrupt_handler()
736 IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device); in maple_set_vblank_interrupt_handler()
745 return -ENOMEM; in maple_get_dma_buffer()
756 if (maple_dev->devinfo.function == 0xFFFFFFFF) in maple_match_bus_driver()
758 else if (maple_dev->devinfo.function & in maple_match_bus_driver()
759 cpu_to_be32(maple_drv->function)) in maple_match_bus_driver()
771 .bus = &maple_bus_type,
775 * maple_bus_type - core maple bus structure
806 /* allocate memory for maple bus dma */ in maple_bus_init()
816 dev_err(&maple_bus, "bus failed to grab maple " in maple_bus_init()
824 dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n"); in maple_bus_init()
831 retval = -ENOMEM; in maple_bus_init()
844 while (i-- > 0) in maple_bus_init()
846 retval = -ENOMEM; in maple_bus_init()
850 atomic_set(&mdev[i]->busy, 1); in maple_bus_init()
858 dev_info(&maple_bus, "bus core now registered\n"); in maple_bus_init()
884 printk(KERN_ERR "Maple bus registration failed\n"); in maple_bus_init()