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

📄 ftdi-elan.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        return result;}static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi){        mutex_lock(&ftdi->u132_lock);        while (ftdi->respond_next > ftdi->respond_head) {                struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &                        ftdi->respond_head++];                *respond->result = -ESHUTDOWN;                *respond->value = 0;                complete(&respond->wait_completion);        } mutex_unlock(&ftdi->u132_lock);}static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi){        int ed_number = 4;        mutex_lock(&ftdi->u132_lock);        while (ed_number-- > 0) {                struct u132_target *target = &ftdi->target[ed_number];                if (target->active == 1) {                        target->condition_code = TD_DEVNOTRESP;                        mutex_unlock(&ftdi->u132_lock);                        ftdi_elan_do_callback(ftdi, target, NULL, 0);                        mutex_lock(&ftdi->u132_lock);                }        }        ftdi->recieved = 0;        ftdi->expected = 4;        ftdi->ed_found = 0;        mutex_unlock(&ftdi->u132_lock);}static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi){        int ed_number = 4;        mutex_lock(&ftdi->u132_lock);        while (ed_number-- > 0) {                struct u132_target *target = &ftdi->target[ed_number];                target->abandoning = 1;              wait_1:if (target->active == 1) {                        int command_size = ftdi->command_next -                                ftdi->command_head;                        if (command_size < COMMAND_SIZE) {                                struct u132_command *command = &ftdi->command[                                        COMMAND_MASK & ftdi->command_next];                                command->header = 0x80 | (ed_number << 5) | 0x4;                                command->length = 0x00;                                command->address = 0x00;                                command->width = 0x00;                                command->follows = 0;                                command->value = 0;                                command->buffer = &command->value;                                ftdi->command_next += 1;                                ftdi_elan_kick_command_queue(ftdi);                        } else {                                mutex_unlock(&ftdi->u132_lock);                                msleep(100);                                mutex_lock(&ftdi->u132_lock);                                goto wait_1;                        }                }              wait_2:if (target->active == 1) {                        int command_size = ftdi->command_next -                                ftdi->command_head;                        if (command_size < COMMAND_SIZE) {                                struct u132_command *command = &ftdi->command[                                        COMMAND_MASK & ftdi->command_next];                                command->header = 0x90 | (ed_number << 5);                                command->length = 0x00;                                command->address = 0x00;                                command->width = 0x00;                                command->follows = 0;                                command->value = 0;                                command->buffer = &command->value;                                ftdi->command_next += 1;                                ftdi_elan_kick_command_queue(ftdi);                        } else {                                mutex_unlock(&ftdi->u132_lock);                                msleep(100);                                mutex_lock(&ftdi->u132_lock);                                goto wait_2;                        }                }        }        ftdi->recieved = 0;        ftdi->expected = 4;        ftdi->ed_found = 0;        mutex_unlock(&ftdi->u132_lock);}static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi){        int ed_number = 4;        mutex_lock(&ftdi->u132_lock);        while (ed_number-- > 0) {                struct u132_target *target = &ftdi->target[ed_number];                target->abandoning = 1;              wait:if (target->active == 1) {                        int command_size = ftdi->command_next -                                ftdi->command_head;                        if (command_size < COMMAND_SIZE) {                                struct u132_command *command = &ftdi->command[                                        COMMAND_MASK & ftdi->command_next];                                command->header = 0x80 | (ed_number << 5) | 0x4;                                command->length = 0x00;                                command->address = 0x00;                                command->width = 0x00;                                command->follows = 0;                                command->value = 0;                                command->buffer = &command->value;                                ftdi->command_next += 1;                                ftdi_elan_kick_command_queue(ftdi);                        } else {                                mutex_unlock(&ftdi->u132_lock);                                msleep(100);                                mutex_lock(&ftdi->u132_lock);                                goto wait;                        }                }        }        ftdi->recieved = 0;        ftdi->expected = 4;        ftdi->ed_found = 0;        mutex_unlock(&ftdi->u132_lock);}static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi){        ftdi_command_queue_work(ftdi, 0);        return;}static void ftdi_elan_command_work(struct work_struct *work){        struct usb_ftdi *ftdi =		container_of(work, struct usb_ftdi, command_work.work);        if (ftdi->disconnected > 0) {                ftdi_elan_put_kref(ftdi);                return;        } else {                int retval = ftdi_elan_command_engine(ftdi);                if (retval == -ESHUTDOWN) {                        ftdi->disconnected += 1;                } else if (retval == -ENODEV) {                        ftdi->disconnected += 1;                } else if (retval)                        dev_err(&ftdi->udev->dev, "command error %d\n", retval);                ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10));                return;        }}static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi){        ftdi_respond_queue_work(ftdi, 0);        return;}static void ftdi_elan_respond_work(struct work_struct *work){        struct usb_ftdi *ftdi =		container_of(work, struct usb_ftdi, respond_work.work);        if (ftdi->disconnected > 0) {                ftdi_elan_put_kref(ftdi);                return;        } else {                int retval = ftdi_elan_respond_engine(ftdi);                if (retval == 0) {                } else if (retval == -ESHUTDOWN) {                        ftdi->disconnected += 1;                } else if (retval == -ENODEV) {                        ftdi->disconnected += 1;                } else if (retval == -EILSEQ) {                        ftdi->disconnected += 1;                } else {                        ftdi->disconnected += 1;                        dev_err(&ftdi->udev->dev, "respond error %d\n", retval);                }                if (ftdi->disconnected > 0) {                        ftdi_elan_abandon_completions(ftdi);                        ftdi_elan_abandon_targets(ftdi);                }                ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10));                return;        }}/** the sw_lock is initially held and will be freed* after the FTDI has been synchronized**/static void ftdi_elan_status_work(struct work_struct *work){        struct usb_ftdi *ftdi =		container_of(work, struct usb_ftdi, status_work.work);        int work_delay_in_msec = 0;        if (ftdi->disconnected > 0) {                ftdi_elan_put_kref(ftdi);                return;        } else if (ftdi->synchronized == 0) {                down(&ftdi->sw_lock);                if (ftdi_elan_synchronize(ftdi) == 0) {                        ftdi->synchronized = 1;                        ftdi_command_queue_work(ftdi, 1);                        ftdi_respond_queue_work(ftdi, 1);                        up(&ftdi->sw_lock);                        work_delay_in_msec = 100;                } else {                        dev_err(&ftdi->udev->dev, "synchronize failed\n");                        up(&ftdi->sw_lock);                        work_delay_in_msec = 10 *1000;                }        } else if (ftdi->stuck_status > 0) {                if (ftdi_elan_stuck_waiting(ftdi) == 0) {                        ftdi->stuck_status = 0;                        ftdi->synchronized = 0;                } else if ((ftdi->stuck_status++ % 60) == 1) {                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "                                "- please remove\n");                } else                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "                                "- checked %d times\n", ftdi->stuck_status);                work_delay_in_msec = 100;        } else if (ftdi->enumerated == 0) {                if (ftdi_elan_enumeratePCI(ftdi) == 0) {                        ftdi->enumerated = 1;                        work_delay_in_msec = 250;                } else                        work_delay_in_msec = 1000;        } else if (ftdi->initialized == 0) {                if (ftdi_elan_setupOHCI(ftdi) == 0) {                        ftdi->initialized = 1;                        work_delay_in_msec = 500;                } else {                        dev_err(&ftdi->udev->dev, "initialized failed - trying "                                "again in 10 seconds\n");                        work_delay_in_msec = 1 *1000;                }        } else if (ftdi->registered == 0) {                work_delay_in_msec = 10;                if (ftdi_elan_hcd_init(ftdi) == 0) {                        ftdi->registered = 1;                } else                        dev_err(&ftdi->udev->dev, "register failed\n");                work_delay_in_msec = 250;        } else {                if (ftdi_elan_checkingPCI(ftdi) == 0) {                        work_delay_in_msec = 250;                } else if (ftdi->controlreg & 0x00400000) {                        if (ftdi->gone_away > 0) {                                dev_err(&ftdi->udev->dev, "PCI device eject con"                                        "firmed platform_dev.dev.parent=%p plat"                                        "form_dev.dev=%p\n",                                        ftdi->platform_dev.dev.parent,                                        &ftdi->platform_dev.dev);                                platform_device_unregister(&ftdi->platform_dev);                                ftdi->platform_dev.dev.parent = NULL;                                ftdi->registered = 0;                                ftdi->enumerated = 0;                                ftdi->card_ejected = 0;                                ftdi->initialized = 0;                                ftdi->gone_away = 0;                        } else                                ftdi_elan_flush_targets(ftdi);                        work_delay_in_msec = 250;                } else {                        dev_err(&ftdi->udev->dev, "PCI device has disappeared\n"                                );                        ftdi_elan_cancel_targets(ftdi);                        work_delay_in_msec = 500;                        ftdi->enumerated = 0;                        ftdi->initialized = 0;                }        }        if (ftdi->disconnected > 0) {                ftdi_elan_put_kref(ftdi);                return;        } else {                ftdi_status_requeue_work(ftdi,                        msecs_to_jiffies(work_delay_in_msec));                return;        }}/** file_operations for the jtag interface** the usage count for the device is incremented on open()* and decremented on release()*/static int ftdi_elan_open(struct inode *inode, struct file *file){        int subminor = iminor(inode);        struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver,                subminor);        if (!interface) {                printk(KERN_ERR "can't find device for minor %d\n", subminor);                return -ENODEV;        } else {                struct usb_ftdi *ftdi = usb_get_intfdata(interface);                if (!ftdi) {                        return -ENODEV;                } else {                        if (down_interruptible(&ftdi->sw_lock)) {                                return -EINTR;                        } else {                                ftdi_elan_get_kref(ftdi);                                file->private_data = ftdi;                                return 0;                        }                }        }}static int ftdi_elan_release(struct inode *inode, struct file *file){        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;        if (ftdi == NULL)                return -ENODEV;        up(&ftdi->sw_lock);        /* decrement the count on our device */        ftdi_elan_put_kref(ftdi);

⌨️ 快捷键说明

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