diff options
author | marcel <marcel@FreeBSD.org> | 2014-04-28 17:58:40 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2014-04-28 17:58:40 +0000 |
commit | a57fca2a55060edbb3813ae93a3e91dfeef38806 (patch) | |
tree | e7eb8ecbeac13e1920cc206456bd2c0cb1c07ea0 | |
parent | b384f8775fb9dac291a6c48827c9f7c4bd2bc455 (diff) | |
download | FreeBSD-src-a57fca2a55060edbb3813ae93a3e91dfeef38806.zip FreeBSD-src-a57fca2a55060edbb3813ae93a3e91dfeef38806.tar.gz |
Add proto(4): A driver for prototyping and diagnostics.
It exposes I/O resources to user space, so that programs can peek
and poke at the hardware. It does not itself have knowledge about
the hardware device it attaches to.
Sponsored by: Juniper Networks, Inc.
-rw-r--r-- | share/man/man4/Makefile | 1 | ||||
-rw-r--r-- | share/man/man4/proto.4 | 121 | ||||
-rw-r--r-- | sys/dev/proto/proto.h | 63 | ||||
-rw-r--r-- | sys/dev/proto/proto_bus_pci.c | 112 | ||||
-rw-r--r-- | sys/dev/proto/proto_core.c | 384 | ||||
-rw-r--r-- | sys/dev/proto/proto_dev.h | 43 | ||||
-rw-r--r-- | sys/modules/Makefile | 1 | ||||
-rw-r--r-- | sys/modules/proto/Makefile | 20 |
8 files changed, 745 insertions, 0 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 59fd3e9..162b423 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -378,6 +378,7 @@ MAN= aac.4 \ ppc.4 \ ppi.4 \ procdesc.4 \ + proto.4 \ psm.4 \ pst.4 \ pt.4 \ diff --git a/share/man/man4/proto.4 b/share/man/man4/proto.4 new file mode 100644 index 0000000..bfbdba2 --- /dev/null +++ b/share/man/man4/proto.4 @@ -0,0 +1,121 @@ +.\" +.\" Copyright (c) 2014 Marcel Moolenaar +.\" All rights reserved. +.\" +.\" 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 AUTHOR ``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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.Dd April 21, 2014 +.Dt PROTO 4 +.Os +.\" +.Sh NAME +.Nm proto +.Nd Driver for prototyping and H/W diagnostics +.\" +.Sh SYNOPSIS +.Cd "device proto" +.\" +.Sh DESCRIPTION +The +.Nm +device driver attaches to PCI devices when no other device drivers are +present and creates device special files for all resources associated +with the device. +The driver itself has no knowledge of the device it attaches to. +Programs can open these device special files and peform register-level +reads and writes. +As such, the +.Nm +device driver is nothing but a conduit or gateway between user space +programs and the hardware device. +.Pp +Examples for why this is useful include hardware diagnostics and prototyping. +In both these use cases, it's far more convenient to develop and run the +logic in user space. +Especially hardware diagnostics requires a somewhat user-friendly interface +and adequate reporting. +Neither is done easily as kernel code. +.\" +.Sh FILES +All device special files corresponding to a PCI device are located under +.Pa /dev/proto/pci<d>:<b>:<s>:<f> +with +.Pa pci<d>:<b>:<s>:<f> +representing the location of the PCI device in the PCI hierarchy. +A location includes: +.Bl -tag -width XXXXXX -compact +.It <d> +The PCI domain number +.It <b> +The PCI bus number +.It <s> +The PCI slot or device number +.It <f> +The PCI function number +.El +.Pp +Every PCI device has a device special file called +.Pa pcicfg . +This device special file gives access to the PCI configuration space. +For each valid base address register (BAR), a device special file is created +that contains the BAR offset and the resource type. +A resource type can be either +.Pa io +or +.Pa mem +representing I/O port or memory mapped I/O space (resp.) +.\" +.Sh EXAMPLES +A single function PCI device in domain 0, on bus 1, in slot 2 and having a +single memory mapped I/O region will have the following device special files: +.Bl -tag -compact +.It Pa /dev/proto/pci0:1:2:0/10.mem +.It Pa /dev/proto/pci0:1:2:0/pcicfg +.El +.\" +.Sh SECURITY CONSIDERATIONS +Because programs have direct access to the hardware, the +.Nm +driver is inherently insecure. +It is not advisable to use this driver on a production machine. +.\" +.Sh MISSING FUNCTIONALITY +The +.Nm +driver does not yet support interrupts. +Since interrupts cannot be handled by the driver itself, they must be converted +into signals and delivered to the program that has registered for interrupts. +.Pp +In order to test the transmission or reception of data, some means of doing +direct memory access (DMA) by the device must be possible. This too much be +under the control of the program. The details of how a program can setup and +initiate DMA still need to be fleshed out. +.Pp +Support for non-PCI devices has not been implemented yet. +.\" +.Sh AUTHORS +The +.Nm +device driver and this manual page were written by +.An Marcel Moolenaar Aq marcel@xcllnt.net . diff --git a/sys/dev/proto/proto.h b/sys/dev/proto/proto.h new file mode 100644 index 0000000..db61da5 --- /dev/null +++ b/sys/dev/proto/proto.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2014 Marcel Moolenaar + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _DEV_PROTO_H_ +#define _DEV_PROTO_H_ + +#define PROTO_RES_MAX 16 + +#define PROTO_RES_UNUSED 0 +#define PROTO_RES_PCICFG 10 + +struct proto_res { + int r_type; + int r_rid; + struct resource *r_res; + u_long r_size; + union { + void *cookie; + struct cdev *cdev; + } r_u; + uintptr_t r_opened; +}; + +struct proto_softc { + device_t sc_dev; + struct proto_res sc_res[PROTO_RES_MAX]; + int sc_rescnt; +}; + +extern devclass_t proto_devclass; +extern char proto_driver_name[]; + +int proto_add_resource(struct proto_softc *, int, int, struct resource *); + +int proto_attach(device_t dev); +int proto_detach(device_t dev); + +#endif /* _DEV_PROTO_H_ */ diff --git a/sys/dev/proto/proto_bus_pci.c b/sys/dev/proto/proto_bus_pci.c new file mode 100644 index 0000000..012469a --- /dev/null +++ b/sys/dev/proto/proto_bus_pci.c @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 2014 Marcel Moolenaar + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> +#include <sys/sbuf.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <dev/proto/proto.h> + +static int proto_pci_probe(device_t dev); +static int proto_pci_attach(device_t dev); + +static device_method_t proto_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, proto_pci_probe), + DEVMETHOD(device_attach, proto_pci_attach), + DEVMETHOD(device_detach, proto_detach), + DEVMETHOD_END +}; + +static driver_t proto_pci_driver = { + proto_driver_name, + proto_pci_methods, + sizeof(struct proto_softc), +}; + +static int +proto_pci_probe(device_t dev) +{ + struct sbuf *sb; + + /* For now we only attach to function 0 devices. */ + if (pci_get_function(dev) != 0) + return (ENXIO); + + sb = sbuf_new_auto(); + sbuf_printf(sb, "pci%d:%d:%d:%d", pci_get_domain(dev), + pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)); + sbuf_finish(sb); + device_set_desc_copy(dev, sbuf_data(sb)); + sbuf_delete(sb); + return (BUS_PROBE_HOOVER); +} + +static int +proto_pci_attach(device_t dev) +{ + struct proto_softc *sc; + struct resource *res; + int bar, rid, type; + + sc = device_get_softc(dev); + + proto_add_resource(sc, PROTO_RES_PCICFG, 0, NULL); + + for (bar = 0; bar < PCIR_MAX_BAR_0; bar++) { + rid = PCIR_BAR(bar); + type = SYS_RES_MEMORY; + res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE); + if (res == NULL) { + type = SYS_RES_IOPORT; + res = bus_alloc_resource_any(dev, type, &rid, + RF_ACTIVE); + } + if (res != NULL) + proto_add_resource(sc, type, rid, res); + } + + rid = 0; + type = SYS_RES_IRQ; + res = bus_alloc_resource_any(dev, type, &rid, RF_ACTIVE | RF_SHAREABLE); + if (res != NULL) + proto_add_resource(sc, type, rid, res); + return (proto_attach(dev)); +} + +DRIVER_MODULE(proto, pci, proto_pci_driver, proto_devclass, NULL, NULL); diff --git a/sys/dev/proto/proto_core.c b/sys/dev/proto/proto_core.c new file mode 100644 index 0000000..5ea0a6c --- /dev/null +++ b/sys/dev/proto/proto_core.c @@ -0,0 +1,384 @@ +/*- + * Copyright (c) 2014 Marcel Moolenaar + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/cons.h> +#include <sys/fcntl.h> +#include <sys/interrupt.h> +#include <sys/kdb.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/mman.h> +#include <sys/proc.h> +#include <sys/queue.h> +#include <sys/reboot.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <sys/uio.h> +#include <machine/resource.h> +#include <machine/stdarg.h> + +#include <dev/pci/pcivar.h> + +#include <dev/proto/proto.h> +#include <dev/proto/proto_dev.h> + +CTASSERT(SYS_RES_IRQ != PROTO_RES_UNUSED && + SYS_RES_MEMORY != PROTO_RES_UNUSED && + SYS_RES_IOPORT != PROTO_RES_UNUSED); +CTASSERT(SYS_RES_IRQ != PROTO_RES_PCICFG && + SYS_RES_MEMORY != PROTO_RES_PCICFG && + SYS_RES_IOPORT != PROTO_RES_PCICFG); + +devclass_t proto_devclass; +char proto_driver_name[] = "proto"; + +static d_open_t proto_open; +static d_close_t proto_close; +static d_read_t proto_read; +static d_write_t proto_write; +static d_ioctl_t proto_ioctl; +static d_mmap_t proto_mmap; + +struct cdevsw proto_devsw = { + .d_version = D_VERSION, + .d_flags = 0, + .d_name = proto_driver_name, + .d_open = proto_open, + .d_close = proto_close, + .d_read = proto_read, + .d_write = proto_write, + .d_ioctl = proto_ioctl, + .d_mmap = proto_mmap, +}; + +static MALLOC_DEFINE(M_PROTO, "PROTO", "PROTO driver"); + +int +proto_add_resource(struct proto_softc *sc, int type, int rid, + struct resource *res) +{ + struct proto_res *r; + + if (type == PROTO_RES_UNUSED) + return (EINVAL); + if (sc->sc_rescnt == PROTO_RES_MAX) + return (ENOSPC); + + r = sc->sc_res + sc->sc_rescnt++; + r->r_type = type; + r->r_rid = rid; + r->r_res = res; + return (0); +} + +#ifdef notyet +static int +proto_intr(void *arg) +{ + struct proto_softc *sc = arg; + + /* XXX TODO */ + return (FILTER_HANDLED); +} +#endif + +int +proto_attach(device_t dev) +{ + struct proto_softc *sc; + struct proto_res *r; + u_int res; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + for (res = 0; res < sc->sc_rescnt; res++) { + r = sc->sc_res + res; + switch (r->r_type) { + case SYS_RES_IRQ: + /* XXX TODO */ + break; + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + r->r_size = rman_get_size(r->r_res); + r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, + "proto/%s/%02x.%s", device_get_desc(dev), r->r_rid, + (r->r_type == SYS_RES_IOPORT) ? "io" : "mem"); + r->r_u.cdev->si_drv1 = sc; + r->r_u.cdev->si_drv2 = r; + break; + case PROTO_RES_PCICFG: + r->r_size = 4096; + r->r_u.cdev = make_dev(&proto_devsw, res, 0, 0, 0666, + "proto/%s/pcicfg", device_get_desc(dev)); + r->r_u.cdev->si_drv1 = sc; + r->r_u.cdev->si_drv2 = r; + break; + } + } + return (0); +} + +int +proto_detach(device_t dev) +{ + struct proto_softc *sc; + struct proto_res *r; + u_int res; + + sc = device_get_softc(dev); + + /* Don't detach if we have open device filess. */ + for (res = 0; res < sc->sc_rescnt; res++) { + r = sc->sc_res + res; + if (r->r_opened) + return (EBUSY); + } + + for (res = 0; res < sc->sc_rescnt; res++) { + r = sc->sc_res + res; + switch (r->r_type) { + case SYS_RES_IRQ: + /* XXX TODO */ + break; + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + case PROTO_RES_PCICFG: + destroy_dev(r->r_u.cdev); + break; + } + if (r->r_res != NULL) { + bus_release_resource(dev, r->r_type, r->r_rid, + r->r_res); + r->r_res = NULL; + } + r->r_type = PROTO_RES_UNUSED; + } + sc->sc_rescnt = 0; + return (0); +} + +/* + * Device functions + */ + +static int +proto_open(struct cdev *cdev, int oflags, int devtype, struct thread *td) +{ + struct proto_res *r; + + r = cdev->si_drv2; + if (!atomic_cmpset_acq_ptr(&r->r_opened, 0UL, (uintptr_t)td->td_proc)) + return (EBUSY); + return (0); +} + +static int +proto_close(struct cdev *cdev, int fflag, int devtype, struct thread *td) +{ + struct proto_res *r; + + r = cdev->si_drv2; + if (!atomic_cmpset_acq_ptr(&r->r_opened, (uintptr_t)td->td_proc, 0UL)) + return (ENXIO); + return (0); +} + +static int +proto_read(struct cdev *cdev, struct uio *uio, int ioflag) +{ + union { + uint8_t x1[8]; + uint16_t x2[4]; + uint32_t x4[2]; + uint64_t x8[1]; + } buf; + struct proto_softc *sc; + struct proto_res *r; + device_t dev; + off_t ofs; + u_long width; + int error; + + sc = cdev->si_drv1; + dev = sc->sc_dev; + r = cdev->si_drv2; + + width = uio->uio_resid; + if (width < 1 || width > 8 || bitcount16(width) > 1) + return (EIO); + ofs = uio->uio_offset; + if (ofs + width > r->r_size) + return (EIO); + + switch (width) { + case 1: + buf.x1[0] = (r->r_type == PROTO_RES_PCICFG) ? + pci_read_config(dev, ofs, 1) : bus_read_1(r->r_res, ofs); + break; + case 2: + buf.x2[0] = (r->r_type == PROTO_RES_PCICFG) ? + pci_read_config(dev, ofs, 2) : bus_read_2(r->r_res, ofs); + break; + case 4: + buf.x4[0] = (r->r_type == PROTO_RES_PCICFG) ? + pci_read_config(dev, ofs, 4) : bus_read_4(r->r_res, ofs); + break; +#ifndef __i386__ + case 8: + if (r->r_type == PROTO_RES_PCICFG) + return (EINVAL); + buf.x8[0] = bus_read_8(r->r_res, ofs); + break; +#endif + default: + return (EIO); + } + + error = uiomove(&buf, width, uio); + return (error); +} + +static int +proto_write(struct cdev *cdev, struct uio *uio, int ioflag) +{ + union { + uint8_t x1[8]; + uint16_t x2[4]; + uint32_t x4[2]; + uint64_t x8[1]; + } buf; + struct proto_softc *sc; + struct proto_res *r; + device_t dev; + off_t ofs; + u_long width; + int error; + + sc = cdev->si_drv1; + dev = sc->sc_dev; + r = cdev->si_drv2; + + width = uio->uio_resid; + if (width < 1 || width > 8 || bitcount16(width) > 1) + return (EIO); + ofs = uio->uio_offset; + if (ofs + width > r->r_size) + return (EIO); + + error = uiomove(&buf, width, uio); + if (error) + return (error); + + switch (width) { + case 1: + if (r->r_type == PROTO_RES_PCICFG) + pci_write_config(dev, ofs, buf.x1[0], 1); + else + bus_write_1(r->r_res, ofs, buf.x1[0]); + break; + case 2: + if (r->r_type == PROTO_RES_PCICFG) + pci_write_config(dev, ofs, buf.x2[0], 2); + else + bus_write_2(r->r_res, ofs, buf.x2[0]); + break; + case 4: + if (r->r_type == PROTO_RES_PCICFG) + pci_write_config(dev, ofs, buf.x4[0], 4); + else + bus_write_4(r->r_res, ofs, buf.x4[0]); + break; +#ifndef __i386__ + case 8: + if (r->r_type == PROTO_RES_PCICFG) + return (EINVAL); + bus_write_8(r->r_res, ofs, buf.x8[0]); + break; +#endif + default: + return (EIO); + } + + return (0); +} + +static int +proto_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, + struct thread *td) +{ + struct proto_ioc_region *region; + struct proto_res *r; + int error; + + r = cdev->si_drv2; + + error = 0; + switch (cmd) { + case PROTO_IOC_REGION: + region = (struct proto_ioc_region *)data; + region->size = r->r_size; + if (r->r_type == PROTO_RES_PCICFG) + region->address = 0; + else + region->address = rman_get_start(r->r_res); + break; + default: + error = ENOIOCTL; + break; + } + return (error); +} + +static int +proto_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, + int prot, vm_memattr_t *memattr) +{ + struct proto_res *r; + + r = cdev->si_drv2; + + if (r->r_type != SYS_RES_MEMORY) + return (ENXIO); + if (offset & PAGE_MASK) + return (EINVAL); + if (prot & PROT_EXEC) + return (EACCES); + if (offset >= r->r_size) + return (EINVAL); + *paddr = rman_get_start(r->r_res) + offset; +#ifndef __sparc64__ + *memattr = VM_MEMATTR_UNCACHEABLE; +#endif + return (0); +} diff --git a/sys/dev/proto/proto_dev.h b/sys/dev/proto/proto_dev.h new file mode 100644 index 0000000..0ea3749 --- /dev/null +++ b/sys/dev/proto/proto_dev.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2014 Marcel Moolenaar + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _DEV_PROTO_DEV_H_ +#define _DEV_PROTO_DEV_H_ + +#include <sys/ioccom.h> + +#define PROTO_IOC_CLASS 'h' + +struct proto_ioc_region { + unsigned long address; + unsigned long size; +}; + +#define PROTO_IOC_REGION _IOWR(PROTO_IOC_CLASS, 1, struct proto_ioc_region) + +#endif /* _DEV_PROTO_H_ */ diff --git a/sys/modules/Makefile b/sys/modules/Makefile index f0034ee..145cac1 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -272,6 +272,7 @@ SUBDIR= \ ppi \ pps \ procfs \ + proto \ pseudofs \ ${_pst} \ pty \ diff --git a/sys/modules/proto/Makefile b/sys/modules/proto/Makefile new file mode 100644 index 0000000..4cfbd72 --- /dev/null +++ b/sys/modules/proto/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/proto + +KMOD= proto +SRCS= \ + proto_bus_pci.c \ + proto_core.c + +SRCS+= \ + bus_if.h \ + device_if.h \ + pci_if.h \ + +MFILES= \ + dev/pci/pci_if.m \ + kern/bus_if.m \ + kern/device_if.m + +.include <bsd.kmod.mk> |