release_mem_region(start,n)
对于arm,powerpc来说,只有I/O内存操作,可以映射到一个虚拟地址,然后用访问指针的方式来读写,而不用ioread等。
相关函数:
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name)) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name)) #define release_region(start,n) __release_region(&ioport_resource, (start), (n)) #define release_mem_region(start,n) __release_region(&iomem_resource, (start), (n))
/* * This is compatibility stuff for IO resources. * * Note how this, unlike the above, knows about * the IO flag meanings (busy etc). * * request_region creates a new busy region. * * check_region returns non-zero if the area is already busy. * * release_region releases a matching busy region. */ /** * __request_region - create a new busy resource region * @parent: parent resource descriptor * @start: resource start address * @n: resource region size * @name: reserving caller's ID string */ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name) { struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (res) { res->name = name; res->start = start; res->end = start + n - 1; res->flags = IORESOURCE_BUSY; write_lock(&resource_lock); for (;;) { struct resource *conflict; conflict = __request_resource(parent, res); if (!conflict) break; if (conflict != parent) { parent = conflict; if (!(conflict->flags & IORESOURCE_BUSY)) continue; } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; break; } write_unlock(&resource_lock); } return res; } EXPORT_SYMBOL(__request_region); /** * __check_region - check if a resource region is busy or free * @parent: parent resource descriptor * @start: resource start address * @n: resource region size * * Returns 0 if the region is free at the moment it is checked, * returns %-EBUSY if the region is busy. * * NOTE: * This function is deprecated because its use is racy. * Even if it returns 0, a subsequent call to request_region() * may fail because another driver etc. just allocated the region. * Do NOT use it. It will be removed from the kernel. */ int __check_region(struct resource *parent, resource_size_t start, resource_size_t n) { struct resource * res; res = __request_region(parent, start, n, "check-region"); if (!res) return -EBUSY; release_resource(res); kfree(res); return 0; } EXPORT_SYMBOL(__check_region); /** * __release_region - release a previously reserved resource region * @parent: parent resource descriptor * @start: resource start address * @n: resource region size * * The described resource region must match a currently busy region. */ void __release_region(struct resource *parent, resource_size_t start, resource_size_t n) { struct resource **p; resource_size_t end; p = &parent->child; end = start + n - 1; write_lock(&resource_lock); for (;;) { struct resource *res = *p; if (!res) break; if (res->start <= start && res->end >= end) { if (!(res->flags & IORESOURCE_BUSY)) { p = &res->child; continue; } if (res->start != start || res->end != end) break; *p = res->sibling; write_unlock(&resource_lock); kfree(res); return; } p = &res->sibling; } write_unlock(&resource_lock); printk(KERN_WARNING "Trying to free nonexistent resource " "<%016llx-%016llx>\n", (unsigned long long)start, (unsigned long long)end); } EXPORT_SYMBOL(__release_region);
/* * We're addressing an 8 or 16-bit peripheral which tranfers * odd addresses on the low ISA byte lane. */ u8 __inb8(unsigned int port) { u32 ret; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2)); else { void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does */ if (port & 1) ret = __raw_readl(a); else ret = __raw_readb(a); } return ret; } /* * We're addressing a 16-bit peripheral which transfers odd * addresses on the high ISA byte lane. */ u8 __inb16(unsigned int port) { unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) offset = port << 2; else offset = (port & ~1) << 1 | (port & 1); return __raw_readb((void __iomem *)ISAIO_BASE + offset); } u16 __inw(unsigned int port) { unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) offset = port << 2; else { offset = port << 1; BUG_ON(port & 1); } return __raw_readw((void __iomem *)ISAIO_BASE + offset); } /* * Fake a 32-bit read with two 16-bit reads. Needed for 3c589. */ u32 __inl(unsigned int port) { void __iomem *a; if (SUPERIO_PORT(port) || port & 3) BUG(); a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); return __raw_readw(a) | __raw_readw(a + 4) << 16; } EXPORT_SYMBOL(__inb8); EXPORT_SYMBOL(__inb16); EXPORT_SYMBOL(__inw); EXPORT_SYMBOL(__inl); void __outb8(u8 val, unsigned int port) { /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2)); else { void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1); /* * Shame nothing else does */ if (port & 1) __raw_writel(val, a); else __raw_writeb(val, a); } } void __outb16(u8 val, unsigned int port) { unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) offset = port << 2; else offset = (port & ~1) << 1 | (port & 1); __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset); } void __outw(u16 val, unsigned int port) { unsigned int offset; /* * The SuperIO registers use sane addressing techniques... */ if (SUPERIO_PORT(port)) offset = port << 2; else { offset = port << 1; BUG_ON(port & 1); } __raw_writew(val, (void __iomem *)ISAIO_BASE + offset); } void __outl(u32 val, unsigned int port) { BUG(); } EXPORT_SYMBOL(__outb8); EXPORT_SYMBOL(__outb16); EXPORT_SYMBOL(__outw); EXPORT_SYMBOL(__outl);
/* * These are typically used in PCI drivers * which are trying to be cross-platform. * * Bus type is always zero on IIep. */ void __iomem *ioremap(unsigned long offset, unsigned long size) { char name[14]; sprintf(name, "phys_%08x", (u32)offset); return _sparc_alloc_io(0, offset, size, name); } /* * Comlimentary to ioremap(). */ void iounmap(volatile void __iomem *virtual) { unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; struct resource *res; if ((res = _sparc_find_resource(&sparc_iomap, vaddr)) == NULL) { printk("free_io/iounmap: cannot free %lx\n", vaddr); return; } _sparc_free_io(res); if ((char *)res >= (char*)xresv && (char *)res < (char *)&xresv[XNRES]) { xres_free((struct xresource *)res); } else { kfree(res); } }