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

📄 pciba.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * arch/ia64/sn/io/pciba.c * * IRIX PCIBA-inspired user mode PCI interface * * requires: devfs * * device nodes show up in /dev/pci/BB/SS.F (where BB is the bus the * device is on, SS is the slot the device is in, and F is the * device's function on a multi-function card). * * when compiled into the kernel, it will only be initialized by the * sgi sn1 specific initialization code.  in this case, device nodes * are under /dev/hw/..../ * * This file is subject to the terms and conditions of the GNU General * Public License.  See the file "COPYING" in the main directory of * this archive for more details. * * Copyright (C) 2001-2002 Silicon Graphics, Inc.  All rights reserved. * * 03262001 - Initial version by Chad Talbott *//* jesse's beefs:   register_pci_device should be documented      grossness with do_swap should be documented      big, gross union'ized node_data should be replaced with independent   structures   replace global list of nodes with global lists of resources.  could   use object oriented approach of allocating and cleaning up   resources.   */#include <linux/config.h>#ifndef CONFIG_DEVFS_FS#  error PCIBA requires devfs#endif#include <linux/module.h>#include <linux/devfs_fs_kernel.h>#include <linux/pci.h>#include <linux/list.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/mman.h>#include <linux/init.h>#include <linux/raw.h>#include <linux/capability.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/pgalloc.h>#include <asm/page.h>#include <asm/sn/pci/pciba.h>MODULE_DESCRIPTION("User mode PCI interface");MODULE_AUTHOR("Chad Talbott");#undef DEBUG_PCIBA/* #define DEBUG_PCIBA */#undef TRACE_PCIBA/* #define TRACE_PCIBA */#if defined(DEBUG_PCIBA)#  define DPRINTF(x...) printk(KERN_DEBUG x)#else#  define DPRINTF(x...)#endif#if defined(TRACE_PCIBA)#  if defined(__GNUC__)#    define TRACE()	printk(KERN_DEBUG "%s:%d:%s\n", \			       __FILE__, __LINE__, __FUNCTION__)#  else#    define TRACE()	printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__)#  endif#else#  define TRACE()#endiftypedef enum { failure, success } status;typedef enum { false, true } boolean;/* major data structures:   struct node_data -      	one for each file registered with devfs.  contains everything   	that any file's fops would need to know about.   struct dma_allocation -   	a single DMA allocation.  only the 'dma' nodes care about   	these.  they are there primarily to allow the driver to look   	up the kernel virtual address of dma buffers allocated by   	pci_alloc_consistent, as the application is only given the   	physical address (to program the device's dma, presumably) and   	cannot supply the kernel virtual address when freeing the   	buffer.	it's also useful to maintain a list of buffers allocated	through a specific node to allow some sanity checking by this	driver.  this prevents (for example) a broken application from	freeing buffers that it didn't allocate, or buffers allocated	on another node.      global_node_list -   	a list of all nodes allocated.  this allows the driver to free   	all the memory it has 'kmalloc'd in case of an error, or on   	module removal.   global_dma_list -        a list of all dma buffers allocated by this driver.  this	allows the driver to 'pci_free_consistent' all buffers on	module removal or error.*/struct node_data {	/* flat list of all the device nodes.  makes it easy to free	   them all when we're unregistered */	struct list_head global_node_list;	devfs_handle_t devfs_handle;	void (* cleanup)(struct node_data *);	union {		struct {			struct pci_dev * dev;			struct list_head dma_allocs;			boolean mmapped;		} dma;		struct {			struct pci_dev * dev;			u32 saved_rom_base_reg;			boolean mmapped;		} rom;		struct {			struct resource * res;		} base;		struct {			struct pci_dev * dev;		} config;	} u;};struct dma_allocation {	struct list_head list;	dma_addr_t handle;	void * va;	size_t size;};static LIST_HEAD(global_node_list);static LIST_HEAD(global_dma_list);/* module entry points */int __init pciba_init(void);void __exit pciba_exit(void);static status __init register_with_devfs(void);static void __exit unregister_with_devfs(void);static status __init register_pci_device(devfs_handle_t device_dir_handle,					 struct pci_dev * dev);/* file operations */static int generic_open(struct inode * inode, struct file * file);static int rom_mmap(struct file * file, struct vm_area_struct * vma);static int rom_release(struct inode * inode, struct file * file);static int base_mmap(struct file * file, struct vm_area_struct * vma);static int config_ioctl(struct inode * inode, struct file * file, 			unsigned int cmd, 			unsigned long arg);static int dma_ioctl(struct inode * inode, struct file * file, 		     unsigned int cmd, 		     unsigned long arg);static int dma_mmap(struct file * file, struct vm_area_struct * vma);/* support routines */static int mmap_pci_address(struct vm_area_struct * vma, unsigned long pci_va);static int mmap_kernel_address(struct vm_area_struct * vma, void * kernel_va);#ifdef DEBUG_PCIBAstatic void dump_nodes(struct list_head * nodes);static void dump_allocations(struct list_head * dalp);#endif/* file operations for each type of node */static struct file_operations rom_fops = {	owner:		THIS_MODULE,	mmap:		rom_mmap,	open:		generic_open,	release:	rom_release}; static struct file_operations base_fops = {	owner:		THIS_MODULE,	mmap:		base_mmap,	open:		generic_open};static struct file_operations config_fops = {	owner:		THIS_MODULE,	ioctl:		config_ioctl,	open:		generic_open};	static struct file_operations dma_fops = {	owner:		THIS_MODULE,	ioctl:		dma_ioctl,	mmap:		dma_mmap,	open:		generic_open};	module_init(pciba_init);module_exit(pciba_exit);int __initpciba_init(void){	TRACE();	if (register_with_devfs() == failure)		return 1; /* failure */	printk("PCIBA (a user mode PCI interface) initialized.\n");	return 0; /* success */}void __exitpciba_exit(void){	TRACE();	/* FIXME: should also free all that memory that we allocated           ;) */	unregister_with_devfs();}# if 0static void __exitfree_nodes(void){	struct node_data * nd;		TRACE();	list_for_each(nd, &node_list) {		kfree(list_entry(nd, struct nd, node_list));	}}#endifstatic devfs_handle_t pciba_devfs_handle;#if !defined(CONFIG_IA64_SGI_SN1)static status __initregister_with_devfs(void){	struct pci_dev * dev;	devfs_handle_t device_dir_handle;	char devfs_path[40];	TRACE();	pciba_devfs_handle = devfs_mk_dir(NULL, "pci", NULL);	if (pciba_devfs_handle == NULL)		return failure;	/* FIXME: don't forget /dev/pci/mem & /dev/pci/io */	pci_for_each_dev(dev) {		sprintf(devfs_path, "%02x/%02x.%x",			dev->bus->number,			PCI_SLOT(dev->devfn),			PCI_FUNC(dev->devfn));    		device_dir_handle =			devfs_mk_dir(pciba_devfs_handle, devfs_path, NULL);		if (device_dir_handle == NULL)			return failure;		if (register_pci_device(device_dir_handle, dev) == failure) {			devfs_unregister(pciba_devfs_handle);			return failure;		}	}	return success;}#elseextern devfs_handle_tdevfn_to_vertex(unsigned char busnum, unsigned int devfn);static status __initregister_with_devfs(void){	struct pci_dev * dev;	devfs_handle_t device_dir_handle;	TRACE();	/* FIXME: don't forget /dev/.../pci/mem & /dev/.../pci/io */	pci_for_each_dev(dev) {		device_dir_handle = devfn_to_vertex(dev->bus->number,						    dev->devfn);		if (device_dir_handle == NULL)			return failure;			if (register_pci_device(device_dir_handle, dev) == failure) {			devfs_unregister(pciba_devfs_handle);			return failure;		}	}	return success;}#endif /* CONFIG_IA64_SGI_SN1 */static void __exitunregister_with_devfs(void){	struct list_head * lhp;	struct node_data * nd;		TRACE();	list_for_each(lhp, &global_node_list) {		nd = list_entry(lhp, struct node_data, global_node_list);		devfs_unregister(nd->devfs_handle);	}}struct node_data * new_node(void){	struct node_data * node;		TRACE();		node = kmalloc(sizeof(struct node_data), GFP_KERNEL);	if (node == NULL)		return NULL;	list_add(&node->global_node_list, &global_node_list);	return node;}void dma_cleanup(struct node_data * dma_node){	TRACE();	/* FIXME: should free these allocations */#ifdef DEBUG_PCIBA	dump_allocations(&dma_node->u.dma.dma_allocs);#endif	devfs_unregister(dma_node->devfs_handle);}void init_dma_node(struct node_data * node,		   struct pci_dev * dev, devfs_handle_t dh){	TRACE();	node->devfs_handle = dh;	node->u.dma.dev = dev;	node->cleanup = dma_cleanup;	INIT_LIST_HEAD(&node->u.dma.dma_allocs);}void rom_cleanup(struct node_data * rom_node){	TRACE();	if (rom_node->u.rom.mmapped)		pci_write_config_dword(rom_node->u.rom.dev,				       PCI_ROM_ADDRESS,				       rom_node->u.rom.saved_rom_base_reg);	devfs_unregister(rom_node->devfs_handle);}void init_rom_node(struct node_data * node,		   struct pci_dev * dev, devfs_handle_t dh){	TRACE();	node->devfs_handle = dh;	node->u.rom.dev = dev;	node->cleanup = rom_cleanup;	node->u.rom.mmapped = false;}static status __initregister_pci_device(devfs_handle_t device_dir_handle, struct pci_dev * dev){	struct node_data * nd;	char devfs_path[20];	devfs_handle_t node_devfs_handle;	int ri;	TRACE();	/* register nodes for all the device's base address registers */	for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {		if (pci_resource_len(dev, ri) != 0) {			sprintf(devfs_path, "base/%d", ri);			if (devfs_register(device_dir_handle, devfs_path,					   DEVFS_FL_NONE,					   0, 0,					   S_IFREG | S_IRUSR | S_IWUSR,					   &base_fops, 					   &dev->resource[ri]) == NULL)				return failure;		}	}		/* register a node corresponding to the first MEM resource on           the device */	for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {		if (dev->resource[ri].flags & IORESOURCE_MEM &&		    pci_resource_len(dev, ri) != 0) {			if (devfs_register(device_dir_handle, "mem",					   DEVFS_FL_NONE, 0, 0,					   S_IFREG | S_IRUSR | S_IWUSR,					   &base_fops, 					   &dev->resource[ri]) == NULL)				return failure;			break;		}	}	/* also register a node corresponding to the first IO resource           on the device */	for (ri = 0; ri < PCI_ROM_RESOURCE; ri++) {		if (dev->resource[ri].flags & IORESOURCE_IO &&		    pci_resource_len(dev, ri) != 0) {

⌨️ 快捷键说明

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