paep.c

来自「这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自」· C语言 代码 · 共 1,171 行 · 第 1/3 页

C
1,171
字号
/* * $Revision: 1.1 $ * $Source: /home/master/uaep/driver/linux/paep.c,v $ * $Date: 2002/02/21 17:00:41 $ * * $CN{$  *  * Copyright (c) 1999-2001 Accelerated Encryption Processing Ltd. (AEP) * Bray Business Park, Southern Cross Route, Bray, Co. Wicklow, Ireland. * All Rights Reserved. *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions are met: *  * 1. Redistributions of source code must retain the above copyright notice,  * this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation  * and/or other materials provided with the distribution. *  * 3. Neither the name of AEP Ltd. nor the names of its contributors  * may be used to endorse or promote products derived from this software  * without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  *  * $}CN$ *//* * AEP driver * For a Uniprocessor: * Compile with "gcc -O -DMODULE -D__KERNEL__ -c paep.c" * For an SMP machine: * Compile with "gcc -O -DMODULE -D__KERNEL__ -D__SMP__ -c paep.c" * Install with "root /sbin/insmod paep.o" * See also "lsmod" and "rmmod" * Get the major number from /var/log/messages * Use via "mknod /dev/aep c <major#> <minor#>" * * * History: * * - implemented proc_entry_owner to open and close /proc/paep entry only once for all AEP devices  * - kernel style indent, changed write_dma_msg and make_dma_msg to static inline  */#include <linux/version.h>/* * Removed this file for compatiblility across *  2.4.* kernels *//*#include <linux/modversions.h>*/#include <linux/kernel.h>#include <linux/init.h>#include <linux/config.h>#include <linux/pci.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/interrupt.h>#include <linux/errno.h>         /* for -EBUSY */#include <linux/proc_fs.h>#include <linux/devfs_fs_kernel.h>#include <linux/poll.h>#include <asm/uaccess.h>         /* for copy_to_user */#include <asm/io.h> #include "paep.h"#ifndef DRIVER_VERSION#define DRIVER_VERSION "UNLABELLED"#endifstatic char const _RCSId[] =  "$Id: paep.c,v 1.1 2002/02/21 17:00:41 tmaher Exp $"                              "$Source: /home/master/uaep/driver/linux/paep.c,v $";static char aep_version_str[100] = "AEP Device Driver. Version: ";/*  add more vendor/id pairs in the future when aep gets its own id's */static struct pci_device_id aep_pci_tbl[] __initdata = {        { AEP_PCI_VENDOR, AEP_PCI_ID, AEP_SUBSYS_VENDOR, AEP_SUBSYS_ID, },        { 0, } ,};static struct file_operations aep_fops = {        owner:     THIS_MODULE,          llseek:    NULL,                read:      read_aep,        write:     write_aep,        readdir:   NULL,         poll:      poll_aep,         ioctl:     NULL,         mmap:      NULL,        open:      open_aep,        flush:     NULL,         release:   release_aep,        fsync:     NULL,         fasync:    NULL,         lock:      NULL,        readv:     NULL,        writev:    NULL};MODULE_DEVICE_TABLE (pci, aep_pci_tbl);static struct pci_driver aep_driver = {        name:      AEP_DRIVER_NAME,        id_table:  aep_pci_tbl,        probe:     aep_init_one_device,        remove:    aep_remove_one_device,        suspend:   NULL,        resume:    NULL};MODULE_AUTHOR("AEP software development team");MODULE_DESCRIPTION("AEP (tm) 1000 PCI cryptographic accelerator driver");MODULE_LICENSE("Dual BSD/GPL");/* globals for this driver - Not visible to the kernel */static struct pci_dev **dev_list_pp       = NULL;  /* list of AEP devices */static struct pci_dev *proc_entry_owner_p = NULL;  /* /proc/paep entry is common to all devices, only open once */static int nb_cards       = 0;  /* used to generate the names in /dev/paep0, /dev/paep1, /dev/paep<nb_cards> */static int dma_buff_order = 0;  /* order of the buffer used to dma data */static void inline write_dma_msg(const DMA_msg_t *msg_p, paep_unit_info_t *dev_param_p, int target_address){        assert(msg_p && dev_param_p && target_address);            DPRINTK("writing message to 0x%08X\n", target_address);        DPRINTK_MSG(msg_p);            writel(msg_p->command, dev_param_p->mem_space + target_address);        writel(msg_p->address, dev_param_p->mem_space + target_address + sizeof(u32));        writel(msg_p->length, dev_param_p->mem_space + target_address + 2*sizeof(u32));        return;}static void inline make_dma_msg(DMA_msg_t *msg_p, int command, int address, int length){        assert(msg_p);            msg_p->command = command;        msg_p->address = address;        msg_p->length = length;}int aep_read_procmem(char *buf_p, char **start_pp, off_t offset,		     int len, int *unused_p, void* also_unused_p){        int              count;        struct pci_dev   *dev_p;        paep_unit_info_t *dev_param_p;        assert(buf_p && start_pp);        len = 0;        for (count = 0; count < AEP_MAXCARDS_NB; count++) {                if (dev_list_pp[count]) {                        dev_p = dev_list_pp[count];                        dev_param_p = dev_p->driver_data;                                    len += sprintf(buf_p+len, "\nDevice %i:\n",count);                            /* flags */                        len += sprintf(buf_p+len, "    Flags = 0x%08X ", dev_param_p->flags);                        if (dev_param_p->flags) {                                len += sprintf(buf_p+len, "( ");                                if (dev_param_p->flags & DEV_OPEN) len += sprintf(buf_p+len, "DEV_OPEN");                                if (dev_param_p->flags & DMA_DEV_BUSY) len += sprintf(buf_p+len, " | DMA_DEV_BUSY");                                if (dev_param_p->flags & WAITING_FOR_READ_DATA) len += sprintf(buf_p+len, " | WAITING_FOR_READ_DATA");                                if (dev_param_p->flags & READ_DATA_AVAILABLE) len += sprintf(buf_p+len, " | READ_DATA_AVAILABLE");                                len += sprintf(buf_p+len, " )\n");                        } else {                                len += sprintf(buf_p+len, "\n");                        }                        if (len > LIMIT) return len;                            /* read state */                        len += sprintf(buf_p+len, "    Read State = 0x%08X ", dev_param_p->read_state);                        if (dev_param_p->read_state == RS_IDLE) {                                len += sprintf(buf_p+len, "( IDLE )\n");                        } else if (dev_param_p->read_state == RS_DMA_ACTIVE) {                                len += sprintf(buf_p+len, "( DMA_ACTIVE )\n");                        } else if (dev_param_p->read_state == RS_DMA_COMPLETE) {                                len += sprintf(buf_p+len, "( DMA_COMPLETE)\n");                        } else if (dev_param_p->read_state == RS_DEAD) {                                len += sprintf(buf_p+len, "( DEAD)\n");                        } else {                                len += sprintf(buf_p+len, "(***Unknown***)\n");                        }                        if (len > LIMIT) return len;                            /* write state */                        len += sprintf(buf_p+len, "    Write State = 0x%08X ", dev_param_p->write_state);                        if (dev_param_p->write_state == WS_IDLE) {                                len += sprintf(buf_p+len, "( IDLE )\n");                        } else if (dev_param_p->write_state == WS_DMA_ACTIVE) {                                len += sprintf(buf_p+len, "( DMA_ACTIVE )\n");                        } else if (dev_param_p->write_state == WS_DMA_COMPLETE) {                                len += sprintf(buf_p+len, "( DMA_COMPLETE)\n");                        } else if (dev_param_p->write_state == WS_DEAD) {                                len += sprintf(buf_p+len, "( DEAD)\n");                        } else {                                len += sprintf(buf_p+len, "(***Unknown***)\n");                        }                        if (len > LIMIT) return len;#ifdef INSTRUMENT                        len += sprintf(buf_p+len, "    Open Count = %ld\n", dev_param_p->open_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Busy on Open Count = %ld\n", dev_param_p->open_busy_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Close Count = %ld\n", dev_param_p->close_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Read Count = %ld\n", dev_param_p->read_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Read DMA Count = %ld\n", dev_param_p->read_dma_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Busy on Read Count = %ld\n", dev_param_p->read_busy_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Read Byte Count = %ld\n", dev_param_p->read_byte_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Write Count = %ld\n", dev_param_p->write_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Write DMA Count = %ld\n", dev_param_p->write_dma_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Busy on Write Count = %ld\n", dev_param_p->write_busy_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Busy on Write Count 2 = %ld\n", dev_param_p->write_busy_cnt2);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Write Byte Count = %ld\n", dev_param_p->write_byte_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "    Interrupt Count = %ld\n", dev_param_p->interrupt_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        SIGNAL_DRIVER: %ld\n", dev_param_p->SIGNAL_DRIVER_int_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        DMA_WRITE_COMPLETE: %ld\n", dev_param_p->DMA_WRITE_COMPLETE_int_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        DMA_WRITE_NO_SPACE: %ld\n", dev_param_p->DMA_WRITE_NO_SPACE_int_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        DMA_WRITE_ERROR: %ld\n", dev_param_p->DMA_WRITE_ERROR_int_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        DMA_READ_COMPLETE: %ld\n", dev_param_p->DMA_READ_COMPLETE_int_cnt);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        DMA_READ_ERROR: %ld\n", dev_param_p->DMA_READ_ERROR_int_cnt);                        if (len > LIMIT) return len;#endif/*INSTRUMENT*/            #ifndef DONT_PRINT_DEBUG_PROC                        len += sprintf(buf_p+len, "        dev_p = 0x%p\n", dev_p);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        config_space = 0x%p\n", dev_param_p->config_space);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        mem_space = 0x%p\n", dev_param_p->mem_space);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        read_dma_buf_p = 0x%p\n", dev_param_p->read_dma_buf_p);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        write_dma_buf_p = 0x%p\n", dev_param_p->write_dma_buf_p);                        if (len > LIMIT) return len;                        len += sprintf(buf_p+len, "        int_inuse = 0x%08x\n", dev_param_p->int_inuse);                        if (len > LIMIT) return len;#endif/* DONT_PRINT_DEBUG_PROC */                }        }        return len;}/* Read function*/static ssize_t read_aep(struct file *file_p, char *buf_p, size_t count, loff_t *ppos_p){	paep_unit_info_t  *dev_param_p = file_p->private_data;	DMA_msg_t         msg;	unsigned int      targ_msg = 0; 	wait_queue_t      local_wq;	assert(file_p && buf_p);	BANNER();	if((file_p->f_flags & O_NONBLOCK) && (!(dev_param_p->flags & READ_DATA_AVAILABLE))){		return -EAGAIN;	}	DPRINTK("file_p = 0x%p, buf_p = 0x%p, count = 0x%08X, ppos_p = 0x%p\n",			file_p, buf_p, count, ppos_p);	init_waitqueue_entry(&local_wq, current); #ifdef INSTRUMENT	++dev_param_p->read_cnt;#endif /* INSTRUMENT */	/* Wait until there is data available before		 * we proceed with the read. 	*/	down_interruptible(&dev_param_p->read_sem);	down(&dev_param_p->aep_sem);	dev_param_p->flags &= ~READ_DATA_AVAILABLE;	/*  Set up the DMA and initiate it */	make_dma_msg(&msg, DMA_DEVICE_READ, virt_to_bus(dev_param_p->read_dma_buf_p), count);	targ_msg = get_msg_ptr(dev_param_p);	exit_if_invalid_msg_ptr(targ_msg, dev_param_p);		/*		 * set up device and go!		 *		 * Note: we don't need to acquire the MUTEX here for two reasons:		 * 1) we are the only top half routine that touches this stuff, and		 * the mutex & conditional variable stuff surrounding DMA_DEV_BUSY		 * art the start of this routine single threads us, therefore 2) only		 * the interrupt routine can interrupt this stuff.		 */		/* Write the message we just made to the device */	write_dma_msg(&msg, dev_param_p, targ_msg);		/*		 *  Put this mesage on the InBound Post list.  When the inbound post list is not		 *  empty the target gets interrupted and takes the next address from the list and		 *  processes the message		 */	DPRINTK("writing request\n");	add_wait_queue(&dev_param_p->rq, &local_wq);	current->state = TASK_INTERRUPTIBLE;	post_msg(targ_msg, dev_param_p);		/* Suspend the process with a timeout in case our device goes to lunch */	schedule_timeout(IO_TIMEOUT * HZ);	remove_wait_queue(&dev_param_p->rq, &local_wq);	up(&dev_param_p->aep_sem);		/*		 *  Determine whether we completed, or timed out. Note that		 *  there is a small chance here that we both completed and

⌨️ 快捷键说明

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