summaryrefslogtreecommitdiffstats
path: root/sys/dev/altera
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2013-01-13 16:43:59 +0000
committerrwatson <rwatson@FreeBSD.org>2013-01-13 16:43:59 +0000
commit37ac175006d12b81ddee3d79a10f5ced5e49196a (patch)
tree769fd38613949ae9e2b4a064a665a94995f3d4fa /sys/dev/altera
parent206a4e8629d17ec6e0264859321a8a7671067092 (diff)
downloadFreeBSD-src-37ac175006d12b81ddee3d79a10f5ced5e49196a.zip
FreeBSD-src-37ac175006d12b81ddee3d79a10f5ced5e49196a.tar.gz
Merge Perforce changeset 219940 to head:
Rework altera_avgen(4) to cleanly(ish) separate nexus bus attachment from the driver itself. This should allow us to plug in an fdt attachment more easily. Sponsored by: DARPA, AFRL
Diffstat (limited to 'sys/dev/altera')
-rw-r--r--sys/dev/altera/avgen/altera_avgen.c94
-rw-r--r--sys/dev/altera/avgen/altera_avgen.h4
-rw-r--r--sys/dev/altera/avgen/altera_avgen_nexus.c322
3 files changed, 21 insertions, 399 deletions
diff --git a/sys/dev/altera/avgen/altera_avgen.c b/sys/dev/altera/avgen/altera_avgen.c
index a90b546..d9d5017 100644
--- a/sys/dev/altera/avgen/altera_avgen.c
+++ b/sys/dev/altera/avgen/altera_avgen.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2012 Robert N. M. Watson
+ * Copyright (c) 2012-2013 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -226,13 +226,6 @@ altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
return (0);
}
-static int
-altera_avgen_nexus_probe(device_t dev)
-{
-
- device_set_desc(dev, "Generic Altera Avalon device attachment");
- return (BUS_PROBE_DEFAULT);
-}
static int
altera_avgen_process_options(struct altera_avgen_softc *sc,
@@ -321,42 +314,14 @@ altera_avgen_process_options(struct altera_avgen_softc *sc,
return (0);
}
-static int
-altera_avgen_nexus_attach(device_t dev)
+int
+altera_avgen_attach(struct altera_avgen_softc *sc, const char *str_fileio,
+ const char *str_mmapio, const char *str_devname, int devunit)
{
- struct altera_avgen_softc *sc;
- const char *str_fileio, *str_mmapio;
- const char *str_devname;
+ device_t dev = sc->avg_dev;
char devname[SPECNAMELEN + 1];
- int devunit, error;
-
- sc = device_get_softc(dev);
- sc->avg_dev = dev;
- sc->avg_unit = device_get_unit(dev);
+ int error;
- /*
- * Query non-standard hints to find out what operations are permitted
- * on the device, and whether it is cached.
- */
- str_fileio = NULL;
- str_mmapio = NULL;
- str_devname = NULL;
- devunit = -1;
- sc->avg_width = 1;
- error = resource_int_value(device_get_name(dev), device_get_unit(dev),
- ALTERA_AVALON_STR_WIDTH, &sc->avg_width);
- if (error != 0 && error != ENOENT) {
- device_printf(dev, "invalid %s\n", ALTERA_AVALON_STR_WIDTH);
- return (error);
- }
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_FILEIO, &str_fileio);
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_MMAPIO, &str_mmapio);
- (void)resource_string_value(device_get_name(dev),
- device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
- (void)resource_int_value(device_get_name(dev), device_get_unit(dev),
- ALTERA_AVALON_STR_DEVUNIT, &devunit);
error = altera_avgen_process_options(sc, str_fileio, str_mmapio,
str_devname, devunit);
if (error)
@@ -374,25 +339,15 @@ altera_avgen_nexus_attach(device_t dev)
snprintf(devname, sizeof(devname), "%s%d", "avgen",
sc->avg_unit);
- /* Memory allocation and checking. */
- sc->avg_rid = 0;
- sc->avg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->avg_rid, RF_ACTIVE);
- if (sc->avg_res == NULL) {
- device_printf(dev, "couldn't map memory\n");
- return (ENXIO);
- }
if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) {
if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) {
device_printf(dev,
"memory region not even multiple of page size\n");
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) {
device_printf(dev, "memory region not page-aligned\n");
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
}
@@ -409,43 +364,16 @@ altera_avgen_nexus_attach(device_t dev)
GID_WHEEL, S_IRUSR | S_IWUSR, str_devname);
if (sc->avg_cdev == NULL) {
device_printf(sc->avg_dev, "%s: make_dev failed\n", __func__);
- error = ENXIO;
- goto error;
+ return (ENXIO);
}
/* XXXRW: Slight race between make_dev(9) and here. */
sc->avg_cdev->si_drv1 = sc;
return (0);
-
-error:
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
- return (error);
}
-static int
-altera_avgen_nexus_detach(device_t dev)
+void
+altera_avgen_detach(struct altera_avgen_softc *sc)
{
- struct altera_avgen_softc *sc;
- sc = device_get_softc(dev);
destroy_dev(sc->avg_cdev);
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
- return (0);
}
-
-static device_method_t altera_avgen_nexus_methods[] = {
- DEVMETHOD(device_probe, altera_avgen_nexus_probe),
- DEVMETHOD(device_attach, altera_avgen_nexus_attach),
- DEVMETHOD(device_detach, altera_avgen_nexus_detach),
- { 0, 0 }
-};
-
-static driver_t altera_avgen_nexus_driver = {
- "altera_avgen",
- altera_avgen_nexus_methods,
- sizeof(struct altera_avgen_softc),
-};
-
-static devclass_t altera_avgen_devclass;
-
-DRIVER_MODULE(avgen, nexus, altera_avgen_nexus_driver, altera_avgen_devclass,
- 0, 0);
diff --git a/sys/dev/altera/avgen/altera_avgen.h b/sys/dev/altera/avgen/altera_avgen.h
index c8c7947..f49ec23 100644
--- a/sys/dev/altera/avgen/altera_avgen.h
+++ b/sys/dev/altera/avgen/altera_avgen.h
@@ -77,7 +77,9 @@ struct altera_avgen_softc {
/*
* Driver setup routines from the bus attachment/teardown.
*/
-int altera_avgen_attach(struct altera_avgen_softc *sc);
+int altera_avgen_attach(struct altera_avgen_softc *sc,
+ const char *str_fileio, const char *str_mmapio,
+ const char *str_devname, int devunit);
void altera_avgen_detach(struct altera_avgen_softc *sc);
#endif /* _DEV_ALTERA_AVALON_H_ */
diff --git a/sys/dev/altera/avgen/altera_avgen_nexus.c b/sys/dev/altera/avgen/altera_avgen_nexus.c
index a90b546..38dd446 100644
--- a/sys/dev/altera/avgen/altera_avgen_nexus.c
+++ b/sys/dev/altera/avgen/altera_avgen_nexus.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2012 Robert N. M. Watson
+ * Copyright (c) 2012-2013 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -53,179 +53,6 @@ __FBSDID("$FreeBSD$");
#include <dev/altera/avgen/altera_avgen.h>
-/*
- * Generic device driver for allowing read(), write(), and mmap() on
- * memory-mapped, Avalon-attached devices. There is no actual dependence on
- * Avalon, so conceivably this should just be soc_dev or similar, since many
- * system-on-chip bus environments would work fine with the same code.
- */
-
-static d_mmap_t altera_avgen_mmap;
-static d_read_t altera_avgen_read;
-static d_write_t altera_avgen_write;
-
-static struct cdevsw avg_cdevsw = {
- .d_version = D_VERSION,
- .d_mmap = altera_avgen_mmap,
- .d_read = altera_avgen_read,
- .d_write = altera_avgen_write,
- .d_name = "altera_avgen",
-};
-
-static int
-altera_avgen_read(struct cdev *dev, struct uio *uio, int flag)
-{
- struct altera_avgen_softc *sc;
- u_long offset, size;
-#ifdef NOTYET
- uint64_t v8;
-#endif
- uint32_t v4;
- uint16_t v2;
- uint8_t v1;
- u_int width;
- int error;
-
- sc = dev->si_drv1;
- if ((sc->avg_flags & ALTERA_AVALON_FLAG_READ) == 0)
- return (EACCES);
- width = sc->avg_width;
- if (uio->uio_offset < 0 || uio->uio_offset % width != 0 ||
- uio->uio_resid % width != 0)
- return (ENODEV);
- size = rman_get_size(sc->avg_res);
- if ((uio->uio_offset + uio->uio_resid < 0) ||
- (uio->uio_offset + uio->uio_resid > size))
- return (ENODEV);
- while (uio->uio_resid > 0) {
- offset = uio->uio_offset;
- if (offset + width > size)
- return (ENODEV);
- switch (width) {
- case 1:
- v1 = bus_read_1(sc->avg_res, offset);
- error = uiomove(&v1, sizeof(v1), uio);
- break;
-
- case 2:
- v2 = bus_read_2(sc->avg_res, offset);
- error = uiomove(&v2, sizeof(v2), uio);
- break;
-
- case 4:
- v4 = bus_read_4(sc->avg_res, offset);
- error = uiomove(&v4, sizeof(v4), uio);
- break;
-
-#ifdef NOTYET
- case 8:
- v8 = bus_read_8(sc->avg_res, offset);
- error = uiomove(&v8, sizeof(v8), uio);
- break;
-
-#endif
-
- default:
- panic("%s: unexpected widthment %u", __func__, width);
- }
- if (error)
- return (error);
- }
- return (0);
-}
-
-static int
-altera_avgen_write(struct cdev *dev, struct uio *uio, int flag)
-{
- struct altera_avgen_softc *sc;
- u_long offset, size;
-#ifdef NOTYET
- uint64_t v8;
-#endif
- uint32_t v4;
- uint16_t v2;
- uint8_t v1;
- u_int width;
- int error;
-
- sc = dev->si_drv1;
- if ((sc->avg_flags & ALTERA_AVALON_FLAG_WRITE) == 0)
- return (EACCES);
- width = sc->avg_width;
- if (uio->uio_offset < 0 || uio->uio_offset % width != 0 ||
- uio->uio_resid % width != 0)
- return (ENODEV);
- size = rman_get_size(sc->avg_res);
- while (uio->uio_resid > 0) {
- offset = uio->uio_offset;
- if (offset + width > size)
- return (ENODEV);
- switch (width) {
- case 1:
- error = uiomove(&v1, sizeof(v1), uio);
- if (error)
- return (error);
- bus_write_1(sc->avg_res, offset, v1);
- break;
-
- case 2:
- error = uiomove(&v2, sizeof(v2), uio);
- if (error)
- return (error);
- bus_write_2(sc->avg_res, offset, v2);
- break;
-
- case 4:
- error = uiomove(&v4, sizeof(v4), uio);
- if (error)
- return (error);
- bus_write_4(sc->avg_res, offset, v4);
- break;
-
-#ifdef NOTYET
- case 8:
- error = uiomove(&v8, sizeof(v8), uio);
- if (error)
- return (error);
- bus_write_8(sc->avg_res, offset, v8);
- break;
-#endif
-
- default:
- panic("%s: unexpected width %u", __func__, width);
- }
- }
- return (0);
-}
-
-static int
-altera_avgen_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
- int nprot, vm_memattr_t *memattr)
-{
- struct altera_avgen_softc *sc;
-
- sc = dev->si_drv1;
- if (nprot & VM_PROT_READ) {
- if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_READ) == 0)
- return (EACCES);
- }
- if (nprot & VM_PROT_WRITE) {
- if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_WRITE) == 0)
- return (EACCES);
- }
- if (nprot & VM_PROT_EXECUTE) {
- if ((sc->avg_flags & ALTERA_AVALON_FLAG_MMAP_EXEC) == 0)
- return (EACCES);
- }
- if (trunc_page(offset) == offset &&
- rman_get_size(sc->avg_res) >= offset + PAGE_SIZE) {
- *paddr = rman_get_start(sc->avg_res) + offset;
- *memattr = VM_MEMATTR_UNCACHEABLE;
- } else
- return (ENODEV);
- return (0);
-}
-
static int
altera_avgen_nexus_probe(device_t dev)
{
@@ -235,99 +62,11 @@ altera_avgen_nexus_probe(device_t dev)
}
static int
-altera_avgen_process_options(struct altera_avgen_softc *sc,
- const char *str_fileio, const char *str_mmapio, const char *str_devname,
- int devunit)
-{
- const char *cp;
- device_t dev = sc->avg_dev;
-
- /*
- * Check for valid combinations of options.
- */
- if (str_fileio == NULL && str_mmapio == NULL) {
- device_printf(dev,
- "at least one of %s or %s must be specified\n",
- ALTERA_AVALON_STR_FILEIO, ALTERA_AVALON_STR_MMAPIO);
- return (ENXIO);
- }
- if (str_devname == NULL && devunit != -1) {
- device_printf(dev, "%s requires %s be specified\n",
- ALTERA_AVALON_STR_DEVUNIT, ALTERA_AVALON_STR_DEVNAME);
- return (ENXIO);
- }
-
- /*
- * Extract, digest, and save values.
- */
- switch (sc->avg_width) {
- case 1:
- case 2:
- case 4:
-#ifdef NOTYET
- case 8:
-#endif
- break;
-
- default:
- device_printf(dev, "%s unsupported value %u\n",
- ALTERA_AVALON_STR_WIDTH, sc->avg_width);
- return (ENXIO);
- }
- sc->avg_flags = 0;
- if (str_fileio != NULL) {
- for (cp = str_fileio; *cp != '\0'; cp++) {
- switch (*cp) {
- case ALTERA_AVALON_CHAR_READ:
- sc->avg_flags |= ALTERA_AVALON_FLAG_READ;
- break;
-
- case ALTERA_AVALON_CHAR_WRITE:
- sc->avg_flags |= ALTERA_AVALON_FLAG_WRITE;
- break;
-
- default:
- device_printf(dev,
- "invalid %s character %c\n",
- ALTERA_AVALON_STR_FILEIO, *cp);
- return (ENXIO);
- }
- }
- }
- if (str_mmapio != NULL) {
- for (cp = str_mmapio; *cp != '\0'; cp++) {
- switch (*cp) {
- case ALTERA_AVALON_CHAR_READ:
- sc->avg_flags |= ALTERA_AVALON_FLAG_MMAP_READ;
- break;
-
- case ALTERA_AVALON_CHAR_WRITE:
- sc->avg_flags |=
- ALTERA_AVALON_FLAG_MMAP_WRITE;
- break;
-
- case ALTERA_AVALON_CHAR_EXEC:
- sc->avg_flags |= ALTERA_AVALON_FLAG_MMAP_EXEC;
- break;
-
- default:
- device_printf(dev,
- "invalid %s character %c\n",
- ALTERA_AVALON_STR_MMAPIO, *cp);
- return (ENXIO);
- }
- }
- }
- return (0);
-}
-
-static int
altera_avgen_nexus_attach(device_t dev)
{
struct altera_avgen_softc *sc;
const char *str_fileio, *str_mmapio;
const char *str_devname;
- char devname[SPECNAMELEN + 1];
int devunit, error;
sc = device_get_softc(dev);
@@ -357,22 +96,6 @@ altera_avgen_nexus_attach(device_t dev)
device_get_unit(dev), ALTERA_AVALON_STR_DEVNAME, &str_devname);
(void)resource_int_value(device_get_name(dev), device_get_unit(dev),
ALTERA_AVALON_STR_DEVUNIT, &devunit);
- error = altera_avgen_process_options(sc, str_fileio, str_mmapio,
- str_devname, devunit);
- if (error)
- return (error);
-
- /* Select a device name. */
- if (str_devname != NULL) {
- if (devunit != -1)
- (void)snprintf(devname, sizeof(devname), "%s%d",
- str_devname, devunit);
- else
- (void)snprintf(devname, sizeof(devname), "%s",
- str_devname);
- } else
- snprintf(devname, sizeof(devname), "%s%d", "avgen",
- sc->avg_unit);
/* Memory allocation and checking. */
sc->avg_rid = 0;
@@ -382,42 +105,11 @@ altera_avgen_nexus_attach(device_t dev)
device_printf(dev, "couldn't map memory\n");
return (ENXIO);
}
- if (rman_get_size(sc->avg_res) >= PAGE_SIZE || str_mmapio != NULL) {
- if (rman_get_size(sc->avg_res) % PAGE_SIZE != 0) {
- device_printf(dev,
- "memory region not even multiple of page size\n");
- error = ENXIO;
- goto error;
- }
- if (rman_get_start(sc->avg_res) % PAGE_SIZE != 0) {
- device_printf(dev, "memory region not page-aligned\n");
- error = ENXIO;
- goto error;
- }
- }
-
- /* Device node allocation. */
- if (str_devname == NULL) {
- str_devname = "altera_avgen%d";
- devunit = sc->avg_unit;
- }
- if (devunit != -1)
- sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit, UID_ROOT,
- GID_WHEEL, S_IRUSR | S_IWUSR, str_devname, devunit);
- else
- sc->avg_cdev = make_dev(&avg_cdevsw, sc->avg_unit, UID_ROOT,
- GID_WHEEL, S_IRUSR | S_IWUSR, str_devname);
- if (sc->avg_cdev == NULL) {
- device_printf(sc->avg_dev, "%s: make_dev failed\n", __func__);
- error = ENXIO;
- goto error;
- }
- /* XXXRW: Slight race between make_dev(9) and here. */
- sc->avg_cdev->si_drv1 = sc;
- return (0);
-
-error:
- bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
+ error = altera_avgen_attach(sc, str_fileio, str_mmapio, str_devname,
+ devunit);
+ if (error != 0)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid,
+ sc->avg_res);
return (error);
}
@@ -427,7 +119,7 @@ altera_avgen_nexus_detach(device_t dev)
struct altera_avgen_softc *sc;
sc = device_get_softc(dev);
- destroy_dev(sc->avg_cdev);
+ altera_avgen_detach(sc);
bus_release_resource(dev, SYS_RES_MEMORY, sc->avg_rid, sc->avg_res);
return (0);
}
OpenPOWER on IntegriCloud