--- drivers/misc/Kconfig | 5 + drivers/misc/Makefile | 1 drivers/misc/parport_blinky.c | 152 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) Index: linux-parport-blinky/drivers/misc/Kconfig =================================================================== --- linux-parport-blinky.orig/drivers/misc/Kconfig 2008-04-24 16:04:13.000000000 -0700 +++ linux-parport-blinky/drivers/misc/Kconfig 2008-04-24 16:04:19.000000000 -0700 @@ -13,6 +13,11 @@ menuconfig MISC_DEVICES if MISC_DEVICES +config PARPORT_BLINKY + tristate "Parallel Port Blinky Driver" + help + Yippee!! + config ATMEL_PWM tristate "Atmel AT32/AT91 PWM support" depends on AVR32 || ARCH_AT91 Index: linux-parport-blinky/drivers/misc/parport_blinky.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-parport-blinky/drivers/misc/parport_blinky.c 2008-04-24 16:04:19.000000000 -0700 @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long base = 0x378; +static int irq = -1; +static int flashy = 0; +static int led_state = 0xff; +static void __iomem *iobase; + +static struct platform_device *parport_blinky_platform_driver; + +static ssize_t write_flashy(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + if (!count) + return -EINVAL; + + sscanf(buf, "%d\n", &flashy); + return count; +} +static DEVICE_ATTR(flashy, S_IWUSR, NULL, write_flashy); + +static void parport_blinky_blinky(void) +{ + int i; + + if (flashy) { + for (i = 0; i < 7; i++) { + iowrite8((1 << i), iobase); + mdelay(50); + } + } else { + iowrite8(led_state, iobase); + led_state ? (led_state = 0) : (led_state = 0xff); + } +} + +static void parport_blinky_clear_interrupts(void) +{ + int val; + + val = ioread8(iobase); + val &= 0x7f; + iowrite8(val, iobase); +} + +static void parport_blinky_led_off(void) +{ + iowrite8(0, iobase); +} + +static void parport_blinky_enable_interrupts(void) +{ + iowrite8(0x10, iobase + 2); +} + +irqreturn_t parport_blinky_irq(int irq, void *dev_id) +{ + parport_blinky_blinky(); + parport_blinky_clear_interrupts(); + return IRQ_HANDLED; +} + +static int __init parport_blinky_init(void) +{ + int err; + + if (!request_region(base, 8, "parport_blinky")) { + printk("unable to get i/o region\n"); + } + + iobase = ioport_map(base, 8); + if (!iobase) { + printk("Unable to map ioport\n"); + err = -ENODEV; + goto err_out; + } + + parport_blinky_platform_driver = + platform_device_register_simple("parport_blinky", 0, NULL, 0); + if (IS_ERR(parport_blinky_platform_driver)) { + printk("Unable to register driver\n"); + err = PTR_ERR(parport_blinky_platform_driver); + goto err_out_unmap; + } + + /* create sysfs files */ + err = device_create_file(&parport_blinky_platform_driver->dev, + &dev_attr_flashy); + if (err) { + printk("Error %d registering sysfs file\n", err); + goto err_unregister; + } + + /* should base irq on port address */ + if (irq < 0) + irq = 7; + + /* request IRQ */ + err = request_irq(irq, parport_blinky_irq, 0, + "parport_blinky", NULL); + if (err) { + printk("Unable to request irq\n"); + goto err_remove_sysfs; + } + + parport_blinky_led_off(); + parport_blinky_enable_interrupts(); + return 0; + +err_remove_sysfs: + device_remove_file(&parport_blinky_platform_driver->dev, + &dev_attr_flashy); +err_unregister: + platform_device_unregister(parport_blinky_platform_driver); +err_out_unmap: + ioport_unmap(iobase); +err_out: + release_region(base, 8); + return err; + +} + +static void __exit parport_blinky_exit(void) +{ + free_irq(irq, NULL); + device_remove_file(&parport_blinky_platform_driver->dev, + &dev_attr_flashy); + platform_device_unregister(parport_blinky_platform_driver); + ioport_unmap(iobase); + release_region(base, 8); +} + +MODULE_AUTHOR("Kristen Carlson Accardi