Fail* directories reorganized, Code-cleanup (-> coding-style), Typos+comments fixed.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1321 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
adrian
2012-06-08 20:09:43 +00:00
parent d474a5b952
commit 2575604b41
866 changed files with 1848 additions and 1879 deletions

View File

@ -0,0 +1,2 @@
obj-m += pcidev.o

View File

@ -0,0 +1,75 @@
ifneq ($(KERNELRELEASE), )
# linux kernel 2.6 kbuild invocation
include $(src)/Make.kbuild
else
# command prompt invocation or linux kernel 2.4 build
KERNELDIR = @KERNELDIR@
CC = @CC@
LSMOD = @LSMOD@
INSMOD = @INSMOD@
RMMOD = @RMMOD@
DEPMOD = @DEPMOD@
KERNEL_MODULE_SUFFIX = @KERNEL_MODULE_SUFFIX@
MODULE_NAME = pcidev
MODULE_FILE = $(MODULE_NAME).$(KERNEL_MODULE_SUFFIX)
PCIDEV_MODULE_MAKE_ALL = @PCIDEV_MODULE_MAKE_ALL@
CFLAGS = -Wstrict-prototypes -Wno-trigraphs -g -fno-strict-aliasing -fno-common -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -O -Wall
.PHONY : all
all : $(PCIDEV_MODULE_MAKE_ALL)
.PHONY : all-kernel24
all-kernel24 : $(MODULE_FILE)
$(MODULE_FILE) : pcidev.c kernel_pcidev.h
.PHONY : all-kernel26
all-kernel26 :
$(MAKE) -C $(KERNELDIR) SUBDIRS=$(shell pwd) modules
.PHONY : clean
clean :
@RMCOMMAND@ *.o *~ core *.mod.* .*.cmd *.ko
.PHONY : dist-clean
dist-clean: clean
@RMCOMMAND@ Makefile
.PHONY : devices
devices:
@DEVICE="/dev/pcidev" ; \
if test \! -c $$DEVICE ; then \
echo "Adding $$DEVICE ..." ; \
mknod $$DEVICE c 240 0 ; \
chmod a+wr $$DEVICE ; \
ls -l $$DEVICE ; \
else \
echo "Device $$DEVICE already exists." ; \
fi
# works only under linux of course
.PHONY : install
install:
@if test $$USER != "root" ; then \
echo "Only root can install." ; \
exit 1 ; \
fi ; \
if $(LSMOD) | grep -q $(MODULE_NAME) ; then \
echo "Unloading $(MODULE_NAME) ..." ; \
$(RMMOD) $(MODULE_NAME) ; \
fi ; \
echo "Loading $(MODULE_NAME) ..." ; \
$(INSMOD) $(MODULE_FILE) ; \
echo "Done."
endif

View File

@ -0,0 +1,93 @@
/*
* PCIDEV: PCI host device mapping
* Copyright (C) 2003 Frank Cornelis <fcorneli@pandora.be>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _KERNEL_PCIDEV_H
#define _KERNEL_PCIDEV_H
#define PCIDEV_MAJOR 240
#define PCIDEV_NAME "pcidev"
#define PCIDEV_COUNT_RESOURCES 6
struct pcidev_find_struct {
unsigned long vendorID;
unsigned long deviceID;
unsigned long bus;
unsigned long device;
unsigned long func;
struct {
unsigned long start;
unsigned long end;
unsigned long flags; // see linux/ioport.h
} resources [PCIDEV_COUNT_RESOURCES];
};
// we copied these values from linux/ioport.h since these
// are not accessible from within user space code
#define PCIDEV_RESOURCE_IO 0x100
#define PCIDEV_RESOURCE_MEM 0x200
struct pcidev_io_struct {
unsigned long address;
unsigned long value;
};
#define PCIDEV_IOCTL_MAGIC 'p'
#define PCIDEV_IOCTL_FIND _IOWR(PCIDEV_IOCTL_MAGIC, 0, struct pcidev_find_struct)
#define PCIDEV_IOCTL_READ_CONFIG_BYTE _IOWR(PCIDEV_IOCTL_MAGIC, 1, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_CONFIG_WORD _IOWR(PCIDEV_IOCTL_MAGIC, 2, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_CONFIG_DWORD _IOWR(PCIDEV_IOCTL_MAGIC, 3, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_CONFIG_BYTE _IOR(PCIDEV_IOCTL_MAGIC, 4, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_CONFIG_WORD _IOR(PCIDEV_IOCTL_MAGIC, 5, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_CONFIG_DWORD _IOR(PCIDEV_IOCTL_MAGIC, 6, struct pcidev_io_struct)
#define PCIDEV_IOCTL_INTERRUPT _IO(PCIDEV_IOCTL_MAGIC, 7)
#define PCIDEV_IOCTL_INTERRUPT_TEST _IO(PCIDEV_IOCTL_MAGIC, 8)
#define PCIDEV_IOCTL_READ_IO_BYTE _IOWR(PCIDEV_IOCTL_MAGIC, 9, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_IO_WORD _IOWR(PCIDEV_IOCTL_MAGIC, 10, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_IO_DWORD _IOWR(PCIDEV_IOCTL_MAGIC, 11, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_IO_BYTE _IOR(PCIDEV_IOCTL_MAGIC, 12, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_IO_WORD _IOR(PCIDEV_IOCTL_MAGIC, 13, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_IO_DWORD _IOR(PCIDEV_IOCTL_MAGIC, 14, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_MEM_BYTE _IOWR(PCIDEV_IOCTL_MAGIC, 15, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_MEM_WORD _IOWR(PCIDEV_IOCTL_MAGIC, 16, struct pcidev_io_struct)
#define PCIDEV_IOCTL_READ_MEM_DWORD _IOWR(PCIDEV_IOCTL_MAGIC, 17, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_MEM_BYTE _IOR(PCIDEV_IOCTL_MAGIC, 18, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_MEM_WORD _IOR(PCIDEV_IOCTL_MAGIC, 19, struct pcidev_io_struct)
#define PCIDEV_IOCTL_WRITE_MEM_DWORD _IOR(PCIDEV_IOCTL_MAGIC, 20, struct pcidev_io_struct)
#define PCIDEV_IOCTL_PROBE_CONFIG_DWORD _IOWR(PCIDEV_IOCTL_MAGIC, 21, struct pcidev_io_struct)
#ifdef __KERNEL__
struct pcidev_struct {
struct pci_dev *dev;
int pid; // send irq signals to this task
struct timer_list irq_timer; // for testing the irq signals
void *mapped_mem [PCIDEV_COUNT_RESOURCES];
};
#endif // __KERNEL__
#endif // _KERNEL_PCIDEV_H

View File

@ -0,0 +1,481 @@
/*
* PCIDEV: PCI host device mapping
* Copyright (C) 2003, 2004 Frank Cornelis <fcorneli@pandora.be>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Create the PCIDEV using:
* mknod /dev/pcidev c 240 0
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/version.h>
#include "kernel_pcidev.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Frank Cornelis <fcorneli@pandora.be>");
MODULE_DESCRIPTION("PCI Host Device Mapper Driver");
MODULE_SUPPORTED_DEVICE("pcidev");
//EXPORT_NO_SYMBOLS;
static char *pcidev_name = PCIDEV_NAME;
static int pcidev_open(struct inode *inode, struct file *file)
{
struct pcidev_struct *pcidev = kmalloc(sizeof(struct pcidev_struct), GFP_KERNEL);
int idx;
if (!pcidev)
goto out;
pcidev->dev = NULL;
pcidev->pid = 0;
for (idx = 0; idx < PCIDEV_COUNT_RESOURCES; idx++)
pcidev->mapped_mem[idx] = NULL;
init_timer(&pcidev->irq_timer);
pcidev->irq_timer.function = NULL; // no test irq signaling
out:
file->private_data = pcidev;
return 0;
}
static int pcidev_release(struct inode *inode, struct file *file)
{
struct pcidev_struct *pcidev = (struct pcidev_struct *)file->private_data;
int idx;
if (!pcidev)
return 0;
if (!pcidev->dev)
goto out;
if (pcidev->irq_timer.function)
del_timer_sync(&pcidev->irq_timer);
if (pcidev->pid) {
u8 irq;
pci_read_config_byte(pcidev->dev, PCI_INTERRUPT_PIN, &irq);
pci_read_config_byte(pcidev->dev, PCI_INTERRUPT_LINE, &irq);
free_irq(irq, (void *)pcidev->pid);
}
for (idx = 0; idx < PCIDEV_COUNT_RESOURCES; idx++)
if (pcidev->mapped_mem[idx])
iounmap(pcidev->mapped_mem[idx]);
pci_release_regions(pcidev->dev);
out:
kfree(file->private_data);
return 0;
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
// linux kernel 2.4
typedef void irqreturn_t;
#define IRQ_NONE
#endif
static irqreturn_t pcidev_irqhandler(int irq, void *dev_id, struct pt_regs *regs)
{
int pid = (int)dev_id;
struct task_struct *task;
read_lock(&tasklist_lock);
task = find_task_by_pid(pid);
if (task)
send_sig_info(SIGUSR1, (struct siginfo *)1, task); // XXX: should be converted to real-time signals
read_unlock(&tasklist_lock);
return IRQ_NONE;
/*
* we cannot possible say IRQ_HANDLED because we simply
* don't know yet... only bochs could tell
*/
}
static void irq_test_timer(unsigned long data)
{
struct task_struct *task;
struct pcidev_struct *pcidev = (struct pcidev_struct *)data;
read_lock(&tasklist_lock);
task = find_task_by_pid(pcidev->pid);
if (task)
send_sig_info(SIGUSR1, (struct siginfo *)1, task);
read_unlock(&tasklist_lock);
//printk(KERN_INFO "irq_test_timer\n");
init_timer(&pcidev->irq_timer);
pcidev->irq_timer.data = data;
pcidev->irq_timer.function = irq_test_timer;
pcidev->irq_timer.expires = jiffies + HZ;
add_timer(&pcidev->irq_timer);
}
static int pcidev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0;
struct pcidev_struct *pcidev = (struct pcidev_struct *)file->private_data;
if (!pcidev)
return -EIO;
switch(cmd) {
case PCIDEV_IOCTL_FIND: {
struct pcidev_find_struct *find;
struct pci_dev *dev;
unsigned long vendorID, deviceID;
int idx;
if (pcidev->dev)
return -EIO; // only alloc once for now
if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_find_struct)))
return -EFAULT;
find = (struct pcidev_find_struct *)arg;
__get_user(vendorID, &find->vendorID);
__get_user(deviceID, &find->deviceID);
__put_user(-1, &find->bus);
__put_user(-1, &find->device);
__put_user(-1, &find->func);
dev = pci_find_device(vendorID, deviceID, NULL);
if (!dev)
return -ENOENT;
if (pci_enable_device(dev)) {
printk(KERN_WARNING "pcidev: Could not enable the PCI device.\n");
return -EIO;
}
if (pci_set_dma_mask(dev, 0xffffffff))
printk(KERN_WARNING "pcidev: only limited PCI busmaster DMA support.\n");
pci_set_master(dev);
printk(KERN_INFO "pcidev: device found at %x:%x.%d\n",
dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn));
ret = pci_request_regions(dev, pcidev_name);
if (ret < 0)
break;
for (idx = 0; idx < PCIDEV_COUNT_RESOURCES; idx++) {
if (pci_resource_flags(dev, idx) & IORESOURCE_MEM) {
long len = pci_resource_len(dev, idx);
unsigned long mapped_start = (unsigned long)ioremap(pci_resource_start(dev, idx), len);
__put_user(mapped_start, &find->resources[idx].start);
__put_user(mapped_start + len - 1, &find->resources[idx].end);
pcidev->mapped_mem[idx] = (void *)mapped_start;
}
else {
pcidev->mapped_mem[idx] = NULL;
__put_user(pci_resource_start(dev, idx), &find->resources[idx].start);
__put_user(pci_resource_end(dev, idx), &find->resources[idx].end);
}
__put_user(pci_resource_flags(dev, idx), &find->resources[idx].flags);
}
pcidev->dev = dev;
__put_user(dev->bus->number, &find->bus);
__put_user(PCI_SLOT(dev->devfn), &find->device);
__put_user(PCI_FUNC(dev->devfn), &find->func);
ret = 0;
break;
}
case PCIDEV_IOCTL_READ_CONFIG_BYTE:
case PCIDEV_IOCTL_READ_CONFIG_WORD:
case PCIDEV_IOCTL_READ_CONFIG_DWORD: {
struct pcidev_io_struct *io;
unsigned long address, value;
if (!pcidev->dev)
return -EIO;
if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
__put_user(-1, &io->value);
printk(KERN_DEBUG "pcidev: reading config address %#x\n", (int)address);
switch(cmd) {
case PCIDEV_IOCTL_READ_CONFIG_BYTE:
ret = pci_read_config_byte(pcidev->dev, address, (u8 *)&value);
break;
case PCIDEV_IOCTL_READ_CONFIG_WORD:
ret = pci_read_config_word(pcidev->dev, address, (u16 *)&value);
break;
case PCIDEV_IOCTL_READ_CONFIG_DWORD:
ret = pci_read_config_dword(pcidev->dev, address, (u32 *)&value);
break;
}
if (ret < 0)
return ret;
__put_user(value, &io->value);
break;
}
case PCIDEV_IOCTL_WRITE_CONFIG_BYTE:
case PCIDEV_IOCTL_WRITE_CONFIG_WORD:
case PCIDEV_IOCTL_WRITE_CONFIG_DWORD: {
struct pcidev_io_struct *io;
unsigned long address, value;
if (!pcidev->dev)
return -EIO;
if (!access_ok(VERIFY_READ, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
__get_user(value, &io->value);
/*
* Next tests prevent the pcidev user from remapping
* the PCI host device since this could cause great
* trouble because we don't own those I/O resources.
* If the pcidev wants to remap a device he needs to
* emulate the mapping himself and not bother the host
* kernel about it.
*/
if (address == PCI_INTERRUPT_PIN) {
printk(KERN_WARNING "pcidev: not allowed to set irq pin!\n");
return -EIO;
}
if (address == PCI_INTERRUPT_LINE) {
printk(KERN_WARNING "pcidev: not allowed to set irq line!\n");
return -EIO;
}
if (PCI_BASE_ADDRESS_0 <= address && (address & ~3UL) <= PCI_BASE_ADDRESS_5) {
printk(KERN_WARNING "pcidev: now allowed to change base address %d\n",
(int)((address & ~3UL) - PCI_BASE_ADDRESS_0) / 4);
return -EIO;
}
printk(KERN_DEBUG "pcidev: writing config address %#x\n", (int)address);
switch(cmd) {
case PCIDEV_IOCTL_WRITE_CONFIG_BYTE:
ret = pci_write_config_byte(pcidev->dev, address, (u8)value);
break;
case PCIDEV_IOCTL_WRITE_CONFIG_WORD:
ret = pci_write_config_word(pcidev->dev, address, (u16)value);
break;
case PCIDEV_IOCTL_WRITE_CONFIG_DWORD:
ret = pci_write_config_dword(pcidev->dev, address, (u32)value);
break;
}
break;
}
case PCIDEV_IOCTL_INTERRUPT: {
u8 irq;
if (!pcidev->dev)
return -EIO;
ret = pci_read_config_byte(pcidev->dev, PCI_INTERRUPT_PIN, &irq);
if (ret < 0)
break;
if (!irq)
return -EIO;
ret = pci_read_config_byte(pcidev->dev, PCI_INTERRUPT_LINE, &irq);
if (ret < 0)
break;
if (arg & 1) {
pcidev->pid = current->pid; // our dev_id
printk(KERN_INFO "pcidev: enabling IRQ %d\n", irq);
ret = request_irq(irq, pcidev_irqhandler, SA_SHIRQ,
pcidev_name, (void *)current->pid);
}
else {
if (!pcidev->pid)
return -EIO;
printk(KERN_INFO "pcidev: disabling IRQ %d\n", irq);
free_irq(irq, (void *)pcidev->pid);
pcidev->pid = 0;
ret = 0;
}
break;
}
/*
* Next ioctl is only for testing purposes.
*/
case PCIDEV_IOCTL_INTERRUPT_TEST: {
ret = -EIO;
if (!pcidev->dev)
break;
if (!pcidev->pid)
break;
if (pcidev->irq_timer.function)
del_timer_sync(&pcidev->irq_timer);
pcidev->irq_timer.function = NULL;
if (arg & 1) {
init_timer(&pcidev->irq_timer);
pcidev->irq_timer.function = irq_test_timer;
pcidev->irq_timer.data = (unsigned long)pcidev;
pcidev->irq_timer.expires = jiffies + HZ;
add_timer(&pcidev->irq_timer);
}
ret = 0;
break;
}
case PCIDEV_IOCTL_READ_IO_BYTE:
case PCIDEV_IOCTL_READ_IO_WORD:
case PCIDEV_IOCTL_READ_IO_DWORD: {
/*
* We should probably check access rights against
* the PCI resource list... but who cares for a
* security hole more or less :)
*/
struct pcidev_io_struct *io;
unsigned long address, value = -1;
if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
printk(KERN_DEBUG "pcidev: reading I/O port %#x\n", (int)address);
switch(cmd) {
case PCIDEV_IOCTL_READ_IO_BYTE:
value = inb(address);
break;
case PCIDEV_IOCTL_READ_IO_WORD:
value = inw(address);
break;
case PCIDEV_IOCTL_READ_IO_DWORD:
value = inl(address);
break;
}
__put_user(value, &io->value);
ret = 0;
break;
}
case PCIDEV_IOCTL_WRITE_IO_BYTE:
case PCIDEV_IOCTL_WRITE_IO_WORD:
case PCIDEV_IOCTL_WRITE_IO_DWORD: {
struct pcidev_io_struct *io;
unsigned long address, value;
if (!access_ok(VERIFY_READ, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
__get_user(value, &io->value);
printk(KERN_DEBUG "pcidev: writing I/O port %#x\n", (int)address);
switch(cmd) {
case PCIDEV_IOCTL_WRITE_IO_BYTE:
outb(value, address);
break;
case PCIDEV_IOCTL_WRITE_IO_WORD:
outw(value, address);
break;
case PCIDEV_IOCTL_WRITE_IO_DWORD:
outl(value, address);
break;
}
ret = 0;
break;
}
case PCIDEV_IOCTL_READ_MEM_BYTE:
case PCIDEV_IOCTL_READ_MEM_WORD:
case PCIDEV_IOCTL_READ_MEM_DWORD: {
struct pcidev_io_struct *io;
unsigned long address, value = -1;
if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
printk(KERN_DEBUG "pcidev: reading memory %#x\n", (int)address);
switch(cmd) {
case PCIDEV_IOCTL_READ_MEM_BYTE:
value = readb((unsigned char *)address);
break;
case PCIDEV_IOCTL_READ_MEM_WORD:
value = readw((unsigned short *)address);
break;
case PCIDEV_IOCTL_READ_MEM_DWORD:
value = readl((unsigned int *)address);
break;
}
__put_user(value, &io->value);
ret = 0;
break;
}
case PCIDEV_IOCTL_WRITE_MEM_BYTE:
case PCIDEV_IOCTL_WRITE_MEM_WORD:
case PCIDEV_IOCTL_WRITE_MEM_DWORD: {
struct pcidev_io_struct *io;
unsigned long address, value;
if (!access_ok(VERIFY_READ, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
__get_user(value, &io->value);
printk(KERN_DEBUG "pcidev: writing memory %#x\n", (int)address);
switch(cmd) {
case PCIDEV_IOCTL_WRITE_MEM_BYTE:
writeb(value, (unsigned char *)address);
break;
case PCIDEV_IOCTL_WRITE_MEM_WORD:
writew(value, (unsigned short *)address);
break;
case PCIDEV_IOCTL_WRITE_MEM_DWORD:
writel(value, (unsigned int *)address);
break;
}
ret = 0;
break;
}
case PCIDEV_IOCTL_PROBE_CONFIG_DWORD: {
/*
* This ioctl allows for probing a config space value.
* This can be used for base address size probing
*/
struct pcidev_io_struct *io;
unsigned long address, value, orig_value;
if (!pcidev->dev)
return -EIO;
if (!access_ok(VERIFY_WRITE, (void *)arg, sizeof(struct pcidev_io_struct)))
return -EFAULT;
io = (struct pcidev_io_struct *)arg;
__get_user(address, &io->address);
__get_user(value, &io->value);
__put_user(-1, &io->value);
printk(KERN_INFO "pcidev: probing config space address: %#x\n", (int)address);
ret = pci_read_config_dword(pcidev->dev, address, (u32 *)&orig_value);
if (ret < 0)
break;
pci_write_config_dword(pcidev->dev, address, (u32)value);
pci_read_config_dword(pcidev->dev, address, (u32 *)&value);
ret = pci_write_config_dword(pcidev->dev, address, (u32)orig_value);
if (ret < 0)
break;
__put_user(value, &io->value);
break;
}
default:
ret = -ENOTTY;
}
return ret;
}
static struct file_operations pcidev_fops = {
open: pcidev_open,
release: pcidev_release,
ioctl: pcidev_ioctl,
owner: THIS_MODULE
};
int __init init_module(void)
{
int result;
printk(KERN_INFO "pcidev init\n");
if ((result = register_chrdev(PCIDEV_MAJOR, pcidev_name, &pcidev_fops)) < 0)
printk(KERN_WARNING "Could not register pcidev.\n");
return result;
}
void __exit cleanup_module(void)
{
if (unregister_chrdev(PCIDEV_MAJOR, pcidev_name) < 0)
printk(KERN_WARNING "Could not unregister pcidev.\n");
printk(KERN_INFO "pcidev cleanup\n");
}