On Tue, May 03, 2016 at 03:32:34PM -0500, Chase Davis wrote: > Mike, > > We took your suggestion and re-wrote the driver to model sdhc_acpi. I > have attached the new code. However, the match function never returns > a 1. We put temporary print statements in the match routine. It is > being called several times during the kernel boot process, but it > never finds a device with HID SEL0002. Do you have any suggestions for > why it would show up in the DSDT tables when we do an acpidump, but > that the match routine never finds it? > > This is a snippet from the dmesg boot log > > Attempting to match SEL: result (0) > acpitimer0 at acpi0: 3579545 Hz, 24 bits > Attempting to match SEL: result (0) > Attempting to match SEL: result (0) > Attempting to match SEL: result (0) > Attempting to match SEL: result (0) > acpihpet0 at acpi0: 14318179 Hz > Attempting to match SEL: result (0) > acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat > > int > sel_acpi_match(struct device *parent, void *match, void *aux) > { > struct acpi_attach_args *aaa = aux; > struct cfdata *cf = match; > printf("Attempting to match SEL: "); > int res = acpi_matchhids(aaa, sel_hids, cf->cf_driver->cd_name); > printf("result (%d)\n", res); > return res; > } > > Thanks, > Chase
I think this diff is missing some parts. Like GENERIC? Also, you need a NULL after your last HID or matchhids will walk all through memory until it hits a NULL. -ml > /* $OpenBSD: sel.c,v 1.0 2016/04/01 05:00:00 jsg Exp $ */ > /* > * Copyright (c) 2016 PREMIER System Integrators > * > * Permission to use, copy, modify, and distribute this software for any > * purpose with or without fee is hereby granted, provided that the above > * copyright notice and this permission notice appear in all copies. > * > * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > * > * Schweitzer Engineering Laboratories: SEL-3355 Embedded controller > */ > > #include <sys/types.h> > #include <sys/param.h> > #include <sys/systm.h> > #include <sys/device.h> > #include <sys/kernel.h> > #include <sys/malloc.h> > > #include <machine/bus.h> > > #include <dev/acpi/acpireg.h> > #include <dev/acpi/acpivar.h> > #include <dev/acpi/acpidev.h> > #include <dev/acpi/amltypes.h> > #include <dev/acpi/dsdt.h> > > #include <dev/isa/selreg.h> > > struct sel_host; > > struct sel_softc { > /* sc_dev must be the first item in the struct */ > struct device sc_dev; > struct sel_host **sc_host; > }; > > struct sel_acpi_softc { > struct sel_softc sc; > struct acpi_softc *sc_acpi; > struct aml_node *sc_node; > > /* device access through bus space */ > bus_space_tag_t sc_iot; > bus_space_handle_t sc_ioh; > bus_addr_t sc_addr; > bus_size_t sc_size; > > struct sel_host *sc_host; > }; > > int sel_wait(bus_space_tag_t, bus_space_handle_t, bool); > > /* Autoconfiguration glue */ > int sel_acpi_match(struct device *, void *, void *); > void sel_acpi_attach(struct device *, struct device *, void *); > int sel_print(void *, const char *); > int sel_wd_cb(void *, int); > > /* functions to interact with the controller */ > void sel_write_wdog(bus_space_tag_t, bus_space_handle_t, int); > u_int8_t sel_read_wdog(bus_space_tag_t, bus_space_handle_t); > u_int8_t sel_read_status(bus_space_tag_t, bus_space_handle_t); > void sel_abort(bus_space_tag_t, bus_space_handle_t); > u_int32_t sel_read_boardid(bus_space_tag_t, bus_space_handle_t); > u_int32_t sel_read_mcversion(bus_space_tag_t, bus_space_handle_t); > u_int16_t sel_read_pciboardid(bus_space_tag_t, bus_space_handle_t); > u_int8_t sel_read_ledctl0(bus_space_tag_t, bus_space_handle_t); > void sel_write_ledctl0(bus_space_tag_t, bus_space_handle_t, u_int8_t); > u_int8_t sel_read_ledctl1(bus_space_tag_t, bus_space_handle_t); > void sel_write_ledctl1(bus_space_tag_t, bus_space_handle_t, u_int8_t); > u_int8_t sel_read_miscctl0(bus_space_tag_t, bus_space_handle_t); > u_int8_t sel_read_miscctl1(bus_space_tag_t, bus_space_handle_t); > void sel_read_modelno(bus_space_tag_t, bus_space_handle_t, char*); > void sel_read_serialno(bus_space_tag_t, bus_space_handle_t, char*); > void sel_read_configid(bus_space_tag_t, bus_space_handle_t, char*); > > /* macros to extract bits from the status register */ > #define EC_STATUS_IBF(status) (((status) >> 0x1) & 0x1) > #define EC_STATUS_OBF(status) (((status) & 0x1)) > #define EC_STATUS_BUSY(status) (((status) >> 0x4) & 0x1) > #define EC_STATUS_STATE(status) (((status) >> 0x6) & 0x3) > > struct cfattach sel_acpi_ca = { > sizeof(struct sel_acpi_softc), sel_acpi_match, sel_acpi_attach > }; > > struct cfdriver sel_cd = { > NULL, "sel", DV_DULL > }; > > const char* sel_hids[] = { "SEL0002" }; > > int sel_wait(bus_space_tag_t iot, bus_space_handle_t ioh, bool useobf) > { > uint32_t timeout = 0; > uint8_t status = 0; > > while (timeout < 50) { > status = bus_space_read_1(iot, ioh, SELWD_CMD); > if ((EC_STATUS_IBF(status) == 0x0) && > (EC_STATUS_BUSY(status) == 0x0) && > (EC_STATUS_STATE(status) != 0x3) && > ((EC_STATUS_OBF(status) == 0x0) || !useobf)) { > return 1; > } > delay(10); > ++timeout; > } > return 0; > } > > static __inline void > sel_conf_enable(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t cmd) > { > /* write the desired command to the command register */ > bus_space_write_1(iot, ioh, SELWD_CMD, cmd); > /* wait for controller to be ready */ > sel_wait(iot,ioh,0); > } > > static __inline u_int8_t > sel_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t target) > { > /* write the target address to the data register */ > bus_space_write_1(iot, ioh, SELWD_DATA, target); > /* wait for controller to be ready */ > sel_wait(iot, ioh,1); > /* return the value from the data register */ > return (bus_space_read_1(iot, ioh, SELWD_DATA)); > } > > static __inline void > sel_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t target, > u_int8_t data) > { > /* write the target address to the data register */ > bus_space_write_1(iot, ioh, SELWD_DATA, target); > /* wait for controller to be ready */ > sel_wait(iot, ioh,0); > /* write the desired data to the data register */ > bus_space_write_1(iot, ioh, SELWD_DATA, data); > /* wait for controller to be ready */ > sel_wait(iot, ioh,0); > } > > int > sel_acpi_parse_resources(union acpi_resource *crs, void *arg) > { > struct sel_acpi_softc *sc = arg; > int type = AML_CRSTYPE(crs); > > printf(" SEL parse resource type (%d)", type); > > sc->sc_addr = crs->lr_m32fixed._bas; > sc->sc_size = crs->lr_m32fixed._len; > > return 0; > } > > int > sel_acpi_match(struct device *parent, void *match, void *aux) > { > struct acpi_attach_args *aaa = aux; > struct cfdata *cf = match; > > printf("Attempting to match SEL: "); > int res = acpi_matchhids(aaa, sel_hids, cf->cf_driver->cd_name); > printf("result (%d)\n", res); > return res; > } > > void > sel_acpi_attach(struct device *parent, struct device *self, void *aux) > { > struct acpi_attach_args *aaa = aux; > struct sel_acpi_softc *sc = (struct sel_acpi_softc *)self; > struct aml_value res; > > sc->sc_acpi = (struct acpi_softc *)parent; > sc->sc_node = aaa->aaa_node; > printf(": %s", sc->sc_node->name); > > if (aml_evalname(sc->ac_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { > printf(", can't find registers\n"); > return; > } > > aml_parse_resource(&res, sel_acpi_parse_resources, sc); > printf(" addr 0x%1x/0x%1x", sc->sc_addr, sc->sc_size); > if (sc->sc_addr == 0 || sc->sc_size == 0) { > printf("\n"); > return; > } > printf(" irq %d", sc->sc_irq); > > /* Match by device ID */ > sc->sc_iot = aaa->aaa_memt; > if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, > &sc->sc_ioh)) { > printf(", can't map registers\n"); > return; > } > > /* read from bus space first */ > u_int8_t test = bus_space_read_1(sc->sc_iot, sc->sc_ioh, SELWD_DATA); > /* if 0xFF is returned, there is nothing at the specified address */ > if (test == 0xff) { > bus_space_unmap(sc->sc_iot, sc->sc_ioh, SELWD_IOSIZE); > return; > } > > /* read board ID */ > u_int32_t devid = sel_read_boardid(sc->sc_iot, sc->sc_ioh); > printf(": SEL Board ID (%x)",devid); > > /* read model number */ > char *model = malloc(sizeof(char)*16, M_DEVBUF, M_WAITOK | M_ZERO); > sel_read_modelno(sc->sc_iot, sc->sc_ioh, model); > printf(", Model No (%s)",model); > free(model, M_DEVBUF, 0); > > /* read serial number */ > char *serial = malloc(sizeof(char)*16, M_DEVBUF, M_WAITOK | M_ZERO); > sel_read_serialno(sc->sc_iot, sc->sc_ioh, serial); > printf(", Serial No (%s)\n",serial); > free(serial, M_DEVBUF, 0); > > /* write to Enabled and Alarm LEDs */ > /* turns Enabled green and Alarm off */ > u_int8_t led0 = 0x02; > sel_write_ledctl0(sc->sc_iot, sc->sc_ioh, led0); > > /* write to Aux LEDs */ > /* turns off the LEDs */ > u_int8_t led1 = 0x00; > sel_write_ledctl1(sc->sc_iot, sc->sc_ioh, led1); > > sc->sc.sc_host = &sc->sc_host; > //wdog_register(sel_wd_cb,sc); > } > > int > sel_wd_cb(void *arg, int period) > { > /* This function is called by the watchdog daemon */ > /* Get a reference to the software context */ > struct sel_softc *sc = arg; > if (period < 0) > period = 0; > /* The period value is in seconds, the watchdog value is in > twos-of-secs */ > int wd = period / 2; > /* write watchdog value */ > sel_write_wdog(sc->sc_iot, sc->sc_ioh, wd); > /* return the period back to the daemon */ > return period; > } > > void > sel_write_wdog(bus_space_tag_t iot, bus_space_handle_t ioh, int value) > { > /* Check to make sure that the state is idle */ > sel_abort(iot, ioh); > /* Write watchdog timer value */ > /* write the WRITECFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_WRITECFG); > /* write the watchdog value to the watchdog address */ > sel_conf_write(iot, ioh, SELWD_CFG_WATCHDOG, value); > } > > u_int8_t > sel_read_wdog(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the watchdog value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t wdog; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the WATCHDOG data value from the data register */ > wdog = sel_conf_read(iot, ioh, SELWD_CFG_WATCHDOG); > return wdog; > } > > u_int8_t > sel_read_status(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the command/status register */ > u_int8_t status = 0; > status = bus_space_read_1(iot, ioh, SELWD_CMD); > return status; > } > > void > sel_abort(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* write the abort value to the command/status register */ > u_int8_t status = 0; > /* first read the status register */ > status = bus_space_read_1(iot, ioh, SELWD_CMD); > /* if the state is IDLE return */ > if (EC_STATUS_STATE(status) == 0) > return; > uint32_t timeout = 0; > /* make sure status is 0 before proceeding */ > while (EC_STATUS_STATE(status) != 0 && timeout < 50) { > /* write the abort command */ > bus_space_write_1(iot, ioh, SELWD_CMD, SELWD_CMD_ABORT); > /* wait until controller isn't busy */ > sel_wait(iot, ioh, 0); > /* read the status register */ > status = bus_space_read_1(iot, ioh, SELWD_CMD); > delay(10); > /* increment timeout */ > ++timeout; > } > > } > > u_int32_t > sel_read_boardid(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the board ID from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg0, reg1, reg2, reg3; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the BOARID0 data value from the data register */ > reg0 = sel_conf_read(iot, ioh, SELWD_CFG_BOARDID0); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the BOARID1 data value from the data register */ > reg1 = sel_conf_read(iot, ioh, SELWD_CFG_BOARDID1); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the BOARID2 data value from the data register */ > reg2 = sel_conf_read(iot, ioh, SELWD_CFG_BOARDID2); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the BOARID3 data value from the data register */ > reg3 = sel_conf_read(iot, ioh, SELWD_CFG_BOARDID3); > > /* convert the 4 bytes into a 32 bit number */ > u_int32_t boardid = (reg3 << 24) | (reg2 << 16) | (reg1 << 8) | reg0; > return boardid; > } > > u_int32_t > sel_read_mcversion(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the MC version from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg0, reg1, reg2, reg3; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the VERSION0 data value from the data register */ > reg0 = sel_conf_read(iot, ioh, SELWD_CFG_VERSION0); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the VERSION1 data value from the data register */ > reg1 = sel_conf_read(iot, ioh, SELWD_CFG_VERSION1); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the VERSION2 data value from the data register */ > reg2 = sel_conf_read(iot, ioh, SELWD_CFG_VERSION2); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the VERSION3 data value from the data register */ > reg3 = sel_conf_read(iot, ioh, SELWD_CFG_VERSION3); > > /* convert the 4 bytes into a 32 bit number */ > u_int32_t version = (reg3 << 24) | (reg2 << 16) | (reg1 << 8) | reg0; > return version; > } > > > u_int16_t > sel_read_pciboardid(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the PCI board ID from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg0, reg1; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the PCIBRDID0 data value from the data register */ > reg0 = sel_conf_read(iot, ioh, SELWD_CFG_PCIBRDID0); > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the PCIBRDID1 data value from the data register */ > reg1 = sel_conf_read(iot, ioh, SELWD_CFG_PCIBRDID1); > > /* convert the 2 bytes into a 16 bit number */ > u_int16_t boardid = (reg1 << 8) | reg0; > return boardid; > } > > u_int8_t > sel_read_miscctl0(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the misc control 0 value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the MISCCTL0 data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_MISCCTL0); > return reg; > } > > u_int8_t > sel_read_miscctl1(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the misc control 1 value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the MISCCTL1 data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_MISCCTL1); > return reg; > } > > u_int8_t > sel_read_ledctl0(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the LED control 0 value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the LEDCTRL0 data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_LEDCTRL0); > return reg; > } > > void > sel_write_ledctl0(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t data) > { > /* write the LED control 0 value to the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > /* write the WRITECFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_WRITECFG); > /* write the LEDCTRL0 data value to the data register */ > sel_conf_write(iot, ioh, SELWD_CFG_LEDCTRL0, data); > } > > u_int8_t > sel_read_ledctl1(bus_space_tag_t iot, bus_space_handle_t ioh) > { > /* read the LED control 1 value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the LEDCTRL1 data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_LEDCTRL1); > return reg; > } > > > void > sel_write_ledctl1(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t data) > { > /* write the LED control 1 value to the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > /* write the WRITECFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_WRITECFG); > /* write the LEDCTRL1 data value to the data register */ > sel_conf_write(iot, ioh, SELWD_CFG_LEDCTRL1, data); > } > > void > sel_read_modelno(bus_space_tag_t iot, bus_space_handle_t ioh, char* model) > { > /* read the MODEL NUMBER value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > int i = 0; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the MODELNO data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_MODELNO); > while (reg != 0 && i < 15) { > model[i] = reg; > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the MODELNO data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_MODELNO); > i++; > } > > } > > void > sel_read_serialno(bus_space_tag_t iot, bus_space_handle_t ioh, char* serial) > { > /* read the SERIAL NUMBER value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > int i = 0; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the SERIALNO data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_SERIALNO); > while (reg != 0 && i < 15) { > serial[i] = reg; > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the SERIALNO data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_SERIALNO); > i++; > } > > } > > void > sel_read_configid(bus_space_tag_t iot, bus_space_handle_t ioh, char* configid) > { > /* read the CONFIGURATION ID value from the controller */ > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > u_int8_t reg; > int i = 0; > > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the CONFIGID data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_CONFIGID); > while (reg != 0 && i < 15) { > configid[i] = reg; > /* make sure status is 0 before proceeding */ > sel_abort(iot, ioh); > /* write the READCFG command to the command register */ > sel_conf_enable(iot, ioh, SELWD_CMD_READCFG); > /* read the CONFIGID data value from the data register */ > reg = sel_conf_read(iot, ioh, SELWD_CFG_CONFIGID); > i++; > } > > } > /* > * > * Definitions for the SEL Watchdog device. > * > */ > > #define SELWD_DATA 0x00 > #define SELWD_CMD 0x01 > #define SELWD_IOSIZE 0x02 > > /* Valid Device IDs */ > #define SELWD_DEV_3355 "3355" > #define SELWD_DEV_3360 "3360" > > /* Config Register Map */ > #define SELWD_CFG_BOARDID0 0x00 > #define SELWD_CFG_BOARDID1 0x01 > #define SELWD_CFG_BOARDID2 0x02 > #define SELWD_CFG_BOARDID3 0x03 > #define SELWD_CFG_VERSION0 0x0c > #define SELWD_CFG_VERSION1 0x0d > #define SELWD_CFG_VERSION2 0x0e > #define SELWD_CFG_VERSION3 0x0f > #define SELWD_CFG_LEDCTRL0 0x10 > #define SELWD_CFG_LEDCTRL1 0x11 > #define SELWD_CFG_JUMPER0 0x20 > #define SELWD_CFG_WATCHDOG 0x30 > #define SELWD_CFG_SERIALCTL 0x40 > #define SELWD_CFG_MISCCTL0 0x42 > #define SELWD_CFG_MISCCTL1 0x43 > #define SELWD_CFG_SERIALNO 0x50 > #define SELWD_CFG_MODELNO 0x51 > #define SELWD_CFG_CONFIGID 0x52 > #define SELWD_CFG_PCIBRDID0 0x70 > #define SELWD_CFG_PCIBRDID1 0x71 > > /* Command functions */ > #define SELWD_CMD_WRITECFG 0x10 > #define SELWD_CMD_WRITEDIAG 0x11 > #define SELWD_CMD_READCFG 0x20 > #define SELWD_CMD_READDIAG 0x21 > #define SELWD_CMD_ABORT 0x00