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

📄 raw1394.c

📁 Armlinux ieee1394接口驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
                        req->data = ibs->data;                        req->req.type = RAW1394_REQ_FCP_REQUEST;                        req->req.generation = get_hpsb_generation(host);                        req->req.misc = nodeid | (direction << 16);                        req->req.recvb = ptr2int(fi->fcp_buffer);                        req->req.length = length;                                                list_add_tail(&req->list, &reqs);                }        }        spin_unlock_irqrestore(&host_info_lock, flags);        lh = reqs.next;        while (lh != &reqs) {                req = list_entry(lh, struct pending_request, list);                lh = lh->next;                queue_complete_req(req);        }}static ssize_t raw1394_read(struct file *file, char *buffer, size_t count,                    loff_t *offset_is_ignored){        struct file_info *fi = (struct file_info *)file->private_data;        struct list_head *lh;        struct pending_request *req;        if (count != sizeof(struct raw1394_request)) {                return -EINVAL;        }        if (!access_ok(VERIFY_WRITE, buffer, count)) {                return -EFAULT;        }        if (file->f_flags & O_NONBLOCK) {                if (down_trylock(&fi->complete_sem)) {                        return -EAGAIN;                }        } else {                if (down_interruptible(&fi->complete_sem)) {                        return -ERESTARTSYS;                }        }        spin_lock_irq(&fi->reqlists_lock);        lh = fi->req_complete.next;        list_del(lh);        spin_unlock_irq(&fi->reqlists_lock);        req = list_entry(lh, struct pending_request, list);        if (req->req.length) {                if (copy_to_user(int2ptr(req->req.recvb), req->data,                                 req->req.length)) {                        req->req.error = RAW1394_ERROR_MEMFAULT;                }        }        __copy_to_user(buffer, &req->req, sizeof(req->req));        free_pending_request(req);        return sizeof(struct raw1394_request);}static int state_opened(struct file_info *fi, struct pending_request *req){        if (req->req.type == RAW1394_REQ_INITIALIZE) {                switch (req->req.misc) {                case RAW1394_KERNELAPI_VERSION:                case 3:                        fi->state = initialized;                        fi->protocol_version = req->req.misc;                        req->req.error = RAW1394_ERROR_NONE;                        req->req.generation = atomic_read(&internal_generation);                        break;                default:                        req->req.error = RAW1394_ERROR_COMPAT;                        req->req.misc = RAW1394_KERNELAPI_VERSION;                }        } else {                req->req.error = RAW1394_ERROR_STATE_ORDER;        }        req->req.length = 0;        queue_complete_req(req);        return sizeof(struct raw1394_request);}static int state_initialized(struct file_info *fi, struct pending_request *req){        struct list_head *lh;        struct host_info *hi;        struct raw1394_khost_list *khl;        if (req->req.generation != atomic_read(&internal_generation)) {                req->req.error = RAW1394_ERROR_GENERATION;                req->req.generation = atomic_read(&internal_generation);                req->req.length = 0;                queue_complete_req(req);                return sizeof(struct raw1394_request);        }        switch (req->req.type) {        case RAW1394_REQ_LIST_CARDS:                spin_lock_irq(&host_info_lock);                khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,                              SLAB_ATOMIC);                if (khl != NULL) {                        req->req.misc = host_count;                        req->data = (quadlet_t *)khl;                                                list_for_each(lh, &host_info_list) {                                hi = list_entry(lh, struct host_info, list);                                khl->nodes = hi->host->node_count;                                strcpy(khl->name, hi->host->template->name);                                khl++;                        }                }                spin_unlock_irq(&host_info_lock);                if (khl != NULL) {                        req->req.error = RAW1394_ERROR_NONE;                        req->req.length = MIN(req->req.length,                                              sizeof(struct raw1394_khost_list)                                              * req->req.misc);                        req->free_data = 1;                } else {                        return -ENOMEM;                }                break;        case RAW1394_REQ_SET_CARD:                lh = NULL;                spin_lock_irq(&host_info_lock);                if (req->req.misc < host_count) {                        lh = host_info_list.next;                        while (req->req.misc--) {                                lh = lh->next;                        }                        hi = list_entry(lh, struct host_info, list);                        hpsb_inc_host_usage(hi->host);                        list_add_tail(&fi->list, &hi->file_info_list);                        fi->host = hi->host;                        fi->state = connected;                }                spin_unlock_irq(&host_info_lock);                if (lh != NULL) {                        req->req.error = RAW1394_ERROR_NONE;                        req->req.generation = get_hpsb_generation(fi->host);                        req->req.misc = (fi->host->node_id << 16)                                 | fi->host->node_count;                        if (fi->protocol_version > 3) {                                req->req.misc |=                                        (fi->host->irm_id & NODE_MASK) << 8;                        }                } else {                        req->req.error = RAW1394_ERROR_INVALID_ARG;                }                req->req.length = 0;                break;        default:                req->req.error = RAW1394_ERROR_STATE_ORDER;                req->req.length = 0;                break;        }        queue_complete_req(req);        return sizeof(struct raw1394_request);}static void handle_iso_listen(struct file_info *fi, struct pending_request *req){        int channel = req->req.misc;        spin_lock(&host_info_lock);        if ((channel > 63) || (channel < -64)) {                req->req.error = RAW1394_ERROR_INVALID_ARG;        } else if (channel >= 0) {                /* allocate channel req.misc */                if (fi->listen_channels & (1ULL << channel)) {                        req->req.error = RAW1394_ERROR_ALREADY;                } else {                        fi->listen_channels |= 1ULL << channel;                        hpsb_listen_channel(hl_handle, fi->host, channel);                        fi->iso_buffer = int2ptr(req->req.recvb);                        fi->iso_buffer_length = req->req.length;                }        } else {                /* deallocate channel (one's complement neg) req.misc */                channel = ~channel;                if (fi->listen_channels & (1ULL << channel)) {                        hpsb_unlisten_channel(hl_handle, fi->host, channel);                        fi->listen_channels &= ~(1ULL << channel);                } else {                        req->req.error = RAW1394_ERROR_INVALID_ARG;                }        }        req->req.length = 0;        queue_complete_req(req);        spin_unlock(&host_info_lock);}static void handle_fcp_listen(struct file_info *fi, struct pending_request *req){        if (req->req.misc) {                if (fi->fcp_buffer) {                        req->req.error = RAW1394_ERROR_ALREADY;                } else {                        fi->fcp_buffer = (u8 *)int2ptr(req->req.recvb);                }        } else {                if (!fi->fcp_buffer) {                        req->req.error = RAW1394_ERROR_ALREADY;                } else {                        fi->fcp_buffer = NULL;                }        }        req->req.length = 0;        queue_complete_req(req);}static int handle_local_request(struct file_info *fi,                                struct pending_request *req, int node){        u64 addr = req->req.address & 0xffffffffffffULL;        req->data = kmalloc(req->req.length, SLAB_KERNEL);        if (!req->data) return -ENOMEM;        req->free_data = 1;        switch (req->req.type) {        case RAW1394_REQ_ASYNC_READ:                req->req.error = highlevel_read(fi->host, node, req->data, addr,                                                req->req.length);                break;        case RAW1394_REQ_ASYNC_WRITE:                if (copy_from_user(req->data, int2ptr(req->req.sendb),                                   req->req.length)) {                        req->req.error = RAW1394_ERROR_MEMFAULT;                        break;                }                req->req.error = highlevel_write(fi->host, node, node, req->data,                                                 addr, req->req.length);                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;                        }                }                if (copy_from_user(req->data, int2ptr(req->req.sendb),                                   req->req.length)) {                        req->req.error = RAW1394_ERROR_MEMFAULT;                        break;                }                if (req->req.length == 8) {                        req->req.error = highlevel_lock(fi->host, node,                                                        req->data, addr,                                                        req->data[1],                                                        req->data[0],                                                        req->req.misc);                        req->req.length = 4;                } else {                        req->req.error = highlevel_lock(fi->host, node,                                                        req->data, addr,                                                        req->data[0], 0,                                                        req->req.misc);                }                break;        case RAW1394_REQ_LOCK64:        default:                req->req.error = RAW1394_ERROR_STATE_ORDER;        }        if (req->req.error)                req->req.length = 0;        if (req->req.error >= 0)                req->req.error |= ACK_PENDING << 16;        queue_complete_req(req);        return sizeof(struct raw1394_request);}static int handle_remote_request(struct file_info *fi,                                 struct pending_request *req, int node){        struct hpsb_packet *packet = NULL;        u64 addr = req->req.address & 0xffffffffffffULL;        switch (req->req.type) {        case RAW1394_REQ_ASYNC_READ:                if (req->req.length == 4) {                        packet = hpsb_make_readqpacket(fi->host, node, addr);                        if (!packet) return -ENOMEM;                        req->data = &packet->header[3];                } else {                        packet = hpsb_make_readbpacket(fi->host, node, addr,                                                       req->req.length);                        if (!packet) return -ENOMEM;                        req->data = packet->data;                }                break;        case RAW1394_REQ_ASYNC_WRITE:                if (req->req.length == 4) {                        quadlet_t x;                        if (copy_from_user(&x, int2ptr(req->req.sendb), 4)) {                                req->req.error = RAW1394_ERROR_MEMFAULT;                        }                        packet = hpsb_make_writeqpacket(fi->host, node, addr,                                                        x);                        if (!packet) return -ENOMEM;                } else {                        packet = hpsb_make_writebpacket(fi->host, node, addr,                                                        req->req.length);                        if (!packet) return -ENOMEM;

⌨️ 快捷键说明

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