Index: sys/arm/arm/mem.c =================================================================== --- sys/arm/arm/mem.c (revision 269763) +++ sys/arm/arm/mem.c (working copy) @@ -68,9 +68,21 @@ /* * Used in /dev/mem drivers and elsewhere */ +static void arm_mrinit(struct mem_range_softc *); +static int arm_mrset(struct mem_range_softc *, struct mem_range_desc *, int *); + MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors"); -struct mem_range_softc mem_range_softc; +static struct mem_range_ops arm_mem_range_ops = { + arm_mrinit, + arm_mrset, + NULL, + NULL +}; +struct mem_range_softc mem_range_softc = { + &arm_mem_range_ops, + 0, 0, NULL +}; /* ARGSUSED */ int @@ -152,12 +164,132 @@ int memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, - int prot __unused, vm_memattr_t *memattr __unused) + int prot __unused, vm_memattr_t *memattr) { - if (dev2unit(dev) == CDEV_MINOR_MEM) + int i; + + if (dev2unit(dev) == CDEV_MINOR_KMEM) + *paddr = vtophys(offset); + else if (dev2unit(dev) == CDEV_MINOR_MEM) { *paddr = offset; - else if (dev2unit(dev) == CDEV_MINOR_KMEM) - *paddr = vtophys(offset); + + for (i = 0; i < mem_range_softc.mr_ndesc; i++) { + if ((mem_range_softc.mr_desc[i].mr_flags & + MDF_ACTIVE) != 0 && + offset >= mem_range_softc.mr_desc[i].mr_base && + offset < mem_range_softc.mr_desc[i].mr_base + + mem_range_softc.mr_desc[i].mr_len && + (mem_range_softc.mr_desc[i].mr_flags & + MDF_ATTRMASK) == MDF_UNCACHEABLE) { + *memattr = VM_MEMATTR_UNCACHEABLE; + break; + } + } + } /* else panic! */ return (0); } + +static void +arm_mrinit(struct mem_range_softc *sc) +{ + sc->mr_cap = 0; + sc->mr_ndesc = 8; /* XXX: Should be dynamically expandable */ + sc->mr_desc = malloc(sc->mr_ndesc * sizeof(struct mem_range_desc), + M_MEMDESC, M_NOWAIT | M_ZERO); + if (sc->mr_desc == NULL) + panic("%s: malloc returns NULL", __func__); +} + +static int +arm_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int *arg) +{ + int i; + + switch(*arg) { + case MEMRANGE_SET_UPDATE: + for (i = 0; i < sc->mr_ndesc; i++) { + if (!sc->mr_desc[i].mr_len) { + sc->mr_desc[i] = *desc; + sc->mr_desc[i].mr_flags |= MDF_ACTIVE; + return (0); + } + if (sc->mr_desc[i].mr_base == desc->mr_base && + sc->mr_desc[i].mr_len == desc->mr_len) + return (EEXIST); + } + return (ENOSPC); + case MEMRANGE_SET_REMOVE: + for (i = 0; i < sc->mr_ndesc; i++) + if (sc->mr_desc[i].mr_base == desc->mr_base && + sc->mr_desc[i].mr_len == desc->mr_len) { + bzero(&sc->mr_desc[i], sizeof(sc->mr_desc[i])); + return (0); + } + return (ENOENT); + default: + return (EOPNOTSUPP); + } + + return (0); +} + +/* + * Operations for changing memory attributes. + * + * This is basically just an ioctl shim for mem_range_attr_get + * and mem_range_attr_set. + */ +/* ARGSUSED */ +int +memioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int flags, + struct thread *td) +{ + int nd, error = 0; + struct mem_range_op *mo = (struct mem_range_op *)data; + struct mem_range_desc *md; + + /* is this for us? */ + if ((cmd != MEMRANGE_GET) && + (cmd != MEMRANGE_SET)) + return (ENOTTY); + + /* any chance we can handle this? */ + if (mem_range_softc.mr_op == NULL) + return (EOPNOTSUPP); + + /* do we have any descriptors? */ + if (mem_range_softc.mr_ndesc == 0) + return (ENXIO); + + switch (cmd) { + case MEMRANGE_GET: + nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc); + if (nd > 0) { + md = (struct mem_range_desc *) + malloc(nd * sizeof(struct mem_range_desc), + M_MEMDESC, M_WAITOK); + error = mem_range_attr_get(md, &nd); + if (!error) + error = copyout(md, mo->mo_desc, + nd * sizeof(struct mem_range_desc)); + free(md, M_MEMDESC); + } + else + nd = mem_range_softc.mr_ndesc; + mo->mo_arg[0] = nd; + break; + + case MEMRANGE_SET: + md = (struct mem_range_desc *)malloc(sizeof(struct mem_range_desc), + M_MEMDESC, M_WAITOK); + error = copyin(mo->mo_desc, md, sizeof(struct mem_range_desc)); + /* clamp description string */ + md->mr_owner[sizeof(md->mr_owner) - 1] = 0; + if (error == 0) + error = mem_range_attr_set(md, &mo->mo_arg[0]); + free(md, M_MEMDESC); + break; + } + return (error); +} Index: sys/arm/include/memdev.h =================================================================== --- sys/arm/include/memdev.h (revision 269763) +++ sys/arm/include/memdev.h (working copy) @@ -34,7 +34,7 @@ d_open_t memopen; d_read_t memrw; +d_ioctl_t memioctl; d_mmap_t memmmap; -#define memioctl (d_ioctl_t *)NULL #endif /* _MACHINE_MEMDEV_H_ */