📄 raw1394.c
字号:
} 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->driver->name); khl++; } } spin_unlock_irq(&host_info_lock); if (khl != NULL) { req->req.error = RAW1394_ERROR_NONE; req->req.length = min(req->req.length, (u32)(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_ref_host(hi->host); // XXX Need to handle failure case 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 |= NODEID_TO_NODE(fi->host->irm_id) << 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_irq(&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 { if (hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { fi->listen_channels |= 1ULL << 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(&raw1394_highlevel, 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_irq(&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_async_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: DBGMSG("read_request called"); packet = hpsb_make_readpacket(fi->host, node, addr, req->req.length); if (!packet) return -ENOMEM; if (req->req.length == 4) req->data = &packet->header[3]; else req->data = packet->data; break; case RAW1394_REQ_ASYNC_WRITE: DBGMSG("write_request called"); packet = hpsb_make_writepacket(fi->host, node, addr, NULL, req->req.length); if (!packet) return -ENOMEM; if (req->req.length == 4) { if (copy_from_user(&packet->header[3], int2ptr(req->req.sendb), req->req.length)) req->req.error = RAW1394_ERROR_MEMFAULT; } else { 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_ASYNC_STREAM: DBGMSG("stream_request called"); packet = hpsb_make_streampacket(fi->host, NULL, req->req.length, node & 0x3f/*channel*/, (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); if (!packet) return -ENOMEM; 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: DBGMSG("lock_request called"); 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, NULL, 0); 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: DBGMSG("lock64_request called"); if ((req->req.misc == EXTCODE_FETCH_ADD) || (req->req.misc == EXTCODE_LITTLE_ADD)) { if (req->req.length != 8) { req->req.error = RAW1394_ERROR_INVALID_ARG; break; } } else { if (req->req.length != 16) { req->req.error = RAW1394_ERROR_INVALID_ARG; break; } } packet = hpsb_make_lock64packet(fi->host, node, addr, req->req.misc, NULL, 0); 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 = 8; break; 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); } hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); 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; hpsb_free_tlabel(packet); 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 = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); if (!packet) return -ENOMEM; packet->speed_code = req->req.address & 0x3; req->packet = packet; 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->req.length = 0; hpsb_set_packet_complete_task(packet, (void (*)(void*))queue_complete_req, req); 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 = req->req.generation; if (!hpsb_send_packet(packet)) { req->req.error = RAW1394_ERROR_SEND_ERROR; queue_complete_req(req); } return sizeof(struct raw1394_request);}static int handle_async_send(struct file_info *fi, struct pending_request *req){ struct hpsb_packet *packet; int header_length = req->req.misc & 0xffff; int expect_response = req->req.misc >> 16; if ((header_length > req->req.length) || (header_length < 12)) { req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.length = 0; queue_complete_req(req); return sizeof(struct raw1394_request); } packet = alloc_hpsb_packet(req->req.length-header_length); req->packet = packet; if (!packet) return -ENOMEM; if (copy_from_user(packet->header, int2ptr(req->req.sendb), header_length)) { req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; queue_complete_req(req); return sizeof(struct raw1394_request); } if (copy_from_user(packet->data, ((u8*) int2ptr(req->req.sendb)) + header_length, packet->data_size)) { req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; queue_complete_req(req); return sizeof(struct raw1394_request); } packet->type = hpsb_async; packet->node_id = packet->header[0] >> 16; packet->tcode = (packet->header[0] >> 4) & 0xf; packet->tlabel = (packet->header[0] >> 10) &0x3f; packet->host = fi->host; packet->expect_response = expect_response; packet->header_size=header_length; packet->data_size=req->req.length-header_length; req->req.length = 0; hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); 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 = req->req.generation; if (!hpsb_send_packet(packet)) { req->req.error = RAW1394_ERROR_SEND_ERROR; queue_complete_req(req); } return sizeof(struct raw1394_request);}static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer, u64 addr, size_t length, u16 flags){ struct pending_request *req; struct list_head *lh; struct host_info *hi; struct file_info *fi = NULL; struct list_head *entry; struct arm_addr *arm_addr = NULL; struct arm_request *arm_req = NULL; struct arm_response *arm_resp = NULL; int found=0, size=0, rcode=-1; struct arm_request_response *arm_req_resp = NULL; DBGMSG("arm_read called by node: %X" "addr: %4.4x %8.8x length: %Zu", nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), length); spin_lock(&host_info_lock); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -