#include "local.h" #include /** Request an IO port region. * * \param start start port * \param n number of ports * \param name name of allocator (unused) * * \return NULL error * \return !=NULL success * * \bug Since no one in Linux uses this function's return value, * we do not allocate and fill a resource struct. */ static struct resource *l4dde26_request_region(resource_size_t start, resource_size_t n, const char *name) { int err = ddekit_request_io(start, n); if (err) return NULL; return (struct resource *)1; } /** List of memory regions that have been requested. This is used to * perform ioremap() and iounmap() */ static LIST_HEAD(dde_mem_regions); /** va->pa mapping used to store memory regions */ struct dde_mem_region { ddekit_addr_t pa; ddekit_addr_t va; unsigned int size; struct list_head list; }; void __iomem * ioremap(unsigned long phys_addr, unsigned long size); /** Request an IO memory region. * * \param start start address * \param n size of memory area * \param name name of allocator (unused) * * \return NULL error * \return !=NULL success * * \bug Since no one in Linux uses this function's return value, * we do not allocate and fill a resource struct. */ static struct resource *l4dde26_request_mem_region(resource_size_t start, resource_size_t n, const char *name) { ddekit_addr_t va = 0; struct dde_mem_region *mreg; // do not a resource request twice if (ioremap(start, n)) return (struct resource *)1; int i = ddekit_request_mem(start, n, &va); if (i) { ddekit_printf("request_mem_region() failed (start %lx, size %x)", start, n); return NULL; } mreg = kmalloc(sizeof(struct dde_mem_region), GFP_KERNEL); Assert(mreg); mreg->pa = start; mreg->va = va; mreg->size = n; list_add(&mreg->list, &dde_mem_regions); #if 0 ddekit_pgtab_set_region_with_size((void *)va, start, n, PTE_TYPE_OTHER); #endif return (struct resource *)1; } struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { Assert(parent); Assert(parent->flags & IORESOURCE_IO || parent->flags & IORESOURCE_MEM); switch (parent->flags) { case IORESOURCE_IO: printk("IO: name: %s, start: %x, len: %d\n", name, start, n); return l4dde26_request_region(start, n, name); case IORESOURCE_MEM: printk("MEM: name: %s, start: %x, len: %d\n", name, start, n); return l4dde26_request_mem_region(start, n, name); } return NULL; } /** Release IO port region. */ static void l4dde26_release_region(resource_size_t start, resource_size_t n) { /* FIXME: we need a list of "struct resource"s that have been * allocated by request_region() and then need to * free this stuff here! */ ddekit_release_io(start, n); } /** Release IO memory region. */ static void l4dde26_release_mem_region(resource_size_t start, resource_size_t n) { ddekit_release_mem(start, n); ddekit_pgtab_clear_region((void *)start, PTE_TYPE_OTHER); } int __check_region(struct resource *root, resource_size_t s, resource_size_t n) { WARN_UNIMPL; return -1; } void __release_region(struct resource *root, resource_size_t start, resource_size_t n) { switch (root->flags) { case IORESOURCE_IO: return l4dde26_release_region(start, n); case IORESOURCE_MEM: return l4dde26_release_mem_region(start, n); } } /** Map physical I/O region into virtual address space. * * For our sake, this only returns the virtual address belonging to * the physical region, since we don't manage page tables ourselves. */ void __iomem * ioremap(unsigned long phys_addr, unsigned long size) { struct list_head *pos, *head; head = &dde_mem_regions; list_for_each(pos, head) { struct dde_mem_region *mreg = list_entry(pos, struct dde_mem_region, list); if (mreg->pa <= phys_addr && mreg->pa + mreg->size >= phys_addr + size) { printk ("ioremap: phys: %x <-> virt: %x\n", phys_addr, (mreg->va + (phys_addr - mreg->pa))); return (void *)(mreg->va + (phys_addr - mreg->pa)); } } return NULL; } void __iomem * ioremap_nocache(unsigned long offset, unsigned long size) { return ioremap(offset, size); } void iounmap(volatile void __iomem *addr) { WARN_UNIMPL; }