Thanks for the pointers. Heres the update.
And just a quick question for anybody, why do some of the macros in the
OS look like:
#define DEBUG(x) do { ... } while(0);
Is this some kind of compiler trick?
Thanks Again
Jonathan Steel
=====================
File: /sys/dev/isa/wbwdg.c
=====================
/*
* Copyright (c) 2007 Jonathan Steel <[EMAIL PROTECTED]>
*
* 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.
*/
/*
* Winbond W83627HF watchdog driver.
* Datasheet:
* www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627HF_HGb.pdf
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/bus.h>
#include <sys/sensors.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
/* Registers */
#define WBWDG_ADDR 0x00
#define WBWDG_DATA (WBWDG_ADDR + 1)
#define WBWDG_LOGICAL_DEVICE 0x07
#define WBWDG_DEVID 0x20
#define WBWDG_DEVREV 0x21
/* Locial device 8 registers */
#define WBWDG_ENABLE 0x30
#define WBWDG_COUNT_METHOD 0xF3
#define WBWDG_MODE 0xF5
#define WBWDG_TIMEOUT 0xF6
/* Magic numbers */
#define WB_DEVID_W83627HF 0x52
#define WBWDG_ADDR_SIZE 0x02
#define WBWDG_ENTER_CONFIG_MODE 0x87
#define WBWDG_EXIT_CONFIG_MODE 0xAA
#define WBWDG_DEV_WDG 0x08
#define WBWDG_MODE_MIN (1 << 3)
#define WBWDG_MAX_TIMEOUT (0xFF * 60)
#ifdef WBWDG_DEBUG
#define DPRINTF(x) printf x
#else
#define DPRINTF(x)
#endif
struct wbwdg_softc;
int winbond_wdg_match(struct device *, void *, void *);
void winbond_wdg_attach(struct device *, struct device *, void *);
void winbond_wdg_init(struct wbwdg_softc *sc);
int winbond_wdg_cb(void *, int);
struct wbwdg_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
/* If the timeout is in minutes or seconds */
int wdg_mode_sec;
};
struct cfattach wbwdg_ca = {
sizeof(struct wbwdg_softc),
winbond_wdg_match,
winbond_wdg_attach
};
struct cfdriver wbwdg_cd = {
NULL, "wbwdg", DV_DULL
};
static __inline void
winbond_conf_enable(struct wbwdg_softc *sc)
{
bus_space_write_1(sc->sc_iot, sc->sc_ioh, WBWDG_ADDR,
WBWDG_ENTER_CONFIG_MODE);
bus_space_write_1(sc->sc_iot, sc->sc_ioh, WBWDG_ADDR,
WBWDG_ENTER_CONFIG_MODE);
}
static __inline void
winbond_conf_disable(struct wbwdg_softc *sc)
{
bus_space_write_1(sc->sc_iot, sc->sc_ioh, WBWDG_ADDR,
WBWDG_EXIT_CONFIG_MODE);
}
static __inline u_int8_t
winbond_conf_read(struct wbwdg_softc *sc, u_int8_t index)
{
bus_space_write_1(sc->sc_iot, sc->sc_ioh, WBWDG_ADDR, index);
return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, WBWDG_DATA));
}
static __inline void
winbond_conf_write(struct wbwdg_softc *sc, u_int8_t index, u_int8_t data)
{
bus_space_write_1(sc->sc_iot, sc->sc_ioh, WBWDG_ADDR, index);
bus_space_write_1(sc->sc_iot, sc->sc_ioh, WBWDG_DATA, data);
}
int
winbond_wdg_match(struct device *parent, void *match, void *aux)
{
struct isa_attach_args *ia = aux;
bus_space_tag_t iot;
bus_space_handle_t ioh;
u_int8_t device_id;
struct wbwdg_softc sc;
iot = ia->ia_iot;
if (bus_space_map(iot, ia->ipa_io[0].base, WBWDG_ADDR_SIZE, 0, &ioh))
return (0);
sc.sc_iot = iot;
sc.sc_ioh = ioh;
/* See if this machine has a compatible winbond chipset */
winbond_conf_enable(&sc);
device_id = winbond_conf_read(&sc, WBWDG_DEVID);
DPRINTF(("wbwdg_match: id 0x%02x\n", device_id));
winbond_conf_disable(&sc);
bus_space_unmap(iot, ioh, WBWDG_ADDR_SIZE);
if (device_id != WB_DEVID_W83627HF)
return (0);
DPRINTF(("W83627HF Watchdog\n"));
ia->ipa_nio = 1;
ia->ipa_io[0].length = WBWDG_ADDR_SIZE;
ia->ipa_nmem = 0;
ia->ipa_nirq = 0;
ia->ipa_ndrq = 0;
return (1);
}
void
winbond_wdg_attach(struct device *parent, struct device *self, void *aux)
{
struct wbwdg_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
u_int8_t buf;
sc->sc_iot = ia->ia_iot;
if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base,
WBWDG_ADDR_SIZE, 0, &sc->sc_ioh)) {
printf(": can't map I/O space\n");
return;
}
/* Enter configuration mode */
winbond_conf_enable(sc);
/* Read device id and revision */
buf = winbond_conf_read(sc, WBWDG_DEVID);
if (buf == WB_DEVID_W83627HF)
printf(": W83627HF : ");
buf = winbond_conf_read(sc, WBWDG_DEVREV);
printf("rev 0x%02x:", buf);
/* Initialize logical devices */
winbond_wdg_init(sc);
printf("\n");
/* Escape from configuration mode */
winbond_conf_disable(sc);
return;
}
void
winbond_wdg_init(struct wbwdg_softc *sc)
{
/* Select WDG logical device */
winbond_conf_write(sc, WBWDG_LOGICAL_DEVICE, WBWDG_DEV_WDG);
/*
* Enable the timer. The default value of timeout is 0 which
* means that the timeout is disabled
*/
winbond_conf_write(sc, WBWDG_ENABLE, 1);
sc->wdg_mode_sec = 0;
wdog_register(sc, winbond_wdg_cb);
return;
}
int
winbond_wdg_cb(void *arg, int period)
{
struct wbwdg_softc *sc = arg;
int chip_period;
u_int8_t mode;
if (period < 0)
period = 0;
else if (period > WBWDG_MAX_TIMEOUT)
period = WBWDG_MAX_TIMEOUT;
/* Setup the chip to talk to the watchdog device */
winbond_conf_enable(sc);
winbond_conf_write(sc, WBWDG_LOGICAL_DEVICE, WBWDG_DEV_WDG);
/* Tell the device to read the timeout as either seconds or minutes */
if (sc->wdg_mode_sec && period > 0xFF) {
sc->wdg_mode_sec = 0;
mode = winbond_conf_read(sc, WBWDG_MODE);
mode |= WBWDG_MODE_MIN;
winbond_conf_write(sc, WBWDG_MODE, mode);
}
else if (!sc->wdg_mode_sec && period <= 0xFF) {
sc->wdg_mode_sec = 1;
mode = winbond_conf_read(sc, WBWDG_MODE);
mode &= ~WBWDG_MODE_MIN;
winbond_conf_write(sc, WBWDG_MODE, mode);
}
chip_period = period;
/* Convert the period to minutes if necessary */
if (period > 0xFF)
chip_period = period / 60;
winbond_conf_write(sc, WBWDG_TIMEOUT, chip_period);
winbond_conf_disable(sc);
return (period);
}
=====================
File: wbwdg.4
=====================
.\" Copyright (c) 2007 Jonathan Steel <[EMAIL PROTECTED]>
.\"
.\" 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.
.\"
.Dd April 27, 2007
.Dt WBWDG 4
.Os
.Sh NAME
.Nm wbwdg
.Nd Winbond W83627HF watchdog driver
.Sh SYNOPSIS
.Cd "wbwdg0 at isa? port 0x2e"
.Cd "wbwdg1 at isa? port 0x4e"
.Sh DESCRIPTION
The
.Nm
driver provides support for the Winbond W83627HF watchdog.
The watchdog timer provides a standard
.Xr watchdog 4
interface.
.Pp
The sensors on the W83627HF are controlled by the
.Xr lm 4
driver.
.Ar flags .
.Sh SEE ALSO
.Xr isa 4 ,
.Xr lm 4,
.Xr watchdog 4 ,
.Xr sysctl 8
.Sh AUTHORS
The
.Nm
driver was written by
.An Jonathan Steel Aq [EMAIL PROTECTED] .
====================
Additions to GENERIC
====================
- Add the following in the section for the National Semiconductor drivers.
wbwdt0 at isa? port 0x2e # Winbond W83627HF watchdog
wbwdt1 at isa? port 0x4e
====================
Additions to /sys/dev/isa/lpt_isa
====================
- Again, add the following in the section for the National Semiconductor
drivers.
# Winbond w83627hf watchdog timer
device wbwdg
attach wbwdg at isa
file dev/isa/wbwdg.c wbwdg
Jonathan Gray wrote:
> On Sat, Apr 28, 2007 at 02:58:27AM +1000, Jonathan Gray wrote:
>
>> On Fri, Apr 27, 2007 at 12:30:56PM -0400, Jon Steel wrote:
>>
>>> Hi
>>>
>>> I have created a driver for the watchdog on the W83627HF. It would be
>>> very easy to support other Winbond watchdogs with this driver but I
>>> didnt bother to because I dont have access to any other chips. I have
>>> tested it on both the SuperMicro 5013G-M and 5015M-MT, and with OpenBSD
>>> 3.6, 4.0, and 4.1.
>>>
>>> Thanks
>>>
>>> Jonathan Steel
>>>
>> You should combine the header with the .c file in this case,
>> headers get included in userland and chew up space.
>>
>> Also I think readability would be aided if you made your
>> conf_read/conf_write functions take a softc as a parameter
>> instead of iot and ioh.
>>
>> Jonathan
>>
>
> And:
>
> use proper (safe) macros for DRPINTF, see other drivers
> return at end of void functions uneeded
> man page required
>
> if (device_id == WB_DEVID_W83627HF) {
> DPRINTF(("W83627HF Watchdog\n"));
> }
> else {
> return (0);
> }
>
> ->
>
> if (device_id != WB_DEVID_W83627HF)
> return (0);