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

📄 raw1394.c

📁 Armlinux ieee1394接口驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
                        if (copy_from_user(packet->data, int2ptr(req->req.sendb),                                           req->req.length)) {                                req->req.error = RAW1394_ERROR_MEMFAULT;                        }                }                req->req.length = 0;                break;        case RAW1394_REQ_LOCK:                if ((req->req.misc == EXTCODE_FETCH_ADD)                    || (req->req.misc == EXTCODE_LITTLE_ADD)) {                        if (req->req.length != 4) {                                req->req.error = RAW1394_ERROR_INVALID_ARG;                                break;                        }                } else {                        if (req->req.length != 8) {                                req->req.error = RAW1394_ERROR_INVALID_ARG;                                break;                        }                }                packet = hpsb_make_lockpacket(fi->host, node, addr,                                              req->req.misc);                if (!packet) return -ENOMEM;                if (copy_from_user(packet->data, int2ptr(req->req.sendb),                                   req->req.length)) {                        req->req.error = RAW1394_ERROR_MEMFAULT;                        break;                }                req->data = packet->data;                req->req.length = 4;                break;        case RAW1394_REQ_LOCK64:        default:                req->req.error = RAW1394_ERROR_STATE_ORDER;        }        req->packet = packet;        if (req->req.error) {                req->req.length = 0;                queue_complete_req(req);                return sizeof(struct raw1394_request);        }        req->tq.data = req;        queue_task(&req->tq, &packet->complete_tq);        spin_lock_irq(&fi->reqlists_lock);        list_add_tail(&req->list, &fi->req_pending);        spin_unlock_irq(&fi->reqlists_lock);	packet->generation = req->req.generation;        if (!hpsb_send_packet(packet)) {                req->req.error = RAW1394_ERROR_SEND_ERROR;                req->req.length = 0;                free_tlabel(packet->host, packet->node_id, packet->tlabel);                queue_complete_req(req);        }        return sizeof(struct raw1394_request);}static int handle_iso_send(struct file_info *fi, struct pending_request *req,                           int channel){        struct hpsb_packet *packet;        packet = alloc_hpsb_packet(req->req.length);        if (!packet) return -ENOMEM;        req->packet = packet;        fill_iso_packet(packet, req->req.length, channel & 0x3f,                        (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);        packet->type = hpsb_iso;        packet->speed_code = req->req.address & 0x3;        packet->host = fi->host;        if (copy_from_user(packet->data, int2ptr(req->req.sendb),                           req->req.length)) {                req->req.error = RAW1394_ERROR_MEMFAULT;                req->req.length = 0;                queue_complete_req(req);                return sizeof(struct raw1394_request);        }        req->tq.data = req;        req->tq.routine = (void (*)(void*))queue_complete_req;        req->req.length = 0;        queue_task(&req->tq, &packet->complete_tq);        spin_lock_irq(&fi->reqlists_lock);        list_add_tail(&req->list, &fi->req_pending);        spin_unlock_irq(&fi->reqlists_lock);	/* Update the generation of the packet just before sending. */	packet->generation = get_hpsb_generation(fi->host);        if (!hpsb_send_packet(packet)) {                req->req.error = RAW1394_ERROR_SEND_ERROR;                queue_complete_req(req);        }        return sizeof(struct raw1394_request);}static int state_connected(struct file_info *fi, struct pending_request *req){        int node = req->req.address >> 48;        req->req.error = RAW1394_ERROR_NONE;        if (req->req.type ==  RAW1394_REQ_ISO_SEND) {                return handle_iso_send(fi, req, node);        }        if (req->req.generation != get_hpsb_generation(fi->host)) {                req->req.error = RAW1394_ERROR_GENERATION;                req->req.generation = get_hpsb_generation(fi->host);                req->req.length = 0;                queue_complete_req(req);                return sizeof(struct raw1394_request);        }        switch (req->req.type) {        case RAW1394_REQ_ISO_LISTEN:                handle_iso_listen(fi, req);                return sizeof(struct raw1394_request);        case RAW1394_REQ_FCP_LISTEN:                handle_fcp_listen(fi, req);                return sizeof(struct raw1394_request);        case RAW1394_REQ_RESET_BUS:                hpsb_reset_bus(fi->host, LONG_RESET);                return sizeof(struct raw1394_request);        }        if (req->req.length == 0) {                req->req.error = RAW1394_ERROR_INVALID_ARG;                queue_complete_req(req);                return sizeof(struct raw1394_request);        }        if (fi->host->node_id == node) {                return handle_local_request(fi, req, node);        }        return handle_remote_request(fi, req, node);}static ssize_t raw1394_write(struct file *file, const char *buffer, size_t count,                     loff_t *offset_is_ignored){        struct file_info *fi = (struct file_info *)file->private_data;        struct pending_request *req;        ssize_t retval = 0;        if (count != sizeof(struct raw1394_request)) {                return -EINVAL;        }        req = alloc_pending_request();        if (req == NULL) {                return -ENOMEM;        }        req->file_info = fi;        if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {                free_pending_request(req);                return -EFAULT;        }        switch (fi->state) {        case opened:                retval = state_opened(fi, req);                break;        case initialized:                retval = state_initialized(fi, req);                break;        case connected:                retval = state_connected(fi, req);                break;        }        if (retval < 0) {                free_pending_request(req);        }        return retval;}static unsigned int raw1394_poll(struct file *file, poll_table *pt){        struct file_info *fi = file->private_data;        unsigned int mask = POLLOUT | POLLWRNORM;        poll_wait(file, &fi->poll_wait_complete, pt);        spin_lock_irq(&fi->reqlists_lock);        if (!list_empty(&fi->req_complete)) {                mask |= POLLIN | POLLRDNORM;        }        spin_unlock_irq(&fi->reqlists_lock);        return mask;}static int raw1394_open(struct inode *inode, struct file *file){        struct file_info *fi;        if (MINOR(inode->i_rdev)) {                return -ENXIO;        }        V22_COMPAT_MOD_INC_USE_COUNT;        fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);        if (fi == NULL) {                V22_COMPAT_MOD_DEC_USE_COUNT;                return -ENOMEM;        }                memset(fi, 0, sizeof(struct file_info));        INIT_LIST_HEAD(&fi->list);        fi->state = opened;        INIT_LIST_HEAD(&fi->req_pending);        INIT_LIST_HEAD(&fi->req_complete);        sema_init(&fi->complete_sem, 0);        spin_lock_init(&fi->reqlists_lock);        init_waitqueue_head(&fi->poll_wait_complete);        file->private_data = fi;        return 0;}static int raw1394_release(struct inode *inode, struct file *file){        struct file_info *fi = file->private_data;        struct list_head *lh;        struct pending_request *req;        int done = 0, i;        lock_kernel();        for (i = 0; i < 64; i++) {                if (fi->listen_channels & (1ULL << i)) {                        hpsb_unlisten_channel(hl_handle, fi->host, i);                }        }        spin_lock(&host_info_lock);        fi->listen_channels = 0;        spin_unlock(&host_info_lock);        while (!done) {                spin_lock_irq(&fi->reqlists_lock);                while (!list_empty(&fi->req_complete)) {                        lh = fi->req_complete.next;                        list_del(lh);                        req = list_entry(lh, struct pending_request, list);                        free_pending_request(req);                }                if (list_empty(&fi->req_pending)) done = 1;                spin_unlock_irq(&fi->reqlists_lock);                if (!done) down_interruptible(&fi->complete_sem);        }        if (fi->state == connected) {                spin_lock_irq(&host_info_lock);                list_del(&fi->list);                spin_unlock_irq(&host_info_lock);                hpsb_dec_host_usage(fi->host);        }        kfree(fi);        V22_COMPAT_MOD_DEC_USE_COUNT;        unlock_kernel();        return 0;}static struct hpsb_highlevel_ops hl_ops = {        add_host:     add_host,        remove_host:  remove_host,        host_reset:   host_reset,        iso_receive:  iso_receive,        fcp_request:  fcp_request,};static struct file_operations file_ops = {        OWNER_THIS_MODULE        read:     raw1394_read,         write:    raw1394_write,         poll:     raw1394_poll,         open:     raw1394_open,         release:  raw1394_release, };static int __init init_raw1394(void){        hl_handle = hpsb_register_highlevel(RAW1394_DEVICE_NAME, &hl_ops);        if (hl_handle == NULL) {                HPSB_ERR("raw1394 failed to register with ieee1394 highlevel");                return -ENOMEM;        }	devfs_handle = devfs_register(NULL, RAW1394_DEVICE_NAME, DEVFS_FL_NONE,                                      RAW1394_DEVICE_MAJOR, 0,                                      S_IFCHR | S_IRUSR | S_IWUSR, &file_ops,                                      NULL);        if (devfs_register_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME,                                   &file_ops)) {                HPSB_ERR("raw1394 failed to register /dev/raw1394 device");                return -EBUSY;        }	printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME);        return 0;}static void __exit cleanup_raw1394(void){        devfs_unregister_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME);	devfs_unregister(devfs_handle);        hpsb_unregister_highlevel(hl_handle);}module_init(init_raw1394);module_exit(cleanup_raw1394);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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