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

📄 raw1394.c

📁 Armlinux ieee1394接口驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * IEEE 1394 for Linux * * Raw interface to the bus * * Copyright (C) 1999, 2000 Andreas E. Bombe * * This code is licensed under the GPL.  See the file COPYING in the root * directory of the kernel sources for details. */#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 <asm/uaccess.h>#include <asm/atomic.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)#include <linux/devfs_fs_kernel.h>#endif#include "ieee1394.h"#include "ieee1394_types.h"#include "ieee1394_core.h"#include "hosts.h"#include "highlevel.h"#include "ieee1394_transactions.h"#include "raw1394.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)#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 struct hpsb_highlevel *hl_handle;static atomic_t iso_buffer_size;static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */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);		INIT_TQUEUE(&req->tq, (void(*)(void*))queue_complete_cb, NULL);        }        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);}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);        list_del(&req->list);        list_add_tail(&req->list, &fi->req_complete);        spin_unlock_irqrestore(&fi->reqlists_lock, flags);        up(&fi->complete_sem);        wake_up_interruptible(&fi->poll_wait_complete);}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;        }        free_tlabel(packet->host, packet->node_id, packet->tlabel);        queue_complete_req(req);}static void add_host(struct hpsb_host *host){        struct host_info *hi;        hi = (struct host_info *)kmalloc(sizeof(struct host_info), SLAB_KERNEL);        if (hi != NULL) {                INIT_LIST_HEAD(&hi->list);                hi->host = host;                INIT_LIST_HEAD(&hi->file_info_list);                spin_lock_irq(&host_info_lock);                list_add_tail(&hi->list, &host_info_list);                host_count++;                spin_unlock_irq(&host_info_lock);        }        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;        spin_lock_irq(&host_info_lock);        hi = find_host_info(host);        if (hi != NULL) {                list_del(&hi->list);                host_count--;        }        spin_unlock_irq(&host_info_lock);        if (hi == NULL) {                printk(KERN_ERR "raw1394: attempt to remove unknown host "                       "0x%p\n", host);                return;        }        kfree(hi);}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);                        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 |= ((host->irm_id                                                           & NODE_MASK) << 8);                                }                                queue_complete_req(req);                        }                }        }        spin_unlock_irqrestore(&host_info_lock, flags);        atomic_inc(&internal_generation);}static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,                        unsigned int 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);        if (hi != NULL) {		list_for_each(lh, &hi->file_info_list) {                        fi = list_entry(lh, struct file_info, list);                        if (!(fi->listen_channels & (1ULL << channel))) {                                continue;                        }                        req = __alloc_pending_request(SLAB_ATOMIC);                        if (!req) break;                        if (!ibs) {                                ibs = kmalloc(sizeof(struct iso_block_store)                                              + length, SLAB_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);        lh = reqs.next;        while (lh != &reqs) {                req = list_entry(lh, struct pending_request, list);                lh = lh->next;                queue_complete_req(req);        }}static void fcp_request(struct hpsb_host *host, int nodeid, int direction,                        int cts, u8 *data, unsigned int 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 fcp request");                return;        }        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->fcp_buffer) {                                continue;                        }                        req = __alloc_pending_request(SLAB_ATOMIC);                        if (!req) break;                        if (!ibs) {                                ibs = kmalloc(sizeof(struct iso_block_store)                                              + length, SLAB_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;

⌨️ 快捷键说明

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