Skip to content

Instantly share code, notes, and snippets.

@DanielO
Last active August 29, 2015 14:09
Show Gist options
  • Save DanielO/f0f6643de567981a9a10 to your computer and use it in GitHub Desktop.
Save DanielO/f0f6643de567981a9a10 to your computer and use it in GitHub Desktop.
/*-
* Copyright (c) 2014 Daniel O'Connor <darius@dons.net.au>
* 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 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.
*/
/* Driver for EHCI debug port */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include "dbgp_var.h"
static void dbgp_add(device_t dev, uint8_t bus, uint8_t slot, uint8_t func, uint16_t offset, uint16_t map);
static int dbgp_probe(device_t dev);
static int dbgp_search(module_t mod, int /* modeventtype_t */ what, void *arg);
static device_method_t dbgp_methods[] = {
DEVMETHOD(device_probe, dbgp_probe),
DEVMETHOD_END
};
static devclass_t dbgp_devclass;
static driver_t dbgp_driver = {
"dbgp",
dbgp_methods,
sizeof(struct dbgp_softc)
};
static moduledata_t mod_data = {
"dbgp",
dbgp_search,
0
};
MODULE_VERSION(dbgp, 1);
MODULE_DEPEND(dbgp, pci, 1, 1, 1);
DRIVER_MODULE(dbgp, pci, dbgp_driver, dbgp_devclass, NULL, NULL);
DECLARE_MODULE(dbgp, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
void
dbgp_add(device_t dev, uint8_t bus, uint8_t slot, uint8_t func, uint16_t offset, uint16_t map)
{
device_t parent;
u_long start, count;
int rid;
device_t child;
printf("Found debug capability on %d.%d.%d at 0x%x map 0x%x\n",
bus, slot, func, offset, map);
if ((parent = device_get_parent(dev)) == NULL) {
printf("Unable to get parent device\n");
return;
}
rid = PCIR_BAR(0);
if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
printf("Unable to get BAR 0\n");
return;
}
printf("start 0x%08lx length %lu\n", start, count);
if (device_find_child(dev, "dbgp", -1) != NULL) {
printf("Creating child device\n");
if ((child = device_add_child(dev, "dbgpa", -1)) == NULL) {
printf("Unable to create child device\n");
return;
}
} else {
printf("Child already present\n");
return;
}
device_set_driver(child, &dbgp_driver);
if (bus_set_resource(child, SYS_RES_MEMORY, 0, start, count) != 0)
printf("Unable to add resource\n");
}
static int
dbgp_probe(device_t dev)
{
driver_t *drv;
if ((drv = device_get_driver(dev)) == NULL) {
printf("No driver for dev\n");
} else {
printf("Driver is %s\n", drv->name);
}
device_set_desc_copy(dev, "EHCI debug port");
printf("Probed\n");
return (ENXIO);
}
static int
dbgp_search(module_t mod, int /*modeventtype_t*/ what, void *arg)
{
uint8_t bus, func, slot;
uint16_t offset;
int reg;
device_t dev;
switch (what) {
case MOD_LOAD:
printf("========== MOD_LOAD ==========\n");
for (bus = 0; bus < PCI_BUSMAX; bus++) {
for (slot = 0; slot < PCI_SLOTMAX; slot++) {
for (func = 0; func < PCI_FUNCMAX; func++) {
dev = pci_find_bsf(bus, slot, func);
if (dev == NULL)
continue;
if (pci_find_cap(dev, PCIY_DEBUG, &reg) != 0)
continue;
offset = pci_read_config(dev, reg + PCIR_DEBUG_PORT, 2);
dbgp_add(dev, bus, slot, func, offset & PCIM_DEBUG_PORT_OFFSET,
PCIR_BAR(offset >> 13));
}
}
}
return (0);
break;
case MOD_UNLOAD:
return (0);
default:
return (EOPNOTSUPP);
break;
}
return (ENXIO);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment