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