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

📄 ieee1394_core.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 3 页
字号:
		build_speed_map(host, host->node_count);	}	HPSB_VERBOSE("selfid_complete called with successful SelfID stage "		     "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);	/* irm_id is kept up to date by check_selfids() */	if (host->irm_id == host->node_id) {		host->is_irm = 1;	} else {		host->is_busmgr = 0;		host->is_irm = 0;	}	if (isroot) {		host->driver->devctl(host, ACT_CYCLE_MASTER, 1);		host->is_cycmst = 1;	}	atomic_inc(&host->generation);	host->in_bus_reset = 0;	highlevel_host_reset(host);}void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,		      int ackcode){	unsigned long flags;	spin_lock_irqsave(&host->pending_packet_queue.lock, flags);	packet->ack_code = ackcode;	if (packet->no_waiter || packet->state == hpsb_complete) {		/* if packet->no_waiter, must not have a tlabel allocated */		spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);		hpsb_free_packet(packet);		return;	}	atomic_dec(&packet->refcnt);	/* drop HC's reference */	/* here the packet must be on the host->pending_packet_queue */	if (ackcode != ACK_PENDING || !packet->expect_response) {		packet->state = hpsb_complete;		__skb_unlink(packet->skb, &host->pending_packet_queue);		spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);		queue_packet_complete(packet);		return;	}	packet->state = hpsb_pending;	packet->sendtime = jiffies;	spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);	mod_timer(&host->timeout, jiffies + host->timeout_interval);}/** * hpsb_send_phy_config - transmit a PHY configuration packet on the bus * @host: host that PHY config packet gets sent through * @rootid: root whose force_root bit should get set (-1 = don't set force_root) * @gapcnt: gap count value to set (-1 = don't set gap count) * * This function sends a PHY config packet on the bus through the specified host. * * Return value: 0 for success or error number otherwise. */int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt){	struct hpsb_packet *packet;	quadlet_t d = 0;	int retval = 0;	if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||	   (rootid == -1 && gapcnt == -1)) {		HPSB_DEBUG("Invalid Parameter: rootid = %d   gapcnt = %d",			   rootid, gapcnt);		return -EINVAL;	}	if (rootid != -1)		d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;	if (gapcnt != -1)		d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;	packet = hpsb_make_phypacket(host, d);	if (!packet)		return -ENOMEM;	packet->generation = get_hpsb_generation(host);	retval = hpsb_send_packet_and_wait(packet);	hpsb_free_packet(packet);	return retval;}/** * hpsb_send_packet - transmit a packet on the bus * @packet: packet to send * * The packet is sent through the host specified in the packet->host field. * Before sending, the packet's transmit speed is automatically determined * using the local speed map when it is an async, non-broadcast packet. * * Possibilities for failure are that host is either not initialized, in bus * reset, the packet's generation number doesn't match the current generation * number or the host reports a transmit error. * * Return value: 0 on success, negative errno on failure. */int hpsb_send_packet(struct hpsb_packet *packet){	struct hpsb_host *host = packet->host;	if (host->is_shutdown)		return -EINVAL;	if (host->in_bus_reset ||	    (packet->generation != get_hpsb_generation(host)))		return -EAGAIN;	packet->state = hpsb_queued;	/* This just seems silly to me */	WARN_ON(packet->no_waiter && packet->expect_response);	if (!packet->no_waiter || packet->expect_response) {		atomic_inc(&packet->refcnt);		/* Set the initial "sendtime" to 10 seconds from now, to		   prevent premature expiry.  If a packet takes more than		   10 seconds to hit the wire, we have bigger problems :) */		packet->sendtime = jiffies + 10 * HZ;		skb_queue_tail(&host->pending_packet_queue, packet->skb);	}	if (packet->node_id == host->node_id) {		/* it is a local request, so handle it locally */		quadlet_t *data;		size_t size = packet->data_size + packet->header_size;		data = kmalloc(size, GFP_ATOMIC);		if (!data) {			HPSB_ERR("unable to allocate memory for concatenating header and data");			return -ENOMEM;		}		memcpy(data, packet->header, packet->header_size);		if (packet->data_size)			memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);		dump_packet("send packet local", packet->header, packet->header_size, -1);		hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);		hpsb_packet_received(host, data, size, 0);		kfree(data);		return 0;	}	if (packet->type == hpsb_async &&	    NODEID_TO_NODE(packet->node_id) != ALL_NODES)		packet->speed_code =			host->speed[NODEID_TO_NODE(packet->node_id)];	dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);	return host->driver->transmit_packet(host, packet);}/* We could just use complete() directly as the packet complete * callback, but this is more typesafe, in the sense that we get a * compiler error if the prototype for complete() changes. */static void complete_packet(void *data){	complete((struct completion *) data);}int hpsb_send_packet_and_wait(struct hpsb_packet *packet){	struct completion done;	int retval;	init_completion(&done);	hpsb_set_packet_complete_task(packet, complete_packet, &done);	retval = hpsb_send_packet(packet);	if (retval == 0)		wait_for_completion(&done);	return retval;}static void send_packet_nocare(struct hpsb_packet *packet){	if (hpsb_send_packet(packet) < 0) {		hpsb_free_packet(packet);	}}static void handle_packet_response(struct hpsb_host *host, int tcode,				   quadlet_t *data, size_t size){	struct hpsb_packet *packet = NULL;	struct sk_buff *skb;	int tcode_match = 0;	int tlabel;	unsigned long flags;	tlabel = (data[0] >> 10) & 0x3f;	spin_lock_irqsave(&host->pending_packet_queue.lock, flags);	skb_queue_walk(&host->pending_packet_queue, skb) {		packet = (struct hpsb_packet *)skb->data;		if ((packet->tlabel == tlabel)		    && (packet->node_id == (data[1] >> 16))){			break;		}		packet = NULL;	}	if (packet == NULL) {		HPSB_DEBUG("unsolicited response packet received - no tlabel match");		dump_packet("contents", data, 16, -1);		spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);		return;	}	switch (packet->tcode) {	case TCODE_WRITEQ:	case TCODE_WRITEB:		if (tcode != TCODE_WRITE_RESPONSE)			break;		tcode_match = 1;		memcpy(packet->header, data, 12);		break;	case TCODE_READQ:		if (tcode != TCODE_READQ_RESPONSE)			break;		tcode_match = 1;		memcpy(packet->header, data, 16);		break;	case TCODE_READB:		if (tcode != TCODE_READB_RESPONSE)			break;		tcode_match = 1;		BUG_ON(packet->skb->len - sizeof(*packet) < size - 16);		memcpy(packet->header, data, 16);		memcpy(packet->data, data + 4, size - 16);		break;	case TCODE_LOCK_REQUEST:		if (tcode != TCODE_LOCK_RESPONSE)			break;		tcode_match = 1;		size = min((size - 16), (size_t)8);		BUG_ON(packet->skb->len - sizeof(*packet) < size);		memcpy(packet->header, data, 16);		memcpy(packet->data, data + 4, size);		break;	}	if (!tcode_match) {		spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);		HPSB_INFO("unsolicited response packet received - tcode mismatch");		dump_packet("contents", data, 16, -1);		return;	}	__skb_unlink(skb, &host->pending_packet_queue);	if (packet->state == hpsb_queued) {		packet->sendtime = jiffies;		packet->ack_code = ACK_PENDING;	}	packet->state = hpsb_complete;	spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);	queue_packet_complete(packet);}static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,					       quadlet_t *data, size_t dsize){	struct hpsb_packet *p;	p = hpsb_alloc_packet(dsize);	if (unlikely(p == NULL)) {		/* FIXME - send data_error response */		return NULL;	}	p->type = hpsb_async;	p->state = hpsb_unused;	p->host = host;	p->node_id = data[1] >> 16;	p->tlabel = (data[0] >> 10) & 0x3f;	p->no_waiter = 1;	p->generation = get_hpsb_generation(host);	if (dsize % 4)		p->data[dsize / 4] = 0;	return p;}#define PREP_ASYNC_HEAD_RCODE(tc) \	packet->tcode = tc; \	packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \		| (1 << 8) | (tc << 4); \	packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \	packet->header[2] = 0static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,			      quadlet_t data){	PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);	packet->header[3] = data;	packet->header_size = 16;	packet->data_size = 0;}static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,			       int length){	if (rcode != RCODE_COMPLETE)		length = 0;	PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);	packet->header[3] = length << 16;	packet->header_size = 16;	packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);}static void fill_async_write_resp(struct hpsb_packet *packet, int rcode){	PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);	packet->header[2] = 0;	packet->header_size = 12;	packet->data_size = 0;}static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,			  int length){	if (rcode != RCODE_COMPLETE)		length = 0;	PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);	packet->header[3] = (length << 16) | extcode;	packet->header_size = 16;	packet->data_size = length;}#define PREP_REPLY_PACKET(length) \		packet = create_reply_packet(host, data, length); \		if (packet == NULL) breakstatic void handle_incoming_packet(struct hpsb_host *host, int tcode,				   quadlet_t *data, size_t size, int write_acked){	struct hpsb_packet *packet;	int length, rcode, extcode;	quadlet_t buffer;	nodeid_t source = data[1] >> 16;	nodeid_t dest = data[0] >> 16;	u16 flags = (u16) data[0];	u64 addr;	/* big FIXME - no error checking is done for an out of bounds length */	switch (tcode) {	case TCODE_WRITEQ:		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];		rcode = highlevel_write(host, source, dest, data+3,					addr, 4, flags);		if (!write_acked		    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)		    && (rcode >= 0)) {			/* not a broadcast write, reply */			PREP_REPLY_PACKET(0);			fill_async_write_resp(packet, rcode);			send_packet_nocare(packet);		}		break;	case TCODE_WRITEB:		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];		rcode = highlevel_write(host, source, dest, data+4,					addr, data[3]>>16, flags);		if (!write_acked		    && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)		    && (rcode >= 0)) {			/* not a broadcast write, reply */			PREP_REPLY_PACKET(0);			fill_async_write_resp(packet, rcode);			send_packet_nocare(packet);		}		break;	case TCODE_READQ:		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];		rcode = highlevel_read(host, source, &buffer, addr, 4, flags);		if (rcode >= 0) {			PREP_REPLY_PACKET(0);			fill_async_readquad_resp(packet, rcode, buffer);			send_packet_nocare(packet);		}		break;	case TCODE_READB:		length = data[3] >> 16;		PREP_REPLY_PACKET(length);		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];		rcode = highlevel_read(host, source, packet->data, addr,				       length, flags);		if (rcode >= 0) {			fill_async_readblock_resp(packet, rcode, length);			send_packet_nocare(packet);		} else {			hpsb_free_packet(packet);		}		break;	case TCODE_LOCK_REQUEST:		length = data[3] >> 16;		extcode = data[3] & 0xffff;		addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];

⌨️ 快捷键说明

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