mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-05 18:20:40 +08:00
Added pcib for Nics.
This commit is contained in:
parent
ae53d9e793
commit
fb4c8a98f5
4
Makefile
4
Makefile
@ -56,6 +56,8 @@ C_FILES += rtemsbsd/src/rtems-bsd-newproc.c
|
|||||||
C_FILES += rtemsbsd/src/rtems-bsd-vm_glue.c
|
C_FILES += rtemsbsd/src/rtems-bsd-vm_glue.c
|
||||||
C_FILES += rtemsbsd/src/rtems-bsd-copyinout.c
|
C_FILES += rtemsbsd/src/rtems-bsd-copyinout.c
|
||||||
C_FILES += rtemsbsd/src/rtems-bsd-descrip.c
|
C_FILES += rtemsbsd/src/rtems-bsd-descrip.c
|
||||||
|
C_FILES += rtemsbsd/src/rtems-bsd-conf.c
|
||||||
|
C_FILES += rtemsbsd/src/rtems-bsd-subr_param.c
|
||||||
C_FILES += freebsd/kern/subr_eventhandler.c
|
C_FILES += freebsd/kern/subr_eventhandler.c
|
||||||
C_FILES += freebsd/kern/kern_subr.c
|
C_FILES += freebsd/kern/kern_subr.c
|
||||||
C_FILES += freebsd/kern/kern_tc.c
|
C_FILES += freebsd/kern/kern_tc.c
|
||||||
@ -365,12 +367,14 @@ C_FILES += freebsd/libkern/arc4random.c
|
|||||||
C_FILES += freebsd/kern/subr_pcpu.c
|
C_FILES += freebsd/kern/subr_pcpu.c
|
||||||
C_FILES += freebsd/kern/subr_sbuf.c
|
C_FILES += freebsd/kern/subr_sbuf.c
|
||||||
C_FILES += freebsd/kern/subr_rman.c
|
C_FILES += freebsd/kern/subr_rman.c
|
||||||
|
C_FILES += freebsd/kern/subr_module.c
|
||||||
C_FILES += freebsd/libkern/inet_ntoa.c
|
C_FILES += freebsd/libkern/inet_ntoa.c
|
||||||
C_FILES += freebsd/kern/kern_prot.c
|
C_FILES += freebsd/kern/kern_prot.c
|
||||||
C_FILES += freebsd/kern/kern_time.c
|
C_FILES += freebsd/kern/kern_time.c
|
||||||
C_FILES += freebsd/kern/kern_event.c
|
C_FILES += freebsd/kern/kern_event.c
|
||||||
C_FILES += freebsd/netinet/tcp_hostcache.c
|
C_FILES += freebsd/netinet/tcp_hostcache.c
|
||||||
C_FILES += freebsd/dev/pci/pci.c
|
C_FILES += freebsd/dev/pci/pci.c
|
||||||
|
C_FILES += freebsd/dev/pci/pci_user.c
|
||||||
C_FILES += freebsd/kern/uipc_accf.c
|
C_FILES += freebsd/kern/uipc_accf.c
|
||||||
C_FILES += freebsd/kern/kern_ntptime.c
|
C_FILES += freebsd/kern/kern_ntptime.c
|
||||||
C_FILES += freebsd/kern/kern_environment.c
|
C_FILES += freebsd/kern/kern_environment.c
|
||||||
|
@ -551,6 +551,8 @@ rtems.addRTEMSSourceFiles(
|
|||||||
'src/rtems-bsd-vm_glue.c',
|
'src/rtems-bsd-vm_glue.c',
|
||||||
'src/rtems-bsd-copyinout.c',
|
'src/rtems-bsd-copyinout.c',
|
||||||
'src/rtems-bsd-descrip.c',
|
'src/rtems-bsd-descrip.c',
|
||||||
|
'src/rtems-bsd-conf.c',
|
||||||
|
'src/rtems-bsd-subr_param.c',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
rtems.addEmptyHeaderFiles(
|
rtems.addEmptyHeaderFiles(
|
||||||
@ -1202,6 +1204,7 @@ devNic.addCPUDependentHeaderFiles(
|
|||||||
[
|
[
|
||||||
'i386/include/specialreg.h',
|
'i386/include/specialreg.h',
|
||||||
'i386/include/md_var.h',
|
'i386/include/md_var.h',
|
||||||
|
'i386/include/intr_machdep.h',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1215,12 +1218,14 @@ devNic.addSourceFiles(
|
|||||||
'kern/subr_pcpu.c',
|
'kern/subr_pcpu.c',
|
||||||
'kern/subr_sbuf.c',
|
'kern/subr_sbuf.c',
|
||||||
'kern/subr_rman.c',
|
'kern/subr_rman.c',
|
||||||
|
'kern/subr_module.c',
|
||||||
'libkern/inet_ntoa.c',
|
'libkern/inet_ntoa.c',
|
||||||
'kern/kern_prot.c',
|
'kern/kern_prot.c',
|
||||||
'kern/kern_time.c',
|
'kern/kern_time.c',
|
||||||
'kern/kern_event.c',
|
'kern/kern_event.c',
|
||||||
'netinet/tcp_hostcache.c',
|
'netinet/tcp_hostcache.c',
|
||||||
'dev/pci/pci.c',
|
'dev/pci/pci.c',
|
||||||
|
'dev/pci/pci_user.c',
|
||||||
'kern/uipc_accf.c',
|
'kern/uipc_accf.c',
|
||||||
'kern/kern_ntptime.c',
|
'kern/kern_ntptime.c',
|
||||||
'kern/kern_environment.c',
|
'kern/kern_environment.c',
|
||||||
|
@ -57,21 +57,20 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <freebsd/machine/resource.h>
|
#include <freebsd/machine/resource.h>
|
||||||
#include <freebsd/machine/stdarg.h>
|
#include <freebsd/machine/stdarg.h>
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
|
#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
|
||||||
#include <freebsd/machine/intr_machdep.h>
|
#include <freebsd/machine/intr_machdep.h>
|
||||||
#endif
|
#endif
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
#include <freebsd/sys/pciio.h>
|
#include <freebsd/sys/pciio.h>
|
||||||
#include <freebsd/dev/pci/pcireg.h>
|
#include <freebsd/dev/pci/pcireg.h>
|
||||||
#include <freebsd/dev/pci/pcivar.h>
|
#include <freebsd/dev/pci/pcivar.h>
|
||||||
#ifndef __rtems__
|
|
||||||
#include <freebsd/dev/pci/pci_private.h>
|
#include <freebsd/dev/pci/pci_private.h>
|
||||||
|
|
||||||
#include <freebsd/dev/usb/controller/ehcireg.h>
|
#include <freebsd/dev/usb/controller/ehcireg.h>
|
||||||
#include <freebsd/dev/usb/controller/ohcireg.h>
|
#include <freebsd/dev/usb/controller/ohcireg.h>
|
||||||
|
#ifndef __rtems__
|
||||||
#include <freebsd/dev/usb/controller/uhcireg.h>
|
#include <freebsd/dev/usb/controller/uhcireg.h>
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
#include <freebsd/local/pcib_if.h>
|
#include <freebsd/local/pcib_if.h>
|
||||||
#include <freebsd/local/pci_if.h>
|
#include <freebsd/local/pci_if.h>
|
||||||
@ -82,9 +81,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#else
|
#else
|
||||||
#define ACPI_PWR_FOR_SLEEP(x, y, z)
|
#define ACPI_PWR_FOR_SLEEP(x, y, z)
|
||||||
#endif
|
#endif
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
static pci_addr_t pci_mapbase(uint64_t mapreg);
|
static pci_addr_t pci_mapbase(uint64_t mapreg);
|
||||||
static const char *pci_maptype(uint64_t mapreg);
|
static const char *pci_maptype(uint64_t mapreg);
|
||||||
static int pci_mapsize(uint64_t testval);
|
static int pci_mapsize(uint64_t testval);
|
||||||
@ -332,6 +329,7 @@ pci_find_dbsf(uint32_t domain, uint8_t bus, uint8_t slot, uint8_t func)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __rtems__
|
||||||
/* Find a device_t by vendor/device ID */
|
/* Find a device_t by vendor/device ID */
|
||||||
|
|
||||||
device_t
|
device_t
|
||||||
@ -348,6 +346,7 @@ pci_find_device(uint16_t vendor, uint16_t device)
|
|||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pci_printf(pcicfgregs *cfg, const char *fmt, ...)
|
pci_printf(pcicfgregs *cfg, const char *fmt, ...)
|
||||||
@ -1614,7 +1613,6 @@ pci_ht_map_msi(device_t dev, uint64_t addr)
|
|||||||
ht->ht_msictrl, 2);
|
ht->ht_msictrl, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
pci_get_max_read_req(device_t dev)
|
pci_get_max_read_req(device_t dev)
|
||||||
@ -1650,7 +1648,6 @@ pci_set_max_read_req(device_t dev, int size)
|
|||||||
return (size);
|
return (size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
/*
|
/*
|
||||||
* Support for MSI message signalled interrupts.
|
* Support for MSI message signalled interrupts.
|
||||||
*/
|
*/
|
||||||
@ -2625,11 +2622,13 @@ pci_assign_interrupt(device_t bus, device_t dev, int force_route)
|
|||||||
|
|
||||||
/* Let the user override the IRQ with a tunable. */
|
/* Let the user override the IRQ with a tunable. */
|
||||||
irq = PCI_INVALID_IRQ;
|
irq = PCI_INVALID_IRQ;
|
||||||
|
#ifndef __rtems__
|
||||||
snprintf(tunable_name, sizeof(tunable_name),
|
snprintf(tunable_name, sizeof(tunable_name),
|
||||||
"hw.pci%d.%d.%d.INT%c.irq",
|
"hw.pci%d.%d.%d.INT%c.irq",
|
||||||
cfg->domain, cfg->bus, cfg->slot, cfg->intpin + 'A' - 1);
|
cfg->domain, cfg->bus, cfg->slot, cfg->intpin + 'A' - 1);
|
||||||
if (TUNABLE_INT_FETCH(tunable_name, &irq) && (irq >= 255 || irq <= 0))
|
if (TUNABLE_INT_FETCH(tunable_name, &irq) && (irq >= 255 || irq <= 0))
|
||||||
irq = PCI_INVALID_IRQ;
|
irq = PCI_INVALID_IRQ;
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we didn't get an IRQ via the tunable, then we either use the
|
* If we didn't get an IRQ via the tunable, then we either use the
|
||||||
@ -2696,6 +2695,7 @@ ohci_early_takeover(device_t self)
|
|||||||
bus_release_resource(self, SYS_RES_MEMORY, rid, res);
|
bus_release_resource(self, SYS_RES_MEMORY, rid, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __rtems__
|
||||||
/* Perform early UHCI takeover from SMM. */
|
/* Perform early UHCI takeover from SMM. */
|
||||||
static void
|
static void
|
||||||
uhci_early_takeover(device_t self)
|
uhci_early_takeover(device_t self)
|
||||||
@ -2719,6 +2719,7 @@ uhci_early_takeover(device_t self)
|
|||||||
bus_release_resource(self, SYS_RES_IOPORT, rid, res);
|
bus_release_resource(self, SYS_RES_IOPORT, rid, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
/* Perform early EHCI takeover from SMM. */
|
/* Perform early EHCI takeover from SMM. */
|
||||||
static void
|
static void
|
||||||
@ -2826,8 +2827,10 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
|
|||||||
ehci_early_takeover(dev);
|
ehci_early_takeover(dev);
|
||||||
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_OHCI)
|
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_OHCI)
|
||||||
ohci_early_takeover(dev);
|
ohci_early_takeover(dev);
|
||||||
|
#ifndef __rtems__
|
||||||
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_UHCI)
|
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_UHCI)
|
||||||
uhci_early_takeover(dev);
|
uhci_early_takeover(dev);
|
||||||
|
#endif /* __rtems__ */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4114,4 +4117,3 @@ pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
|
|||||||
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D3)
|
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D3)
|
||||||
pci_set_powerstate(dev, PCI_POWERSTATE_D3);
|
pci_set_powerstate(dev, PCI_POWERSTATE_D3);
|
||||||
}
|
}
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
748
freebsd/dev/pci/pci_user.c
Normal file
748
freebsd/dev/pci/pci_user.c
Normal file
@ -0,0 +1,748 @@
|
|||||||
|
#include <freebsd/machine/rtems-bsd-config.h>
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
|
||||||
|
* 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 unmodified, 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 <freebsd/sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <freebsd/local/opt_bus.h> /* XXX trim includes */
|
||||||
|
#include <freebsd/local/opt_compat.h>
|
||||||
|
|
||||||
|
#include <freebsd/sys/param.h>
|
||||||
|
#include <freebsd/sys/systm.h>
|
||||||
|
#include <freebsd/sys/malloc.h>
|
||||||
|
#include <freebsd/sys/module.h>
|
||||||
|
#include <freebsd/sys/linker.h>
|
||||||
|
#include <freebsd/sys/fcntl.h>
|
||||||
|
#include <freebsd/sys/conf.h>
|
||||||
|
#include <freebsd/sys/kernel.h>
|
||||||
|
#include <freebsd/sys/proc.h>
|
||||||
|
#include <freebsd/sys/queue.h>
|
||||||
|
#include <freebsd/sys/types.h>
|
||||||
|
|
||||||
|
#include <freebsd/vm/vm.h>
|
||||||
|
#include <freebsd/vm/pmap.h>
|
||||||
|
#ifndef __rtems__
|
||||||
|
#include <freebsd/vm/vm_extern.h>
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
|
#include <freebsd/sys/bus.h>
|
||||||
|
#include <freebsd/machine/bus.h>
|
||||||
|
#include <freebsd/sys/rman.h>
|
||||||
|
#include <freebsd/machine/resource.h>
|
||||||
|
|
||||||
|
#include <freebsd/sys/pciio.h>
|
||||||
|
#include <freebsd/dev/pci/pcireg.h>
|
||||||
|
#include <freebsd/dev/pci/pcivar.h>
|
||||||
|
|
||||||
|
#include <freebsd/local/pcib_if.h>
|
||||||
|
#include <freebsd/local/pci_if.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the user interface to PCI configuration space.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static d_open_t pci_open;
|
||||||
|
static d_close_t pci_close;
|
||||||
|
static int pci_conf_match(struct pci_match_conf *matches, int num_matches,
|
||||||
|
struct pci_conf *match_buf);
|
||||||
|
static d_ioctl_t pci_ioctl;
|
||||||
|
|
||||||
|
struct cdevsw pcicdev = {
|
||||||
|
.d_version = D_VERSION,
|
||||||
|
.d_flags = D_NEEDGIANT,
|
||||||
|
.d_open = pci_open,
|
||||||
|
.d_close = pci_close,
|
||||||
|
.d_ioctl = pci_ioctl,
|
||||||
|
.d_name = "pci",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
pci_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (oflags & FWRITE) {
|
||||||
|
error = securelevel_gt(td->td_ucred, 0);
|
||||||
|
if (error)
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pci_close(struct cdev *dev, int flag, int devtype, struct thread *td)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Match a single pci_conf structure against an array of pci_match_conf
|
||||||
|
* structures. The first argument, 'matches', is an array of num_matches
|
||||||
|
* pci_match_conf structures. match_buf is a pointer to the pci_conf
|
||||||
|
* structure that will be compared to every entry in the matches array.
|
||||||
|
* This function returns 1 on failure, 0 on success.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pci_conf_match(struct pci_match_conf *matches, int num_matches,
|
||||||
|
struct pci_conf *match_buf)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0))
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
for (i = 0; i < num_matches; i++) {
|
||||||
|
/*
|
||||||
|
* I'm not sure why someone would do this...but...
|
||||||
|
*/
|
||||||
|
if (matches[i].flags == PCI_GETCONF_NO_MATCH)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look at each of the match flags. If it's set, do the
|
||||||
|
* comparison. If the comparison fails, we don't have a
|
||||||
|
* match, go on to the next item if there is one.
|
||||||
|
*/
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_DOMAIN) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_domain !=
|
||||||
|
matches[i].pc_sel.pc_domain))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_BUS) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_DEV) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR) != 0)
|
||||||
|
&& (match_buf->pc_vendor != matches[i].pc_vendor))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE) != 0)
|
||||||
|
&& (match_buf->pc_device != matches[i].pc_device))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS) != 0)
|
||||||
|
&& (match_buf->pc_class != matches[i].pc_class))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT) != 0)
|
||||||
|
&& (match_buf->pd_unit != matches[i].pd_unit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_NAME) != 0)
|
||||||
|
&& (strncmp(matches[i].pd_name, match_buf->pd_name,
|
||||||
|
sizeof(match_buf->pd_name)) != 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
|
||||||
|
defined(COMPAT_FREEBSD6)
|
||||||
|
#define PRE7_COMPAT
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PCI_GETCONF_NO_MATCH_OLD = 0x00,
|
||||||
|
PCI_GETCONF_MATCH_BUS_OLD = 0x01,
|
||||||
|
PCI_GETCONF_MATCH_DEV_OLD = 0x02,
|
||||||
|
PCI_GETCONF_MATCH_FUNC_OLD = 0x04,
|
||||||
|
PCI_GETCONF_MATCH_NAME_OLD = 0x08,
|
||||||
|
PCI_GETCONF_MATCH_UNIT_OLD = 0x10,
|
||||||
|
PCI_GETCONF_MATCH_VENDOR_OLD = 0x20,
|
||||||
|
PCI_GETCONF_MATCH_DEVICE_OLD = 0x40,
|
||||||
|
PCI_GETCONF_MATCH_CLASS_OLD = 0x80
|
||||||
|
} pci_getconf_flags_old;
|
||||||
|
|
||||||
|
struct pcisel_old {
|
||||||
|
u_int8_t pc_bus; /* bus number */
|
||||||
|
u_int8_t pc_dev; /* device on this bus */
|
||||||
|
u_int8_t pc_func; /* function on this device */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pci_conf_old {
|
||||||
|
struct pcisel_old pc_sel; /* bus+slot+function */
|
||||||
|
u_int8_t pc_hdr; /* PCI header type */
|
||||||
|
u_int16_t pc_subvendor; /* card vendor ID */
|
||||||
|
u_int16_t pc_subdevice; /* card device ID, assigned by
|
||||||
|
card vendor */
|
||||||
|
u_int16_t pc_vendor; /* chip vendor ID */
|
||||||
|
u_int16_t pc_device; /* chip device ID, assigned by
|
||||||
|
chip vendor */
|
||||||
|
u_int8_t pc_class; /* chip PCI class */
|
||||||
|
u_int8_t pc_subclass; /* chip PCI subclass */
|
||||||
|
u_int8_t pc_progif; /* chip PCI programming interface */
|
||||||
|
u_int8_t pc_revid; /* chip revision ID */
|
||||||
|
char pd_name[PCI_MAXNAMELEN + 1]; /* device name */
|
||||||
|
u_long pd_unit; /* device unit number */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pci_match_conf_old {
|
||||||
|
struct pcisel_old pc_sel; /* bus+slot+function */
|
||||||
|
char pd_name[PCI_MAXNAMELEN + 1]; /* device name */
|
||||||
|
u_long pd_unit; /* Unit number */
|
||||||
|
u_int16_t pc_vendor; /* PCI Vendor ID */
|
||||||
|
u_int16_t pc_device; /* PCI Device ID */
|
||||||
|
u_int8_t pc_class; /* PCI class */
|
||||||
|
pci_getconf_flags_old flags; /* Matching expression */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pci_io_old {
|
||||||
|
struct pcisel_old pi_sel; /* device to operate on */
|
||||||
|
int pi_reg; /* configuration register to examine */
|
||||||
|
int pi_width; /* width (in bytes) of read or write */
|
||||||
|
u_int32_t pi_data; /* data to write or result of read */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PCIOCGETCONF_OLD _IOWR('p', 1, struct pci_conf_io)
|
||||||
|
#define PCIOCREAD_OLD _IOWR('p', 2, struct pci_io_old)
|
||||||
|
#define PCIOCWRITE_OLD _IOWR('p', 3, struct pci_io_old)
|
||||||
|
|
||||||
|
static int pci_conf_match_old(struct pci_match_conf_old *matches,
|
||||||
|
int num_matches, struct pci_conf *match_buf);
|
||||||
|
|
||||||
|
static int
|
||||||
|
pci_conf_match_old(struct pci_match_conf_old *matches, int num_matches,
|
||||||
|
struct pci_conf *match_buf)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0))
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
for (i = 0; i < num_matches; i++) {
|
||||||
|
if (match_buf->pc_sel.pc_domain != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I'm not sure why someone would do this...but...
|
||||||
|
*/
|
||||||
|
if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look at each of the match flags. If it's set, do the
|
||||||
|
* comparison. If the comparison fails, we don't have a
|
||||||
|
* match, go on to the next item if there is one.
|
||||||
|
*/
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0)
|
||||||
|
&& (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0)
|
||||||
|
&& (match_buf->pc_vendor != matches[i].pc_vendor))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0)
|
||||||
|
&& (match_buf->pc_device != matches[i].pc_device))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0)
|
||||||
|
&& (match_buf->pc_class != matches[i].pc_class))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0)
|
||||||
|
&& (match_buf->pd_unit != matches[i].pd_unit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0)
|
||||||
|
&& (strncmp(matches[i].pd_name, match_buf->pd_name,
|
||||||
|
sizeof(match_buf->pd_name)) != 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||||
|
{
|
||||||
|
device_t pcidev, brdev;
|
||||||
|
void *confdata;
|
||||||
|
const char *name;
|
||||||
|
struct devlist *devlist_head;
|
||||||
|
struct pci_conf_io *cio;
|
||||||
|
struct pci_devinfo *dinfo;
|
||||||
|
struct pci_io *io;
|
||||||
|
struct pci_bar_io *bio;
|
||||||
|
struct pci_match_conf *pattern_buf;
|
||||||
|
struct resource_list_entry *rle;
|
||||||
|
uint32_t value;
|
||||||
|
size_t confsz, iolen, pbufsz;
|
||||||
|
int error, ionum, i, num_patterns;
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
struct pci_conf_old conf_old;
|
||||||
|
struct pci_io iodata;
|
||||||
|
struct pci_io_old *io_old;
|
||||||
|
struct pci_match_conf_old *pattern_buf_old;
|
||||||
|
|
||||||
|
io_old = NULL;
|
||||||
|
pattern_buf_old = NULL;
|
||||||
|
|
||||||
|
if (!(flag & FWRITE) && cmd != PCIOCGETBAR &&
|
||||||
|
cmd != PCIOCGETCONF && cmd != PCIOCGETCONF_OLD)
|
||||||
|
return EPERM;
|
||||||
|
#else
|
||||||
|
if (!(flag & FWRITE) && cmd != PCIOCGETBAR && cmd != PCIOCGETCONF)
|
||||||
|
return EPERM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(cmd) {
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
case PCIOCGETCONF_OLD:
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
#endif
|
||||||
|
case PCIOCGETCONF:
|
||||||
|
cio = (struct pci_conf_io *)data;
|
||||||
|
|
||||||
|
pattern_buf = NULL;
|
||||||
|
num_patterns = 0;
|
||||||
|
dinfo = NULL;
|
||||||
|
|
||||||
|
cio->num_matches = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the user specified an offset into the device list,
|
||||||
|
* but the list has changed since they last called this
|
||||||
|
* ioctl, tell them that the list has changed. They will
|
||||||
|
* have to get the list from the beginning.
|
||||||
|
*/
|
||||||
|
if ((cio->offset != 0)
|
||||||
|
&& (cio->generation != pci_generation)){
|
||||||
|
cio->status = PCI_GETCONF_LIST_CHANGED;
|
||||||
|
error = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see whether the user has asked for an offset
|
||||||
|
* past the end of our list.
|
||||||
|
*/
|
||||||
|
if (cio->offset >= pci_numdevs) {
|
||||||
|
cio->status = PCI_GETCONF_LAST_DEVICE;
|
||||||
|
error = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the head of the device queue */
|
||||||
|
devlist_head = &pci_devq;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine how much room we have for pci_conf structures.
|
||||||
|
* Round the user's buffer size down to the nearest
|
||||||
|
* multiple of sizeof(struct pci_conf) in case the user
|
||||||
|
* didn't specify a multiple of that size.
|
||||||
|
*/
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if (cmd == PCIOCGETCONF_OLD)
|
||||||
|
confsz = sizeof(struct pci_conf_old);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
confsz = sizeof(struct pci_conf);
|
||||||
|
iolen = min(cio->match_buf_len - (cio->match_buf_len % confsz),
|
||||||
|
pci_numdevs * confsz);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since we know that iolen is a multiple of the size of
|
||||||
|
* the pciconf union, it's okay to do this.
|
||||||
|
*/
|
||||||
|
ionum = iolen / confsz;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this test is true, the user wants the pci_conf
|
||||||
|
* structures returned to match the supplied entries.
|
||||||
|
*/
|
||||||
|
if ((cio->num_patterns > 0) && (cio->num_patterns < pci_numdevs)
|
||||||
|
&& (cio->pat_buf_len > 0)) {
|
||||||
|
/*
|
||||||
|
* pat_buf_len needs to be:
|
||||||
|
* num_patterns * sizeof(struct pci_match_conf)
|
||||||
|
* While it is certainly possible the user just
|
||||||
|
* allocated a large buffer, but set the number of
|
||||||
|
* matches correctly, it is far more likely that
|
||||||
|
* their kernel doesn't match the userland utility
|
||||||
|
* they're using. It's also possible that the user
|
||||||
|
* forgot to initialize some variables. Yes, this
|
||||||
|
* may be overly picky, but I hazard to guess that
|
||||||
|
* it's far more likely to just catch folks that
|
||||||
|
* updated their kernel but not their userland.
|
||||||
|
*/
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if (cmd == PCIOCGETCONF_OLD)
|
||||||
|
pbufsz = sizeof(struct pci_match_conf_old);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
pbufsz = sizeof(struct pci_match_conf);
|
||||||
|
if (cio->num_patterns * pbufsz != cio->pat_buf_len) {
|
||||||
|
/* The user made a mistake, return an error. */
|
||||||
|
cio->status = PCI_GETCONF_ERROR;
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a buffer to hold the patterns.
|
||||||
|
*/
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if (cmd == PCIOCGETCONF_OLD) {
|
||||||
|
pattern_buf_old = malloc(cio->pat_buf_len,
|
||||||
|
M_TEMP, M_WAITOK);
|
||||||
|
error = copyin(cio->patterns,
|
||||||
|
pattern_buf_old, cio->pat_buf_len);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
pattern_buf = malloc(cio->pat_buf_len, M_TEMP,
|
||||||
|
M_WAITOK);
|
||||||
|
error = copyin(cio->patterns, pattern_buf,
|
||||||
|
cio->pat_buf_len);
|
||||||
|
}
|
||||||
|
if (error != 0) {
|
||||||
|
error = EINVAL;
|
||||||
|
goto getconfexit;
|
||||||
|
}
|
||||||
|
num_patterns = cio->num_patterns;
|
||||||
|
} else if ((cio->num_patterns > 0)
|
||||||
|
|| (cio->pat_buf_len > 0)) {
|
||||||
|
/*
|
||||||
|
* The user made a mistake, spit out an error.
|
||||||
|
*/
|
||||||
|
cio->status = PCI_GETCONF_ERROR;
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Go through the list of devices and copy out the devices
|
||||||
|
* that match the user's criteria.
|
||||||
|
*/
|
||||||
|
for (cio->num_matches = 0, error = 0, i = 0,
|
||||||
|
dinfo = STAILQ_FIRST(devlist_head);
|
||||||
|
(dinfo != NULL) && (cio->num_matches < ionum)
|
||||||
|
&& (error == 0) && (i < pci_numdevs) && (dinfo != NULL);
|
||||||
|
dinfo = STAILQ_NEXT(dinfo, pci_links), i++) {
|
||||||
|
|
||||||
|
if (i < cio->offset)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Populate pd_name and pd_unit */
|
||||||
|
name = NULL;
|
||||||
|
if (dinfo->cfg.dev)
|
||||||
|
name = device_get_name(dinfo->cfg.dev);
|
||||||
|
if (name) {
|
||||||
|
strncpy(dinfo->conf.pd_name, name,
|
||||||
|
sizeof(dinfo->conf.pd_name));
|
||||||
|
dinfo->conf.pd_name[PCI_MAXNAMELEN] = 0;
|
||||||
|
dinfo->conf.pd_unit =
|
||||||
|
device_get_unit(dinfo->cfg.dev);
|
||||||
|
} else {
|
||||||
|
dinfo->conf.pd_name[0] = '\0';
|
||||||
|
dinfo->conf.pd_unit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if ((cmd == PCIOCGETCONF_OLD &&
|
||||||
|
(pattern_buf_old == NULL ||
|
||||||
|
pci_conf_match_old(pattern_buf_old, num_patterns,
|
||||||
|
&dinfo->conf) == 0)) ||
|
||||||
|
(cmd == PCIOCGETCONF &&
|
||||||
|
(pattern_buf == NULL ||
|
||||||
|
pci_conf_match(pattern_buf, num_patterns,
|
||||||
|
&dinfo->conf) == 0))) {
|
||||||
|
#else
|
||||||
|
if (pattern_buf == NULL ||
|
||||||
|
pci_conf_match(pattern_buf, num_patterns,
|
||||||
|
&dinfo->conf) == 0) {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* If we've filled up the user's buffer,
|
||||||
|
* break out at this point. Since we've
|
||||||
|
* got a match here, we'll pick right back
|
||||||
|
* up at the matching entry. We can also
|
||||||
|
* tell the user that there are more matches
|
||||||
|
* left.
|
||||||
|
*/
|
||||||
|
if (cio->num_matches >= ionum)
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if (cmd == PCIOCGETCONF_OLD) {
|
||||||
|
conf_old.pc_sel.pc_bus =
|
||||||
|
dinfo->conf.pc_sel.pc_bus;
|
||||||
|
conf_old.pc_sel.pc_dev =
|
||||||
|
dinfo->conf.pc_sel.pc_dev;
|
||||||
|
conf_old.pc_sel.pc_func =
|
||||||
|
dinfo->conf.pc_sel.pc_func;
|
||||||
|
conf_old.pc_hdr = dinfo->conf.pc_hdr;
|
||||||
|
conf_old.pc_subvendor =
|
||||||
|
dinfo->conf.pc_subvendor;
|
||||||
|
conf_old.pc_subdevice =
|
||||||
|
dinfo->conf.pc_subdevice;
|
||||||
|
conf_old.pc_vendor =
|
||||||
|
dinfo->conf.pc_vendor;
|
||||||
|
conf_old.pc_device =
|
||||||
|
dinfo->conf.pc_device;
|
||||||
|
conf_old.pc_class =
|
||||||
|
dinfo->conf.pc_class;
|
||||||
|
conf_old.pc_subclass =
|
||||||
|
dinfo->conf.pc_subclass;
|
||||||
|
conf_old.pc_progif =
|
||||||
|
dinfo->conf.pc_progif;
|
||||||
|
conf_old.pc_revid =
|
||||||
|
dinfo->conf.pc_revid;
|
||||||
|
strncpy(conf_old.pd_name,
|
||||||
|
dinfo->conf.pd_name,
|
||||||
|
sizeof(conf_old.pd_name));
|
||||||
|
conf_old.pd_name[PCI_MAXNAMELEN] = 0;
|
||||||
|
conf_old.pd_unit =
|
||||||
|
dinfo->conf.pd_unit;
|
||||||
|
confdata = &conf_old;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
confdata = &dinfo->conf;
|
||||||
|
/* Only if we can copy it out do we count it. */
|
||||||
|
if (!(error = copyout(confdata,
|
||||||
|
(caddr_t)cio->matches +
|
||||||
|
confsz * cio->num_matches, confsz)))
|
||||||
|
cio->num_matches++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the pointer into the list, so if the user is getting
|
||||||
|
* n records at a time, where n < pci_numdevs,
|
||||||
|
*/
|
||||||
|
cio->offset = i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the generation, the user will need this if they make
|
||||||
|
* another ioctl call with offset != 0.
|
||||||
|
*/
|
||||||
|
cio->generation = pci_generation;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is the last device, inform the user so he won't
|
||||||
|
* bother asking for more devices. If dinfo isn't NULL, we
|
||||||
|
* know that there are more matches in the list because of
|
||||||
|
* the way the traversal is done.
|
||||||
|
*/
|
||||||
|
if (dinfo == NULL)
|
||||||
|
cio->status = PCI_GETCONF_LAST_DEVICE;
|
||||||
|
else
|
||||||
|
cio->status = PCI_GETCONF_MORE_DEVS;
|
||||||
|
|
||||||
|
getconfexit:
|
||||||
|
if (pattern_buf != NULL)
|
||||||
|
free(pattern_buf, M_TEMP);
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if (pattern_buf_old != NULL)
|
||||||
|
free(pattern_buf_old, M_TEMP);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
case PCIOCREAD_OLD:
|
||||||
|
case PCIOCWRITE_OLD:
|
||||||
|
io_old = (struct pci_io_old *)data;
|
||||||
|
iodata.pi_sel.pc_domain = 0;
|
||||||
|
iodata.pi_sel.pc_bus = io_old->pi_sel.pc_bus;
|
||||||
|
iodata.pi_sel.pc_dev = io_old->pi_sel.pc_dev;
|
||||||
|
iodata.pi_sel.pc_func = io_old->pi_sel.pc_func;
|
||||||
|
iodata.pi_reg = io_old->pi_reg;
|
||||||
|
iodata.pi_width = io_old->pi_width;
|
||||||
|
iodata.pi_data = io_old->pi_data;
|
||||||
|
data = (caddr_t)&iodata;
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
#endif
|
||||||
|
case PCIOCREAD:
|
||||||
|
case PCIOCWRITE:
|
||||||
|
io = (struct pci_io *)data;
|
||||||
|
switch(io->pi_width) {
|
||||||
|
case 4:
|
||||||
|
case 2:
|
||||||
|
case 1:
|
||||||
|
/* Make sure register is not negative and aligned. */
|
||||||
|
if (io->pi_reg < 0 ||
|
||||||
|
io->pi_reg & (io->pi_width - 1)) {
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Assume that the user-level bus number is
|
||||||
|
* in fact the physical PCI bus number.
|
||||||
|
* Look up the grandparent, i.e. the bridge device,
|
||||||
|
* so that we can issue configuration space cycles.
|
||||||
|
*/
|
||||||
|
pcidev = pci_find_dbsf(io->pi_sel.pc_domain,
|
||||||
|
io->pi_sel.pc_bus, io->pi_sel.pc_dev,
|
||||||
|
io->pi_sel.pc_func);
|
||||||
|
if (pcidev) {
|
||||||
|
brdev = device_get_parent(
|
||||||
|
device_get_parent(pcidev));
|
||||||
|
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
if (cmd == PCIOCWRITE || cmd == PCIOCWRITE_OLD)
|
||||||
|
#else
|
||||||
|
if (cmd == PCIOCWRITE)
|
||||||
|
#endif
|
||||||
|
PCIB_WRITE_CONFIG(brdev,
|
||||||
|
io->pi_sel.pc_bus,
|
||||||
|
io->pi_sel.pc_dev,
|
||||||
|
io->pi_sel.pc_func,
|
||||||
|
io->pi_reg,
|
||||||
|
io->pi_data,
|
||||||
|
io->pi_width);
|
||||||
|
#ifdef PRE7_COMPAT
|
||||||
|
else if (cmd == PCIOCREAD_OLD)
|
||||||
|
io_old->pi_data =
|
||||||
|
PCIB_READ_CONFIG(brdev,
|
||||||
|
io->pi_sel.pc_bus,
|
||||||
|
io->pi_sel.pc_dev,
|
||||||
|
io->pi_sel.pc_func,
|
||||||
|
io->pi_reg,
|
||||||
|
io->pi_width);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
io->pi_data =
|
||||||
|
PCIB_READ_CONFIG(brdev,
|
||||||
|
io->pi_sel.pc_bus,
|
||||||
|
io->pi_sel.pc_dev,
|
||||||
|
io->pi_sel.pc_func,
|
||||||
|
io->pi_reg,
|
||||||
|
io->pi_width);
|
||||||
|
error = 0;
|
||||||
|
} else {
|
||||||
|
#ifdef COMPAT_FREEBSD4
|
||||||
|
if (cmd == PCIOCREAD_OLD) {
|
||||||
|
io_old->pi_data = -1;
|
||||||
|
error = 0;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
error = ENODEV;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCIOCGETBAR:
|
||||||
|
bio = (struct pci_bar_io *)data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume that the user-level bus number is
|
||||||
|
* in fact the physical PCI bus number.
|
||||||
|
*/
|
||||||
|
pcidev = pci_find_dbsf(bio->pbi_sel.pc_domain,
|
||||||
|
bio->pbi_sel.pc_bus, bio->pbi_sel.pc_dev,
|
||||||
|
bio->pbi_sel.pc_func);
|
||||||
|
if (pcidev == NULL) {
|
||||||
|
error = ENODEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dinfo = device_get_ivars(pcidev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look for a resource list entry matching the requested BAR.
|
||||||
|
*
|
||||||
|
* XXX: This will not find BARs that are not initialized, but
|
||||||
|
* maybe that is ok?
|
||||||
|
*/
|
||||||
|
rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY,
|
||||||
|
bio->pbi_reg);
|
||||||
|
if (rle == NULL)
|
||||||
|
rle = resource_list_find(&dinfo->resources,
|
||||||
|
SYS_RES_IOPORT, bio->pbi_reg);
|
||||||
|
if (rle == NULL || rle->res == NULL) {
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ok, we have a resource for this BAR. Read the lower
|
||||||
|
* 32 bits to get any flags.
|
||||||
|
*/
|
||||||
|
value = pci_read_config(pcidev, bio->pbi_reg, 4);
|
||||||
|
if (PCI_BAR_MEM(value)) {
|
||||||
|
if (rle->type != SYS_RES_MEMORY) {
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value &= ~PCIM_BAR_MEM_BASE;
|
||||||
|
} else {
|
||||||
|
if (rle->type != SYS_RES_IOPORT) {
|
||||||
|
error = EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value &= ~PCIM_BAR_IO_BASE;
|
||||||
|
}
|
||||||
|
bio->pbi_base = rman_get_start(rle->res) | value;
|
||||||
|
bio->pbi_length = rman_get_size(rle->res);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the command register to determine if this BAR
|
||||||
|
* is enabled.
|
||||||
|
*/
|
||||||
|
value = pci_read_config(pcidev, PCIR_COMMAND, 2);
|
||||||
|
if (rle->type == SYS_RES_MEMORY)
|
||||||
|
bio->pbi_enabled = (value & PCIM_CMD_MEMEN) != 0;
|
||||||
|
else
|
||||||
|
bio->pbi_enabled = (value & PCIM_CMD_PORTEN) != 0;
|
||||||
|
error = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error = ENOTTY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
@ -446,7 +446,9 @@ pci_msix_count(device_t dev)
|
|||||||
|
|
||||||
device_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
|
device_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
|
||||||
device_t pci_find_dbsf(uint32_t, uint8_t, uint8_t, uint8_t);
|
device_t pci_find_dbsf(uint32_t, uint8_t, uint8_t, uint8_t);
|
||||||
|
#ifndef __rtems__
|
||||||
device_t pci_find_device(uint16_t, uint16_t);
|
device_t pci_find_device(uint16_t, uint16_t);
|
||||||
|
#endif /* __rtems__ */
|
||||||
|
|
||||||
/* Can be used by drivers to manage the MSI-X table. */
|
/* Can be used by drivers to manage the MSI-X table. */
|
||||||
int pci_pending_msix(device_t dev, u_int index);
|
int pci_pending_msix(device_t dev, u_int index);
|
||||||
|
161
freebsd/i386/include/freebsd/machine/intr_machdep.h
Normal file
161
freebsd/i386/include/freebsd/machine/intr_machdep.h
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
|
||||||
|
* 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 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 AUTHOR 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.
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MACHINE_INTR_MACHDEP_HH__
|
||||||
|
#define __MACHINE_INTR_MACHDEP_HH__
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of I/O interrupts we allow. This number is rather
|
||||||
|
* arbitrary as it is just the maximum IRQ resource value. The interrupt
|
||||||
|
* source for a given IRQ maps that I/O interrupt to device interrupt
|
||||||
|
* source whether it be a pin on an interrupt controller or an MSI interrupt.
|
||||||
|
* The 16 ISA IRQs are assigned fixed IDT vectors, but all other device
|
||||||
|
* interrupts allocate IDT vectors on demand. Currently we have 191 IDT
|
||||||
|
* vectors available for device interrupts. On many systems with I/O APICs,
|
||||||
|
* a lot of the IRQs are not used, so this number can be much larger than
|
||||||
|
* 191 and still be safe since only interrupt sources in actual use will
|
||||||
|
* allocate IDT vectors.
|
||||||
|
*
|
||||||
|
* The first 255 IRQs (0 - 254) are reserved for ISA IRQs and PCI intline IRQs.
|
||||||
|
* IRQ values beyond 256 are used by MSI. We leave 255 unused to avoid
|
||||||
|
* confusion since 255 is used in PCI to indicate an invalid IRQ.
|
||||||
|
*/
|
||||||
|
#define NUM_MSI_INTS 512
|
||||||
|
#define FIRST_MSI_INT 256
|
||||||
|
#define NUM_IO_INTS (FIRST_MSI_INT + NUM_MSI_INTS)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default base address for MSI messages on x86 platforms.
|
||||||
|
*/
|
||||||
|
#define MSI_INTEL_ADDR_BASE 0xfee00000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* - 1 ??? dummy counter.
|
||||||
|
* - 2 counters for each I/O interrupt.
|
||||||
|
* - 1 counter for each CPU for lapic timer.
|
||||||
|
* - 7 counters for each CPU for IPI counters for SMP.
|
||||||
|
*/
|
||||||
|
#ifdef SMP
|
||||||
|
#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + (1 + 7) * MAXCPU)
|
||||||
|
#else
|
||||||
|
#define INTRCNT_COUNT (1 + NUM_IO_INTS * 2 + 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCORE
|
||||||
|
|
||||||
|
typedef void inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
|
||||||
|
|
||||||
|
#define IDTVEC(name) __CONCAT(X,name)
|
||||||
|
|
||||||
|
struct intsrc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods that a PIC provides to mask/unmask a given interrupt source,
|
||||||
|
* "turn on" the interrupt on the CPU side by setting up an IDT entry, and
|
||||||
|
* return the vector associated with this source.
|
||||||
|
*/
|
||||||
|
struct pic {
|
||||||
|
void (*pic_enable_source)(struct intsrc *);
|
||||||
|
void (*pic_disable_source)(struct intsrc *, int);
|
||||||
|
void (*pic_eoi_source)(struct intsrc *);
|
||||||
|
void (*pic_enable_intr)(struct intsrc *);
|
||||||
|
void (*pic_disable_intr)(struct intsrc *);
|
||||||
|
int (*pic_vector)(struct intsrc *);
|
||||||
|
int (*pic_source_pending)(struct intsrc *);
|
||||||
|
void (*pic_suspend)(struct pic *);
|
||||||
|
void (*pic_resume)(struct pic *);
|
||||||
|
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
|
||||||
|
enum intr_polarity);
|
||||||
|
int (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
|
||||||
|
STAILQ_ENTRY(pic) pics;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Flags for pic_disable_source() */
|
||||||
|
enum {
|
||||||
|
PIC_EOI,
|
||||||
|
PIC_NO_EOI,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An interrupt source. The upper-layer code uses the PIC methods to
|
||||||
|
* control a given source. The lower-layer PIC drivers can store additional
|
||||||
|
* private data in a given interrupt source such as an interrupt pin number
|
||||||
|
* or an I/O APIC pointer.
|
||||||
|
*/
|
||||||
|
struct intsrc {
|
||||||
|
struct pic *is_pic;
|
||||||
|
struct intr_event *is_event;
|
||||||
|
u_long *is_count;
|
||||||
|
u_long *is_straycount;
|
||||||
|
u_int is_index;
|
||||||
|
u_int is_handlers;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct trapframe;
|
||||||
|
|
||||||
|
extern struct mtx icu_lock;
|
||||||
|
extern int elcr_found;
|
||||||
|
|
||||||
|
/* XXX: The elcr_* prototypes probably belong somewhere else. */
|
||||||
|
int elcr_probe(void);
|
||||||
|
enum intr_trigger elcr_read_trigger(u_int irq);
|
||||||
|
void elcr_resume(void);
|
||||||
|
void elcr_write_trigger(u_int irq, enum intr_trigger trigger);
|
||||||
|
#ifdef SMP
|
||||||
|
void intr_add_cpu(u_int cpu);
|
||||||
|
#endif
|
||||||
|
int intr_add_handler(const char *name, int vector, driver_filter_t filter,
|
||||||
|
driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep);
|
||||||
|
#ifdef SMP
|
||||||
|
int intr_bind(u_int vector, u_char cpu);
|
||||||
|
#endif
|
||||||
|
int intr_config_intr(int vector, enum intr_trigger trig,
|
||||||
|
enum intr_polarity pol);
|
||||||
|
int intr_describe(u_int vector, void *ih, const char *descr);
|
||||||
|
void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame);
|
||||||
|
u_int intr_next_cpu(void);
|
||||||
|
struct intsrc *intr_lookup_source(int vector);
|
||||||
|
int intr_register_pic(struct pic *pic);
|
||||||
|
int intr_register_source(struct intsrc *isrc);
|
||||||
|
int intr_remove_handler(void *cookie);
|
||||||
|
void intr_resume(void);
|
||||||
|
void intr_suspend(void);
|
||||||
|
void intrcnt_add(const char *name, u_long **countp);
|
||||||
|
void nexus_add_irq(u_long irq);
|
||||||
|
int msi_alloc(device_t dev, int count, int maxcount, int *irqs);
|
||||||
|
void msi_init(void);
|
||||||
|
int msi_map(int irq, uint64_t *addr, uint32_t *data);
|
||||||
|
int msi_release(int* irqs, int count);
|
||||||
|
int msix_alloc(device_t dev, int *irq);
|
||||||
|
int msix_release(int irq);
|
||||||
|
|
||||||
|
#endif /* !LOCORE */
|
||||||
|
#endif /* _KERNEL */
|
||||||
|
#endif /* !__MACHINE_INTR_MACHDEP_HH__ */
|
@ -1286,7 +1286,6 @@ groupmember(gid_t gid, struct ucred *cred)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
/*
|
/*
|
||||||
* Test the active securelevel against a given level. securelevel_gt()
|
* Test the active securelevel against a given level. securelevel_gt()
|
||||||
* implements (securelevel > level). securelevel_ge() implements
|
* implements (securelevel > level). securelevel_ge() implements
|
||||||
@ -1314,8 +1313,6 @@ securelevel_ge(struct ucred *cr, int level)
|
|||||||
return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0);
|
return (cr->cr_prison->pr_securelevel >= level ? EPERM : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 'see_other_uids' determines whether or not visibility of processes
|
* 'see_other_uids' determines whether or not visibility of processes
|
||||||
* and sockets with credentials holding different real uids is possible
|
* and sockets with credentials holding different real uids is possible
|
||||||
|
@ -2861,7 +2861,6 @@ device_set_unit(device_t dev, int unit)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
/*======================================*/
|
/*======================================*/
|
||||||
/*
|
/*
|
||||||
* Some useful method implementations to make life easier for bus drivers.
|
* Some useful method implementations to make life easier for bus drivers.
|
||||||
@ -3193,7 +3192,6 @@ resource_list_purge(struct resource_list *rl)
|
|||||||
free(rle, M_BUS);
|
free(rle, M_BUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
device_t
|
device_t
|
||||||
bus_generic_add_child(device_t dev, u_int order, const char *name, int unit)
|
bus_generic_add_child(device_t dev, u_int order, const char *name, int unit)
|
||||||
@ -3518,7 +3516,6 @@ bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq,
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function for implementing BUS_ALLOC_RESOURCE().
|
* @brief Helper function for implementing BUS_ALLOC_RESOURCE().
|
||||||
*
|
*
|
||||||
@ -3586,7 +3583,6 @@ bus_generic_deactivate_resource(device_t dev, device_t child, int type,
|
|||||||
r));
|
r));
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function for implementing BUS_BIND_INTR().
|
* @brief Helper function for implementing BUS_BIND_INTR().
|
||||||
@ -3656,7 +3652,6 @@ bus_generic_get_dma_tag(device_t dev, device_t child)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __rtems__
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function for implementing BUS_GET_RESOURCE().
|
* @brief Helper function for implementing BUS_GET_RESOURCE().
|
||||||
*
|
*
|
||||||
@ -3773,7 +3768,6 @@ bus_generic_rl_alloc_resource(device_t dev, device_t child, int type,
|
|||||||
return (resource_list_alloc(rl, dev, child, type, rid,
|
return (resource_list_alloc(rl, dev, child, type, rid,
|
||||||
start, end, count, flags));
|
start, end, count, flags));
|
||||||
}
|
}
|
||||||
#endif /* __rtems__ */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function for implementing BUS_CHILD_PRESENT().
|
* @brief Helper function for implementing BUS_CHILD_PRESENT().
|
||||||
|
269
freebsd/kern/subr_module.c
Normal file
269
freebsd/kern/subr_module.c
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#include <freebsd/machine/rtems-bsd-config.h>
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1998 Michael Smith
|
||||||
|
* 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 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 AUTHOR 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 <freebsd/sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <freebsd/sys/param.h>
|
||||||
|
#include <freebsd/sys/systm.h>
|
||||||
|
#include <freebsd/sys/linker.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preloaded module support
|
||||||
|
*/
|
||||||
|
|
||||||
|
caddr_t preload_metadata;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for the preloaded module (name)
|
||||||
|
*/
|
||||||
|
caddr_t
|
||||||
|
preload_search_by_name(const char *name)
|
||||||
|
{
|
||||||
|
caddr_t curp;
|
||||||
|
u_int32_t *hdr;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
if (preload_metadata != NULL) {
|
||||||
|
|
||||||
|
curp = preload_metadata;
|
||||||
|
for (;;) {
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
if (hdr[0] == 0 && hdr[1] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Search for a MODINFO_NAME field */
|
||||||
|
if ((hdr[0] == MODINFO_NAME) &&
|
||||||
|
!strcmp(name, curp + sizeof(u_int32_t) * 2))
|
||||||
|
return(curp);
|
||||||
|
|
||||||
|
/* skip to next field */
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for the first preloaded module of (type)
|
||||||
|
*/
|
||||||
|
caddr_t
|
||||||
|
preload_search_by_type(const char *type)
|
||||||
|
{
|
||||||
|
caddr_t curp, lname;
|
||||||
|
u_int32_t *hdr;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
if (preload_metadata != NULL) {
|
||||||
|
|
||||||
|
curp = preload_metadata;
|
||||||
|
lname = NULL;
|
||||||
|
for (;;) {
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
if (hdr[0] == 0 && hdr[1] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* remember the start of each record */
|
||||||
|
if (hdr[0] == MODINFO_NAME)
|
||||||
|
lname = curp;
|
||||||
|
|
||||||
|
/* Search for a MODINFO_TYPE field */
|
||||||
|
if ((hdr[0] == MODINFO_TYPE) &&
|
||||||
|
!strcmp(type, curp + sizeof(u_int32_t) * 2))
|
||||||
|
return(lname);
|
||||||
|
|
||||||
|
/* skip to next field */
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk through the preloaded module list
|
||||||
|
*/
|
||||||
|
caddr_t
|
||||||
|
preload_search_next_name(caddr_t base)
|
||||||
|
{
|
||||||
|
caddr_t curp;
|
||||||
|
u_int32_t *hdr;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
if (preload_metadata != NULL) {
|
||||||
|
|
||||||
|
/* Pick up where we left off last time */
|
||||||
|
if (base) {
|
||||||
|
/* skip to next field */
|
||||||
|
curp = base;
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
} else
|
||||||
|
curp = preload_metadata;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
if (hdr[0] == 0 && hdr[1] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Found a new record? */
|
||||||
|
if (hdr[0] == MODINFO_NAME)
|
||||||
|
return curp;
|
||||||
|
|
||||||
|
/* skip to next field */
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a preloaded module handle (mod), return a pointer
|
||||||
|
* to the data for the attribute (inf).
|
||||||
|
*/
|
||||||
|
caddr_t
|
||||||
|
preload_search_info(caddr_t mod, int inf)
|
||||||
|
{
|
||||||
|
caddr_t curp;
|
||||||
|
u_int32_t *hdr;
|
||||||
|
u_int32_t type = 0;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
curp = mod;
|
||||||
|
for (;;) {
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
/* end of module data? */
|
||||||
|
if (hdr[0] == 0 && hdr[1] == 0)
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* We give up once we've looped back to what we were looking at
|
||||||
|
* first - this should normally be a MODINFO_NAME field.
|
||||||
|
*/
|
||||||
|
if (type == 0) {
|
||||||
|
type = hdr[0];
|
||||||
|
} else {
|
||||||
|
if (hdr[0] == type)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attribute match? Return pointer to data.
|
||||||
|
* Consumer may safely assume that size value precedes
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
if (hdr[0] == inf)
|
||||||
|
return(curp + (sizeof(u_int32_t) * 2));
|
||||||
|
|
||||||
|
/* skip to next field */
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a preload record by name.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
preload_delete_name(const char *name)
|
||||||
|
{
|
||||||
|
caddr_t curp;
|
||||||
|
u_int32_t *hdr;
|
||||||
|
int next;
|
||||||
|
int clearing;
|
||||||
|
|
||||||
|
if (preload_metadata != NULL) {
|
||||||
|
|
||||||
|
clearing = 0;
|
||||||
|
curp = preload_metadata;
|
||||||
|
for (;;) {
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
if (hdr[0] == 0 && hdr[1] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Search for a MODINFO_NAME field */
|
||||||
|
if (hdr[0] == MODINFO_NAME) {
|
||||||
|
if (!strcmp(name, curp + sizeof(u_int32_t) * 2))
|
||||||
|
clearing = 1; /* got it, start clearing */
|
||||||
|
else if (clearing)
|
||||||
|
clearing = 0; /* at next one now.. better stop */
|
||||||
|
}
|
||||||
|
if (clearing)
|
||||||
|
hdr[0] = MODINFO_EMPTY;
|
||||||
|
|
||||||
|
/* skip to next field */
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called from locore on i386. Convert physical pointers to kvm. Sigh. */
|
||||||
|
void
|
||||||
|
preload_bootstrap_relocate(vm_offset_t offset)
|
||||||
|
{
|
||||||
|
caddr_t curp;
|
||||||
|
u_int32_t *hdr;
|
||||||
|
vm_offset_t *ptr;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
if (preload_metadata != NULL) {
|
||||||
|
|
||||||
|
curp = preload_metadata;
|
||||||
|
for (;;) {
|
||||||
|
hdr = (u_int32_t *)curp;
|
||||||
|
if (hdr[0] == 0 && hdr[1] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Deal with the ones that we know we have to fix */
|
||||||
|
switch (hdr[0]) {
|
||||||
|
case MODINFO_ADDR:
|
||||||
|
case MODINFO_METADATA|MODINFOMD_SSYM:
|
||||||
|
case MODINFO_METADATA|MODINFOMD_ESYM:
|
||||||
|
ptr = (vm_offset_t *)(curp + (sizeof(u_int32_t) * 2));
|
||||||
|
*ptr += offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* The rest is beyond us for now */
|
||||||
|
|
||||||
|
/* skip to next field */
|
||||||
|
next = sizeof(u_int32_t) * 2 + hdr[1];
|
||||||
|
next = roundup(next, sizeof(u_long));
|
||||||
|
curp += next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
libbsd.txt
25
libbsd.txt
@ -554,6 +554,8 @@ been partially tested. If they contain both USB and Nic, then they are used
|
|||||||
by both and MAY contain methods that have not been tested yet. Files that
|
by both and MAY contain methods that have not been tested yet. Files that
|
||||||
are only used by the Nic test are the most suspect.
|
are only used by the Nic test are the most suspect.
|
||||||
|
|
||||||
|
[listing]
|
||||||
|
----
|
||||||
rtems-libbsd File: rtems-bsd-assert.c
|
rtems-libbsd File: rtems-bsd-assert.c
|
||||||
FreeBSD File: rtems-bsd-config.h redefines BSD_ASSERT.
|
FreeBSD File: rtems-bsd-config.h redefines BSD_ASSERT.
|
||||||
Description: This file contains the support method rtems_bsd_assert_func().
|
Description: This file contains the support method rtems_bsd_assert_func().
|
||||||
@ -737,9 +739,23 @@ rtems-libbsd File: rtems-bsd-vm_glue.c
|
|||||||
FreeBSD File: vm/vm_glue.c
|
FreeBSD File: vm/vm_glue.c
|
||||||
Description:
|
Description:
|
||||||
Status: USB, Nic
|
Status: USB, Nic
|
||||||
|
----
|
||||||
|
|
||||||
|
== Notes by File ==
|
||||||
|
|
||||||
|
altq_subr.c - Arbitrary choices were made in this file that RTEMS would
|
||||||
|
not support tsc frequency change. Additionally, the clock frequency
|
||||||
|
for machclk_freq is always measured for RTEMS.
|
||||||
|
|
||||||
|
conf.h - In order to add make_dev and destroy_dev, variables in the cdev
|
||||||
|
structure that were not being used were conditionally compiled out. The
|
||||||
|
capability of supporting children did not appear to be needed and was
|
||||||
|
not implemented in the rtems version of these routines.
|
||||||
|
|
||||||
== NICs Status ==
|
== NICs Status ==
|
||||||
|
|
||||||
|
[listing]
|
||||||
|
----
|
||||||
Driver Symbol Status
|
Driver Symbol Status
|
||||||
====== ====== ======
|
====== ====== ======
|
||||||
RealTek _bsd_re_pcimodule_sys_init Links
|
RealTek _bsd_re_pcimodule_sys_init Links
|
||||||
@ -748,13 +764,10 @@ DEC tulip _bsd_dc_pcimodule_sys_init Links
|
|||||||
Broadcom BCM57xxx _bsd_bce_pcimodule_sys_init Links
|
Broadcom BCM57xxx _bsd_bce_pcimodule_sys_init Links
|
||||||
Broadcom BCM4401 _bsd_bfe_pcimodule_sys_init Links
|
Broadcom BCM4401 _bsd_bfe_pcimodule_sys_init Links
|
||||||
Broadcom BCM570x _bsd_bge_pcimodule_sys_init Needs Symbols (A)
|
Broadcom BCM570x _bsd_bge_pcimodule_sys_init Needs Symbols (A)
|
||||||
E1000 xxx _bsd_igb_pcimodule_sys_init Needs Symbols (B)
|
E1000 IGB _bsd_igb_pcimodule_sys_init Links
|
||||||
E1000 XXX _bsd_em_pcimodule_sys_init Needs Symbols (B)
|
E1000 EM _bsd_em_pcimodule_sys_init Links
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
Symbols (A)
|
Symbols (A)
|
||||||
pci_find_dbsf
|
|
||||||
pci_get_vpd_ident
|
pci_get_vpd_ident
|
||||||
Symbols (B)
|
|
||||||
make_dev()
|
|
||||||
destroy_dev()
|
|
||||||
|
65
rtemsbsd/src/rtems-bsd-conf.c
Normal file
65
rtemsbsd/src/rtems-bsd-conf.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup rtems_bsd_rtems
|
||||||
|
*
|
||||||
|
* @brief This file is an rtems representation of needed methods from
|
||||||
|
* the FreeBSD file kern_conf.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* COPYRIGHT (c) 2012. On-Line Applications Research Corporation (OAR).
|
||||||
|
* 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 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 AUTHOR 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 <freebsd/machine/rtems-bsd-config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <rtems.h>
|
||||||
|
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <freebsd/sys/param.h>
|
||||||
|
#include <freebsd/sys/conf.h>
|
||||||
|
|
||||||
|
struct cdev *
|
||||||
|
make_dev(struct cdevsw *devsw, int unit, uid_t uid, gid_t gid, int mode,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct cdev *dev;
|
||||||
|
dev = malloc( sizeof(struct cdev) );
|
||||||
|
|
||||||
|
/* Initialize the elements that rtems uses. */
|
||||||
|
dev->si_flags = 0;
|
||||||
|
dev->si_drv0 = unit;
|
||||||
|
dev->si_drv1 = NULL;
|
||||||
|
dev->si_drv2 = NULL;
|
||||||
|
|
||||||
|
return (dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroy_dev(struct cdev *dev)
|
||||||
|
{
|
||||||
|
free (dev);
|
||||||
|
}
|
37
rtemsbsd/src/rtems-bsd-subr_param.c
Normal file
37
rtemsbsd/src/rtems-bsd-subr_param.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup rtems_bsd_rtems
|
||||||
|
*
|
||||||
|
* @brief This file is an rtems representation of needed methods
|
||||||
|
* and/or variables associated with the FreeBSD file subr_param.c
|
||||||
|
|
||||||
|
/*
|
||||||
|
* COPYRIGHT (c) 2012. On-Line Applications Research Corporation (OAR).
|
||||||
|
* 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 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 AUTHOR 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 <freebsd/machine/rtems-bsd-config.h>
|
||||||
|
|
||||||
|
int vm_guest = 0;
|
Loading…
x
Reference in New Issue
Block a user