📄 ieee1394_core.c
字号:
case TCODE_LOCK_RESPONSE: handle_packet_response(host, tcode, data, size); break; case TCODE_WRITEQ: case TCODE_WRITEB: case TCODE_READQ: case TCODE_READB: case TCODE_LOCK_REQUEST: handle_incoming_packet(host, tcode, data, size, write_acked); break; case TCODE_ISO_DATA: highlevel_iso_receive(host, data, size); break; case TCODE_CYCLE_START: /* simply ignore this packet if it is passed on */ break; default: HPSB_NOTICE("received packet with bogus transaction code %d", tcode); break; }}void abort_requests(struct hpsb_host *host){ unsigned long flags; struct hpsb_packet *packet; struct list_head *lh, *tlh; LIST_HEAD(llist); host->driver->devctl(host, CANCEL_REQUESTS, 0); spin_lock_irqsave(&host->pending_pkt_lock, flags); list_splice(&host->pending_packets, &llist); INIT_LIST_HEAD(&host->pending_packets); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); list_for_each_safe(lh, tlh, &llist) { packet = list_entry(lh, struct hpsb_packet, list); list_del(&packet->list); packet->state = hpsb_complete; packet->ack_code = ACKX_ABORTED; up(&packet->state_change); run_packet_complete(packet); }}void abort_timedouts(unsigned long __opaque){ struct hpsb_host *host = (struct hpsb_host *)__opaque; unsigned long flags; struct hpsb_packet *packet; unsigned long expire; struct list_head *lh, *tlh; LIST_HEAD(expiredlist); spin_lock_irqsave(&host->csr.lock, flags); expire = host->csr.expire; spin_unlock_irqrestore(&host->csr.lock, flags); spin_lock_irqsave(&host->pending_pkt_lock, flags); list_for_each_safe(lh, tlh, &host->pending_packets) { packet = list_entry(lh, struct hpsb_packet, list); if (time_before(packet->sendtime + expire, jiffies)) { list_del(&packet->list); list_add(&packet->list, &expiredlist); } } if (!list_empty(&host->pending_packets)) mod_timer(&host->timeout, jiffies + host->timeout_interval); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); list_for_each_safe(lh, tlh, &expiredlist) { packet = list_entry(lh, struct hpsb_packet, list); list_del(&packet->list); packet->state = hpsb_complete; packet->ack_code = ACKX_TIMEOUT; up(&packet->state_change); run_packet_complete(packet); }}/** character device dispatching (see ieee1394_core.h)* Dan Maas <dmaas@dcine.com>*/static struct { struct file_operations *file_ops; struct module *module;} ieee1394_chardevs[16];static rwlock_t ieee1394_chardevs_lock = RW_LOCK_UNLOCKED;static int ieee1394_dispatch_open(struct inode *inode, struct file *file);static struct file_operations ieee1394_chardev_ops = { .owner =THIS_MODULE, .open = ieee1394_dispatch_open,};devfs_handle_t ieee1394_devfs_handle;/* claim a block of minor numbers */int ieee1394_register_chardev(int blocknum, struct module *module, struct file_operations *file_ops){ int retval; if ( (blocknum < 0) || (blocknum > 15) ) return -EINVAL; write_lock(&ieee1394_chardevs_lock); if (ieee1394_chardevs[blocknum].file_ops == NULL) { /* grab the minor block */ ieee1394_chardevs[blocknum].file_ops = file_ops; ieee1394_chardevs[blocknum].module = module; retval = 0; } else { /* block already taken */ retval = -EBUSY; } write_unlock(&ieee1394_chardevs_lock); return retval;}/* release a block of minor numbers */void ieee1394_unregister_chardev(int blocknum){ if ( (blocknum < 0) || (blocknum > 15) ) return; write_lock(&ieee1394_chardevs_lock); if (ieee1394_chardevs[blocknum].file_ops) { ieee1394_chardevs[blocknum].file_ops = NULL; ieee1394_chardevs[blocknum].module = NULL; } write_unlock(&ieee1394_chardevs_lock);}/*ieee1394_get_chardev() - look up and acquire a character devicedriver that has previously registered using ieee1394_register_chardev() On success, returns 1 and sets module and file_ops to the driver. The module will have an incremented reference count. On failure, returns 0. The module will NOT have an incremented reference count.*/static int ieee1394_get_chardev(int blocknum, struct module **module, struct file_operations **file_ops){ int ret = 0; if ((blocknum < 0) || (blocknum > 15)) return ret; read_lock(&ieee1394_chardevs_lock); *module = ieee1394_chardevs[blocknum].module; *file_ops = ieee1394_chardevs[blocknum].file_ops; if (*file_ops == NULL) goto out; /* don't need try_inc_mod_count if the driver is non-modular */ if (*module && (try_inc_mod_count(*module) == 0)) goto out; /* success! */ ret = 1; out: read_unlock(&ieee1394_chardevs_lock); return ret;}/* the point of entry for open() on any ieee1394 character device */static int ieee1394_dispatch_open(struct inode *inode, struct file *file){ struct file_operations *file_ops; struct module *module; int blocknum; int retval; /* Maintaining correct module reference counts is tricky here! The key thing to remember is that the VFS increments the reference count of ieee1394 before it calls ieee1394_dispatch_open(). If the open() succeeds, then we need to transfer this extra reference to the task-specific driver module (e.g. raw1394). The VFS will deref the driver module automatically when the file is later released. If the open() fails, then the VFS will drop the reference count of whatever module file->f_op->owner points to, immediately after this function returns. */ /* shift away lower four bits of the minor to get the index of the ieee1394_driver we want */ blocknum = (MINOR(inode->i_rdev) >> 4) & 0xF; /* look up the driver */ if (ieee1394_get_chardev(blocknum, &module, &file_ops) == 0) return -ENODEV; /* redirect all subsequent requests to the driver's own file_operations */ file->f_op = file_ops; /* at this point BOTH ieee1394 and the task-specific driver have an extra reference */ /* follow through with the open() */ retval = file_ops->open(inode, file); if (retval == 0) { /* If the open() succeeded, then ieee1394 will be left with an extra module reference, so we discard it here. The task-specific driver still has the extra reference given to it by ieee1394_get_chardev(). This extra reference prevents the module from unloading while the file is open, and will be dropped by the VFS when the file is released. */ if (THIS_MODULE) __MOD_DEC_USE_COUNT((struct module*) THIS_MODULE); /* note that if ieee1394 is compiled into the kernel, THIS_MODULE will be (void*) NULL, hence the if and the cast are necessary */ } else { /* if the open() failed, then we need to drop the extra reference we gave to the task-specific driver */ if (module) __MOD_DEC_USE_COUNT(module); /* point the file's f_ops back to ieee1394. The VFS will then decrement ieee1394's reference count immediately after this function returns. */ file->f_op = &ieee1394_chardev_ops; } return retval;}struct proc_dir_entry *ieee1394_procfs_entry;static int __init ieee1394_init(void){ hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet), 0, 0, NULL, NULL); ieee1394_devfs_handle = devfs_mk_dir(NULL, "ieee1394", NULL); if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) { HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR); devfs_unregister(ieee1394_devfs_handle); return -ENODEV; } #ifdef CONFIG_PROC_FS /* Must be done before we start everything else, since the drivers * may use it. */ ieee1394_procfs_entry = proc_mkdir("ieee1394", proc_bus); if (ieee1394_procfs_entry == NULL) { HPSB_ERR("unable to create /proc/bus/ieee1394\n"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); devfs_unregister(ieee1394_devfs_handle); return -ENOMEM; } ieee1394_procfs_entry->owner = THIS_MODULE;#endif init_hpsb_highlevel(); init_csr(); if (!disable_nodemgr) init_ieee1394_nodemgr(); else HPSB_INFO("nodemgr functionality disabled"); return 0;}static void __exit ieee1394_cleanup(void){ if (!disable_nodemgr) cleanup_ieee1394_nodemgr(); cleanup_csr(); kmem_cache_destroy(hpsb_packet_cache); unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); /* it's ok to pass a NULL devfs_handle to devfs_unregister */ devfs_unregister(ieee1394_devfs_handle); remove_proc_entry("ieee1394", proc_bus);}module_init(ieee1394_init);module_exit(ieee1394_cleanup);/* Exported symbols *//** hosts.c **/EXPORT_SYMBOL(hpsb_alloc_host);EXPORT_SYMBOL(hpsb_add_host);EXPORT_SYMBOL(hpsb_remove_host);EXPORT_SYMBOL(hpsb_ref_host);EXPORT_SYMBOL(hpsb_unref_host);/** ieee1394_core.c **/EXPORT_SYMBOL(hpsb_speedto_str);EXPORT_SYMBOL(hpsb_set_packet_complete_task);EXPORT_SYMBOL(alloc_hpsb_packet);EXPORT_SYMBOL(free_hpsb_packet);EXPORT_SYMBOL(hpsb_send_phy_config);EXPORT_SYMBOL(hpsb_send_packet);EXPORT_SYMBOL(hpsb_reset_bus);EXPORT_SYMBOL(hpsb_bus_reset);EXPORT_SYMBOL(hpsb_selfid_received);EXPORT_SYMBOL(hpsb_selfid_complete);EXPORT_SYMBOL(hpsb_packet_sent);EXPORT_SYMBOL(hpsb_packet_received);EXPORT_SYMBOL(ieee1394_register_chardev);EXPORT_SYMBOL(ieee1394_unregister_chardev);EXPORT_SYMBOL(ieee1394_devfs_handle);EXPORT_SYMBOL(ieee1394_procfs_entry);/** ieee1394_transactions.c **/EXPORT_SYMBOL(hpsb_get_tlabel);EXPORT_SYMBOL(hpsb_free_tlabel);EXPORT_SYMBOL(hpsb_make_readpacket);EXPORT_SYMBOL(hpsb_make_writepacket);EXPORT_SYMBOL(hpsb_make_streampacket);EXPORT_SYMBOL(hpsb_make_lockpacket);EXPORT_SYMBOL(hpsb_make_lock64packet);EXPORT_SYMBOL(hpsb_make_phypacket);EXPORT_SYMBOL(hpsb_make_isopacket);EXPORT_SYMBOL(hpsb_read);EXPORT_SYMBOL(hpsb_write);EXPORT_SYMBOL(hpsb_lock);EXPORT_SYMBOL(hpsb_lock64);EXPORT_SYMBOL(hpsb_send_gasp);EXPORT_SYMBOL(hpsb_packet_success);/** highlevel.c **/EXPORT_SYMBOL(hpsb_register_highlevel);EXPORT_SYMBOL(hpsb_unregister_highlevel);EXPORT_SYMBOL(hpsb_register_addrspace);EXPORT_SYMBOL(hpsb_unregister_addrspace);EXPORT_SYMBOL(hpsb_listen_channel);EXPORT_SYMBOL(hpsb_unlisten_channel);EXPORT_SYMBOL(hpsb_get_hostinfo);EXPORT_SYMBOL(hpsb_get_host_bykey);EXPORT_SYMBOL(hpsb_create_hostinfo);EXPORT_SYMBOL(hpsb_destroy_hostinfo);EXPORT_SYMBOL(hpsb_set_hostinfo_key);EXPORT_SYMBOL(hpsb_get_hostinfo_key);EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);EXPORT_SYMBOL(hpsb_set_hostinfo);EXPORT_SYMBOL(highlevel_read);EXPORT_SYMBOL(highlevel_write);EXPORT_SYMBOL(highlevel_lock);EXPORT_SYMBOL(highlevel_lock64);EXPORT_SYMBOL(highlevel_add_host);EXPORT_SYMBOL(highlevel_remove_host);EXPORT_SYMBOL(highlevel_host_reset);/** nodemgr.c **/EXPORT_SYMBOL(hpsb_guid_get_entry);EXPORT_SYMBOL(hpsb_nodeid_get_entry);EXPORT_SYMBOL(hpsb_node_fill_packet);EXPORT_SYMBOL(hpsb_node_read);EXPORT_SYMBOL(hpsb_node_write);EXPORT_SYMBOL(hpsb_node_lock);EXPORT_SYMBOL(hpsb_register_protocol);EXPORT_SYMBOL(hpsb_unregister_protocol);EXPORT_SYMBOL(hpsb_release_unit_directory);/** csr.c **/EXPORT_SYMBOL(hpsb_update_config_rom);EXPORT_SYMBOL(hpsb_get_config_rom);/** dma.c **/EXPORT_SYMBOL(dma_prog_region_init);EXPORT_SYMBOL(dma_prog_region_alloc);EXPORT_SYMBOL(dma_prog_region_free);EXPORT_SYMBOL(dma_region_init);EXPORT_SYMBOL(dma_region_alloc);EXPORT_SYMBOL(dma_region_free);EXPORT_SYMBOL(dma_region_sync);EXPORT_SYMBOL(dma_region_mmap);EXPORT_SYMBOL(dma_region_offset_to_bus);/** iso.c **/EXPORT_SYMBOL(hpsb_iso_xmit_init);EXPORT_SYMBOL(hpsb_iso_recv_init);EXPORT_SYMBOL(hpsb_iso_xmit_start);EXPORT_SYMBOL(hpsb_iso_recv_start);EXPORT_SYMBOL(hpsb_iso_recv_listen_channel);EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel);EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask);EXPORT_SYMBOL(hpsb_iso_stop);EXPORT_SYMBOL(hpsb_iso_shutdown);EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet);EXPORT_SYMBOL(hpsb_iso_xmit_sync);EXPORT_SYMBOL(hpsb_iso_recv_release_packets);EXPORT_SYMBOL(hpsb_iso_n_ready);EXPORT_SYMBOL(hpsb_iso_packet_sent);EXPORT_SYMBOL(hpsb_iso_packet_received);EXPORT_SYMBOL(hpsb_iso_wake);EXPORT_SYMBOL(hpsb_iso_recv_flush);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -