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

📄 ieee1394_core.c

📁 Ieee1394驱动实现
💻 C
📖 第 1 页 / 共 3 页
字号:
				       length, flags);
		if (rcode < 0) {
			hpsb_free_packet(packet);
			return;
		}
		fill_async_readblock_resp(packet, rcode, length);
		send_packet_nocare(packet);
		return;

	case TCODE_LOCK_REQUEST:
		length = data[3] >> 16;
		extcode = data[3] & 0xffff;
		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];

		packet = create_reply_packet(host, data, 8);
		if (!packet)
			return;

		if (extcode == 0 || extcode >= 7) {
			/* let switch default handle error */
			length = 0;
		}

		switch (length) {
		case 4:
			rcode = highlevel_lock(host, source, packet->data, addr,
					       data[4], 0, extcode, flags);
			fill_async_lock_resp(packet, rcode, extcode, 4);
			break;
		case 8:
			if (extcode != EXTCODE_FETCH_ADD &&
			    extcode != EXTCODE_LITTLE_ADD) {
				rcode = highlevel_lock(host, source,
						       packet->data, addr,
						       data[5], data[4],
						       extcode, flags);
				fill_async_lock_resp(packet, rcode, extcode, 4);
			} else {
				rcode = highlevel_lock64(host, source,
					     (octlet_t *)packet->data, addr,
					     *(octlet_t *)(data + 4), 0ULL,
					     extcode, flags);
				fill_async_lock_resp(packet, rcode, extcode, 8);
			}
			break;
		case 16:
			rcode = highlevel_lock64(host, source,
						 (octlet_t *)packet->data, addr,
						 *(octlet_t *)(data + 6),
						 *(octlet_t *)(data + 4),
						 extcode, flags);
			fill_async_lock_resp(packet, rcode, extcode, 8);
			break;
		default:
			rcode = RCODE_TYPE_ERROR;
			fill_async_lock_resp(packet, rcode, extcode, 0);
		}

		if (rcode < 0)
			hpsb_free_packet(packet);
		else
			send_packet_nocare(packet);
		return;
	}
}

/**
 * hpsb_packet_received - hand over received packet to the core
 *
 * For host driver module usage.
 *
 * The contents of data are expected to be the full packet but with the CRCs
 * left out (data block follows header immediately), with the header (i.e. the
 * first four quadlets) in machine byte order and the data block in big endian.
 * *@data can be safely overwritten after this call.
 *
 * If the packet is a write request, @write_acked is to be set to true if it was
 * ack_complete'd already, false otherwise.  This argument is ignored for any
 * other packet type.
 */
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
			  int write_acked)
{
	int tcode;

	if (unlikely(host->in_bus_reset)) {
		HPSB_DEBUG("received packet during reset; ignoring");
		return;
	}

	dump_packet("received packet", data, size, -1);

	tcode = (data[0] >> 4) & 0xf;

	switch (tcode) {
	case TCODE_WRITE_RESPONSE:
	case TCODE_READQ_RESPONSE:
	case TCODE_READB_RESPONSE:
	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_CYCLE_START:
		/* simply ignore this packet if it is passed on */
		break;

	default:
		HPSB_DEBUG("received packet with bogus transaction code %d",
			   tcode);
		break;
	}
}

static void abort_requests(struct hpsb_host *host)
{
	struct hpsb_packet *packet, *p;
	struct list_head tmp;
	unsigned long flags;

	host->driver->devctl(host, CANCEL_REQUESTS, 0);

	INIT_LIST_HEAD(&tmp);
	spin_lock_irqsave(&pending_packets_lock, flags);
	list_splice_init(&host->pending_packets, &tmp);
	spin_unlock_irqrestore(&pending_packets_lock, flags);

	list_for_each_entry_safe(packet, p, &tmp, queue) {
		list_del_init(&packet->queue);
		packet->state = hpsb_complete;
		packet->ack_code = ACKX_ABORTED;
		queue_packet_complete(packet);
	}
}

