summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hardsid.c124
-rw-r--r--test/Makefile1
-rw-r--r--test/sidtest.c77
3 files changed, 153 insertions, 49 deletions
diff --git a/hardsid.c b/hardsid.c
index 2b514c9..86b1cbe 100644
--- a/hardsid.c
+++ b/hardsid.c
@@ -31,6 +31,9 @@
#include <sys/uio.h>
#include <sys/malloc.h>
#include <sys/bus.h>
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <machine/bus.h>
#include <sys/rman.h>
@@ -39,11 +42,17 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
-/* The softc holds our per-instance data. */
+/* The softc holds our per-instance data.
+*/
struct hardsid_softc
{
- device_t my_dev;
- struct cdev *my_cdev;
+ device_t dev;
+ struct cdev *cdev;
+ int rid;
+ struct mtx lock;
+ struct resource *res;
+ int opened;
+ int reg;
};
/* Function prototypes
@@ -65,29 +74,41 @@ static struct cdevsw hardsid_cdevsw =
.d_name = "hardsid",
};
-/*
- * In the cdevsw routines, we find our softc by using the si_drv1 member
- * of struct cdev. We set this variable to point to our softc in our
- * attach routine when we create the /dev entry.
- */
-
int hardsid_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
struct hardsid_softc *sc;
+ int ret;
- /* Look up our softc. */
sc = dev->si_drv1;
- device_printf(sc->my_dev, "Opened successfully.\n");
- return 0;
+
+ mtx_lock(&sc->lock);
+
+ if (sc->opened)
+ {
+ ret = EACCES;
+ }
+ else
+ {
+ ret = 0;
+ sc->opened = 1;
+ sc->reg = -1;
+ }
+
+ mtx_unlock(&sc->lock);
+
+ return ret;
}
int hardsid_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
struct hardsid_softc *sc;
- /* Look up our softc. */
sc = dev->si_drv1;
- device_printf(sc->my_dev, "Closed.\n");
+
+ mtx_lock(&sc->lock);
+ sc->opened = 0;
+ mtx_unlock(&sc->lock);
+
return 0;
}
@@ -95,9 +116,8 @@ int hardsid_read(struct cdev *dev, struct uio *uio, int ioflag)
{
struct hardsid_softc *sc;
- /* Look up our softc. */
sc = dev->si_drv1;
- device_printf(sc->my_dev, "Asked to read %zd bytes.\n", uio->uio_resid);
+
return 0;
}
@@ -105,18 +125,13 @@ int hardsid_write(struct cdev *dev, struct uio *uio, int ioflag)
{
struct hardsid_softc *sc;
- /* Look up our softc. */
sc = dev->si_drv1;
- device_printf(sc->my_dev, "Asked to write %zd bytes.\n", uio->uio_resid);
+
return 0;
}
/* PCI Support Functions */
-/*
- * Compare the device ID of this device against the IDs that this driver
- * supports. If there is a match, set the description and return success.
- */
static int hardsid_probe(device_t dev)
{
if ((pci_get_vendor(dev) == 0x6581) && (pci_get_device(dev) == 0x8580))
@@ -128,60 +143,70 @@ static int hardsid_probe(device_t dev)
return ENXIO;
}
-/* Attach function is only called if the probe is successful. */
-
+/* Attach function is only called if the probe is successful.
+*/
static int hardsid_attach(device_t dev)
{
struct hardsid_softc *sc;
- /* Look up our softc and initialize its fields. */
+ /* Look up our softc and initialize its fields.
+ */
sc = device_get_softc(dev);
- sc->my_dev = dev;
-
- /*
- * Create a /dev entry for this device. The kernel will assign us
- * a major number automatically. We use the unit number of this
- * device as the minor number and name the character device
- * "hardsid<unit>".
- */
- sc->my_cdev = make_dev(&hardsid_cdevsw, device_get_unit(dev),
- UID_ROOT, GID_WHEEL, 0666, "hardsid%u", device_get_unit(dev));
- sc->my_cdev->si_drv1 = sc;
+ sc->dev = dev;
+ sc->opened = 0;
+ sc->rid = PCIR_BAR(0);
+ sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->rid, RF_ACTIVE);
+ mtx_init(&sc->lock, "hardsid", NULL, MTX_DEF);
+
+ if (sc->res == NULL)
+ {
+ device_printf(dev, "couldn't configure PCI IO resources\n");
+ return ENXIO;
+ }
+
+ /*Create a /dev entry for this device.
+ */
+ sc->cdev = make_dev(&hardsid_cdevsw,
+ device_get_unit(dev),
+ UID_ROOT, GID_WHEEL, 0666,
+ "hardsid%u", device_get_unit(dev));
+
+ sc->cdev->si_drv1 = sc;
return 0;
}
-/* Detach device. */
-
+/* Detach device.
+*/
static int hardsid_detach(device_t dev)
{
struct hardsid_softc *sc;
- /* Teardown the state in our softc created in our attach routine. */
+ /* Teardown the state in our softc created in our attach routine.
+ */
sc = device_get_softc(dev);
- destroy_dev(sc->my_cdev);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->res);
+ destroy_dev(sc->cdev);
return 0;
}
-/* Called during system shutdown after sync. */
-
+/* Called during system shutdown after sync.
+*/
static int hardsid_shutdown(device_t dev)
{
return 0;
}
-/*
- * Device suspend routine.
- */
+/* Device suspend routine.
+*/
static int hardsid_suspend(device_t dev)
{
return 0;
}
-/*
- * Device resume routine.
- */
+/* Device resume routine.
+*/
static int hardsid_resume(device_t dev)
{
return 0;
@@ -189,7 +214,8 @@ static int hardsid_resume(device_t dev)
static device_method_t hardsid_methods[] =
{
- /* Device interface */
+ /* Device interface
+ */
DEVMETHOD(device_probe, hardsid_probe),
DEVMETHOD(device_attach, hardsid_attach),
DEVMETHOD(device_detach, hardsid_detach),
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..60e233d
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1 @@
+sidtest: sidtest.c
diff --git a/test/sidtest.c b/test/sidtest.c
new file mode 100644
index 0000000..767417c
--- /dev/null
+++ b/test/sidtest.c
@@ -0,0 +1,77 @@
+/* Copyright 2018 Ian Cowburn
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+
+int main(int argc, char *argv[])
+{
+ char setsound[] =
+ {
+ 4, 17,
+ 24, 15,
+ 5, 97,
+ 6, 200,
+ 0, 128,
+ 1, 127
+ };
+
+ char clearsound[] =
+ {
+ 24, 0
+ };
+
+ int fd;
+ int wrote;
+
+ fd = open("/dev/hardsid0", O_RDWR);
+
+ if (fd == -1)
+ {
+ perror("open");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((wrote = write(fd, setsound, sizeof setsound)) != sizeof setsound)
+ {
+ printf("Only wrote %d of %zu bytes\n", wrote, sizeof setsound);
+ perror("write");
+ }
+
+ printf("<RET>\n");
+ getchar();
+
+ if ((wrote = write(fd, clearsound, sizeof clearsound)) != sizeof clearsound)
+ {
+ printf("Only wrote %d of %zu bytes\n", wrote, sizeof clearsound);
+ perror("write");
+ }
+
+ close(fd);
+
+ return EXIT_SUCCESS;
+}