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

📄 raw1394.c

📁 1394在linux下单独的驱动程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}		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 + -