void abort_timedouts(unsigned long __opaque)
{
	struct hpsb_host *host = (struct hpsb_host *)__opaque;
	struct hpsb_packet *packet, *p;
	struct list_head tmp;
	unsigned long flags, expire, j;

	spin_lock_irqsave(&host->csr.lock, flags);
	expire = host->csr.expire;
	spin_unlock_irqrestore(&host->csr.lock, flags);

	j = jiffies;
	INIT_LIST_HEAD(&tmp);
	spin_lock_irqsave(&pending_packets_lock, flags);

	list_for_each_entry_safe(packet, p, &host->pending_packets, queue) {
		if (time_before(packet->sendtime + expire, j))
			list_move_tail(&packet->queue, &tmp);
		else
			/* Since packets are added to the tail, the oldest
			 * ones are first, always. When we get to one that
			 * isn't timed out, the rest aren't either. */
			break;
	}
	if (!list_empty(&host->pending_packets))
		mod_timer(&host->timeout, j + host->timeout_interval);

	spin_unlock_irqrestore(&pending_packets_lock, flags);

	list_for_each_entry_safe(packet, p, &tmp, queue) {
		list_del_init(&packet->queue);
		packet->state = hpsb_complete;
		packet->ack_code = ACKX_TIMEOUT;
		queue_packet_complete(packet);
	}
}

static struct task_struct *khpsbpkt_thread;
static LIST_HEAD(hpsbpkt_queue);

static void queue_packet_complete(struct hpsb_packet *packet)
{
	unsigned long flags;

	if (packet->no_waiter) {
		hpsb_free_packet(packet);
		return;
	}
	if (packet->complete_routine != NULL) {
		spin_lock_irqsave(&pending_packets_lock, flags);
		list_add_tail(&packet->queue, &hpsbpkt_queue);
		spin_unlock_irqrestore(&pending_packets_lock, flags);
		wake_up_process(khpsbpkt_thread);
	}
	return;
}

/*
 * Kernel thread which handles packets that are completed.  This way the
 * packet's "complete" function is asynchronously run in process context.
 * Only packets which have a "complete" function may be sent here.
 */
static int hpsbpkt_thread(void *__hi)
{
	struct hpsb_packet *packet, *p;
	struct list_head tmp;
	int may_schedule;

	current->flags |= PF_NOFREEZE;

	while (!kthread_should_stop()) {

		INIT_LIST_HEAD(&tmp);
		spin_lock_irq(&pending_packets_lock);
		list_splice_init(&hpsbpkt_queue, &tmp);
		spin_unlock_irq(&pending_packets_lock);

		list_for_each_entry_safe(packet, p, &tmp, queue) {
			list_del_init(&packet->queue);
			packet->complete_routine(packet->complete_data);
		}

		set_current_state(TASK_INTERRUPTIBLE);
		spin_lock_irq(&pending_packets_lock);
		may_schedule = list_empty(&hpsbpkt_queue);
		spin_unlock_irq(&pending_packets_lock);
		if (may_schedule)
			schedule();
		__set_current_state(TASK_RUNNING);
	}
	return 0;
}

static int __init ieee1394_init(void)
{
	int i, ret;

	/* non-fatal error */
	if (hpsb_init_config_roms()) {
		HPSB_ERR("Failed to initialize some config rom entries.\n");
		HPSB_ERR("Some features may not be available\n");
	}

	khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt");
	if (IS_ERR(khpsbpkt_thread)) {
		HPSB_ERR("Failed to start hpsbpkt thread!\n");
		ret = PTR_ERR(khpsbpkt_thread);
		goto exit_cleanup_config_roms;
	}

	if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) {
		HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
		ret = -ENODEV;
		goto exit_release_kernel_thread;
	}

	ret = bus_register(&ieee1394_bus_type);
	if (ret < 0) {
		HPSB_INFO("bus register failed");
		goto release_chrdev;
	}

	for (i = 0; fw_bus_attrs[i]; i++) {
		ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
		if (ret < 0) {
			while (i >= 0) {
				bus_remove_file(&ieee1394_bus_type,
						fw_bus_attrs[i--]);
			}
			bus_unregister(&ieee1394_bus_type);
			goto release_chrdev;
		}
	}

	ret = class_register(&hpsb_host_class);
	if (ret < 0)
		goto release_all_bus;

	hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol");
	if (IS_ERR(hpsb_protocol_class)) {
		ret = PTR_ERR(hpsb_protocol_class);
		goto release_class_host;
	}

	ret = init_csr();
	if (ret) {
		HPSB_INFO("init csr failed");
		ret = -ENOMEM;
		goto release_class_protocol;
	}

	if (disable_nodemgr) {
		HPSB_INFO("nodemgr and IRM functionality disabled");
		/* We shouldn't contend for IRM with nodemgr disabled, since
		   nodemgr implements functionality required of ieee1394a-2000
		   IRMs */
		hpsb_disable_irm = 1;

		return 0;
	}

	if (hpsb_disable_irm) {
		HPSB_INFO("IRM functionality disabled");
	}

	ret = init_ieee1394_nodemgr();
	if (ret < 0) {
		HPSB_INFO("init nodemgr failed");
		goto cleanup_csr;
	}

	return 0;

