diff options
-rw-r--r-- | drivers/staging/comedi/drivers/ii_pci20kc.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index b1f44b31162..687db433e13 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -33,6 +33,7 @@ /* * Register I/O map */ +#define II20K_SIZE 0x400 #define II20K_MOD_OFFSET 0x100 #define II20K_ID_REG 0x00 #define II20K_ID_MOD1_EMPTY (1 << 7) @@ -439,12 +440,29 @@ static int ii20k_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct comedi_subdevice *s; + unsigned int membase; unsigned char id; bool has_dio; int ret; - /* FIXME: this doesn't seem right, should 'mmio' be ioremap'ed? */ - dev->mmio = (void __iomem *)(unsigned long)it->options[0]; + membase = it->options[0]; + if (!membase || (membase & ~(0x100000 - II20K_SIZE))) { + dev_warn(dev->class_dev, + "%s: invalid memory address specified\n", + dev->board_name); + return -EINVAL; + } + + if (!request_mem_region(membase, II20K_SIZE, dev->board_name)) { + dev_warn(dev->class_dev, "%s: I/O mem conflict (%#x,%u)\n", + dev->board_name, membase, II20K_SIZE); + return -EIO; + } + dev->iobase = membase; /* actually, a memory address */ + + dev->mmio = ioremap(membase, II20K_SIZE); + if (!dev->mmio) + return -ENOMEM; id = readb(dev->mmio + II20K_ID_REG); switch (id & II20K_ID_MASK) { @@ -509,11 +527,19 @@ static int ii20k_attach(struct comedi_device *dev, return 0; } +static void ii20k_detach(struct comedi_device *dev) +{ + if (dev->mmio) + iounmap(dev->mmio); + if (dev->iobase) /* actually, a memory address */ + release_mem_region(dev->iobase, II20K_SIZE); +} + static struct comedi_driver ii20k_driver = { .driver_name = "ii_pci20kc", .module = THIS_MODULE, .attach = ii20k_attach, - .detach = comedi_legacy_detach, + .detach = ii20k_detach, }; module_comedi_driver(ii20k_driver); |