⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maple.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
                       maple_add_packet(maple_dev->mq);                       liststatus++;               }       }       return 0;}/* VBLANK bottom half - implemented via workqueue */static void maple_vblank_handler(struct work_struct *work){       if (!maple_dma_done())               return;       if (!list_empty(&maple_sentq))               return;       ctrl_outl(0, MAPLE_ENABLE);       liststatus = 0;       bus_for_each_dev(&maple_bus_type, NULL, NULL,                        setup_maple_commands);       if (time_after(jiffies, maple_pnp_time))               maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL;       if (liststatus && list_empty(&maple_sentq)) {               INIT_LIST_HEAD(&maple_sentq);               maple_send();       }       maplebus_dma_reset();}/* handle devices added via hotplugs - placing them on queue for DEVINFO*/static void maple_map_subunits(struct maple_device *mdev, int submask){       int retval, k, devcheck;       struct maple_device *mdev_add;       struct maple_device_specify ds;       for (k = 0; k < 5; k++) {               ds.port = mdev->port;               ds.unit = k + 1;               retval =                   bus_for_each_dev(&maple_bus_type, NULL, &ds,                                    detach_maple_device);               if (retval) {                       submask = submask >> 1;                       continue;               }               devcheck = submask & 0x01;               if (devcheck) {                       mdev_add = maple_alloc_dev(mdev->port, k + 1);                       if (!mdev_add)                               return;                       mdev_add->mq->command = MAPLE_COMMAND_DEVINFO;                       mdev_add->mq->length = 0;                       maple_add_packet(mdev_add->mq);                       scanning = 1;               }               submask = submask >> 1;       }}/* mark a device as removed */static void maple_clean_submap(struct maple_device *mdev){       int killbit;       killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20);       killbit = ~killbit;       killbit &= 0xFF;       subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit;}/* handle empty port or hotplug removal */static void maple_response_none(struct maple_device *mdev,                               struct mapleq *mq){       if (mdev->unit != 0) {               list_del(&mq->list);               maple_clean_submap(mdev);               printk(KERN_INFO                      "Maple bus device detaching at (%d, %d)\n",                      mdev->port, mdev->unit);               maple_detach_driver(mdev);               return;       }       if (!started) {               printk(KERN_INFO "No maple devices attached to port %d\n",                      mdev->port);               return;       }       maple_clean_submap(mdev);}/* preprocess hotplugs or scans */static void maple_response_devinfo(struct maple_device *mdev,                                  char *recvbuf){       char submask;       if ((!started) || (scanning == 2)) {               maple_attach_driver(mdev);               return;       }       if (mdev->unit == 0) {               submask = recvbuf[2] & 0x1F;               if (submask ^ subdevice_map[mdev->port]) {                       maple_map_subunits(mdev, submask);                       subdevice_map[mdev->port] = submask;               }       }}/* maple dma end bottom half - implemented via workqueue */static void maple_dma_handler(struct work_struct *work){       struct mapleq *mq, *nmq;       struct maple_device *dev;       char *recvbuf;       enum maple_code code;       if (!maple_dma_done())               return;       ctrl_outl(0, MAPLE_ENABLE);       if (!list_empty(&maple_sentq)) {               list_for_each_entry_safe(mq, nmq, &maple_sentq, list) {                       recvbuf = mq->recvbuf;                       code = recvbuf[0];                       dev = mq->dev;                       switch (code) {                       case MAPLE_RESPONSE_NONE:                               maple_response_none(dev, mq);                               break;                       case MAPLE_RESPONSE_DEVINFO:                               maple_response_devinfo(dev, recvbuf);                               break;                       case MAPLE_RESPONSE_DATATRF:                               if (dev->callback)                                       dev->callback(mq);                               break;                       case MAPLE_RESPONSE_FILEERR:                       case MAPLE_RESPONSE_AGAIN:                       case MAPLE_RESPONSE_BADCMD:                       case MAPLE_RESPONSE_BADFUNC:                               printk(KERN_DEBUG                                      "Maple non-fatal error 0x%X\n",                                      code);                               break;                       case MAPLE_RESPONSE_ALLINFO:                               printk(KERN_DEBUG                                      "Maple - extended device information not supported\n");                               break;                       case MAPLE_RESPONSE_OK:                               break;                       default:                               break;                       }               }               INIT_LIST_HEAD(&maple_sentq);               if (scanning == 1) {                       maple_send();                       scanning = 2;               } else                       scanning = 0;               if (started == 0)                       started = 1;       }       maplebus_dma_reset();}static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id){       /* Load everything into the bottom half */       schedule_work(&maple_dma_process);       return IRQ_HANDLED;}static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id){       schedule_work(&maple_vblank_process);       return IRQ_HANDLED;}static struct irqaction maple_dma_irq = {       .name = "maple bus DMA handler",       .handler = maplebus_dma_interrupt,       .flags = IRQF_SHARED,};static struct irqaction maple_vblank_irq = {       .name = "maple bus VBLANK handler",       .handler = maplebus_vblank_interrupt,       .flags = IRQF_SHARED,};static int maple_set_dma_interrupt_handler(void){       return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq);}static int maple_set_vblank_interrupt_handler(void){       return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq);}static int maple_get_dma_buffer(void){       maple_sendbuf =           (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,                                     MAPLE_DMA_PAGES);       if (!maple_sendbuf)               return -ENOMEM;       return 0;}static int match_maple_bus_driver(struct device *devptr,                                 struct device_driver *drvptr){       struct maple_driver *maple_drv;       struct maple_device *maple_dev;       maple_drv = container_of(drvptr, struct maple_driver, drv);       maple_dev = container_of(devptr, struct maple_device, dev);       /* Trap empty port case */       if (maple_dev->devinfo.function == 0xFFFFFFFF)               return 0;       else if (maple_dev->devinfo.function &                be32_to_cpu(maple_drv->function))               return 1;       return 0;}static int maple_bus_uevent(struct device *dev, struct kobj_uevent_env *env){       return 0;}static void maple_bus_release(struct device *dev){}static struct maple_driver maple_dummy_driver = {       .drv = {               .name = "maple_dummy_driver",               .bus =  &maple_bus_type,       },};struct bus_type maple_bus_type = {       .name =         "maple",       .match =        match_maple_bus_driver,       .uevent =       maple_bus_uevent,};EXPORT_SYMBOL_GPL(maple_bus_type);static struct device maple_bus = {       .bus_id = "maple",       .release = maple_bus_release,};static int __init maple_bus_init(void){       int retval, i;       struct maple_device *mdev[MAPLE_PORTS];       ctrl_outl(0, MAPLE_STATE);       retval = device_register(&maple_bus);       if (retval)               goto cleanup;       retval = bus_register(&maple_bus_type);       if (retval)               goto cleanup_device;       retval = driver_register(&maple_dummy_driver.drv);       if (retval)               goto cleanup_bus;       /* allocate memory for maple bus dma */       retval = maple_get_dma_buffer();       if (retval) {               printk(KERN_INFO                      "Maple bus: Failed to allocate Maple DMA buffers\n");               goto cleanup_basic;       }       /* set up DMA interrupt handler */       retval = maple_set_dma_interrupt_handler();       if (retval) {               printk(KERN_INFO                      "Maple bus: Failed to grab maple DMA IRQ\n");               goto cleanup_dma;       }       /* set up VBLANK interrupt handler */       retval = maple_set_vblank_interrupt_handler();       if (retval) {               printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n");               goto cleanup_irq;       }       maple_queue_cache =           kmem_cache_create("maple_queue_cache", 0x400, 0,                             SLAB_HWCACHE_ALIGN, NULL);       if (!maple_queue_cache)               goto cleanup_bothirqs;       /* setup maple ports */       for (i = 0; i < MAPLE_PORTS; i++) {               mdev[i] = maple_alloc_dev(i, 0);               if (!mdev[i]) {                       while (i-- > 0)                               maple_free_dev(mdev[i]);                       goto cleanup_cache;               }               mdev[i]->registered = 0;               mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO;               mdev[i]->mq->length = 0;               maple_attach_driver(mdev[i]);               maple_add_packet(mdev[i]->mq);               subdevice_map[i] = 0;       }       /* setup maplebus hardware */       maplebus_dma_reset();       /* initial detection */       maple_send();       maple_pnp_time = jiffies;       printk(KERN_INFO "Maple bus core now registered.\n");       return 0;cleanup_cache:       kmem_cache_destroy(maple_queue_cache);cleanup_bothirqs:       free_irq(HW_EVENT_VSYNC, 0);cleanup_irq:       free_irq(HW_EVENT_MAPLE_DMA, 0);cleanup_dma:       free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);cleanup_basic:       driver_unregister(&maple_dummy_driver.drv);cleanup_bus:       bus_unregister(&maple_bus_type);cleanup_device:       device_unregister(&maple_bus);cleanup:       printk(KERN_INFO "Maple bus registration failed\n");       return retval;}subsys_initcall(maple_bus_init);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -