Commit fc15bc81 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/uio-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/uio-2.6:
  UIO: Hilscher CIF card driver
  UIO: Documentation
  UIO: Add the User IO core code
parents a8dcf12f bc4c4f45
......@@ -408,6 +408,10 @@ X!Edrivers/pnp/system.c
!Edrivers/pnp/manager.c
!Edrivers/pnp/support.c
</sect1>
<sect1><title>Userspace IO devices</title>
!Edrivers/uio/uio.c
!Iinclude/linux/uio_driver.h
</sect1>
</chapter>
<chapter id="blkdev">
......
This diff is collapsed.
......@@ -84,4 +84,5 @@ source "drivers/auxdisplay/Kconfig"
source "drivers/kvm/Kconfig"
source "drivers/uio/Kconfig"
endmenu
......@@ -40,6 +40,7 @@ obj-$(CONFIG_ATA) += ata/
obj-$(CONFIG_FUSION) += message/
obj-$(CONFIG_FIREWIRE) += firewire/
obj-$(CONFIG_IEEE1394) += ieee1394/
obj-$(CONFIG_UIO) += uio/
obj-y += cdrom/
obj-y += auxdisplay/
obj-$(CONFIG_MTD) += mtd/
......
menu "Userspace I/O"
depends on !S390
config UIO
tristate "Userspace I/O drivers"
default n
help
Enable this to allow the userspace driver core code to be
built. This code allows userspace programs easy access to
kernel interrupts and memory locations, allowing some drivers
to be written in userspace. Note that a small kernel driver
is also required for interrupt handling to work properly.
If you don't know what to do here, say N.
config UIO_CIF
tristate "generic Hilscher CIF Card driver"
depends on UIO && PCI
default n
help
Driver for Hilscher CIF DeviceNet and Profibus cards. This
driver requires a userspace component that handles all of the
heavy lifting and can be found at:
http://www.osadl.org/projects/downloads/UIO/user/cif-*
To compile this driver as a module, choose M here: the module
will be called uio_cif.
endmenu
obj-$(CONFIG_UIO) += uio.o
obj-$(CONFIG_UIO_CIF) += uio_cif.o
This diff is collapsed.
/*
* UIO Hilscher CIF card driver
*
* (C) 2007 Hans J. Koch <hjk@linutronix.de>
* Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
*
* Licensed under GPL version 2 only.
*
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/uio_driver.h>
#include <asm/io.h>
#ifndef PCI_DEVICE_ID_PLX_9030
#define PCI_DEVICE_ID_PLX_9030 0x9030
#endif
#define PLX9030_INTCSR 0x4C
#define INTSCR_INT1_ENABLE 0x01
#define INTSCR_INT1_STATUS 0x04
#define INT1_ENABLED_AND_ACTIVE (INTSCR_INT1_ENABLE | INTSCR_INT1_STATUS)
#define PCI_SUBVENDOR_ID_PEP 0x1518
#define CIF_SUBDEVICE_PROFIBUS 0x430
#define CIF_SUBDEVICE_DEVICENET 0x432
static irqreturn_t hilscher_handler(int irq, struct uio_info *dev_info)
{
void __iomem *plx_intscr = dev_info->mem[0].internal_addr
+ PLX9030_INTCSR;
if ((ioread8(plx_intscr) & INT1_ENABLED_AND_ACTIVE)
!= INT1_ENABLED_AND_ACTIVE)
return IRQ_NONE;
/* Disable interrupt */
iowrite8(ioread8(plx_intscr) & ~INTSCR_INT1_ENABLE, plx_intscr);
return IRQ_HANDLED;
}
static int __devinit hilscher_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
struct uio_info *info;
info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if (pci_enable_device(dev))
goto out_free;
if (pci_request_regions(dev, "hilscher"))
goto out_disable;
info->mem[0].addr = pci_resource_start(dev, 0);
if (!info->mem[0].addr)
goto out_release;
info->mem[0].internal_addr = ioremap(pci_resource_start(dev, 0),
pci_resource_len(dev, 0));
if (!info->mem[0].internal_addr)
goto out_release;
info->mem[0].size = pci_resource_len(dev, 0);
info->mem[0].memtype = UIO_MEM_PHYS;
info->mem[1].addr = pci_resource_start(dev, 2);
info->mem[1].size = pci_resource_len(dev, 2);
info->mem[1].memtype = UIO_MEM_PHYS;
switch (id->subdevice) {
case CIF_SUBDEVICE_PROFIBUS:
info->name = "CIF_Profibus";
break;
case CIF_SUBDEVICE_DEVICENET:
info->name = "CIF_Devicenet";
break;
default:
info->name = "CIF_???";
}
info->version = "0.0.1";
info->irq = dev->irq;
info->irq_flags = IRQF_DISABLED | IRQF_SHARED;
info->handler = hilscher_handler;
if (uio_register_device(&dev->dev, info))
goto out_unmap;
pci_set_drvdata(dev, info);
return 0;
out_unmap:
iounmap(info->mem[0].internal_addr);
out_release:
pci_release_regions(dev);
out_disable:
pci_disable_device(dev);
out_free:
kfree (info);
return -ENODEV;
}
static void hilscher_pci_remove(struct pci_dev *dev)
{
struct uio_info *info = pci_get_drvdata(dev);
uio_unregister_device(info);
pci_release_regions(dev);
pci_disable_device(dev);
pci_set_drvdata(dev, NULL);
iounmap(info->mem[0].internal_addr);
kfree (info);
}
static struct pci_device_id hilscher_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9030,
.subvendor = PCI_SUBVENDOR_ID_PEP,
.subdevice = CIF_SUBDEVICE_PROFIBUS,
},
{
.vendor = PCI_VENDOR_ID_PLX,
.device = PCI_DEVICE_ID_PLX_9030,
.subvendor = PCI_SUBVENDOR_ID_PEP,
.subdevice = CIF_SUBDEVICE_DEVICENET,
},
{ 0, }
};
static struct pci_driver hilscher_pci_driver = {
.name = "hilscher",
.id_table = hilscher_pci_ids,
.probe = hilscher_pci_probe,
.remove = hilscher_pci_remove,
};
static int __init hilscher_init_module(void)
{
return pci_register_driver(&hilscher_pci_driver);
}
static void __exit hilscher_exit_module(void)
{
pci_unregister_driver(&hilscher_pci_driver);
}
module_init(hilscher_init_module);
module_exit(hilscher_exit_module);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
/*
* include/linux/uio_driver.h
*
* Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
* Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
* Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de>
* Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
*
* Userspace IO driver.
*
* Licensed under the GPLv2 only.
*/
#ifndef _UIO_DRIVER_H_
#define _UIO_DRIVER_H_
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
/**
* struct uio_mem - description of a UIO memory region
* @kobj: kobject for this mapping
* @addr: address of the device's memory
* @size: size of IO
* @memtype: type of memory addr points to
* @internal_addr: ioremap-ped version of addr, for driver internal use
*/
struct uio_mem {
struct kobject kobj;
unsigned long addr;
unsigned long size;
int memtype;
void __iomem *internal_addr;
};
#define MAX_UIO_MAPS 5
struct uio_device;
/**
* struct uio_info - UIO device capabilities
* @uio_dev: the UIO device this info belongs to
* @name: device name
* @version: device driver version
* @mem: list of mappable memory regions, size==0 for end of list
* @irq: interrupt number or UIO_IRQ_CUSTOM
* @irq_flags: flags for request_irq()
* @priv: optional private data
* @handler: the device's irq handler
* @mmap: mmap operation for this uio device
* @open: open operation for this uio device
* @release: release operation for this uio device
*/
struct uio_info {
struct uio_device *uio_dev;
char *name;
char *version;
struct uio_mem mem[MAX_UIO_MAPS];
long irq;
unsigned long irq_flags;
void *priv;
irqreturn_t (*handler)(int irq, struct uio_info *dev_info);
int (*mmap)(struct uio_info *info, struct vm_area_struct *vma);
int (*open)(struct uio_info *info, struct inode *inode);
int (*release)(struct uio_info *info, struct inode *inode);
};
extern int __must_check
__uio_register_device(struct module *owner,
struct device *parent,
struct uio_info *info);
static inline int __must_check
uio_register_device(struct device *parent, struct uio_info *info)
{
return __uio_register_device(THIS_MODULE, parent, info);
}
extern void uio_unregister_device(struct uio_info *info);
extern void uio_event_notify(struct uio_info *info);
/* defines for uio_device->irq */
#define UIO_IRQ_CUSTOM -1
#define UIO_IRQ_NONE -2
/* defines for uio_device->memtype */
#define UIO_MEM_NONE 0
#define UIO_MEM_PHYS 1
#define UIO_MEM_LOGICAL 2
#define UIO_MEM_VIRTUAL 3
#endif /* _LINUX_UIO_DRIVER_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment