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

📄 raw1394.c

📁 IEE1394 火线接口驱动 for linux
💻 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/version.h>#include <linux/smp_lock.h>#include <linux/vmalloc.h>#include <asm/uaccess.h>#include <asm/atomic.h>#include <linux/devfs_fs_kernel.h>#include "ieee1394.h"#include "ieee1394_types.h"#include "ieee1394_core.h"#include "nodemgr.h"#include "hosts.h"#include "highlevel.h"#include "iso.h"#include "ieee1394_transactions.h"#include "raw1394.h"#include "raw1394-private.h"#if BITS_PER_LONG == 64#define int2ptr(x) ((void *)x)#define ptr2int(x) ((u64)x)#else#define int2ptr(x) ((void *)(u32)x)#define ptr2int(x) ((u64)(u32)x)#endif#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...)#endifstatic devfs_handle_t devfs_handle;static LIST_HEAD(host_info_list);static int host_count;static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;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);static struct pending_request *__alloc_pending_request(int flags){        struct pending_request *req;        req = (struct pending_request *)kmalloc(sizeof(struct pending_request),                                                flags);        if (req != NULL) {                memset(req, 0, sizeof(struct pending_request));                INIT_LIST_HEAD(&req->list);        }        return req;}static inline struct pending_request *alloc_pending_request(void){        return __alloc_pending_request(SLAB_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);        }        free_hpsb_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_del(&req->list);        list_add_tail(&req->list, &fi->req_complete);	up(&fi->complete_sem);        wake_up_interruptible(&fi->poll_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 = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);        if (hi != NULL) {                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 list_head *lh;        struct host_info *hi;        list_for_each(lh, &host_info_list) {                hi = list_entry(lh, struct host_info, 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 list_head *lh;        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(lh, &hi->file_info_list) {                        fi = list_entry(lh, struct file_info, list);                        if (fi->notification == RAW1394_NOTIFY_ON) {                                req = __alloc_pending_request(SLAB_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 list_head *lh;        struct host_info *hi;        struct file_info *fi;        struct pending_request *req;        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);

⌨️ 快捷键说明

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