aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2016-04-19 15:56:39 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2016-04-19 15:56:39 +0000
commit36e4410ab0aa435639556b39dac37fb9f90cd962 (patch)
tree719fc09d561193dbb55ff9d9b8ca4bcba654f7ae
parent386fb140a6ffdae9b5229269456897816809fbf3 (diff)
downloadsrc-36e4410ab0aa435639556b39dac37fb9f90cd962.tar.gz
src-36e4410ab0aa435639556b39dac37fb9f90cd962.zip
[bhnd] Standardize bhnd device tables and quirk matching.
This add a bhnd device table mechanism that standardizes matching of devices on the bhnd(4) bus, discovery of device quirk flags, and should be pluggable into the new PNPINFO machinery. Submitted by: Landon Fuller <landonf@landonf.org> Differential Revision: https://reviews.freebsd.org/D5759
Notes
Notes: svn path=/head/; revision=298278
-rw-r--r--sys/dev/bhnd/bhnd.h128
-rw-r--r--sys/dev/bhnd/bhnd_subr.c107
-rw-r--r--sys/dev/bhnd/bhndb/bhndb_pci.c74
-rw-r--r--sys/dev/bhnd/bhndb/bhndb_pcivar.h9
-rw-r--r--sys/dev/bhnd/cores/chipc/chipc.c50
-rw-r--r--sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c2
6 files changed, 241 insertions, 129 deletions
diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h
index 7548c8a4dbce..5a3e9926f00c 100644
--- a/sys/dev/bhnd/bhnd.h
+++ b/sys/dev/bhnd/bhnd.h
@@ -167,72 +167,104 @@ struct bhnd_hwrev_match {
/**
* Wildcard hardware revision match descriptor.
*/
-#define BHND_HWREV_MATCH_ANY { BHND_HWREV_INVALID, BHND_HWREV_INVALID }
-
-
-/** A core match descriptor. */
-struct bhnd_core_match {
- uint16_t vendor; /**< required JEP106 device vendor or BHND_MFGID_INVALID. */
- uint16_t device; /**< required core ID or BHND_COREID_INVALID */
- struct bhnd_hwrev_match hwrev; /**< matching revisions. */
- bhnd_devclass_t class; /**< required class or BHND_DEVCLASS_INVALID */
- int unit; /**< required core unit, or -1 */
-};
-
-
-/**
- * Revision-specific hardware quirk descriptor.
- *
- * Defines a set of quirk flags applicable to a range of hardware
- * revisions.
- */
-struct bhnd_device_quirk {
- struct bhnd_hwrev_match hwrev; /**< applicable hardware revisions */
- uint32_t quirks; /**< applicable quirk flags */
-};
+#define BHND_HWREV_ANY { BHND_HWREV_INVALID, BHND_HWREV_INVALID }
+#define BHND_HWREV_IS_ANY(_m) \
+ ((_m)->start == BHND_HWREV_INVALID && (_m)->end == BHND_HWREV_INVALID)
/**
- * Define a bhnd_device_quirk over a range of hardware revisions.
+ * Hardware revision match descriptor for an inclusive range.
*
* @param _start The first applicable hardware revision.
* @param _end The last applicable hardware revision, or BHND_HWREV_INVALID
* to match on any revision.
- * @param _quirks Quirk flags applicable to this revision range.
*/
-#define BHND_QUIRK_HWREV_RANGE(_start, _end, _quirks) \
- { .hwrev = { _start, _end }, .quirks = _quirks }
+#define BHND_HWREV_RANGE(_start, _end) { _start, _end }
/**
- * Define a bhnd_device_quirk for a specific hardware revision.
+ * Hardware revision match descriptor for a single revision.
*
* @param _hwrev The hardware revision to match on.
- * @param _quirks Quirk flags applicable to this revision.
*/
-#define BHND_QUIRK_HWREV_EQ(_hwrev, _quirks) \
- BHND_QUIRK_HWREV_RANGE(_hwrev, _hwrev, _quirks)
+#define BHND_HWREV_EQ(_hwrev) BHND_HWREV_RANGE(_hwrev, _hwrev)
/**
- * Define a bhnd_device_quirk for any hardware revision equal or greater
+ * Hardware revision match descriptor for any revision equal to or greater
* than @p _start.
*
* @param _start The first hardware revision to match on.
- * @param _quirks Quirk flags applicable to this revision.
*/
-#define BHND_QUIRK_HWREV_GTE(_start, _quirks) \
- BHND_QUIRK_HWREV_RANGE(_start, BHND_HWREV_INVALID, _quirks)
+#define BHND_HWREV_GTE(_start) BHND_HWREV_RANGE(_start, BHND_HWREV_INVALID)
/**
- * Define a bhnd_device_quirk for any hardware revision equal or less
+ * Hardware revision match descriptor for any revision equal to or less
* than @p _end.
*
* @param _end The last hardware revision to match on.
- * @param _quirks Quirk flags applicable to this revision.
*/
-#define BHND_QUIRK_HWREV_LTE(_end, _quirks) \
- BHND_QUIRK_HWREV_RANGE(0, _end, _quirks)
+#define BHND_HWREV_LTE(_end) BHND_HWREV_RANGE(0, _end)
-/** Mark the end of a bhnd_device_quirk table. */
-#define BHND_QUIRK_HWREV_END { BHND_HWREV_MATCH_ANY, 0 }
+
+/** A core match descriptor. */
+struct bhnd_core_match {
+ uint16_t vendor; /**< required JEP106 device vendor or BHND_MFGID_INVALID. */
+ uint16_t device; /**< required core ID or BHND_COREID_INVALID */
+ struct bhnd_hwrev_match hwrev; /**< matching revisions. */
+ bhnd_devclass_t class; /**< required class or BHND_DEVCLASS_INVALID */
+ int unit; /**< required core unit, or -1 */
+};
+
+/**
+ * Core match descriptor matching against the given @p _vendor, @p _device,
+ * and @p _hwrev match descriptors.
+ */
+#define BHND_CORE_MATCH(_vendor, _device, _hwrev) \
+ { _vendor, _device, _hwrev, BHND_DEVCLASS_INVALID, -1 }
+
+/**
+ * Wildcard core match descriptor.
+ */
+#define BHND_CORE_MATCH_ANY \
+ { \
+ .vendor = BHND_MFGID_INVALID, \
+ .device = BHND_COREID_INVALID, \
+ .hwrev = BHND_HWREV_ANY, \
+ .class = BHND_DEVCLASS_INVALID, \
+ .unit = -1 \
+ }
+
+/**
+ * Device quirk table descriptor.
+ */
+struct bhnd_device_quirk {
+ struct bhnd_hwrev_match hwrev; /**< applicable hardware revisions */
+ uint32_t quirks; /**< quirk flags */
+};
+#define BHND_DEVICE_QUIRK_END { BHND_HWREV_ANY, 0 }
+#define BHND_DEVICE_QUIRK_IS_END(_q) \
+ (BHND_HWREV_IS_ANY(&(_q)->hwrev) && (_q)->quirks == 0)
+
+enum {
+ BHND_DF_ANY = 0,
+ BHND_DF_HOSTB = (1<<0) /**< core is serving as the bus'
+ * host bridge */
+};
+
+/** Device probe table descriptor */
+struct bhnd_device {
+ const struct bhnd_core_match core; /**< core match descriptor */
+ const char *desc; /**< device description, or NULL. */
+ const struct bhnd_device_quirk *quirks_table; /**< quirks table for this device, or NULL */
+ uint32_t device_flags; /**< required BHND_DF_* flags */
+};
+
+#define _BHND_DEVICE(_device, _desc, _quirks, _flags, ...) \
+ { BHND_CORE_MATCH(BHND_MFGID_BCM, BHND_COREID_ ## _device, \
+ BHND_HWREV_ANY), _desc, _quirks, _flags }
+
+#define BHND_DEVICE(_device, _desc, _quirks, ...) \
+ _BHND_DEVICE(_device, _desc, _quirks, ## __VA_ARGS__, 0)
+
+#define BHND_DEVICE_END { BHND_CORE_MATCH_ANY, NULL, NULL, 0 }
const char *bhnd_vendor_name(uint16_t vendor);
const char *bhnd_port_type_name(bhnd_port_type port_type);
@@ -271,6 +303,14 @@ bool bhnd_hwrev_matches(uint16_t hwrev,
bool bhnd_device_matches(device_t dev,
const struct bhnd_core_match *desc);
+const struct bhnd_device *bhnd_device_lookup(device_t dev,
+ const struct bhnd_device *table,
+ size_t entry_size);
+
+uint32_t bhnd_device_quirks(device_t dev,
+ const struct bhnd_device *table,
+ size_t entry_size);
+
struct bhnd_core_info bhnd_get_core_info(device_t dev);
@@ -290,9 +330,9 @@ int bhnd_read_chipid(device_t dev,
bus_size_t chipc_offset,
struct bhnd_chipid *result);
-void bhnd_set_generic_core_desc(device_t dev);
-
-
+void bhnd_set_custom_core_desc(device_t dev,
+ const char *name);
+void bhnd_set_default_core_desc(device_t dev);
bool bhnd_bus_generic_is_hostb_device(device_t dev,
diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c
index ac1bada33242..04dcf699e3f4 100644
--- a/sys/dev/bhnd/bhnd_subr.c
+++ b/sys/dev/bhnd/bhnd_subr.c
@@ -470,6 +470,85 @@ bhnd_device_matches(device_t dev, const struct bhnd_core_match *desc)
}
/**
+ * Search @p table for an entry matching @p dev.
+ *
+ * @param dev A bhnd device to match against @p table.
+ * @param table The device table to search.
+ * @param entry_size The @p table entry size, in bytes.
+ *
+ * @retval bhnd_device the first matching device, if any.
+ * @retval NULL if no matching device is found in @p table.
+ */
+const struct bhnd_device *
+bhnd_device_lookup(device_t dev, const struct bhnd_device *table,
+ size_t entry_size)
+{
+ const struct bhnd_device *entry;
+
+ for (entry = table; entry->desc != NULL; entry =
+ (const struct bhnd_device *) ((const char *) entry + entry_size))
+ {
+ /* match core info */
+ if (!bhnd_device_matches(dev, &entry->core))
+ continue;
+
+ /* match device flags */
+ if (entry->device_flags & BHND_DF_HOSTB) {
+ if (!bhnd_is_hostb_device(dev))
+ continue;
+ }
+
+ /* device found */
+ return (entry);
+ }
+
+ /* not found */
+ return (NULL);
+}
+
+/**
+ * Scan @p table for all quirk flags applicable to @p dev.
+ *
+ * @param dev A bhnd device to match against @p table.
+ * @param table The device table to search.
+ * @param entry_size The @p table entry size, in bytes.
+ *
+ * @return returns all matching quirk flags.
+ */
+uint32_t
+bhnd_device_quirks(device_t dev, const struct bhnd_device *table,
+ size_t entry_size)
+{
+ const struct bhnd_device *dent;
+ const struct bhnd_device_quirk *qtable, *qent;
+ uint32_t quirks;
+ uint16_t hwrev;
+
+ hwrev = bhnd_get_hwrev(dev);
+ quirks = 0;
+
+ /* Find the quirk table */
+ if ((dent = bhnd_device_lookup(dev, table, entry_size)) == NULL) {
+ /* This is almost certainly a (caller) implementation bug */
+ device_printf(dev, "quirk lookup did not match any device\n");
+ return (0);
+ }
+
+ /* Quirks aren't a mandatory field */
+ if ((qtable = dent->quirks_table) == NULL)
+ return (0);
+
+ /* Collect matching quirk entries */
+ for (qent = qtable; !BHND_DEVICE_QUIRK_IS_END(qent); qent++) {
+ if (bhnd_hwrev_matches(hwrev, &qent->hwrev))
+ quirks |= qent->quirks;
+ }
+
+ return (quirks);
+}
+
+
+/**
* Allocate bhnd(4) resources defined in @p rs from a parent bus.
*
* @param dev The device requesting ownership of the resources.
@@ -619,25 +698,21 @@ cleanup:
}
/**
- * Using the bhnd(4) bus-level core information, populate @p dev's device
- * description.
+ * Using the bhnd(4) bus-level core information and a custom core name,
+ * populate @p dev's device description.
*
* @param dev A bhnd-bus attached device.
+ * @param dev_name The core's name (e.g. "SDIO Device Core")
*/
void
-bhnd_set_generic_core_desc(device_t dev)
+bhnd_set_custom_core_desc(device_t dev, const char *dev_name)
{
- const char *dev_name;
const char *vendor_name;
char *desc;
vendor_name = bhnd_get_vendor_name(dev);
- dev_name = bhnd_get_device_name(dev);
-
- asprintf(&desc, M_BHND, "%s %s, rev %hhu",
- bhnd_get_vendor_name(dev),
- bhnd_get_device_name(dev),
- bhnd_get_hwrev(dev));
+ asprintf(&desc, M_BHND, "%s %s, rev %hhu", vendor_name, dev_name,
+ bhnd_get_hwrev(dev));
if (desc != NULL) {
device_set_desc_copy(dev, desc);
@@ -648,6 +723,18 @@ bhnd_set_generic_core_desc(device_t dev)
}
/**
+ * Using the bhnd(4) bus-level core information, populate @p dev's device
+ * description.
+ *
+ * @param dev A bhnd-bus attached device.
+ */
+void
+bhnd_set_default_core_desc(device_t dev)
+{
+ bhnd_set_custom_core_desc(dev, bhnd_get_device_name(dev));
+}
+
+/**
* Helper function for implementing BHND_BUS_IS_HOSTB_DEVICE().
*
* If a parent device is available, this implementation delegates the
diff --git a/sys/dev/bhnd/bhndb/bhndb_pci.c b/sys/dev/bhnd/bhndb/bhndb_pci.c
index dd11c1249273..cc15ddeeb7ff 100644
--- a/sys/dev/bhnd/bhndb/bhndb_pci.c
+++ b/sys/dev/bhnd/bhndb/bhndb_pci.c
@@ -111,56 +111,60 @@ static const struct bhndb_pci_id *bhndb_pci_find_core_id(
*/
static const struct bhndb_pci_id bhndb_pci_ids[] = {
/* PCI */
- BHNDB_PCI_ID(PCI,
- BHND_QUIRK_HWREV_GTE (0,
- BHNDB_PCI_QUIRK_EXT_CLOCK_GATING |
- BHNDB_PCI_QUIRK_SBTOPCI2_PREF_BURST),
+ { BHND_COREID_PCI, BHND_PCI_REGFMT_PCI,
+ (struct bhnd_device_quirk[]) {
+ { BHND_HWREV_GTE (0),
+ BHNDB_PCI_QUIRK_EXT_CLOCK_GATING |
+ BHNDB_PCI_QUIRK_SBTOPCI2_PREF_BURST },
- BHND_QUIRK_HWREV_RANGE (0, 5,
- BHNDB_PCI_QUIRK_SBINTVEC),
+ { BHND_HWREV_RANGE (0, 5),
+ BHNDB_PCI_QUIRK_SBINTVEC },
- BHND_QUIRK_HWREV_GTE (11,
- BHNDB_PCI_QUIRK_SBTOPCI2_READMULTI |
- BHNDB_PCI_QUIRK_CLKRUN_DSBL),
+ { BHND_HWREV_GTE (11),
+ BHNDB_PCI_QUIRK_SBTOPCI2_READMULTI |
+ BHNDB_PCI_QUIRK_CLKRUN_DSBL },
- BHND_QUIRK_HWREV_END
- ),
+ BHND_DEVICE_QUIRK_END
+ }
+ },
/* PCI Gen 1 */
- BHNDB_PCI_ID(PCIE,
- BHND_QUIRK_HWREV_EQ (0,
- BHNDB_PCIE_QUIRK_SDR9_L0s_HANG),
+ { BHND_COREID_PCIE, BHND_PCI_REGFMT_PCIE,
+ (struct bhnd_device_quirk[]) {
+ { BHND_HWREV_EQ (0),
+ BHNDB_PCIE_QUIRK_SDR9_L0s_HANG },
- BHND_QUIRK_HWREV_RANGE (0, 1,
- BHNDB_PCIE_QUIRK_UR_STATUS_FIX),
+ { BHND_HWREV_RANGE (0, 1),
+ BHNDB_PCIE_QUIRK_UR_STATUS_FIX },
- BHND_QUIRK_HWREV_EQ (1,
- BHNDB_PCIE_QUIRK_PCIPM_REQEN),
+ { BHND_HWREV_EQ (1),
+ BHNDB_PCIE_QUIRK_PCIPM_REQEN },
- BHND_QUIRK_HWREV_RANGE (3, 5,
- BHNDB_PCIE_QUIRK_ASPM_OVR |
- BHNDB_PCIE_QUIRK_SDR9_POLARITY |
- BHNDB_PCIE_QUIRK_SDR9_NO_FREQRETRY),
+ { BHND_HWREV_RANGE (3, 5),
+ BHNDB_PCIE_QUIRK_ASPM_OVR |
+ BHNDB_PCIE_QUIRK_SDR9_POLARITY |
+ BHNDB_PCIE_QUIRK_SDR9_NO_FREQRETRY },
- BHND_QUIRK_HWREV_LTE (6,
- BHNDB_PCIE_QUIRK_L1_IDLE_THRESH),
+ { BHND_HWREV_LTE (6),
+ BHNDB_PCIE_QUIRK_L1_IDLE_THRESH },
- BHND_QUIRK_HWREV_GTE (6,
- BHNDB_PCIE_QUIRK_SPROM_L23_PCI_RESET),
+ { BHND_HWREV_GTE (6),
+ BHNDB_PCIE_QUIRK_SPROM_L23_PCI_RESET },
- BHND_QUIRK_HWREV_EQ (7,
- BHNDB_PCIE_QUIRK_SERDES_NOPLLDOWN),
+ { BHND_HWREV_EQ (7),
+ BHNDB_PCIE_QUIRK_SERDES_NOPLLDOWN },
- BHND_QUIRK_HWREV_GTE (8,
- BHNDB_PCIE_QUIRK_L1_TIMER_PERF),
+ { BHND_HWREV_GTE (8),
+ BHNDB_PCIE_QUIRK_L1_TIMER_PERF },
- BHND_QUIRK_HWREV_GTE (10,
- BHNDB_PCIE_QUIRK_SD_C22_EXTADDR),
+ { BHND_HWREV_GTE (10),
+ BHNDB_PCIE_QUIRK_SD_C22_EXTADDR },
- BHND_QUIRK_HWREV_END
- ),
+ BHND_DEVICE_QUIRK_END
+ }
+ },
- { BHND_COREID_INVALID, BHND_PCI_REGFMT_PCI, NULL }
+ { BHND_COREID_INVALID, BHND_PCI_REGFMT_PCI }
};
diff --git a/sys/dev/bhnd/bhndb/bhndb_pcivar.h b/sys/dev/bhnd/bhndb/bhndb_pcivar.h
index 0549bcc8fee4..8f86a8561349 100644
--- a/sys/dev/bhnd/bhndb/bhndb_pcivar.h
+++ b/sys/dev/bhnd/bhndb/bhndb_pcivar.h
@@ -97,15 +97,6 @@ struct bhndb_pci_softc {
} sdr9_quirk_polarity;
};
-/* Declare a bhndb_pci_id entry */
-#define BHNDB_PCI_ID(_device, _desc, ...) { \
- BHND_COREID_ ## _device, \
- BHND_PCI_REGFMT_ ## _device, \
- (struct bhnd_device_quirk[]) { \
- __VA_ARGS__ \
- } \
-}
-
/*
* PCI/PCIe-Gen1 endpoint-mode device quirks
*/
diff --git a/sys/dev/bhnd/cores/chipc/chipc.c b/sys/dev/bhnd/cores/chipc/chipc.c
index e03ddfe06e02..b16fb4bb6e88 100644
--- a/sys/dev/bhnd/cores/chipc/chipc.c
+++ b/sys/dev/bhnd/cores/chipc/chipc.c
@@ -62,21 +62,22 @@ static const struct resource_spec chipc_rspec[CHIPC_MAX_RSPEC] = {
{ -1, -1, 0 }
};
+static struct bhnd_device_quirk chipc_quirks[];
+
/* Supported device identifiers */
-static const struct chipc_device {
- uint16_t device;
-} chipc_devices[] = {
- { BHND_COREID_CC },
- { BHND_COREID_INVALID }
+static const struct bhnd_device chipc_devices[] = {
+ BHND_DEVICE(CC, "", chipc_quirks),
+ BHND_DEVICE_END
};
+
/* Device quirks table */
static struct bhnd_device_quirk chipc_quirks[] = {
- BHND_QUIRK_HWREV_RANGE (0, 21, CHIPC_QUIRK_ALWAYS_HAS_SPROM),
- BHND_QUIRK_HWREV_EQ (22, CHIPC_QUIRK_SPROM_CHECK_CST_R22),
- BHND_QUIRK_HWREV_RANGE (23, 31, CHIPC_QUIRK_SPROM_CHECK_CST_R23),
- BHND_QUIRK_HWREV_GTE (35, CHIPC_QUIRK_SUPPORTS_NFLASH),
- BHND_QUIRK_HWREV_END
+ { BHND_HWREV_RANGE (0, 21), CHIPC_QUIRK_ALWAYS_HAS_SPROM },
+ { BHND_HWREV_EQ (22), CHIPC_QUIRK_SPROM_CHECK_CST_R22 },
+ { BHND_HWREV_RANGE (23, 31), CHIPC_QUIRK_SPROM_CHECK_CST_R23 },
+ { BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH },
+ BHND_DEVICE_QUIRK_END
};
/* quirk and capability flag convenience macros */
@@ -95,25 +96,19 @@ static struct bhnd_device_quirk chipc_quirks[] = {
static int
chipc_probe(device_t dev)
{
- const struct chipc_device *id;
-
- for (id = chipc_devices; id->device != BHND_COREID_INVALID; id++)
- {
- if (bhnd_get_vendor(dev) == BHND_MFGID_BCM &&
- bhnd_get_device(dev) == id->device)
- {
- bhnd_set_generic_core_desc(dev);
- return (BUS_PROBE_DEFAULT);
- }
- }
+ const struct bhnd_device *id;
- return (ENXIO);
+ id = bhnd_device_lookup(dev, chipc_devices, sizeof(chipc_devices[0]));
+ if (id == NULL)
+ return (ENXIO);
+
+ bhnd_set_default_core_desc(dev);
+ return (BUS_PROBE_DEFAULT);
}
static int
chipc_attach(device_t dev)
{
- struct bhnd_device_quirk *dq;
struct chipc_softc *sc;
bhnd_addr_t enum_addr;
uint32_t ccid_reg;
@@ -122,6 +117,8 @@ chipc_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
+ sc->quirks = bhnd_device_quirks(dev, chipc_devices,
+ sizeof(chipc_devices[0]));
/* Allocate bus resources */
memcpy(sc->rspec, chipc_rspec, sizeof(sc->rspec));
@@ -155,13 +152,6 @@ chipc_attach(device_t dev)
sc->caps = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES);
sc->cst = bhnd_bus_read_4(sc->core, CHIPC_CHIPST);
- /* Populate the set of applicable quirk flags */
- sc->quirks = 0;
- for (dq = chipc_quirks; dq->quirks != 0; dq++) {
- if (bhnd_hwrev_matches(bhnd_get_hwrev(dev), &dq->hwrev))
- sc->quirks |= dq->quirks;
- }
-
// TODO
switch (bhnd_chipc_nvram_src(dev)) {
case BHND_NVRAM_SRC_CIS:
diff --git a/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c b/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c
index c508f8cc1592..6a047fb86675 100644
--- a/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c
+++ b/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c
@@ -68,7 +68,7 @@ bhnd_pci_hostb_probe(device_t dev)
if (!bhnd_is_hostb_device(dev))
return (ENXIO);
- bhnd_set_generic_core_desc(dev);
+ bhnd_set_default_core_desc(dev);
return (BUS_PROBE_DEFAULT);
}