35#include "opt_platform.h"
40#include <sys/libkern.h>
43#include <machine/resource.h>
49#include "ofw_bus_if.h"
51#define OFW_COMPAT_LEN 255
52#define OFW_STATUS_LEN 16
77 if (obd->obd_compat != NULL)
78 free(obd->obd_compat, M_OFWPROP);
79 if (obd->obd_model != NULL)
80 free(obd->obd_model, M_OFWPROP);
81 if (obd->obd_name != NULL)
82 free(obd->obd_name, M_OFWPROP);
83 if (obd->obd_type != NULL)
84 free(obd->obd_type, M_OFWPROP);
85 if (obd->obd_status != NULL)
86 free(obd->obd_status, M_OFWPROP);
110 const struct ofw_bus_devinfo *obd;
112 obd = OFW_BUS_GET_DEVINFO(bus,
dev);
115 return (obd->obd_compat);
121 const struct ofw_bus_devinfo *obd;
123 obd = OFW_BUS_GET_DEVINFO(bus,
dev);
126 return (obd->obd_model);
132 const struct ofw_bus_devinfo *obd;
134 obd = OFW_BUS_GET_DEVINFO(bus,
dev);
137 return (obd->obd_name);
143 const struct ofw_bus_devinfo *obd;
145 obd = OFW_BUS_GET_DEVINFO(bus,
dev);
148 return (obd->obd_node);
154 const struct ofw_bus_devinfo *obd;
156 obd = OFW_BUS_GET_DEVINFO(bus,
dev);
159 return (obd->obd_type);
165 const struct ofw_bus_devinfo *obd;
167 obd = OFW_BUS_GET_DEVINFO(device_get_parent(
dev),
dev);
171 return (obd->obd_status);
180 if (status == NULL || strcmp(status,
"okay") == 0 ||
181 strcmp(status,
"ok") == 0)
198 if ((len == 5 && (bcmp(status,
"okay", len) == 0)) ||
199 (len == 3 && (bcmp(status,
"ok", len))))
207 const char *onecompat)
211 onelen = strlen(onecompat);
215 if (strlen(compat) == onelen &&
216 strncasecmp(compat, onecompat, onelen) == 0) {
223 l = strlen(compat) + 1;
279 len = strlen(compatible);
280 if (strlen(compat) == len &&
281 strncasecmp(compat, compatible, len) == 0)
294 for (; compat->
ocd_str != NULL; ++compat) {
319 if (
OF_getencprop(node,
"#address-cells", &addrc,
sizeof(addrc)) == -1)
332 if (msksz != -1 && msksz != ii->
opi_addrc + intrsz)
333 panic(
"ofw_bus_setup_iinfo: bad interrupt-map-mask "
340 int regsz,
void *pintr,
int pintrsz,
void *mintr,
int mintrsz,
343 uint8_t maskbuf[regsz + pintrsz];
349 (
"ofw_bus_lookup_imap: register size too small: %d < %d",
354 panic(
"ofw_bus_lookup_imap: cannot get reg property");
380 void *imap,
int imapsz,
void *imapmsk,
void *maskbuf,
void *result,
384 uint8_t *ref = maskbuf;
385 uint8_t *uiintr = intr;
386 uint8_t *uiregs = regs;
387 uint8_t *uiimapmsk = imapmsk;
393 if (imapmsk != NULL) {
394 for (i = 0; i < physsz; i++)
395 ref[i] = uiregs[i] & uiimapmsk[i];
396 for (i = 0; i < intrsz; i++)
397 ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i];
399 bcopy(regs, ref, physsz);
400 bcopy(intr, ref + physsz, intrsz);
408#ifndef OFW_IMAP_NO_IPARENT_ADDR_CELLS
415 "#address-cells", &paddrsz,
sizeof(paddrsz)) == -1)
421 "#interrupt-cells", &pintrsz,
sizeof(pintrsz)) == -1)
426 tsz = physsz + intrsz +
sizeof(
phandle_t) + paddrsz + pintrsz;
427 KASSERT(i >= tsz, (
"ofw_bus_search_intrmap: truncated map"));
429 if (bcmp(ref, mptr, physsz + intrsz) == 0) {
430 bcopy(mptr + physsz + intrsz +
sizeof(
parent) + paddrsz,
431 result, MIN(rintrsz, pintrsz));
435 return (pintrsz/
sizeof(
pcell_t));
447 pcell_t *map, mask, msi_base, rid_base, rid_length;
456 if (msi_parent != NULL) {
459 sizeof(*msi_parent));
470 masked_rid = pci_rid & mask;
471 for (i = 0; i < len; i += 4) {
472 rid_base = map[i + 0];
473 rid_length = map[i + 3];
475 if (masked_rid < rid_base ||
476 masked_rid >= (rid_base + rid_length))
479 msi_base = map[i + 2];
481 if (msi_parent != NULL)
482 *msi_parent = map[i + 1];
484 *msi_rid = masked_rid - rid_base + msi_base;
489 free(map, M_OFWPROP);
496 struct resource_list *rl,
const char *reg_source)
499 ssize_t i, j, rid, nreg, ret;
513 nreg = (ret == -1) ? 0 : ret;
515 if (nreg % (acells + scells) != 0) {
517 device_printf(
dev,
"Malformed reg property on <%s>\n",
518 (name == NULL) ?
"unknown" : name);
522 for (i = 0, rid = 0; i < nreg; i += acells + scells, rid++) {
524 for (j = 0; j < acells; j++) {
528 for (j = 0; j < scells; j++) {
530 size |= reg[i + acells + j];
534 resource_list_add(rl, SYS_RES_MEMORY, rid,
537 free(name, M_OFWPROP);
538 free(reg, M_OFWPROP);
545 struct resource_list *rl)
553 pcell_t scells,
struct resource_list *rl)
557 rl,
"assigned-addresses"));
583 struct resource_list *rl,
int *rlen)
587 int err, i, irqnum, nintr, rid;
595 device_printf(
dev,
"No interrupt-parent found, "
596 "assuming direct parent\n");
602 device_printf(
dev,
"Missing #interrupt-cells "
603 "property, assuming <1>\n");
606 if (icells < 1 || icells > nintr) {
607 device_printf(
dev,
"Invalid #interrupt-cells property "
608 "value <%d>, assuming <1>\n",
icells);
614 sizeof(*intr), (
void **)&intr);
621 for (i = 0; i < nintr; i +=
icells) {
626 device_printf(
dev,
"Missing #interrupt-cells "
632 device_printf(
dev,
"Invalid #interrupt-cells "
633 "property value <%d>\n",
icells);
639 resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1);
643 free(intr, M_OFWPROP);
653 int err, i, nintr, rid;
661 device_printf(
dev,
"No interrupt-parent found, "
662 "assuming direct parent\n");
668 device_printf(
dev,
"Missing #interrupt-cells "
669 "property, assuming <1>\n");
672 if (icells < 1 || icells > nintr) {
673 device_printf(
dev,
"Invalid #interrupt-cells property "
674 "value <%d>, assuming <1>\n",
icells);
680 sizeof(*intr), (
void **)&intr);
687 for (i = 0; i < nintr; i +=
icells, rid++) {
692 device_printf(
dev,
"Missing #interrupt-cells "
698 device_printf(
dev,
"Invalid #interrupt-cells "
699 "property value <%d>\n",
icells);
704 if (rid == wanted_rid) {
705 *cells = malloc(
icells *
sizeof(**cells), M_OFWPROP,
709 memcpy(*cells, intr + i,
icells *
sizeof(**cells));
714 free(intr, M_OFWPROP);
729 if (strcmp(name, child_name) == 0) {
730 free(name, M_OFWPROP);
734 free(name, M_OFWPROP);
772 device_t *children, retval,
child;
786 if (device_get_children(bus, &children, &nkid) != 0)
789 for (i = 0; i < nkid; i++) {
791 if (OFW_BUS_GET_NODE(bus,
child) == node) {
796 free(children, M_TEMP);
818 const char *cells_name,
int idx,
phandle_t *producer,
int *ncells,
824 int rv, i, j, nelems, cnt;
831 rv = (idx == -1) ? 0 : ENOENT;
832 for (i = 0, cnt = 0; i < nelems; i += pcells, cnt++) {
835 cells_name, &pcells,
sizeof(pcells)) == -1) {
836 printf(
"Missing %s property\n", cells_name);
841 if ((i + pcells) > nelems) {
842 printf(
"Invalid %s property value <%d>\n", cells_name,
848 *cells= malloc(pcells *
sizeof(**cells), M_OFWPROP,
852 for (j = 0; j < pcells; j++)
853 (*cells)[j] = elems[i + j];
859 free(elems, M_OFWPROP);
860 if (idx == -1 && rv == 0)
880 const char *cells_name,
int idx,
phandle_t *producer,
int *ncells,
885 (
"ofw_bus_parse_xref_list_alloc: negative index supplied"));
888 idx, producer, ncells, cells));
904 const char *cells_name,
int *count)
908 -1, NULL, count, NULL));
916 const char *name,
int *idx)
919 int rv, i, cnt, nelems;
927 for (i = 0, cnt = 0; i < nelems; cnt++) {
928 if (strcmp(elems + i, name) == 0) {
933 i += strlen(elems + i) + 1;
937 free(elems, M_OFWPROP);
946 const char ***out_array)
950 int i, cnt, nelems, len;
958 for (i = 0, cnt = 0; i < nelems; cnt++)
959 i += strlen(elems + i) + 1;
962 array = malloc((cnt + 1) *
sizeof(
char *) + nelems, M_OFWPROP,
966 tptr = (
char *)(array + cnt + 1);
969 memcpy(tptr, elems, nelems);
970 free(elems, M_OFWPROP);
973 for (i = 0, cnt = 0; i < nelems; cnt++) {
974 len = strlen(tptr) + 1;
METHOD phandle_t parent
Return parent of node.
METHOD phandle_t child
Return first child of node.
static __inline phandle_t ofw_bus_get_node(device_t dev)
static __inline int ofw_bus_map_intr(device_t dev, phandle_t iparent, int icells, pcell_t *intr)
static __inline const char * ofw_bus_get_compat(device_t dev)
static __inline const char * ofw_bus_get_name(device_t dev)
static int ofw_bus_node_is_compatible_int(const char *compat, int len, const char *onecompat)
int ofw_bus_node_is_compatible(phandle_t node, const char *compatstr)
static int ofw_bus_reg_to_rl_helper(device_t dev, phandle_t node, pcell_t acells, pcell_t scells, struct resource_list *rl, const char *reg_source)
int ofw_bus_msimap(phandle_t node, uint16_t pci_rid, phandle_t *msi_parent, uint32_t *msi_rid)
int ofw_bus_reg_to_rl(device_t dev, phandle_t node, pcell_t acells, pcell_t scells, struct resource_list *rl)
int ofw_bus_parse_xref_list_get_length(phandle_t node, const char *list_name, const char *cells_name, int *count)
const char * ofw_bus_get_status(device_t dev)
phandle_t ofw_bus_gen_get_node(device_t bus, device_t dev)
int ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result, int rintrsz, phandle_t *iparent)
static int ofw_bus_parse_xref_list_internal(phandle_t node, const char *list_name, const char *cells_name, int idx, phandle_t *producer, int *ncells, pcell_t **cells)
int ofw_bus_is_compatible(device_t dev, const char *onecompat)
const char * ofw_bus_gen_get_compat(device_t bus, device_t dev)
int ofw_bus_string_list_to_array(phandle_t node, const char *list_name, const char ***out_array)
int ofw_bus_node_status_okay(phandle_t node)
int ofw_bus_has_prop(device_t dev, const char *propname)
const char * ofw_bus_gen_get_name(device_t bus, device_t dev)
void ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
int ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl, int *rlen)
int ofw_bus_parse_xref_list_alloc(phandle_t node, const char *list_name, const char *cells_name, int idx, phandle_t *producer, int *ncells, pcell_t **cells)
int ofw_bus_status_okay(device_t dev)
int ofw_bus_is_compatible_strict(device_t dev, const char *compatible)
void ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd)
const struct ofw_compat_data * ofw_bus_search_compatible(device_t dev, const struct ofw_compat_data *compat)
int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *obd, phandle_t node)
phandle_t ofw_bus_find_compatible(phandle_t node, const char *onecompat)
const char * ofw_bus_gen_get_model(device_t bus, device_t dev)
device_t ofw_bus_find_child_device_by_phandle(device_t bus, phandle_t node)
Return child of bus whose phandle is node.
int ofw_bus_gen_child_pnpinfo(device_t cbdev, device_t child, struct sbuf *sb)
int ofw_bus_intr_by_rid(device_t dev, phandle_t node, int wanted_rid, phandle_t *producer, int *ncells, pcell_t **cells)
const char * ofw_bus_gen_get_type(device_t bus, device_t dev)
phandle_t ofw_bus_find_child(phandle_t start, const char *child_name)
phandle_t ofw_bus_find_iparent(phandle_t node)
int ofw_bus_find_string_index(phandle_t node, const char *list_name, const char *name, int *idx)
int ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg, int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz, phandle_t *iparent)
int ofw_bus_assigned_addresses_to_rl(device_t dev, phandle_t node, pcell_t acells, pcell_t scells, struct resource_list *rl)
ssize_t OF_getencprop_alloc(phandle_t package, const char *name, void **buf)
ssize_t OF_getencprop_alloc_multi(phandle_t package, const char *name, int elsz, void **buf)
phandle_t OF_node_from_xref(phandle_t xref)
ssize_t OF_searchencprop(phandle_t node, const char *propname, pcell_t *buf, size_t len)
phandle_t OF_peer(phandle_t node)
phandle_t OF_xref_from_node(phandle_t node)
ssize_t OF_getproplen(phandle_t package, const char *propname)
phandle_t OF_parent(phandle_t node)
ssize_t OF_getencprop(phandle_t node, const char *propname, pcell_t *buf, size_t len)
int OF_hasprop(phandle_t package, const char *propname)
ssize_t OF_getprop_alloc(phandle_t package, const char *propname, void **buf)
phandle_t OF_child(phandle_t node)
ssize_t OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen)