📄 raw1394.c
字号:
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 + -