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

📄 icap.c

📁 fpga上的icap端口的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
// Virtex-II Pro ICAP driver for Linux 2.4.26 on Xilinx XUP// Copyright (C) 2007 by Neil Steiner// Provided by the Virginia Tech Configurable Computing Lab (http://www.ccm.ece.vt.edu)// // This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  // 02110-1301, USA.#ifndef MODULE#define MODULE#endif#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/devfs_fs_kernel.h>#include <linux/slab.h>#include <asm/io.h>#include <asm/errno.h>#include <asm/system.h>#include <asm/uaccess.h>#include <xparameters.h>#include "xhwicap.h"#include "xhwicap_i.h"MODULE_AUTHOR("Neil Steiner <neil.steiner@vt.edu>");MODULE_DESCRIPTION("Virtex-II Pro ICAP driver");MODULE_LICENSE("GPL");#define HWICAP_PHYS_ADDRESS XPAR_OPB_HWICAP_0_BASEADDR#define HWICAP_PHYS_LENGTH (XPAR_OPB_HWICAP_0_HIGHADDR+1-XPAR_OPB_HWICAP_0_BASEADDR)#define true (-1)#define false (0)#define FSM_WRITE_STATE_NULL            0#define FSM_WRITE_STATE_START           1#define FSM_WRITE_STATE_MAGIC           2#define FSM_WRITE_STATE_ZERO_ONE        3#define FSM_WRITE_STATE_A               4#define FSM_WRITE_STATE_DESIGN_LENGTH   5#define FSM_WRITE_STATE_DESIGN          6#define FSM_WRITE_STATE_B               7#define FSM_WRITE_STATE_DEVICE_LENGTH   8#define FSM_WRITE_STATE_DEVICE          9#define FSM_WRITE_STATE_C              10#define FSM_WRITE_STATE_DATE_LENGTH    11#define FSM_WRITE_STATE_DATE           12#define FSM_WRITE_STATE_D              13#define FSM_WRITE_STATE_TIME_LENGTH    14#define FSM_WRITE_STATE_TIME           15#define FSM_WRITE_STATE_E              16#define FSM_WRITE_STATE_LENGTH         17#define FSM_WRITE_STATE_FULL_HEADER    18#define FSM_WRITE_STATE_STREAM         19#define FSM_WRITE_STATE_COLLECT        -1// struct declarationstypedef struct Header {	Xuint16 file_magic_length;	char* file_magic_bytes;	Xuint16 zero_one;	Xuint16 design_name_length;	char* design_name_bytes;	Xuint16 device_name_length;	char* device_name_bytes;	Xuint16 date_string_length;	char* date_string_bytes;	Xuint16 time_string_length;	char* time_string_bytes;	Xuint32 bitstream_length;} Header;// function prototypesstatic int hwicap_init(void);static void hwicap_exit(void);int hwicap_open(struct inode *inode_ptr, struct file *file_ptr);int hwicap_release(struct inode *inode_ptr, struct file *file_ptr);//int hwicap_ioctl(struct inode *inode_ptr, struct file *file_ptr, unsigned int d, unsigned long request);ssize_t hwicap_read(struct file *file_ptr, char *a, size_t b, loff_t *c);ssize_t hwicap_write(struct file *file_ptr, const char *a, size_t b, loff_t *c);ssize_t run_write_state_machine(void);int XHwIcap_init_remap_baseaddress(XHwIcap *xhwicap);XStatus XHwIcap_SetConfiguration_Fixed(XHwIcap *InstancePtr, Xuint32 *Data, Xuint32 Size);// HWICAP base virtual addressvoid* hwicap_virt_ptr = NULL;// global variablesconst char hwicap_driver_name[] = "icap";int hwicap_major_number = 0;int hwicap_minor_number = 0;XHwIcap xhwicap;char* device_name = NULL;devfs_handle_t hwicap_directory = NULL;devfs_handle_t hwicap_device = NULL;Xuint32 word_buffer[XHI_MAX_BUFFER_BYTES >> 2];char local_buffer[1024];char* local_buffer_start;char* local_buffer_pos;char* local_buffer_end;char* local_buffer_wall;loff_t expected_pos = 0;int write_state = FSM_WRITE_STATE_NULL;int next_write_state = FSM_WRITE_STATE_NULL;Header header;int word_count = 0;int total_word_count = 0;// file access function structurestruct file_operations hwicap_ops = {	open: hwicap_open,	release: hwicap_release,	read: hwicap_read,	write: hwicap_write};// declare the module init and exit functionsmodule_init(hwicap_init);module_exit(hwicap_exit);// load the module into the kernelstatic int hwicap_init(void) {	// memory-map the HWICAP	hwicap_virt_ptr = ioremap_nocache(HWICAP_PHYS_ADDRESS,HWICAP_PHYS_LENGTH);	// if the memory region was not virtually mapped, consider initialization a complete failure	if(!hwicap_virt_ptr) {		// return failure		printk("<1>\t%s: cannot map HWICAP device into memory space\n",hwicap_driver_name);		return -EIO;	}	// initialize the XHwIcap structure	XStatus status = XHwIcap_Initialize(&xhwicap,XPAR_OPB_HWICAP_0_DEVICE_ID,		XHI_READ_DEVICEID_FROM_ICAP);	if(status != XST_SUCCESS) {		// return failure		printk("<1>\t%s: cannot initialize HWICAP device %d: %d\n",hwicap_driver_name,			XPAR_OPB_HWICAP_0_DEVICE_ID,(int) status);		return -EIO;	}	// determine the device name	switch(xhwicap.DeviceIdCode) {		case 0x01008093UL: device_name = "XC2V40"; break;		case 0x01010093UL: device_name = "XC2V80"; break;		case 0x01018093UL: device_name = "XC2V250"; break;		case 0x01020093UL: device_name = "XC2V500"; break;		case 0x01028093UL: device_name = "XC2V1000"; break;		case 0x01030093UL: device_name = "XC2V1500"; break;		case 0x01038093UL: device_name = "XC2V2000"; break;		case 0x01040093UL: device_name = "XC2V3000"; break;		case 0x01050093UL: device_name = "XC2V4000"; break;		case 0x01060093UL: device_name = "XC2V6000"; break;		case 0x01070093UL: device_name = "XC2V8000"; break;		case 0x01226093UL: device_name = "XC2VP2"; break;		case 0x0123E093UL: device_name = "XC2VP4"; break;		case 0x0124A093UL: device_name = "XC2VP7"; break;		case 0x01266093UL: device_name = "XC2VP20"; break;		case 0x0127E093UL: device_name = "XC2VP30"; break;		case 0x01292093UL: device_name = "XC2VP40"; break;		case 0x0129E093UL: device_name = "XC2VP50"; break;		case 0x012BA093UL: device_name = "XC2VP70"; break;		case 0x012D6093UL: device_name = "XC2VP100"; break;		case 0x012F2093UL: device_name = "XC2VP125"; break;		default: device_name = "[unknown]"; break;	}	// allocate a major device number	hwicap_major_number = devfs_alloc_major(DEVFS_SPECIAL_CHR);	printk("<1>%s: allocated major device number %d\n",hwicap_driver_name,hwicap_major_number);	// register the hwicap device	hwicap_device = devfs_register(NULL,hwicap_driver_name,DEVFS_FL_DEFAULT,		hwicap_major_number,hwicap_minor_number,0777|S_IFCHR,&hwicap_ops,NULL);	if(hwicap_device == NULL) {		printk("<1>\t%s: unable to register %s device\n",hwicap_driver_name,hwicap_driver_name);		return -EIO;	}	//printk("<1>\t%s: devfs_register for %s returned %8.8X\n",hwicap_driver_name,hwicap_led4_name,(int) devfs_file);	// return success and display the available devices	printk("<1>%s: driver inserted, device %s\n",hwicap_driver_name,device_name);	printk("<1>\t%s: physical address %8.8X mapped to virtual address %8.8X\n",hwicap_driver_name,		HWICAP_PHYS_ADDRESS,(unsigned int) hwicap_virt_ptr);#if 0	// if we're still here, the XHwIcap driver should have determined the device settings	printk("<2>\t%s: BaseAddress:  0x%8.8X\n",hwicap_driver_name,(unsigned int) xhwicap.BaseAddress);	printk("<2>\t%s: IsReady:      0x%8.8X\n",hwicap_driver_name,(unsigned int) xhwicap.IsReady);	printk("<2>\t%s: DeviceIdCode: 0x%8.8X\n",hwicap_driver_name,(unsigned int) xhwicap.DeviceIdCode);	printk("<2>\t%s: DeviceId:     0x%8.8X\n",hwicap_driver_name,xhwicap.DeviceId);	printk("<2>\t%s: Rows:               %4d\n",hwicap_driver_name,(unsigned int) xhwicap.Rows);	printk("<2>\t%s: Cols:               %4d\n",hwicap_driver_name,(unsigned int) xhwicap.Cols);	printk("<2>\t%s: BramCols:           %4d\n",hwicap_driver_name,(unsigned int) xhwicap.BramCols);	printk("<2>\t%s: BytesPerFrame:      %4d\n",hwicap_driver_name,(unsigned int) xhwicap.BytesPerFrame);	printk("<2>\t%s: WordsPerFrame:      %4d\n",hwicap_driver_name,(unsigned int) xhwicap.WordsPerFrame);	printk("<2>\t%s: ClbBlockFrames:     %4d\n",hwicap_driver_name,(unsigned int) xhwicap.ClbBlockFrames);	printk("<2>\t%s: BramBlockFrames:    %4d\n",hwicap_driver_name,(unsigned int) xhwicap.BramBlockFrames);	printk("<2>\t%s: BramIntBlockFrames: %4d\n",hwicap_driver_name,(unsigned int) xhwicap.BramIntBlockFrames);#endif	return 0;}// unload the module from the kernelstatic void hwicap_exit(void) {	// release the icap device	if(hwicap_device) devfs_unregister(hwicap_device);	// release the major number that we've been using	devfs_dealloc_major(DEVFS_SPECIAL_CHR,hwicap_major_number);	// unmap all of the XUP HWICAP	if(hwicap_virt_ptr) { iounmap(hwicap_virt_ptr); hwicap_virt_ptr = NULL; }	// say goodbye	printk("<1>%s: driver removed\n",hwicap_driver_name);}// open the hwicap deviceint hwicap_open(struct inode *inode_ptr, struct file *file_ptr) {	printk("<1>\t%s: opening %s\n",hwicap_driver_name,file_ptr->f_dentry->d_name.name);//	printk("<1>\t%s: %d, %d\n",hwicap_driver_name,major(inode_ptr->i_rdev),minor(inode_ptr->i_rdev));	// prepare variables	expected_pos = 0;	write_state = FSM_WRITE_STATE_START;	next_write_state = FSM_WRITE_STATE_NULL;	// prepare the local buffer iterators	local_buffer_start = local_buffer_pos = local_buffer;	local_buffer_wall = local_buffer_end = local_buffer_start + sizeof(local_buffer);	word_count = 0;	total_word_count = 0;	// ensure that all header string pointers appear unallocated	header.file_magic_bytes = NULL;	header.design_name_bytes = NULL;	header.device_name_bytes = NULL;	header.date_string_bytes = NULL;	header.time_string_bytes = NULL;	// return success	return 0;}// release the hwicap deviceint hwicap_release(struct inode *inode_ptr, struct file *file_ptr) {	printk("<1>\t%s: releasing %s\n",hwicap_driver_name,file_ptr->f_dentry->d_name.name);	// if the word count fell short of what we expected, let the user know	if((total_word_count << 2) < header.bitstream_length) {		printk("<1>\t%s: received only %8.8X of %8.8X expected words\n",hwicap_driver_name,			total_word_count,(int) header.bitstream_length >> 2);	}	// release any memory allocated for header strings	if(header.file_magic_bytes) kfree(header.file_magic_bytes); header.file_magic_bytes = NULL;	if(header.design_name_bytes) kfree(header.design_name_bytes); header.design_name_bytes = NULL;	if(header.device_name_bytes) kfree(header.device_name_bytes); header.device_name_bytes = NULL;	if(header.date_string_bytes) kfree(header.date_string_bytes); header.date_string_bytes = NULL;	if(header.time_string_bytes) kfree(header.time_string_bytes); header.time_string_bytes = NULL;	// return success	return 0;}// read from the hwicap devicessize_t hwicap_read(struct file *file_ptr, char *buffer, size_t count, loff_t *f_pos) {//	printk("<1>\t%s: reading %s\n",hwicap_driver_name,file_ptr->f_dentry->d_name.name);	return 0;}// write to the hwicap devicessize_t hwicap_write(struct file *file_ptr, const char *buffer, size_t count, loff_t *f_pos) {	printk("<1>\t%s: writing %s: %8.8X bytes from %8.8llX\n",hwicap_driver_name,file_ptr->f_dentry->d_name.name,count,*f_pos);	// declare variables	const char* user_buffer_start = buffer;	const char* user_buffer_pos = buffer;	const char* user_buffer_end = buffer + count;	// ensure that the user writes are sequential	if(*f_pos != expected_pos) return -ESPIPE;	// ensure that we don't flip out and hang up the machine	int max_iterations = 0;	// transfer all the data from the user space through our local buffer	while(user_buffer_pos < user_buffer_end) {		// calculate the amount of data remaining in the user buffer		size_t local_buffer_copy_length = local_buffer_wall - local_buffer_pos;		size_t user_buffer_copy_length = user_buffer_end - user_buffer_pos;

⌨️ 快捷键说明

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