📄 raw1394.c
字号:
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; hpsb_add_packet_complete_task(packet, &req->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; hpsb_add_packet_complete_task(packet, &req->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 (ieee1394_file_to_instance(file) > 0) { return -ENXIO; } fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL); if (fi == NULL) 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; 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_unref_host(fi->host); } kfree(fi); 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, IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16, S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL); if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394, THIS_MODULE, &file_ops)) { HPSB_ERR("raw1394 failed to register minor device block"); devfs_unregister(devfs_handle); hpsb_unregister_highlevel(hl_handle); return -EBUSY; } printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME); return 0;}static void __exit cleanup_raw1394(void){ ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_RAW1394); 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 + -