cleanup_csr:
	cleanup_csr();
release_class_protocol:
	class_destroy(hpsb_protocol_class);
release_class_host:
	class_unregister(&hpsb_host_class);
release_all_bus:
	for (i = 0; fw_bus_attrs[i]; i++)
		bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
	bus_unregister(&ieee1394_bus_type);
release_chrdev:
	unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
exit_release_kernel_thread:
	kthread_stop(khpsbpkt_thread);
exit_cleanup_config_roms:
	hpsb_cleanup_config_roms();
	return ret;
}

static void __exit ieee1394_cleanup(void)
{
	int i;

	if (!disable_nodemgr)
		cleanup_ieee1394_nodemgr();

	cleanup_csr();

	class_destroy(hpsb_protocol_class);
	class_unregister(&hpsb_host_class);
	for (i = 0; fw_bus_attrs[i]; i++)
		bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
	bus_unregister(&ieee1394_bus_type);

	kthread_stop(khpsbpkt_thread);

	hpsb_cleanup_config_roms();

	unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
}

fs_initcall(ieee1394_init); /* same as ohci1394 */
module_exit(ieee1394_cleanup);

/* Exported symbols */

/** hosts.c **/
EXPORT_SYMBOL(hpsb_alloc_host);
EXPORT_SYMBOL(hpsb_add_host);
EXPORT_SYMBOL(hpsb_resume_host);
EXPORT_SYMBOL(hpsb_remove_host);
EXPORT_SYMBOL(hpsb_update_config_rom_image);

/** ieee1394_core.c **/
EXPORT_SYMBOL(hpsb_speedto_str);
EXPORT_SYMBOL(hpsb_protocol_class);
EXPORT_SYMBOL(hpsb_set_packet_complete_task);
EXPORT_SYMBOL(hpsb_alloc_packet);
EXPORT_SYMBOL(hpsb_free_packet);
EXPORT_SYMBOL(hpsb_send_packet);
EXPORT_SYMBOL(hpsb_reset_bus);
EXPORT_SYMBOL(hpsb_read_cycle_timer);
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_GPL(hpsb_disable_irm);

/** 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_read);
EXPORT_SYMBOL(hpsb_write);
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_allocate_and_register_addrspace);
EXPORT_SYMBOL(hpsb_get_hostinfo);
EXPORT_SYMBOL(hpsb_create_hostinfo);
EXPORT_SYMBOL(hpsb_destroy_hostinfo);
EXPORT_SYMBOL(hpsb_set_hostinfo_key);
EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
EXPORT_SYMBOL(hpsb_set_hostinfo);

/** nodemgr.c **/
EXPORT_SYMBOL(hpsb_node_fill_packet);
EXPORT_SYMBOL(hpsb_node_write);
EXPORT_SYMBOL(__hpsb_register_protocol);
EXPORT_SYMBOL(hpsb_unregister_protocol);

/** csr.c **/
EXPORT_SYMBOL(hpsb_update_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_for_cpu);
EXPORT_SYMBOL(dma_region_sync_for_device);
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);

/** csr1212.c **/
EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
EXPORT_SYMBOL(csr1212_get_keyval);
EXPORT_SYMBOL(csr1212_new_directory);
EXPORT_SYMBOL(csr1212_parse_keyval);
EXPORT_SYMBOL(csr1212_read);
EXPORT_SYMBOL(csr1212_release_keyval);

⌨️ 快捷键说明

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