Home | History | Annotate | Line # | Download | only in dev
lom.c revision 1.5.6.2
      1  1.5.6.2     rmind /*	$NetBSD: lom.c,v 1.5.6.2 2011/03/05 20:52:05 rmind Exp $	*/
      2  1.5.6.1     rmind /*	$OpenBSD: lom.c,v 1.21 2010/02/28 20:44:39 kettenis Exp $	*/
      3      1.1  nakayama /*
      4      1.1  nakayama  * Copyright (c) 2009 Mark Kettenis
      5      1.1  nakayama  *
      6      1.1  nakayama  * Permission to use, copy, modify, and distribute this software for any
      7      1.1  nakayama  * purpose with or without fee is hereby granted, provided that the above
      8      1.1  nakayama  * copyright notice and this permission notice appear in all copies.
      9      1.1  nakayama  *
     10      1.1  nakayama  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11      1.1  nakayama  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12      1.1  nakayama  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13      1.1  nakayama  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14      1.1  nakayama  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15      1.1  nakayama  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16      1.1  nakayama  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17      1.1  nakayama  */
     18      1.1  nakayama 
     19      1.1  nakayama #include <sys/cdefs.h>
     20  1.5.6.2     rmind __KERNEL_RCSID(0, "$NetBSD: lom.c,v 1.5.6.2 2011/03/05 20:52:05 rmind Exp $");
     21      1.1  nakayama 
     22      1.1  nakayama #include <sys/param.h>
     23      1.1  nakayama #include <sys/device.h>
     24      1.1  nakayama #include <sys/kernel.h>
     25      1.1  nakayama #include <sys/proc.h>
     26      1.1  nakayama #include <sys/envsys.h>
     27      1.1  nakayama #include <sys/systm.h>
     28      1.1  nakayama #include <sys/callout.h>
     29      1.5  nakayama #include <sys/sysctl.h>
     30      1.1  nakayama 
     31      1.1  nakayama #include <machine/autoconf.h>
     32      1.1  nakayama 
     33      1.1  nakayama #include <dev/ebus/ebusreg.h>
     34      1.1  nakayama #include <dev/ebus/ebusvar.h>
     35      1.1  nakayama #include <dev/sysmon/sysmonvar.h>
     36      1.1  nakayama 
     37      1.1  nakayama /*
     38      1.1  nakayama  * LOMlite is a so far unidentified microcontroller.
     39      1.1  nakayama  */
     40      1.1  nakayama #define LOM1_STATUS		0x00	/* R */
     41      1.1  nakayama #define  LOM1_STATUS_BUSY	0x80
     42      1.1  nakayama #define LOM1_CMD		0x00	/* W */
     43      1.1  nakayama #define LOM1_DATA		0x01	/* R/W */
     44      1.1  nakayama 
     45      1.1  nakayama /*
     46      1.1  nakayama  * LOMlite2 is implemented as a H8/3437 microcontroller which has its
     47      1.1  nakayama  * on-chip host interface hooked up to EBus.
     48      1.1  nakayama  */
     49      1.1  nakayama #define LOM2_DATA		0x00	/* R/W */
     50      1.1  nakayama #define LOM2_CMD		0x01	/* W */
     51      1.1  nakayama #define LOM2_STATUS		0x01	/* R */
     52      1.1  nakayama #define  LOM2_STATUS_OBF	0x01	/* Output Buffer Full */
     53      1.1  nakayama #define  LOM2_STATUS_IBF	0x02	/* Input Buffer Full  */
     54      1.1  nakayama 
     55      1.1  nakayama #define LOM_IDX_CMD		0x00
     56      1.1  nakayama #define  LOM_IDX_CMD_GENERIC	0x00
     57      1.1  nakayama #define  LOM_IDX_CMD_TEMP	0x04
     58      1.1  nakayama #define  LOM_IDX_CMD_FAN	0x05
     59      1.1  nakayama 
     60      1.1  nakayama #define LOM_IDX_FW_REV		0x01	/* Firmware revision  */
     61      1.1  nakayama 
     62      1.1  nakayama #define LOM_IDX_FAN1		0x04	/* Fan speed */
     63      1.1  nakayama #define LOM_IDX_FAN2		0x05
     64      1.1  nakayama #define LOM_IDX_FAN3		0x06
     65      1.1  nakayama #define LOM_IDX_FAN4		0x07
     66      1.1  nakayama #define LOM_IDX_PSU1		0x08	/* PSU status */
     67      1.1  nakayama #define LOM_IDX_PSU2		0x09
     68      1.1  nakayama #define LOM_IDX_PSU3		0x0a
     69      1.1  nakayama #define  LOM_PSU_INPUTA		0x01
     70      1.1  nakayama #define  LOM_PSU_INPUTB		0x02
     71      1.1  nakayama #define  LOM_PSU_OUTPUT		0x04
     72      1.1  nakayama #define  LOM_PSU_PRESENT	0x08
     73      1.1  nakayama #define  LOM_PSU_STANDBY	0x10
     74      1.1  nakayama 
     75      1.1  nakayama #define LOM_IDX_TEMP1		0x18	/* Temperature */
     76      1.1  nakayama #define LOM_IDX_TEMP2		0x19
     77      1.1  nakayama #define LOM_IDX_TEMP3		0x1a
     78      1.1  nakayama #define LOM_IDX_TEMP4		0x1b
     79      1.1  nakayama #define LOM_IDX_TEMP5		0x1c
     80      1.1  nakayama #define LOM_IDX_TEMP6		0x1d
     81      1.1  nakayama #define LOM_IDX_TEMP7		0x1e
     82      1.1  nakayama #define LOM_IDX_TEMP8		0x1f
     83      1.1  nakayama 
     84      1.1  nakayama #define LOM_IDX_LED1		0x25
     85      1.1  nakayama 
     86      1.1  nakayama #define LOM_IDX_ALARM		0x30
     87      1.3  nakayama #define  LOM_ALARM_1		0x01
     88      1.3  nakayama #define  LOM_ALARM_2		0x02
     89      1.3  nakayama #define  LOM_ALARM_3		0x04
     90      1.3  nakayama #define  LOM_ALARM_FAULT	0xf0
     91      1.1  nakayama #define LOM_IDX_WDOG_CTL	0x31
     92      1.1  nakayama #define  LOM_WDOG_ENABLE	0x01
     93      1.1  nakayama #define  LOM_WDOG_RESET		0x02
     94      1.1  nakayama #define  LOM_WDOG_AL3_WDOG	0x04
     95      1.1  nakayama #define  LOM_WDOG_AL3_FANPSU	0x08
     96      1.1  nakayama #define LOM_IDX_WDOG_TIME	0x32
     97      1.1  nakayama #define  LOM_WDOG_TIME_MAX	126
     98      1.1  nakayama 
     99      1.1  nakayama #define LOM1_IDX_HOSTNAME1	0x33
    100      1.1  nakayama #define LOM1_IDX_HOSTNAME2	0x34
    101      1.1  nakayama #define LOM1_IDX_HOSTNAME3	0x35
    102      1.1  nakayama #define LOM1_IDX_HOSTNAME4	0x36
    103      1.1  nakayama #define LOM1_IDX_HOSTNAME5	0x37
    104      1.1  nakayama #define LOM1_IDX_HOSTNAME6	0x38
    105      1.1  nakayama #define LOM1_IDX_HOSTNAME7	0x39
    106      1.1  nakayama #define LOM1_IDX_HOSTNAME8	0x3a
    107      1.1  nakayama #define LOM1_IDX_HOSTNAME9	0x3b
    108      1.1  nakayama #define LOM1_IDX_HOSTNAME10	0x3c
    109      1.1  nakayama #define LOM1_IDX_HOSTNAME11	0x3d
    110      1.1  nakayama #define LOM1_IDX_HOSTNAME12	0x3e
    111      1.1  nakayama 
    112      1.1  nakayama #define LOM2_IDX_HOSTNAMELEN	0x38
    113      1.1  nakayama #define LOM2_IDX_HOSTNAME	0x39
    114      1.1  nakayama 
    115      1.1  nakayama #define LOM_IDX_CONFIG		0x5d
    116      1.1  nakayama #define LOM_IDX_FAN1_CAL	0x5e
    117      1.1  nakayama #define LOM_IDX_FAN2_CAL	0x5f
    118      1.1  nakayama #define LOM_IDX_FAN3_CAL	0x60
    119      1.1  nakayama #define LOM_IDX_FAN4_CAL	0x61
    120      1.1  nakayama #define LOM_IDX_FAN1_LOW	0x62
    121      1.1  nakayama #define LOM_IDX_FAN2_LOW	0x63
    122      1.1  nakayama #define LOM_IDX_FAN3_LOW	0x64
    123      1.1  nakayama #define LOM_IDX_FAN4_LOW	0x65
    124      1.1  nakayama 
    125      1.1  nakayama #define LOM_IDX_CONFIG2		0x66
    126      1.1  nakayama #define LOM_IDX_CONFIG3		0x67
    127      1.1  nakayama 
    128      1.1  nakayama #define LOM_IDX_PROBE55		0x7e	/* Always returns 0x55 */
    129      1.1  nakayama #define LOM_IDX_PROBEAA		0x7f	/* Always returns 0xaa */
    130      1.1  nakayama 
    131      1.1  nakayama #define LOM_IDX_WRITE		0x80
    132      1.1  nakayama 
    133      1.1  nakayama #define LOM_IDX4_TEMP_NAME_START	0x40
    134      1.1  nakayama #define LOM_IDX4_TEMP_NAME_END		0xff
    135      1.1  nakayama 
    136      1.1  nakayama #define LOM_IDX5_FAN_NAME_START		0x40
    137      1.1  nakayama #define LOM_IDX5_FAN_NAME_END		0xff
    138      1.1  nakayama 
    139      1.3  nakayama #define LOM_MAX_ALARM	4
    140      1.1  nakayama #define LOM_MAX_FAN	4
    141      1.1  nakayama #define LOM_MAX_PSU	3
    142      1.1  nakayama #define LOM_MAX_TEMP	8
    143      1.1  nakayama 
    144      1.1  nakayama struct lom_cmd {
    145      1.1  nakayama 	uint8_t			lc_cmd;
    146      1.1  nakayama 	uint8_t			lc_data;
    147      1.1  nakayama 
    148      1.1  nakayama 	TAILQ_ENTRY(lom_cmd)	lc_next;
    149      1.1  nakayama };
    150      1.1  nakayama 
    151      1.1  nakayama struct lom_softc {
    152      1.1  nakayama 	device_t		sc_dev;
    153      1.1  nakayama 	bus_space_tag_t		sc_iot;
    154      1.1  nakayama 	bus_space_handle_t	sc_ioh;
    155      1.1  nakayama 
    156      1.1  nakayama 	int			sc_type;
    157      1.1  nakayama #define LOM_LOMLITE		0
    158      1.1  nakayama #define LOM_LOMLITE2		2
    159      1.1  nakayama 	int			sc_space;
    160      1.1  nakayama 
    161      1.1  nakayama 	struct sysmon_envsys	*sc_sme;
    162      1.3  nakayama 	envsys_data_t		sc_alarm[LOM_MAX_ALARM];
    163      1.1  nakayama 	envsys_data_t		sc_fan[LOM_MAX_FAN];
    164      1.1  nakayama 	envsys_data_t		sc_psu[LOM_MAX_PSU];
    165      1.1  nakayama 	envsys_data_t		sc_temp[LOM_MAX_TEMP];
    166      1.1  nakayama 
    167      1.3  nakayama 	int			sc_num_alarm;
    168      1.1  nakayama 	int			sc_num_fan;
    169      1.1  nakayama 	int			sc_num_psu;
    170      1.1  nakayama 	int			sc_num_temp;
    171      1.1  nakayama 
    172      1.5  nakayama 	int32_t			sc_sysctl_num[LOM_MAX_ALARM];
    173      1.5  nakayama 
    174      1.1  nakayama 	uint8_t			sc_fan_cal[LOM_MAX_FAN];
    175      1.1  nakayama 	uint8_t			sc_fan_low[LOM_MAX_FAN];
    176      1.1  nakayama 
    177      1.1  nakayama 	char			sc_hostname[MAXHOSTNAMELEN];
    178      1.1  nakayama 
    179      1.1  nakayama 	struct sysmon_wdog	sc_smw;
    180      1.1  nakayama 	int			sc_wdog_period;
    181      1.1  nakayama 	uint8_t			sc_wdog_ctl;
    182      1.1  nakayama 	struct lom_cmd		sc_wdog_pat;
    183      1.1  nakayama 
    184      1.1  nakayama 	TAILQ_HEAD(, lom_cmd)	sc_queue;
    185      1.1  nakayama 	kmutex_t		sc_queue_mtx;
    186      1.1  nakayama 	struct callout		sc_state_to;
    187      1.1  nakayama 	int			sc_state;
    188      1.1  nakayama #define LOM_STATE_IDLE		0
    189      1.1  nakayama #define LOM_STATE_CMD		1
    190      1.1  nakayama #define LOM_STATE_DATA		2
    191      1.1  nakayama 	int			sc_retry;
    192      1.1  nakayama };
    193      1.1  nakayama 
    194      1.1  nakayama static int	lom_match(device_t, cfdata_t, void *);
    195      1.1  nakayama static void	lom_attach(device_t, device_t, void *);
    196      1.1  nakayama 
    197      1.1  nakayama CFATTACH_DECL_NEW(lom, sizeof(struct lom_softc),
    198      1.1  nakayama     lom_match, lom_attach, NULL, NULL);
    199      1.1  nakayama 
    200      1.1  nakayama static int	lom_read(struct lom_softc *, uint8_t, uint8_t *);
    201      1.1  nakayama static int	lom_write(struct lom_softc *, uint8_t, uint8_t);
    202      1.1  nakayama static void	lom_queue_cmd(struct lom_softc *, struct lom_cmd *);
    203      1.2  nakayama static void	lom_dequeue_cmd(struct lom_softc *, struct lom_cmd *);
    204      1.1  nakayama static int	lom1_read(struct lom_softc *, uint8_t, uint8_t *);
    205      1.1  nakayama static int	lom1_write(struct lom_softc *, uint8_t, uint8_t);
    206      1.1  nakayama static int	lom1_read_polled(struct lom_softc *, uint8_t, uint8_t *);
    207      1.1  nakayama static int	lom1_write_polled(struct lom_softc *, uint8_t, uint8_t);
    208      1.1  nakayama static void	lom1_queue_cmd(struct lom_softc *, struct lom_cmd *);
    209      1.1  nakayama static void	lom1_process_queue(void *);
    210      1.1  nakayama static void	lom1_process_queue_locked(struct lom_softc *);
    211      1.1  nakayama static int	lom2_read(struct lom_softc *, uint8_t, uint8_t *);
    212      1.1  nakayama static int	lom2_write(struct lom_softc *, uint8_t, uint8_t);
    213      1.2  nakayama static int	lom2_read_polled(struct lom_softc *, uint8_t, uint8_t *);
    214      1.2  nakayama static int	lom2_write_polled(struct lom_softc *, uint8_t, uint8_t);
    215      1.1  nakayama static void	lom2_queue_cmd(struct lom_softc *, struct lom_cmd *);
    216      1.2  nakayama static int	lom2_intr(void *);
    217      1.1  nakayama 
    218      1.1  nakayama static int	lom_init_desc(struct lom_softc *);
    219      1.1  nakayama static void	lom_refresh(struct sysmon_envsys *, envsys_data_t *);
    220  1.5.6.2     rmind static void	lom_refresh_alarm(struct lom_softc *, envsys_data_t *, uint32_t);
    221  1.5.6.2     rmind static void	lom_refresh_fan(struct lom_softc *, envsys_data_t *, uint32_t);
    222  1.5.6.2     rmind static void	lom_refresh_psu(struct lom_softc *, envsys_data_t *, uint32_t);
    223  1.5.6.2     rmind static void	lom_refresh_temp(struct lom_softc *, envsys_data_t *, uint32_t);
    224      1.1  nakayama static void	lom1_write_hostname(struct lom_softc *);
    225      1.1  nakayama static void	lom2_write_hostname(struct lom_softc *);
    226      1.1  nakayama 
    227      1.1  nakayama static int	lom_wdog_tickle(struct sysmon_wdog *);
    228      1.1  nakayama static int	lom_wdog_setmode(struct sysmon_wdog *);
    229      1.1  nakayama 
    230      1.2  nakayama static bool	lom_shutdown(device_t, int);
    231      1.2  nakayama 
    232      1.5  nakayama SYSCTL_SETUP_PROTO(sysctl_lom_setup);
    233      1.5  nakayama static int	lom_sysctl_alarm(SYSCTLFN_PROTO);
    234      1.5  nakayama 
    235      1.5  nakayama static int hw_node = CTL_EOL;
    236      1.5  nakayama static const char *nodename[LOM_MAX_ALARM] =
    237      1.5  nakayama     { "fault_led", "alarm1", "alarm2", "alarm3" };
    238      1.5  nakayama #ifdef SYSCTL_INCLUDE_DESCR
    239      1.5  nakayama static const char *nodedesc[LOM_MAX_ALARM] =
    240      1.5  nakayama     { "Fault LED status", "Alarm1 status", "Alarm2 status ", "Alarm3 status" };
    241      1.5  nakayama #endif
    242      1.5  nakayama 
    243      1.1  nakayama static int
    244      1.1  nakayama lom_match(device_t parent, cfdata_t match, void *aux)
    245      1.1  nakayama {
    246      1.1  nakayama 	struct ebus_attach_args *ea = aux;
    247      1.1  nakayama 
    248      1.1  nakayama 	if (strcmp(ea->ea_name, "SUNW,lom") == 0 ||
    249      1.1  nakayama 	    strcmp(ea->ea_name, "SUNW,lomh") == 0)
    250      1.1  nakayama 		return (1);
    251      1.1  nakayama 
    252      1.1  nakayama 	return (0);
    253      1.1  nakayama }
    254      1.1  nakayama 
    255      1.1  nakayama static void
    256      1.1  nakayama lom_attach(device_t parent, device_t self, void *aux)
    257      1.1  nakayama {
    258      1.1  nakayama 	struct lom_softc *sc = device_private(self);
    259      1.1  nakayama 	struct ebus_attach_args *ea = aux;
    260      1.1  nakayama 	uint8_t reg, fw_rev, config, config2, config3;
    261      1.1  nakayama 	uint8_t cal, low;
    262      1.1  nakayama 	int i;
    263      1.5  nakayama 	const struct sysctlnode *node = NULL, *newnode;
    264      1.1  nakayama 
    265      1.2  nakayama 	if (strcmp(ea->ea_name, "SUNW,lomh") == 0) {
    266      1.2  nakayama 		if (ea->ea_nintr < 1) {
    267      1.2  nakayama 			aprint_error(": no interrupt\n");
    268      1.2  nakayama 			return;
    269      1.2  nakayama 		}
    270      1.1  nakayama 		sc->sc_type = LOM_LOMLITE2;
    271      1.2  nakayama 	}
    272      1.1  nakayama 
    273      1.1  nakayama 	sc->sc_dev = self;
    274      1.1  nakayama 	sc->sc_iot = ea->ea_bustag;
    275      1.1  nakayama 	if (bus_space_map(sc->sc_iot, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
    276      1.1  nakayama 	    ea->ea_reg[0].size, 0, &sc->sc_ioh) != 0) {
    277      1.1  nakayama 		aprint_error(": can't map register space\n");
    278      1.1  nakayama 		return;
    279      1.1  nakayama 	}
    280      1.1  nakayama 
    281      1.1  nakayama 	if (sc->sc_type < LOM_LOMLITE2) {
    282      1.1  nakayama 		/* XXX Magic */
    283      1.1  nakayama 		(void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
    284      1.1  nakayama 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, 3, 0xca);
    285      1.1  nakayama 	}
    286      1.1  nakayama 
    287      1.1  nakayama 	if (lom_read(sc, LOM_IDX_PROBE55, &reg) || reg != 0x55 ||
    288      1.1  nakayama 	    lom_read(sc, LOM_IDX_PROBEAA, &reg) || reg != 0xaa ||
    289      1.1  nakayama 	    lom_read(sc, LOM_IDX_FW_REV, &fw_rev) ||
    290      1.1  nakayama 	    lom_read(sc, LOM_IDX_CONFIG, &config))
    291      1.1  nakayama 	{
    292      1.1  nakayama 		aprint_error(": not responding\n");
    293      1.1  nakayama 		return;
    294      1.1  nakayama 	}
    295      1.1  nakayama 
    296      1.1  nakayama 	aprint_normal(": %s: %s rev %d.%d\n", ea->ea_name,
    297      1.1  nakayama 	    sc->sc_type < LOM_LOMLITE2 ? "LOMlite" : "LOMlite2",
    298      1.1  nakayama 	    fw_rev >> 4, fw_rev & 0x0f);
    299      1.1  nakayama 
    300      1.2  nakayama 	TAILQ_INIT(&sc->sc_queue);
    301      1.2  nakayama 	mutex_init(&sc->sc_queue_mtx, MUTEX_DEFAULT, IPL_BIO);
    302      1.2  nakayama 
    303      1.1  nakayama 	config2 = config3 = 0;
    304      1.2  nakayama 	if (sc->sc_type < LOM_LOMLITE2) {
    305      1.2  nakayama 		/*
    306      1.2  nakayama 		 * LOMlite doesn't do interrupts so we limp along on
    307      1.2  nakayama 		 * timeouts.
    308      1.2  nakayama 		 */
    309      1.2  nakayama 		callout_init(&sc->sc_state_to, 0);
    310      1.2  nakayama 		callout_setfunc(&sc->sc_state_to, lom1_process_queue, sc);
    311      1.2  nakayama 	} else {
    312      1.1  nakayama 		lom_read(sc, LOM_IDX_CONFIG2, &config2);
    313      1.1  nakayama 		lom_read(sc, LOM_IDX_CONFIG3, &config3);
    314      1.2  nakayama 
    315      1.2  nakayama 		bus_intr_establish(sc->sc_iot, ea->ea_intr[0],
    316      1.2  nakayama 		    IPL_BIO, lom2_intr, sc);
    317      1.1  nakayama 	}
    318      1.1  nakayama 
    319      1.3  nakayama 	sc->sc_num_alarm = LOM_MAX_ALARM;
    320      1.1  nakayama 	sc->sc_num_fan = min((config >> 5) & 0x7, LOM_MAX_FAN);
    321      1.1  nakayama 	sc->sc_num_psu = min((config >> 3) & 0x3, LOM_MAX_PSU);
    322      1.1  nakayama 	sc->sc_num_temp = min((config2 >> 4) & 0xf, LOM_MAX_TEMP);
    323      1.1  nakayama 
    324      1.1  nakayama 	aprint_verbose_dev(self, "%d fan(s), %d PSU(s), %d temp sensor(s)\n",
    325      1.1  nakayama 	    sc->sc_num_fan, sc->sc_num_psu, sc->sc_num_temp);
    326      1.1  nakayama 
    327      1.1  nakayama 	for (i = 0; i < sc->sc_num_fan; i++) {
    328      1.1  nakayama 		if (lom_read(sc, LOM_IDX_FAN1_CAL + i, &cal) ||
    329      1.1  nakayama 		    lom_read(sc, LOM_IDX_FAN1_LOW + i, &low)) {
    330      1.1  nakayama 			aprint_error_dev(self, "can't read fan information\n");
    331      1.1  nakayama 			return;
    332      1.1  nakayama 		}
    333      1.1  nakayama 		sc->sc_fan_cal[i] = cal;
    334      1.1  nakayama 		sc->sc_fan_low[i] = low;
    335      1.1  nakayama 	}
    336      1.1  nakayama 
    337      1.5  nakayama 	/* Setup our sysctl subtree, hw.lomN */
    338      1.5  nakayama 	if (hw_node != CTL_EOL)
    339      1.5  nakayama 		sysctl_createv(NULL, 0, NULL, &node,
    340      1.5  nakayama 		    0, CTLTYPE_NODE, device_xname(self), NULL,
    341      1.5  nakayama 		    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
    342      1.5  nakayama 
    343      1.1  nakayama 	/* Initialize sensor data. */
    344      1.1  nakayama 	sc->sc_sme = sysmon_envsys_create();
    345      1.3  nakayama 	for (i = 0; i < sc->sc_num_alarm; i++) {
    346      1.3  nakayama 		sc->sc_alarm[i].units = ENVSYS_INDICATOR;
    347      1.3  nakayama 		snprintf(sc->sc_alarm[i].desc, sizeof(sc->sc_alarm[i].desc),
    348      1.3  nakayama 		    i == 0 ? "Fault LED" : "Alarm%d", i);
    349      1.3  nakayama 		if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_alarm[i])) {
    350      1.3  nakayama 			sysmon_envsys_destroy(sc->sc_sme);
    351      1.3  nakayama 			aprint_error_dev(self, "can't attach alarm sensor\n");
    352      1.3  nakayama 			return;
    353      1.3  nakayama 		}
    354      1.5  nakayama 		if (node != NULL) {
    355      1.5  nakayama 			sysctl_createv(NULL, 0, NULL, &newnode,
    356      1.5  nakayama 			    CTLFLAG_READWRITE, CTLTYPE_INT, nodename[i],
    357      1.5  nakayama 			    SYSCTL_DESCR(nodedesc[i]),
    358      1.5  nakayama 			    lom_sysctl_alarm, 0, sc, 0,
    359      1.5  nakayama 			    CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
    360      1.5  nakayama 			if (newnode != NULL)
    361      1.5  nakayama 				sc->sc_sysctl_num[i] = newnode->sysctl_num;
    362      1.5  nakayama 			else
    363      1.5  nakayama 				sc->sc_sysctl_num[i] = 0;
    364      1.5  nakayama 		}
    365      1.3  nakayama 	}
    366      1.1  nakayama 	for (i = 0; i < sc->sc_num_fan; i++) {
    367      1.1  nakayama 		sc->sc_fan[i].units = ENVSYS_SFANRPM;
    368      1.1  nakayama 		snprintf(sc->sc_fan[i].desc, sizeof(sc->sc_fan[i].desc),
    369      1.1  nakayama 		    "fan%d", i + 1);
    370      1.1  nakayama 		if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_fan[i])) {
    371      1.1  nakayama 			sysmon_envsys_destroy(sc->sc_sme);
    372      1.1  nakayama 			aprint_error_dev(self, "can't attach fan sensor\n");
    373      1.1  nakayama 			return;
    374      1.1  nakayama 		}
    375      1.1  nakayama 	}
    376      1.1  nakayama 	for (i = 0; i < sc->sc_num_psu; i++) {
    377      1.1  nakayama 		sc->sc_psu[i].units = ENVSYS_INDICATOR;
    378      1.1  nakayama 		snprintf(sc->sc_psu[i].desc, sizeof(sc->sc_psu[i].desc),
    379      1.1  nakayama 		    "PSU%d", i + 1);
    380      1.1  nakayama 		if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_psu[i])) {
    381      1.1  nakayama 			sysmon_envsys_destroy(sc->sc_sme);
    382      1.1  nakayama 			aprint_error_dev(self, "can't attach PSU sensor\n");
    383      1.1  nakayama 			return;
    384      1.1  nakayama 		}
    385      1.1  nakayama 	}
    386      1.1  nakayama 	for (i = 0; i < sc->sc_num_temp; i++) {
    387      1.1  nakayama 		sc->sc_temp[i].units = ENVSYS_STEMP;
    388      1.1  nakayama 		snprintf(sc->sc_temp[i].desc, sizeof(sc->sc_temp[i].desc),
    389      1.1  nakayama 		    "temp%d", i + 1);
    390      1.1  nakayama 		if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp[i])) {
    391      1.1  nakayama 			sysmon_envsys_destroy(sc->sc_sme);
    392      1.1  nakayama 			aprint_error_dev(self, "can't attach temp sensor\n");
    393      1.1  nakayama 			return;
    394      1.1  nakayama 		}
    395      1.1  nakayama 	}
    396      1.1  nakayama 	if (lom_init_desc(sc)) {
    397      1.1  nakayama 		aprint_error_dev(self, "can't read sensor names\n");
    398      1.1  nakayama 		sysmon_envsys_destroy(sc->sc_sme);
    399      1.1  nakayama 		return;
    400      1.1  nakayama 	}
    401      1.1  nakayama 
    402      1.1  nakayama 	sc->sc_sme->sme_name = device_xname(self);
    403      1.1  nakayama 	sc->sc_sme->sme_cookie = sc;
    404      1.1  nakayama 	sc->sc_sme->sme_refresh = lom_refresh;
    405      1.1  nakayama 	if (sysmon_envsys_register(sc->sc_sme)) {
    406      1.1  nakayama 		aprint_error_dev(self,
    407      1.1  nakayama 		    "unable to register envsys with sysmon\n");
    408      1.1  nakayama 		sysmon_envsys_destroy(sc->sc_sme);
    409      1.1  nakayama 		return;
    410      1.1  nakayama 	}
    411      1.1  nakayama 
    412      1.1  nakayama 	/* Initialize watchdog. */
    413      1.1  nakayama 	lom_write(sc, LOM_IDX_WDOG_TIME, LOM_WDOG_TIME_MAX);
    414      1.1  nakayama 	lom_read(sc, LOM_IDX_WDOG_CTL, &sc->sc_wdog_ctl);
    415      1.1  nakayama 	sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET);
    416      1.1  nakayama 	lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
    417      1.1  nakayama 
    418      1.1  nakayama 	sc->sc_wdog_period = LOM_WDOG_TIME_MAX;
    419      1.1  nakayama 
    420      1.1  nakayama 	sc->sc_smw.smw_name = device_xname(self);
    421      1.1  nakayama 	sc->sc_smw.smw_cookie = sc;
    422      1.1  nakayama 	sc->sc_smw.smw_setmode = lom_wdog_setmode;
    423      1.1  nakayama 	sc->sc_smw.smw_tickle = lom_wdog_tickle;
    424      1.1  nakayama 	sc->sc_smw.smw_period = sc->sc_wdog_period;
    425      1.1  nakayama 	if (sysmon_wdog_register(&sc->sc_smw)) {
    426      1.1  nakayama 		aprint_error_dev(self,
    427      1.1  nakayama 		    "unable to register wdog with sysmon\n");
    428      1.1  nakayama 		return;
    429      1.1  nakayama 	}
    430      1.1  nakayama 
    431      1.1  nakayama 	aprint_verbose_dev(self, "Watchdog timer configured.\n");
    432      1.2  nakayama 
    433      1.2  nakayama 	if (!pmf_device_register1(self, NULL, NULL, lom_shutdown))
    434      1.2  nakayama 		aprint_error_dev(self, "unable to register power handler\n");
    435      1.1  nakayama }
    436      1.1  nakayama 
    437      1.1  nakayama static int
    438      1.1  nakayama lom_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
    439      1.1  nakayama {
    440      1.1  nakayama 	if (sc->sc_type < LOM_LOMLITE2)
    441      1.1  nakayama 		return lom1_read(sc, reg, val);
    442      1.1  nakayama 	else
    443      1.1  nakayama 		return lom2_read(sc, reg, val);
    444      1.1  nakayama }
    445      1.1  nakayama 
    446      1.1  nakayama static int
    447      1.1  nakayama lom_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
    448      1.1  nakayama {
    449      1.1  nakayama 	if (sc->sc_type < LOM_LOMLITE2)
    450      1.1  nakayama 		return lom1_write(sc, reg, val);
    451      1.1  nakayama 	else
    452      1.1  nakayama 		return lom2_write(sc, reg, val);
    453      1.1  nakayama }
    454      1.1  nakayama 
    455      1.1  nakayama static void
    456      1.1  nakayama lom_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
    457      1.1  nakayama {
    458      1.1  nakayama 	if (sc->sc_type < LOM_LOMLITE2)
    459      1.1  nakayama 		return lom1_queue_cmd(sc, lc);
    460      1.1  nakayama 	else
    461      1.1  nakayama 		return lom2_queue_cmd(sc, lc);
    462      1.1  nakayama }
    463      1.1  nakayama 
    464      1.2  nakayama static void
    465      1.2  nakayama lom_dequeue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
    466      1.2  nakayama {
    467      1.2  nakayama 	struct lom_cmd *lcp;
    468      1.2  nakayama 
    469      1.2  nakayama 	mutex_enter(&sc->sc_queue_mtx);
    470      1.2  nakayama 	TAILQ_FOREACH(lcp, &sc->sc_queue, lc_next) {
    471      1.2  nakayama 		if (lcp == lc) {
    472      1.2  nakayama 			TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
    473      1.2  nakayama 			break;
    474      1.2  nakayama 		}
    475      1.2  nakayama 	}
    476      1.2  nakayama 	mutex_exit(&sc->sc_queue_mtx);
    477      1.2  nakayama }
    478      1.2  nakayama 
    479      1.1  nakayama static int
    480      1.1  nakayama lom1_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
    481      1.1  nakayama {
    482      1.1  nakayama 	struct lom_cmd lc;
    483      1.1  nakayama 	int error;
    484      1.1  nakayama 
    485      1.1  nakayama 	if (cold)
    486      1.1  nakayama 		return lom1_read_polled(sc, reg, val);
    487      1.1  nakayama 
    488      1.1  nakayama 	lc.lc_cmd = reg;
    489      1.1  nakayama 	lc.lc_data = 0xff;
    490      1.1  nakayama 	lom1_queue_cmd(sc, &lc);
    491      1.1  nakayama 
    492      1.1  nakayama 	error = tsleep(&lc, PZERO, "lomrd", hz);
    493      1.1  nakayama 	if (error)
    494      1.2  nakayama 		lom_dequeue_cmd(sc, &lc);
    495      1.1  nakayama 
    496      1.1  nakayama 	*val = lc.lc_data;
    497      1.1  nakayama 
    498      1.1  nakayama 	return (error);
    499      1.1  nakayama }
    500      1.1  nakayama 
    501      1.1  nakayama static int
    502      1.2  nakayama lom1_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
    503      1.1  nakayama {
    504      1.1  nakayama 	struct lom_cmd lc;
    505      1.1  nakayama 	int error;
    506      1.1  nakayama 
    507      1.1  nakayama 	if (cold)
    508      1.1  nakayama 		return lom1_write_polled(sc, reg, val);
    509      1.1  nakayama 
    510      1.1  nakayama 	lc.lc_cmd = reg | LOM_IDX_WRITE;
    511      1.1  nakayama 	lc.lc_data = val;
    512      1.1  nakayama 	lom1_queue_cmd(sc, &lc);
    513      1.1  nakayama 
    514      1.2  nakayama 	error = tsleep(&lc, PZERO, "lomwr", 2 * hz);
    515      1.1  nakayama 	if (error)
    516      1.2  nakayama 		lom_dequeue_cmd(sc, &lc);
    517      1.1  nakayama 
    518      1.1  nakayama 	return (error);
    519      1.1  nakayama }
    520      1.1  nakayama 
    521      1.1  nakayama static int
    522      1.1  nakayama lom1_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val)
    523      1.1  nakayama {
    524      1.1  nakayama 	uint8_t str;
    525      1.1  nakayama 	int i;
    526      1.1  nakayama 
    527      1.1  nakayama 	/* Wait for input buffer to become available. */
    528      1.1  nakayama 	for (i = 30; i > 0; i--) {
    529      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
    530      1.1  nakayama 		delay(1000);
    531      1.1  nakayama 		if ((str & LOM1_STATUS_BUSY) == 0)
    532      1.1  nakayama 			break;
    533      1.1  nakayama 	}
    534      1.1  nakayama 	if (i == 0)
    535      1.1  nakayama 		return (ETIMEDOUT);
    536      1.1  nakayama 
    537      1.1  nakayama 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
    538      1.1  nakayama 
    539      1.1  nakayama 	/* Wait until the microcontroller fills output buffer. */
    540      1.1  nakayama 	for (i = 30; i > 0; i--) {
    541      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
    542      1.1  nakayama 		delay(1000);
    543      1.1  nakayama 		if ((str & LOM1_STATUS_BUSY) == 0)
    544      1.1  nakayama 			break;
    545      1.1  nakayama 	}
    546      1.1  nakayama 	if (i == 0)
    547      1.1  nakayama 		return (ETIMEDOUT);
    548      1.1  nakayama 
    549      1.1  nakayama 	*val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
    550      1.1  nakayama 	return (0);
    551      1.1  nakayama }
    552      1.1  nakayama 
    553      1.1  nakayama static int
    554      1.2  nakayama lom1_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val)
    555      1.1  nakayama {
    556      1.1  nakayama 	uint8_t str;
    557      1.1  nakayama 	int i;
    558      1.1  nakayama 
    559      1.1  nakayama 	/* Wait for input buffer to become available. */
    560      1.1  nakayama 	for (i = 30; i > 0; i--) {
    561      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
    562      1.1  nakayama 		delay(1000);
    563      1.1  nakayama 		if ((str & LOM1_STATUS_BUSY) == 0)
    564      1.1  nakayama 			break;
    565      1.1  nakayama 	}
    566      1.1  nakayama 	if (i == 0)
    567      1.1  nakayama 		return (ETIMEDOUT);
    568      1.1  nakayama 
    569      1.1  nakayama 	reg |= LOM_IDX_WRITE;
    570      1.1  nakayama 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, reg);
    571      1.1  nakayama 
    572      1.1  nakayama 	/* Wait until the microcontroller fills output buffer. */
    573      1.1  nakayama 	for (i = 30; i > 0; i--) {
    574      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
    575      1.1  nakayama 		delay(1000);
    576      1.1  nakayama 		if ((str & LOM1_STATUS_BUSY) == 0)
    577      1.1  nakayama 			break;
    578      1.1  nakayama 	}
    579      1.1  nakayama 	if (i == 0)
    580      1.1  nakayama 		return (ETIMEDOUT);
    581      1.1  nakayama 
    582      1.1  nakayama 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, val);
    583      1.1  nakayama 
    584      1.1  nakayama 	return (0);
    585      1.1  nakayama }
    586      1.1  nakayama 
    587      1.1  nakayama static void
    588      1.1  nakayama lom1_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
    589      1.1  nakayama {
    590      1.1  nakayama 	mutex_enter(&sc->sc_queue_mtx);
    591      1.1  nakayama 	TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next);
    592      1.1  nakayama 	if (sc->sc_state == LOM_STATE_IDLE) {
    593      1.1  nakayama 		sc->sc_state = LOM_STATE_CMD;
    594      1.1  nakayama 		lom1_process_queue_locked(sc);
    595      1.1  nakayama 	}
    596      1.1  nakayama 	mutex_exit(&sc->sc_queue_mtx);
    597      1.1  nakayama }
    598      1.1  nakayama 
    599      1.1  nakayama static void
    600      1.1  nakayama lom1_process_queue(void *arg)
    601      1.1  nakayama {
    602      1.1  nakayama 	struct lom_softc *sc = arg;
    603      1.1  nakayama 
    604      1.1  nakayama 	mutex_enter(&sc->sc_queue_mtx);
    605      1.1  nakayama 	lom1_process_queue_locked(sc);
    606      1.1  nakayama 	mutex_exit(&sc->sc_queue_mtx);
    607      1.1  nakayama }
    608      1.1  nakayama 
    609      1.1  nakayama static void
    610      1.1  nakayama lom1_process_queue_locked(struct lom_softc *sc)
    611      1.1  nakayama {
    612      1.1  nakayama 	struct lom_cmd *lc;
    613      1.1  nakayama 	uint8_t str;
    614      1.1  nakayama 
    615      1.1  nakayama 	lc = TAILQ_FIRST(&sc->sc_queue);
    616      1.2  nakayama 	if (lc == NULL) {
    617      1.2  nakayama 		sc->sc_state = LOM_STATE_IDLE;
    618      1.2  nakayama 		return;
    619      1.2  nakayama 	}
    620      1.1  nakayama 
    621      1.1  nakayama 	str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_STATUS);
    622      1.1  nakayama 	if (str & LOM1_STATUS_BUSY) {
    623      1.2  nakayama 		if (sc->sc_retry++ < 30) {
    624      1.2  nakayama 			callout_schedule(&sc->sc_state_to, mstohz(1));
    625      1.1  nakayama 			return;
    626      1.2  nakayama 		}
    627      1.2  nakayama 
    628      1.2  nakayama 		/*
    629      1.2  nakayama 		 * Looks like the microcontroller got wedged.  Unwedge
    630      1.2  nakayama 		 * it by writing this magic value.  Give it some time
    631      1.2  nakayama 		 * to recover.
    632      1.2  nakayama 		 */
    633      1.2  nakayama 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, 0xac);
    634      1.2  nakayama 		callout_schedule(&sc->sc_state_to, mstohz(1000));
    635      1.2  nakayama 		sc->sc_state = LOM_STATE_CMD;
    636      1.1  nakayama 		return;
    637      1.1  nakayama 	}
    638      1.1  nakayama 
    639      1.1  nakayama 	sc->sc_retry = 0;
    640      1.1  nakayama 
    641      1.1  nakayama 	if (sc->sc_state == LOM_STATE_CMD) {
    642      1.1  nakayama 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_CMD, lc->lc_cmd);
    643      1.1  nakayama 		sc->sc_state = LOM_STATE_DATA;
    644      1.1  nakayama 		callout_schedule(&sc->sc_state_to, mstohz(250));
    645      1.1  nakayama 		return;
    646      1.1  nakayama 	}
    647      1.1  nakayama 
    648      1.1  nakayama 	KASSERT(sc->sc_state == LOM_STATE_DATA);
    649      1.1  nakayama 	if ((lc->lc_cmd & LOM_IDX_WRITE) == 0)
    650      1.1  nakayama 		lc->lc_data = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA);
    651      1.1  nakayama 	else
    652      1.1  nakayama 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM1_DATA, lc->lc_data);
    653      1.1  nakayama 
    654      1.1  nakayama 	TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
    655      1.1  nakayama 
    656      1.1  nakayama 	wakeup(lc);
    657      1.1  nakayama 
    658      1.1  nakayama 	if (!TAILQ_EMPTY(&sc->sc_queue)) {
    659      1.1  nakayama 		sc->sc_state = LOM_STATE_CMD;
    660      1.1  nakayama 		callout_schedule(&sc->sc_state_to, mstohz(1));
    661      1.1  nakayama 		return;
    662      1.1  nakayama 	}
    663      1.1  nakayama 
    664      1.1  nakayama 	sc->sc_state = LOM_STATE_IDLE;
    665      1.1  nakayama }
    666      1.1  nakayama 
    667      1.1  nakayama static int
    668      1.1  nakayama lom2_read(struct lom_softc *sc, uint8_t reg, uint8_t *val)
    669      1.1  nakayama {
    670      1.2  nakayama 	struct lom_cmd lc;
    671      1.2  nakayama 	int error;
    672      1.2  nakayama 
    673      1.2  nakayama 	if (cold)
    674      1.2  nakayama 		return lom2_read_polled(sc, reg, val);
    675      1.2  nakayama 
    676      1.2  nakayama 	lc.lc_cmd = reg;
    677      1.2  nakayama 	lc.lc_data = 0xff;
    678      1.2  nakayama 	lom2_queue_cmd(sc, &lc);
    679      1.2  nakayama 
    680      1.2  nakayama 	error = tsleep(&lc, PZERO, "lom2rd", hz);
    681      1.2  nakayama 	if (error)
    682      1.4  nakayama 		lom_dequeue_cmd(sc, &lc);
    683      1.2  nakayama 
    684      1.2  nakayama 	*val = lc.lc_data;
    685      1.2  nakayama 
    686      1.2  nakayama 	return (error);
    687      1.2  nakayama }
    688      1.2  nakayama 
    689      1.2  nakayama static int
    690      1.2  nakayama lom2_read_polled(struct lom_softc *sc, uint8_t reg, uint8_t *val)
    691      1.2  nakayama {
    692      1.1  nakayama 	uint8_t str;
    693      1.1  nakayama 	int i;
    694      1.1  nakayama 
    695      1.1  nakayama 	/* Wait for input buffer to become available. */
    696      1.1  nakayama 	for (i = 1000; i > 0; i--) {
    697      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    698      1.1  nakayama 		delay(10);
    699      1.1  nakayama 		if ((str & LOM2_STATUS_IBF) == 0)
    700      1.1  nakayama 			break;
    701      1.1  nakayama 	}
    702      1.1  nakayama 	if (i == 0)
    703      1.1  nakayama 		return (ETIMEDOUT);
    704      1.1  nakayama 
    705      1.1  nakayama 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
    706      1.1  nakayama 
    707      1.1  nakayama 	/* Wait until the microcontroller fills output buffer. */
    708      1.1  nakayama 	for (i = 1000; i > 0; i--) {
    709      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    710      1.1  nakayama 		delay(10);
    711      1.1  nakayama 		if (str & LOM2_STATUS_OBF)
    712      1.1  nakayama 			break;
    713      1.1  nakayama 	}
    714      1.1  nakayama 	if (i == 0)
    715      1.1  nakayama 		return (ETIMEDOUT);
    716      1.1  nakayama 
    717      1.1  nakayama 	*val = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
    718      1.1  nakayama 	return (0);
    719      1.1  nakayama }
    720      1.1  nakayama 
    721      1.1  nakayama static int
    722      1.1  nakayama lom2_write(struct lom_softc *sc, uint8_t reg, uint8_t val)
    723      1.1  nakayama {
    724      1.2  nakayama 	struct lom_cmd lc;
    725      1.2  nakayama 	int error;
    726      1.2  nakayama 
    727      1.2  nakayama 	if (cold)
    728      1.2  nakayama 		return lom2_write_polled(sc, reg, val);
    729      1.2  nakayama 
    730      1.2  nakayama 	lc.lc_cmd = reg | LOM_IDX_WRITE;
    731      1.2  nakayama 	lc.lc_data = val;
    732      1.2  nakayama 	lom2_queue_cmd(sc, &lc);
    733      1.2  nakayama 
    734      1.2  nakayama 	error = tsleep(&lc, PZERO, "lom2wr", hz);
    735      1.2  nakayama 	if (error)
    736      1.2  nakayama 		lom_dequeue_cmd(sc, &lc);
    737      1.2  nakayama 
    738      1.2  nakayama 	return (error);
    739      1.2  nakayama }
    740      1.2  nakayama 
    741      1.2  nakayama static int
    742      1.2  nakayama lom2_write_polled(struct lom_softc *sc, uint8_t reg, uint8_t val)
    743      1.2  nakayama {
    744      1.1  nakayama 	uint8_t str;
    745      1.1  nakayama 	int i;
    746      1.1  nakayama 
    747      1.1  nakayama 	/* Wait for input buffer to become available. */
    748      1.1  nakayama 	for (i = 1000; i > 0; i--) {
    749      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    750      1.1  nakayama 		delay(10);
    751      1.1  nakayama 		if ((str & LOM2_STATUS_IBF) == 0)
    752      1.1  nakayama 			break;
    753      1.1  nakayama 	}
    754      1.1  nakayama 	if (i == 0)
    755      1.1  nakayama 		return (ETIMEDOUT);
    756      1.1  nakayama 
    757      1.1  nakayama 	if (sc->sc_space == LOM_IDX_CMD_GENERIC && reg != LOM_IDX_CMD)
    758      1.2  nakayama 		reg |= LOM_IDX_WRITE;
    759      1.1  nakayama 
    760      1.1  nakayama 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_CMD, reg);
    761      1.1  nakayama 
    762      1.1  nakayama 	/* Wait until the microcontroller fills output buffer. */
    763      1.1  nakayama 	for (i = 1000; i > 0; i--) {
    764      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    765      1.1  nakayama 		delay(10);
    766      1.1  nakayama 		if (str & LOM2_STATUS_OBF)
    767      1.1  nakayama 			break;
    768      1.1  nakayama 	}
    769      1.1  nakayama 	if (i == 0)
    770      1.1  nakayama 		return (ETIMEDOUT);
    771      1.1  nakayama 
    772      1.1  nakayama 	(void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
    773      1.1  nakayama 
    774      1.1  nakayama 	/* Wait for input buffer to become available. */
    775      1.1  nakayama 	for (i = 1000; i > 0; i--) {
    776      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    777      1.1  nakayama 		delay(10);
    778      1.1  nakayama 		if ((str & LOM2_STATUS_IBF) == 0)
    779      1.1  nakayama 			break;
    780      1.1  nakayama 	}
    781      1.1  nakayama 	if (i == 0)
    782      1.1  nakayama 		return (ETIMEDOUT);
    783      1.1  nakayama 
    784      1.1  nakayama 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA, val);
    785      1.1  nakayama 
    786      1.1  nakayama 	/* Wait until the microcontroller fills output buffer. */
    787      1.1  nakayama 	for (i = 1000; i > 0; i--) {
    788      1.1  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    789      1.1  nakayama 		delay(10);
    790      1.1  nakayama 		if (str & LOM2_STATUS_OBF)
    791      1.1  nakayama 			break;
    792      1.1  nakayama 	}
    793      1.1  nakayama 	if (i == 0)
    794      1.1  nakayama 		return (ETIMEDOUT);
    795      1.1  nakayama 
    796      1.1  nakayama 	(void)bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
    797      1.1  nakayama 
    798      1.1  nakayama 	/* If we switched spaces, remember the one we're in now. */
    799      1.1  nakayama 	if (reg == LOM_IDX_CMD)
    800      1.1  nakayama 		sc->sc_space = val;
    801      1.1  nakayama 
    802      1.1  nakayama 	return (0);
    803      1.1  nakayama }
    804      1.1  nakayama 
    805      1.1  nakayama static void
    806      1.1  nakayama lom2_queue_cmd(struct lom_softc *sc, struct lom_cmd *lc)
    807      1.1  nakayama {
    808      1.2  nakayama 	uint8_t str;
    809      1.2  nakayama 
    810      1.2  nakayama 	mutex_enter(&sc->sc_queue_mtx);
    811      1.2  nakayama 	TAILQ_INSERT_TAIL(&sc->sc_queue, lc, lc_next);
    812      1.2  nakayama 	if (sc->sc_state == LOM_STATE_IDLE) {
    813      1.2  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    814      1.2  nakayama 		if ((str & LOM2_STATUS_IBF) == 0) {
    815      1.2  nakayama 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
    816      1.2  nakayama 			    LOM2_CMD, lc->lc_cmd);
    817      1.2  nakayama 			sc->sc_state = LOM_STATE_DATA;
    818      1.2  nakayama 		}
    819      1.2  nakayama 	}
    820      1.2  nakayama 	mutex_exit(&sc->sc_queue_mtx);
    821      1.2  nakayama }
    822      1.2  nakayama 
    823      1.2  nakayama static int
    824      1.2  nakayama lom2_intr(void *arg)
    825      1.2  nakayama {
    826      1.2  nakayama 	struct lom_softc *sc = arg;
    827      1.2  nakayama 	struct lom_cmd *lc;
    828      1.2  nakayama 	uint8_t str, obr;
    829      1.2  nakayama 
    830      1.2  nakayama 	mutex_enter(&sc->sc_queue_mtx);
    831      1.2  nakayama 
    832      1.2  nakayama 	str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    833      1.2  nakayama 	obr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_DATA);
    834      1.2  nakayama 
    835      1.2  nakayama 	lc = TAILQ_FIRST(&sc->sc_queue);
    836      1.2  nakayama 	if (lc == NULL) {
    837      1.2  nakayama 		mutex_exit(&sc->sc_queue_mtx);
    838      1.2  nakayama 		return (0);
    839      1.2  nakayama 	}
    840      1.2  nakayama 
    841      1.2  nakayama 	if (lc->lc_cmd & LOM_IDX_WRITE) {
    842      1.2  nakayama 		bus_space_write_1(sc->sc_iot, sc->sc_ioh,
    843      1.2  nakayama 		    LOM2_DATA, lc->lc_data);
    844      1.2  nakayama 		lc->lc_cmd &= ~LOM_IDX_WRITE;
    845      1.2  nakayama 		mutex_exit(&sc->sc_queue_mtx);
    846      1.2  nakayama 		return (1);
    847      1.2  nakayama 	}
    848      1.2  nakayama 
    849      1.2  nakayama 	KASSERT(sc->sc_state = LOM_STATE_DATA);
    850      1.2  nakayama 	lc->lc_data = obr;
    851      1.2  nakayama 
    852      1.2  nakayama 	TAILQ_REMOVE(&sc->sc_queue, lc, lc_next);
    853      1.2  nakayama 
    854      1.2  nakayama 	wakeup(lc);
    855      1.2  nakayama 
    856      1.2  nakayama 	sc->sc_state = LOM_STATE_IDLE;
    857      1.2  nakayama 
    858      1.2  nakayama 	if (!TAILQ_EMPTY(&sc->sc_queue)) {
    859      1.2  nakayama 		str = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LOM2_STATUS);
    860      1.2  nakayama 		if ((str & LOM2_STATUS_IBF) == 0) {
    861      1.2  nakayama 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
    862      1.2  nakayama 			    LOM2_CMD, lc->lc_cmd);
    863      1.2  nakayama 			sc->sc_state = LOM_STATE_DATA;
    864      1.2  nakayama 		}
    865      1.2  nakayama 	}
    866      1.2  nakayama 
    867      1.2  nakayama 	mutex_exit(&sc->sc_queue_mtx);
    868      1.2  nakayama 
    869      1.2  nakayama 	return (1);
    870      1.1  nakayama }
    871      1.1  nakayama 
    872      1.1  nakayama static int
    873      1.1  nakayama lom_init_desc(struct lom_softc *sc)
    874      1.1  nakayama {
    875      1.1  nakayama 	uint8_t val;
    876      1.1  nakayama 	int i, j, k;
    877      1.1  nakayama 	int error;
    878      1.1  nakayama 
    879      1.1  nakayama 	/* LOMlite doesn't provide sensor descriptions. */
    880      1.1  nakayama 	if (sc->sc_type < LOM_LOMLITE2)
    881      1.1  nakayama 		return (0);
    882      1.1  nakayama 
    883      1.1  nakayama 	/*
    884      1.1  nakayama 	 * Read temperature sensor names.
    885      1.1  nakayama 	 */
    886      1.1  nakayama 	error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_TEMP);
    887      1.1  nakayama 	if (error)
    888      1.1  nakayama 		return (error);
    889      1.1  nakayama 
    890      1.1  nakayama 	i = 0;
    891      1.1  nakayama 	j = 0;
    892      1.1  nakayama 	k = LOM_IDX4_TEMP_NAME_START;
    893      1.1  nakayama 	while (k <= LOM_IDX4_TEMP_NAME_END) {
    894      1.1  nakayama 		error = lom_read(sc, k++, &val);
    895      1.1  nakayama 		if (error)
    896      1.1  nakayama 			goto fail;
    897      1.1  nakayama 
    898      1.1  nakayama 		if (val == 0xff)
    899      1.1  nakayama 			break;
    900      1.1  nakayama 
    901      1.1  nakayama 		if (j < sizeof (sc->sc_temp[i].desc) - 1)
    902      1.1  nakayama 			sc->sc_temp[i].desc[j++] = val;
    903      1.1  nakayama 
    904      1.1  nakayama 		if (val == '\0') {
    905      1.1  nakayama 			i++;
    906      1.1  nakayama 			j = 0;
    907      1.1  nakayama 			if (i < sc->sc_num_temp)
    908      1.1  nakayama 				continue;
    909      1.1  nakayama 
    910      1.1  nakayama 			break;
    911      1.1  nakayama 		}
    912      1.1  nakayama 	}
    913      1.1  nakayama 
    914      1.1  nakayama 	/*
    915      1.1  nakayama 	 * Read fan names.
    916      1.1  nakayama 	 */
    917      1.1  nakayama 	error = lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_FAN);
    918      1.1  nakayama 	if (error)
    919      1.1  nakayama 		return (error);
    920      1.1  nakayama 
    921      1.1  nakayama 	i = 0;
    922      1.1  nakayama 	j = 0;
    923      1.1  nakayama 	k = LOM_IDX5_FAN_NAME_START;
    924      1.1  nakayama 	while (k <= LOM_IDX5_FAN_NAME_END) {
    925      1.1  nakayama 		error = lom_read(sc, k++, &val);
    926      1.1  nakayama 		if (error)
    927      1.1  nakayama 			goto fail;
    928      1.1  nakayama 
    929      1.1  nakayama 		if (val == 0xff)
    930      1.1  nakayama 			break;
    931      1.1  nakayama 
    932      1.1  nakayama 		if (j < sizeof (sc->sc_fan[i].desc) - 1)
    933      1.1  nakayama 			sc->sc_fan[i].desc[j++] = val;
    934      1.1  nakayama 
    935      1.1  nakayama 		if (val == '\0') {
    936      1.1  nakayama 			i++;
    937      1.1  nakayama 			j = 0;
    938      1.1  nakayama 			if (i < sc->sc_num_fan)
    939      1.1  nakayama 				continue;
    940      1.1  nakayama 
    941      1.1  nakayama 			break;
    942      1.1  nakayama 		}
    943      1.1  nakayama 	}
    944      1.1  nakayama 
    945      1.1  nakayama fail:
    946      1.1  nakayama 	lom_write(sc, LOM_IDX_CMD, LOM_IDX_CMD_GENERIC);
    947      1.1  nakayama 	return (error);
    948      1.1  nakayama }
    949      1.1  nakayama 
    950      1.1  nakayama static void
    951      1.1  nakayama lom_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
    952      1.1  nakayama {
    953      1.1  nakayama 	struct lom_softc *sc = sme->sme_cookie;
    954  1.5.6.2     rmind 	uint32_t i;
    955  1.5.6.2     rmind 
    956  1.5.6.2     rmind 	/* Sensor number */
    957  1.5.6.2     rmind 	i = edata->sensor;
    958  1.5.6.2     rmind 
    959  1.5.6.2     rmind 	/* Sensor type */
    960  1.5.6.2     rmind 	switch (edata->units) {
    961  1.5.6.2     rmind 	case ENVSYS_INDICATOR:
    962  1.5.6.2     rmind 		if (i < sc->sc_num_alarm)
    963  1.5.6.2     rmind 			lom_refresh_alarm(sc, edata, i);
    964  1.5.6.2     rmind 		else
    965  1.5.6.2     rmind 			lom_refresh_psu(sc, edata,
    966  1.5.6.2     rmind 			    i - sc->sc_num_alarm - sc->sc_num_fan);
    967  1.5.6.2     rmind 		break;
    968  1.5.6.2     rmind 	case ENVSYS_SFANRPM:
    969  1.5.6.2     rmind 		lom_refresh_fan(sc, edata, i - sc->sc_num_alarm);
    970  1.5.6.2     rmind 		break;
    971  1.5.6.2     rmind 	case ENVSYS_STEMP:
    972  1.5.6.2     rmind 		lom_refresh_temp(sc, edata,
    973  1.5.6.2     rmind 		    i - sc->sc_num_alarm - sc->sc_num_fan - sc->sc_num_psu);
    974  1.5.6.2     rmind 		break;
    975  1.5.6.2     rmind 	default:
    976  1.5.6.2     rmind 		edata->state = ENVSYS_SINVALID;
    977  1.5.6.2     rmind 		break;
    978  1.5.6.2     rmind 	}
    979  1.5.6.2     rmind 
    980  1.5.6.2     rmind 	/*
    981  1.5.6.2     rmind 	 * If our hostname is set and differs from what's stored in
    982  1.5.6.2     rmind 	 * the LOM, write the new hostname back to the LOM.  Note that
    983  1.5.6.2     rmind 	 * we include the terminating NUL when writing the hostname
    984  1.5.6.2     rmind 	 * back to the LOM, otherwise the LOM will print any trailing
    985  1.5.6.2     rmind 	 * garbage.
    986  1.5.6.2     rmind 	 */
    987  1.5.6.2     rmind 	if (i == 0 && hostnamelen > 0 &&
    988  1.5.6.2     rmind 	    strncmp(sc->sc_hostname, hostname, sizeof(hostname)) != 0) {
    989  1.5.6.2     rmind 		if (sc->sc_type < LOM_LOMLITE2)
    990  1.5.6.2     rmind 			lom1_write_hostname(sc);
    991  1.5.6.2     rmind 		else
    992  1.5.6.2     rmind 			lom2_write_hostname(sc);
    993  1.5.6.2     rmind 		strlcpy(sc->sc_hostname, hostname, sizeof(hostname));
    994  1.5.6.2     rmind 	}
    995  1.5.6.2     rmind }
    996  1.5.6.2     rmind 
    997  1.5.6.2     rmind static void
    998  1.5.6.2     rmind lom_refresh_alarm(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
    999  1.5.6.2     rmind {
   1000      1.1  nakayama 	uint8_t val;
   1001  1.5.6.2     rmind 
   1002  1.5.6.2     rmind 	/* Fault LED or Alarms */
   1003  1.5.6.2     rmind 	KASSERT(i < sc->sc_num_alarm);
   1004      1.1  nakayama 
   1005      1.3  nakayama 	if (lom_read(sc, LOM_IDX_ALARM, &val)) {
   1006  1.5.6.2     rmind 		edata->state = ENVSYS_SINVALID;
   1007      1.3  nakayama 	} else {
   1008  1.5.6.2     rmind 		if (i == 0) {
   1009  1.5.6.2     rmind 			/* Fault LED */
   1010  1.5.6.2     rmind 			if ((val & LOM_ALARM_FAULT) == LOM_ALARM_FAULT)
   1011  1.5.6.2     rmind 				edata->value_cur = 0;
   1012  1.5.6.2     rmind 			else
   1013  1.5.6.2     rmind 				edata->value_cur = 1;
   1014  1.5.6.2     rmind 		} else {
   1015  1.5.6.2     rmind 			/* Alarms */
   1016      1.3  nakayama 			if ((val & (LOM_ALARM_1 << (i - 1))) == 0)
   1017  1.5.6.2     rmind 				edata->value_cur = 0;
   1018      1.3  nakayama 			else
   1019  1.5.6.2     rmind 				edata->value_cur = 1;
   1020      1.3  nakayama 		}
   1021  1.5.6.2     rmind 		edata->state = ENVSYS_SVALID;
   1022      1.3  nakayama 	}
   1023  1.5.6.2     rmind }
   1024      1.3  nakayama 
   1025  1.5.6.2     rmind static void
   1026  1.5.6.2     rmind lom_refresh_fan(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
   1027  1.5.6.2     rmind {
   1028  1.5.6.2     rmind 	uint8_t val;
   1029  1.5.6.2     rmind 
   1030  1.5.6.2     rmind 	/* Fan speed */
   1031  1.5.6.2     rmind 	KASSERT(i < sc->sc_num_fan);
   1032      1.1  nakayama 
   1033  1.5.6.2     rmind 	if (lom_read(sc, LOM_IDX_FAN1 + i, &val)) {
   1034  1.5.6.2     rmind 		edata->state = ENVSYS_SINVALID;
   1035  1.5.6.2     rmind 	} else {
   1036  1.5.6.2     rmind 		edata->value_cur = (60 * sc->sc_fan_cal[i] * val) / 100;
   1037      1.1  nakayama 		if (val < sc->sc_fan_low[i])
   1038  1.5.6.2     rmind 			edata->state = ENVSYS_SCRITICAL;
   1039      1.1  nakayama 		else
   1040  1.5.6.2     rmind 			edata->state = ENVSYS_SVALID;
   1041      1.1  nakayama 	}
   1042  1.5.6.2     rmind }
   1043      1.1  nakayama 
   1044  1.5.6.2     rmind static void
   1045  1.5.6.2     rmind lom_refresh_psu(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
   1046  1.5.6.2     rmind {
   1047  1.5.6.2     rmind 	uint8_t val;
   1048  1.5.6.2     rmind 
   1049  1.5.6.2     rmind 	/* PSU status */
   1050  1.5.6.2     rmind 	KASSERT(i < sc->sc_num_psu);
   1051      1.1  nakayama 
   1052  1.5.6.2     rmind 	if (lom_read(sc, LOM_IDX_PSU1 + i, &val) ||
   1053  1.5.6.2     rmind 	    !ISSET(val, LOM_PSU_PRESENT)) {
   1054  1.5.6.2     rmind 		edata->state = ENVSYS_SINVALID;
   1055  1.5.6.2     rmind 	} else {
   1056      1.1  nakayama 		if (val & LOM_PSU_STANDBY) {
   1057  1.5.6.2     rmind 			edata->value_cur = 0;
   1058  1.5.6.2     rmind 			edata->state = ENVSYS_SVALID;
   1059      1.1  nakayama 		} else {
   1060  1.5.6.2     rmind 			edata->value_cur = 1;
   1061      1.1  nakayama 			if (ISSET(val, LOM_PSU_INPUTA) &&
   1062      1.1  nakayama 			    ISSET(val, LOM_PSU_INPUTB) &&
   1063      1.1  nakayama 			    ISSET(val, LOM_PSU_OUTPUT))
   1064  1.5.6.2     rmind 				edata->state = ENVSYS_SVALID;
   1065      1.1  nakayama 			else
   1066  1.5.6.2     rmind 				edata->state = ENVSYS_SCRITICAL;
   1067      1.1  nakayama 		}
   1068      1.1  nakayama 	}
   1069  1.5.6.2     rmind }
   1070      1.1  nakayama 
   1071  1.5.6.2     rmind static void
   1072  1.5.6.2     rmind lom_refresh_temp(struct lom_softc *sc, envsys_data_t *edata, uint32_t i)
   1073  1.5.6.2     rmind {
   1074  1.5.6.2     rmind 	uint8_t val;
   1075      1.1  nakayama 
   1076  1.5.6.2     rmind 	/* Temperature */
   1077  1.5.6.2     rmind 	KASSERT(i < sc->sc_num_temp);
   1078      1.1  nakayama 
   1079  1.5.6.2     rmind 	if (lom_read(sc, LOM_IDX_TEMP1 + i, &val)) {
   1080  1.5.6.2     rmind 		edata->state = ENVSYS_SINVALID;
   1081  1.5.6.2     rmind 	} else {
   1082  1.5.6.2     rmind 		edata->value_cur = val * 1000000 + 273150000;
   1083  1.5.6.2     rmind 		edata->state = ENVSYS_SVALID;
   1084      1.1  nakayama 	}
   1085      1.1  nakayama }
   1086      1.1  nakayama 
   1087      1.1  nakayama static void
   1088      1.1  nakayama lom1_write_hostname(struct lom_softc *sc)
   1089      1.1  nakayama {
   1090  1.5.6.1     rmind 	char name[(LOM1_IDX_HOSTNAME12 - LOM1_IDX_HOSTNAME1 + 1) + 1];
   1091      1.1  nakayama 	char *p;
   1092      1.1  nakayama 	int i;
   1093      1.1  nakayama 
   1094      1.1  nakayama 	/*
   1095      1.1  nakayama 	 * LOMlite generally doesn't have enough space to store the
   1096      1.1  nakayama 	 * fully qualified hostname.  If the hostname is too long,
   1097      1.1  nakayama 	 * strip off the domain name.
   1098      1.1  nakayama 	 */
   1099      1.1  nakayama 	strlcpy(name, hostname, sizeof(name));
   1100  1.5.6.1     rmind 	if (hostnamelen >= sizeof(name)) {
   1101      1.1  nakayama 		p = strchr(name, '.');
   1102      1.1  nakayama 		if (p)
   1103      1.1  nakayama 			*p = '\0';
   1104      1.1  nakayama 	}
   1105      1.1  nakayama 
   1106      1.1  nakayama 	for (i = 0; i < strlen(name) + 1; i++)
   1107      1.1  nakayama 		if (lom_write(sc, LOM1_IDX_HOSTNAME1 + i, name[i]))
   1108      1.1  nakayama 			break;
   1109      1.1  nakayama }
   1110      1.1  nakayama 
   1111      1.1  nakayama static void
   1112      1.1  nakayama lom2_write_hostname(struct lom_softc *sc)
   1113      1.1  nakayama {
   1114      1.1  nakayama 	int i;
   1115      1.1  nakayama 
   1116      1.1  nakayama 	lom_write(sc, LOM2_IDX_HOSTNAMELEN, hostnamelen + 1);
   1117      1.1  nakayama 	for (i = 0; i < hostnamelen + 1; i++)
   1118      1.1  nakayama 		lom_write(sc, LOM2_IDX_HOSTNAME, hostname[i]);
   1119      1.1  nakayama }
   1120      1.1  nakayama 
   1121      1.1  nakayama static int
   1122      1.1  nakayama lom_wdog_tickle(struct sysmon_wdog *smw)
   1123      1.1  nakayama {
   1124      1.1  nakayama 	struct lom_softc *sc = smw->smw_cookie;
   1125      1.1  nakayama 
   1126      1.1  nakayama 	/* Pat the dog. */
   1127      1.1  nakayama 	sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE;
   1128      1.1  nakayama 	sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl;
   1129      1.1  nakayama 	lom_queue_cmd(sc, &sc->sc_wdog_pat);
   1130      1.1  nakayama 
   1131      1.1  nakayama 	return 0;
   1132      1.1  nakayama }
   1133      1.1  nakayama 
   1134      1.1  nakayama static int
   1135      1.1  nakayama lom_wdog_setmode(struct sysmon_wdog *smw)
   1136      1.1  nakayama {
   1137      1.1  nakayama 	struct lom_softc *sc = smw->smw_cookie;
   1138      1.1  nakayama 
   1139      1.1  nakayama 	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
   1140      1.1  nakayama 		/* disable watchdog */
   1141      1.1  nakayama 		sc->sc_wdog_ctl &= ~(LOM_WDOG_ENABLE|LOM_WDOG_RESET);
   1142      1.1  nakayama 		lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
   1143      1.1  nakayama 	} else {
   1144      1.1  nakayama 		if (smw->smw_period == WDOG_PERIOD_DEFAULT)
   1145      1.1  nakayama 			smw->smw_period = sc->sc_wdog_period;
   1146      1.1  nakayama 		else if (smw->smw_period == 0 ||
   1147      1.1  nakayama 		    smw->smw_period > LOM_WDOG_TIME_MAX)
   1148      1.1  nakayama 			return EINVAL;
   1149      1.1  nakayama 		lom_write(sc, LOM_IDX_WDOG_TIME, smw->smw_period);
   1150      1.1  nakayama 
   1151      1.1  nakayama 		/* enable watchdog */
   1152      1.2  nakayama 		lom_dequeue_cmd(sc, &sc->sc_wdog_pat);
   1153      1.1  nakayama 		sc->sc_wdog_ctl |= LOM_WDOG_ENABLE|LOM_WDOG_RESET;
   1154      1.1  nakayama 		sc->sc_wdog_pat.lc_cmd = LOM_IDX_WDOG_CTL | LOM_IDX_WRITE;
   1155      1.1  nakayama 		sc->sc_wdog_pat.lc_data = sc->sc_wdog_ctl;
   1156      1.1  nakayama 		lom_queue_cmd(sc, &sc->sc_wdog_pat);
   1157      1.1  nakayama 	}
   1158      1.1  nakayama 
   1159      1.1  nakayama 	return 0;
   1160      1.1  nakayama }
   1161      1.2  nakayama 
   1162      1.2  nakayama static bool
   1163      1.2  nakayama lom_shutdown(device_t dev, int how)
   1164      1.2  nakayama {
   1165      1.2  nakayama 	struct lom_softc *sc = device_private(dev);
   1166      1.2  nakayama 
   1167      1.2  nakayama 	sc->sc_wdog_ctl &= ~LOM_WDOG_ENABLE;
   1168      1.2  nakayama 	lom_write(sc, LOM_IDX_WDOG_CTL, sc->sc_wdog_ctl);
   1169      1.2  nakayama 	return true;
   1170      1.2  nakayama }
   1171      1.5  nakayama 
   1172      1.5  nakayama SYSCTL_SETUP(sysctl_lom_setup, "sysctl hw.lom subtree setup")
   1173      1.5  nakayama {
   1174      1.5  nakayama 	const struct sysctlnode *node;
   1175      1.5  nakayama 
   1176      1.5  nakayama 	if (sysctl_createv(clog, 0, NULL, &node,
   1177      1.5  nakayama 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
   1178      1.5  nakayama 	    NULL, 0, NULL, 0, CTL_HW, CTL_EOL) != 0)
   1179      1.5  nakayama 		return;
   1180      1.5  nakayama 
   1181      1.5  nakayama 	hw_node = node->sysctl_num;
   1182      1.5  nakayama }
   1183      1.5  nakayama 
   1184      1.5  nakayama static int
   1185      1.5  nakayama lom_sysctl_alarm(SYSCTLFN_ARGS)
   1186      1.5  nakayama {
   1187      1.5  nakayama 	struct sysctlnode node;
   1188      1.5  nakayama 	struct lom_softc *sc;
   1189      1.5  nakayama 	int i, tmp, error;
   1190      1.5  nakayama 	uint8_t val;
   1191      1.5  nakayama 
   1192      1.5  nakayama 	node = *rnode;
   1193      1.5  nakayama 	sc = node.sysctl_data;
   1194      1.5  nakayama 
   1195      1.5  nakayama 	for (i = 0; i < sc->sc_num_alarm; i++) {
   1196      1.5  nakayama 		if (node.sysctl_num == sc->sc_sysctl_num[i]) {
   1197  1.5.6.2     rmind 			lom_refresh_alarm(sc, &sc->sc_alarm[i], i);
   1198      1.5  nakayama 			tmp = sc->sc_alarm[i].value_cur;
   1199      1.5  nakayama 			node.sysctl_data = &tmp;
   1200      1.5  nakayama 			error = sysctl_lookup(SYSCTLFN_CALL(&node));
   1201      1.5  nakayama 			if (error || newp == NULL)
   1202      1.5  nakayama 				return error;
   1203      1.5  nakayama 			if (tmp < 0 || tmp > 1)
   1204      1.5  nakayama 				return EINVAL;
   1205      1.5  nakayama 
   1206      1.5  nakayama 			if (lom_read(sc, LOM_IDX_ALARM, &val))
   1207      1.5  nakayama 				return EINVAL;
   1208      1.5  nakayama 			if (i == 0) {
   1209      1.5  nakayama 				/* Fault LED */
   1210      1.5  nakayama 				if (tmp != 0)
   1211      1.5  nakayama 					val &= ~LOM_ALARM_FAULT;
   1212      1.5  nakayama 				else
   1213      1.5  nakayama 					val |= LOM_ALARM_FAULT;
   1214      1.5  nakayama 			} else {
   1215      1.5  nakayama 				/* Alarms */
   1216      1.5  nakayama 				if (tmp != 0)
   1217      1.5  nakayama 					val |= LOM_ALARM_1 << (i - 1);
   1218      1.5  nakayama 				else
   1219      1.5  nakayama 					val &= ~(LOM_ALARM_1 << (i - 1));
   1220      1.5  nakayama 			}
   1221      1.5  nakayama 			if (lom_write(sc, LOM_IDX_ALARM, val))
   1222      1.5  nakayama 				return EINVAL;
   1223      1.5  nakayama 
   1224      1.5  nakayama 			sc->sc_alarm[i].value_cur = tmp;
   1225      1.5  nakayama 			return 0;
   1226      1.5  nakayama 		}
   1227      1.5  nakayama 	}
   1228      1.5  nakayama 
   1229      1.5  nakayama 	return ENOENT;
   1230      1.5  nakayama }
   1231