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

📄 raw1394.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * IEEE 1394 for Linux * * Raw interface to the bus * * Copyright (C) 1999, 2000 Andreas E. Bombe *               2001, 2002 Manfred Weihs <weihs@ict.tuwien.ac.at> *                     2002 Christian Toegel <christian.toegel@gmx.at> * * This code is licensed under the GPL.  See the file COPYING in the root * directory of the kernel sources for details. * * * Contributions: * * Manfred Weihs <weihs@ict.tuwien.ac.at> *        configuration ROM manipulation *        address range mapping *        adaptation for new (transparent) loopback mechanism *        sending of arbitrary async packets * Christian Toegel <christian.toegel@gmx.at> *        address range mapping *        lock64 request *        transmit physical packet *        busreset notification control (switch on/off) *        busreset with selection of type (short/long) *        request_reply */#include <linux/kernel.h>#include <linux/list.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/poll.h>#include <linux/module.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <linux/interrupt.h>#include <linux/vmalloc.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <linux/compat.h>#include "csr1212.h"#include "highlevel.h"#include "hosts.h"#include "ieee1394.h"#include "ieee1394_core.h"#include "ieee1394_hotplug.h"#include "ieee1394_transactions.h"#include "ieee1394_types.h"#include "iso.h"#include "nodemgr.h"#include "raw1394.h"#include "raw1394-private.h"#define int2ptr(x) ((void __user *)(unsigned long)x)#define ptr2int(x) ((u64)(unsigned long)(void __user *)x)#ifdef CONFIG_IEEE1394_VERBOSEDEBUG#define RAW1394_DEBUG#endif#ifdef RAW1394_DEBUG#define DBGMSG(fmt, args...) \printk(KERN_INFO "raw1394:" fmt "\n" , ## args)#else#define DBGMSG(fmt, args...) do {} while (0)#endifstatic LIST_HEAD(host_info_list);static int host_count;static DEFINE_SPINLOCK(host_info_lock);static atomic_t internal_generation = ATOMIC_INIT(0);static atomic_t iso_buffer_size;static const int iso_buffer_max = 4 * 1024 * 1024;	/* 4 MB */static struct hpsb_highlevel raw1394_highlevel;static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,		    u64 addr, size_t length, u16 flags);static int arm_write(struct hpsb_host *host, int nodeid, int destid,		     quadlet_t * data, u64 addr, size_t length, u16 flags);static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,		    u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,		    u16 flags);static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,		      u64 addr, octlet_t data, octlet_t arg, int ext_tcode,		      u16 flags);static struct hpsb_address_ops arm_ops = {	.read = arm_read,	.write = arm_write,	.lock = arm_lock,	.lock64 = arm_lock64,};static void queue_complete_cb(struct pending_request *req);#include <asm/current.h>static void print_old_iso_deprecation(void){	static pid_t p;	if (p == current->pid)		return;	p = current->pid;	printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"	       " isochronous request types which will be removed in a next"	       " kernel release\n", current->comm);	printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"	       " newer interface\n");}static struct pending_request *__alloc_pending_request(gfp_t flags){	struct pending_request *req;	req = kzalloc(sizeof(*req), flags);	if (req)		INIT_LIST_HEAD(&req->list);	return req;}static inline struct pending_request *alloc_pending_request(void){	return __alloc_pending_request(GFP_KERNEL);}static void free_pending_request(struct pending_request *req){	if (req->ibs) {		if (atomic_dec_and_test(&req->ibs->refcount)) {			atomic_sub(req->ibs->data_size, &iso_buffer_size);			kfree(req->ibs);		}	} else if (req->free_data) {		kfree(req->data);	}	hpsb_free_packet(req->packet);	kfree(req);}/* fi->reqlists_lock must be taken */static void __queue_complete_req(struct pending_request *req){	struct file_info *fi = req->file_info;	list_move_tail(&req->list, &fi->req_complete); 	wake_up(&fi->wait_complete);}static void queue_complete_req(struct pending_request *req){	unsigned long flags;	struct file_info *fi = req->file_info;	spin_lock_irqsave(&fi->reqlists_lock, flags);	__queue_complete_req(req);	spin_unlock_irqrestore(&fi->reqlists_lock, flags);}static void queue_complete_cb(struct pending_request *req){	struct hpsb_packet *packet = req->packet;	int rcode = (packet->header[1] >> 12) & 0xf;	switch (packet->ack_code) {	case ACKX_NONE:	case ACKX_SEND_ERROR:		req->req.error = RAW1394_ERROR_SEND_ERROR;		break;	case ACKX_ABORTED:		req->req.error = RAW1394_ERROR_ABORTED;		break;	case ACKX_TIMEOUT:		req->req.error = RAW1394_ERROR_TIMEOUT;		break;	default:		req->req.error = (packet->ack_code << 16) | rcode;		break;	}	if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {		req->req.length = 0;	}	if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||	    (req->req.type == RAW1394_REQ_ASYNC_WRITE) ||	    (req->req.type == RAW1394_REQ_ASYNC_STREAM) ||	    (req->req.type == RAW1394_REQ_LOCK) ||	    (req->req.type == RAW1394_REQ_LOCK64))		hpsb_free_tlabel(packet);	queue_complete_req(req);}static void add_host(struct hpsb_host *host){	struct host_info *hi;	unsigned long flags;	hi = kmalloc(sizeof(*hi), GFP_KERNEL);	if (hi) {		INIT_LIST_HEAD(&hi->list);		hi->host = host;		INIT_LIST_HEAD(&hi->file_info_list);		spin_lock_irqsave(&host_info_lock, flags);		list_add_tail(&hi->list, &host_info_list);		host_count++;		spin_unlock_irqrestore(&host_info_lock, flags);	}	atomic_inc(&internal_generation);}static struct host_info *find_host_info(struct hpsb_host *host){	struct host_info *hi;	list_for_each_entry(hi, &host_info_list, list)	    if (hi->host == host)		return hi;	return NULL;}static void remove_host(struct hpsb_host *host){	struct host_info *hi;	unsigned long flags;	spin_lock_irqsave(&host_info_lock, flags);	hi = find_host_info(host);	if (hi != NULL) {		list_del(&hi->list);		host_count--;		/*		   FIXME: address ranges should be removed		   and fileinfo states should be initialized		   (including setting generation to		   internal-generation ...)		 */	}	spin_unlock_irqrestore(&host_info_lock, flags);	if (hi == NULL) {		printk(KERN_ERR "raw1394: attempt to remove unknown host "		       "0x%p\n", host);		return;	}	kfree(hi);	atomic_inc(&internal_generation);}static void host_reset(struct hpsb_host *host){	unsigned long flags;	struct host_info *hi;	struct file_info *fi;	struct pending_request *req;	spin_lock_irqsave(&host_info_lock, flags);	hi = find_host_info(host);	if (hi != NULL) {		list_for_each_entry(fi, &hi->file_info_list, list) {			if (fi->notification == RAW1394_NOTIFY_ON) {				req = __alloc_pending_request(GFP_ATOMIC);				if (req != NULL) {					req->file_info = fi;					req->req.type = RAW1394_REQ_BUS_RESET;					req->req.generation =					    get_hpsb_generation(host);					req->req.misc = (host->node_id << 16)					    | host->node_count;					if (fi->protocol_version > 3) {						req->req.misc |=						    (NODEID_TO_NODE						     (host->irm_id)						     << 8);					}					queue_complete_req(req);				}			}		}	}	spin_unlock_irqrestore(&host_info_lock, flags);}static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,			size_t length){	unsigned long flags;	struct host_info *hi;	struct file_info *fi;	struct pending_request *req, *req_next;	struct iso_block_store *ibs = NULL;	LIST_HEAD(reqs);	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {		HPSB_INFO("dropped iso packet");		return;	}	spin_lock_irqsave(&host_info_lock, flags);	hi = find_host_info(host);	if (hi != NULL) {		list_for_each_entry(fi, &hi->file_info_list, list) {			if (!(fi->listen_channels & (1ULL << channel)))				continue;			req = __alloc_pending_request(GFP_ATOMIC);			if (!req)				break;			if (!ibs) {				ibs = kmalloc(sizeof(*ibs) + length,					      GFP_ATOMIC);				if (!ibs) {					kfree(req);					break;				}				atomic_add(length, &iso_buffer_size);				atomic_set(&ibs->refcount, 0);				ibs->data_size = length;				memcpy(ibs->data, data, length);			}			atomic_inc(&ibs->refcount);			req->file_info = fi;			req->ibs = ibs;			req->data = ibs->data;			req->req.type = RAW1394_REQ_ISO_RECEIVE;			req->req.generation = get_hpsb_generation(host);			req->req.misc = 0;			req->req.recvb = ptr2int(fi->iso_buffer);			req->req.length = min(length, fi->iso_buffer_length);			list_add_tail(&req->list, &reqs);		}	}	spin_unlock_irqrestore(&host_info_lock, flags);	list_for_each_entry_safe(req, req_next, &reqs, list)	    queue_complete_req(req);}static void fcp_request(struct hpsb_host *host, int nodeid, int direction,			int cts, u8 * data, size_t length){	unsigned long flags;	struct host_info *hi;	struct file_info *fi;	struct pending_request *req, *req_next;	struct iso_block_store *ibs = NULL;	LIST_HEAD(reqs);	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {		HPSB_INFO("dropped fcp request");		return;	}	spin_lock_irqsave(&host_info_lock, flags);	hi = find_host_info(host);	if (hi != NULL) {		list_for_each_entry(fi, &hi->file_info_list, list) {			if (!fi->fcp_buffer)				continue;			req = __alloc_pending_request(GFP_ATOMIC);			if (!req)				break;			if (!ibs) {				ibs = kmalloc(sizeof(*ibs) + length,					      GFP_ATOMIC);				if (!ibs) {					kfree(req);					break;				}				atomic_add(length, &iso_buffer_size);				atomic_set(&ibs->refcount, 0);				ibs->data_size = length;				memcpy(ibs->data, data, length);			}			atomic_inc(&ibs->refcount);			req->file_info = fi;			req->ibs = ibs;			req->data = ibs->data;			req->req.type = RAW1394_REQ_FCP_REQUEST;			req->req.generation = get_hpsb_generation(host);			req->req.misc = nodeid | (direction << 16);			req->req.recvb = ptr2int(fi->fcp_buffer);			req->req.length = length;			list_add_tail(&req->list, &reqs);		}	}	spin_unlock_irqrestore(&host_info_lock, flags);	list_for_each_entry_safe(req, req_next, &reqs, list)	    queue_complete_req(req);}#ifdef CONFIG_COMPATstruct compat_raw1394_req {	__u32 type;	__s32 error;	__u32 misc;	__u32 generation;	__u32 length;	__u64 address;	__u64 tag;	__u64 sendb;	__u64 recvb;} __attribute__((packed));static const char __user *raw1394_compat_write(const char __user *buf){	struct compat_raw1394_req __user *cr = (typeof(cr)) buf;	struct raw1394_request __user *r;	r = compat_alloc_user_space(sizeof(struct raw1394_request));#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))	if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||	    C(address) ||	    C(tag) ||	    C(sendb) ||	    C(recvb))		return ERR_PTR(-EFAULT);	return (const char __user *)r;}#undef C#define P(x) __put_user(r->x, &cr->x)static intraw1394_compat_read(const char __user *buf, struct raw1394_request *r){	struct compat_raw1394_req __user *cr = (typeof(cr)) r;	if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||	    P(type) ||

⌨️ 快捷键说明

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