+static int mem_setup(struct smi_info *info)
+{
+ unsigned long *addr = info->io.info;
+ int mapsize;
+
+ if (!addr || (!*addr))
+ return -ENODEV;
+
+ info->io_cleanup = mem_cleanup;
+
+ /* Figure out the actual readb/readw/readl/etc routine to use based
+ upon the register size. */
+ switch (info->io.regsize) {
+ case 1:
+ info->io.inputb = mem_inb;
+ info->io.outputb = mem_outb;
+ break;
+ case 2:
+ info->io.inputb = mem_inw;
+ info->io.outputb = mem_outw;
+ break;
+ case 4:
+ info->io.inputb = mem_inl;
+ info->io.outputb = mem_outl;
+ break;
+#ifdef readq
+ case 8:
+ info->io.inputb = mem_inq;
+ info->io.outputb = mem_outq;
+ break;
+#endif
+ default:
+ printk("ipmi_si: Invalid register size: %d\n",
+ info->io.regsize);
+ return -EINVAL;
+ }
+
+ /* Calculate the total amount of memory to claim. This is an
+ * unusual looking calculation, but it avoids claiming any
+ * more memory than it has to. It will claim everything
+ * between the first address to the end of the last full
+ * register. */
+ mapsize = ((info->io_size * info->io.regspacing)
+ - (info->io.regspacing - info->io.regsize));
+
+ if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL)
+ return -EIO;
+
+ info->io.addr = ioremap(*addr, mapsize);
+ if (info->io.addr == NULL) {
+ release_mem_region(*addr, mapsize);
+ return -EIO;
+ }
+ return 0;
+}
+