From owner-svn-src-head@FreeBSD.ORG Mon Nov 30 11:44:03 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D25551065670; Mon, 30 Nov 2009 11:44:03 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id BCDB28FC18; Mon, 30 Nov 2009 11:44:03 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nAUBi3Uw029502; Mon, 30 Nov 2009 11:44:03 GMT (envelope-from avg@svn.freebsd.org) Received: (from avg@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nAUBi3if029492; Mon, 30 Nov 2009 11:44:03 GMT (envelope-from avg@svn.freebsd.org) Message-Id: <200911301144.nAUBi3if029492@svn.freebsd.org> From: Andriy Gapon Date: Mon, 30 Nov 2009 11:44:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r199969 - in head: share/man/man4 sys/amd64/conf sys/conf sys/dev/amdsbwd sys/i386/conf sys/modules sys/modules/amdsbwd X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Nov 2009 11:44:04 -0000 Author: avg Date: Mon Nov 30 11:44:03 2009 New Revision: 199969 URL: http://svn.freebsd.org/changeset/base/199969 Log: amdsbwd: new driver for AMD SB600/SB7xx watchdog timer The hardware is compliant with WDRT specification, so I originally considered including generic WDRT watchdog support, but decided against it, because I couldn't find anyone to the code for me. WDRT seems to be not very popular. Besides, generic WDRT porbably requires a slightly different driver approach. Reviewed by: des, gavin, rpaulo MFC after: 3 weeks Added: head/share/man/man4/amdsbwd.4 (contents, props changed) head/sys/dev/amdsbwd/ head/sys/dev/amdsbwd/amdsbwd.c (contents, props changed) head/sys/modules/amdsbwd/ head/sys/modules/amdsbwd/Makefile (contents, props changed) Modified: head/share/man/man4/Makefile head/sys/amd64/conf/NOTES head/sys/conf/files.amd64 head/sys/conf/files.i386 head/sys/i386/conf/NOTES head/sys/modules/Makefile Modified: head/share/man/man4/Makefile ============================================================================== --- head/share/man/man4/Makefile Mon Nov 30 11:11:08 2009 (r199968) +++ head/share/man/man4/Makefile Mon Nov 30 11:44:03 2009 (r199969) @@ -31,6 +31,7 @@ MAN= aac.4 \ ale.4 \ altq.4 \ amd.4 \ + ${_amdsbwd.4} \ ${_amdsmb.4} \ ${_amdtemp.4} \ amr.4 \ @@ -610,6 +611,7 @@ _acpi_panasonic.4=acpi_panasonic.4 _acpi_sony.4= acpi_sony.4 _acpi_toshiba.4=acpi_toshiba.4 _acpi_wmi.4= acpi_wmi.4 +_amdsbwd.4= amdsbwd.4 _amdsmb.4= amdsmb.4 _amdtemp.4= amdtemp.4 _asmc.4= asmc.4 Added: head/share/man/man4/amdsbwd.4 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/man/man4/amdsbwd.4 Mon Nov 30 11:44:03 2009 (r199969) @@ -0,0 +1,72 @@ +.\"- +.\" Copyright (c) 2009 Andriy Gapon +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd November 30, 2009 +.Dt AMDSBWD 4 +.Os +.Sh NAME +.Nm amdsbwd +.Nd device driver for the AMD SB600/SB700/SB710/SB750 watchdog timer +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following line in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device amdsbwd" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +amdsbwd_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides +.Xr watchdog 4 +support for the watchdog timers present on +AMD SB600 and SB7xx south bridge chips. +.Sh SEE ALSO +.Xr watchdog 4 , +.Xr watchdog 8 , +.Xr watchdogd 8 , +.Xr watchdog 9 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 9.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Andiry Gapon Aq avg@FreeBSD.org . +This manual page was written by +.An Andiry Gapon Aq avg@FreeBSD.org . Modified: head/sys/amd64/conf/NOTES ============================================================================== --- head/sys/amd64/conf/NOTES Mon Nov 30 11:11:08 2009 (r199968) +++ head/sys/amd64/conf/NOTES Mon Nov 30 11:44:03 2009 (r199969) @@ -399,8 +399,10 @@ device asmc # Hardware watchdog timers: # # ichwd: Intel ICH watchdog timer +# amdsbwd: AMD SB7xx watchdog timer # device ichwd +device amdsbwd # # Temperature sensors: Modified: head/sys/conf/files.amd64 ============================================================================== --- head/sys/conf/files.amd64 Mon Nov 30 11:11:08 2009 (r199968) +++ head/sys/conf/files.amd64 Mon Nov 30 11:44:03 2009 (r199969) @@ -151,6 +151,7 @@ dev/agp/agp_amd64.c optional agp dev/agp/agp_i810.c optional agp dev/agp/agp_intel.c optional agp dev/agp/agp_via.c optional agp +dev/amdsbwd/amdsbwd.c optional amdsbwd dev/amdtemp/amdtemp.c optional amdtemp dev/arcmsr/arcmsr.c optional arcmsr pci dev/asmc/asmc.c optional asmc isa Modified: head/sys/conf/files.i386 ============================================================================== --- head/sys/conf/files.i386 Mon Nov 30 11:11:08 2009 (r199968) +++ head/sys/conf/files.i386 Mon Nov 30 11:44:03 2009 (r199969) @@ -127,6 +127,7 @@ dev/agp/agp_nvidia.c optional agp dev/agp/agp_sis.c optional agp dev/agp/agp_via.c optional agp dev/aic/aic_isa.c optional aic isa +dev/amdsbwd/amdsbwd.c optional amdsbwd dev/amdtemp/amdtemp.c optional amdtemp dev/arcmsr/arcmsr.c optional arcmsr pci dev/asmc/asmc.c optional asmc isa Added: head/sys/dev/amdsbwd/amdsbwd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/amdsbwd/amdsbwd.c Mon Nov 30 11:44:03 2009 (r199969) @@ -0,0 +1,431 @@ +/*- + * Copyright (c) 2009 Andriy Gapon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This is a driver for watchdog timer present in AMD SB600/SB7xx + * south bridges and other watchdog timers advertised via WDRT ACPI table. + * Please see the following specifications for the descriptions of the + * registers and flags: + * - AMD SB600 Register Reference Guide, Public Version, Rev. 3.03 (SB600 RRG) + * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/46155_sb600_rrg_pub_3.03.pdf + * - AMD SB700/710/750 Register Reference Guide (RRG) + * http://developer.amd.com/assets/43009_sb7xx_rrg_pub_1.00.pdf + * - AMD SB700/710/750 Register Programming Requirements (RPR) + * http://developer.amd.com/assets/42413_sb7xx_rpr_pub_1.00.pdf + * Please see the following for Watchdog Resource Table specification: + * - Watchdog Timer Hardware Requirements for Windows Server 2003 (WDRT) + * http://www.microsoft.com/whdc/system/sysinternals/watchdog.mspx + * AMD SB600/SB7xx watchdog hardware seems to conform to the above, + * but my system doesn't provide the table. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* RRG 2.3.3.1.1, page 161. */ +#define AMDSB_PMIO_INDEX 0xcd6 +#define AMDSB_PMIO_DATA (PMIO_INDEX + 1) +#define AMDSB_PMIO_WIDTH 2 +/* RRG 2.3.3.2, page 181. */ +#define AMDSB_PM_RESET_STATUS0 0x44 +#define AMDSB_PM_RESET_STATUS1 0x45 +#define AMDSB_WD_RST_STS 0x02 +/* RRG 2.3.3.2, page 188; RPR 2.36, page 30. */ +#define AMDSB_PM_WDT_CTRL 0x69 +#define AMDSB_WDT_DISABLE 0x01 +#define AMDSB_WDT_RES_MASK (0x02 | 0x04) +#define AMDSB_WDT_RES_32US 0x00 +#define AMDSB_WDT_RES_10MS 0x02 +#define AMDSB_WDT_RES_100MS 0x04 +#define AMDSB_WDT_RES_1S 0x06 +#define AMDSB_PM_WDT_BASE_LSB 0x6c +#define AMDSB_PM_WDT_BASE_MSB 0x6f +/* RRG 2.3.4, page 223, WDRT. */ +#define AMDSB_WD_CTRL 0x00 +#define AMDSB_WD_RUN 0x01 +#define AMDSB_WD_FIRED 0x02 +#define AMDSB_WD_SHUTDOWN 0x04 +#define AMDSB_WD_DISABLE 0x08 +#define AMDSB_WD_RESERVED 0x70 +#define AMDSB_WD_RELOAD 0x80 +#define AMDSB_WD_COUNT 0x04 +#define AMDSB_WD_COUNT_MASK 0xffff +#define AMDSB_WDIO_REG_WIDTH 4 +/* WDRT */ +#define MAXCOUNT_MIN_VALUE 511 +/* RRG 2.3.1.1, page 122; SB600 RRG 2.3.1.1, page 97. */ +#define AMDSB7xx_SMBUS_DEVID 0x43851002 + +#define amdsbwd_verbose_printf(dev, ...) \ + do { \ + if (bootverbose) \ + device_printf(dev, __VA_ARGS__);\ + } while (0) + +struct amdsbwd_softc { + device_t dev; + eventhandler_tag ev_tag; + struct resource *res_ctrl; + struct resource *res_count; + int rid_ctrl; + int rid_count; + int ms_per_tick; + int max_ticks; + int active; + unsigned int timeout; +}; + +static void amdsbwd_identify(driver_t *driver, device_t parent); +static int amdsbwd_probe(device_t dev); +static int amdsbwd_attach(device_t dev); +static int amdsbwd_detach(device_t dev); + +static device_method_t amdsbwd_methods[] = { + DEVMETHOD(device_identify, amdsbwd_identify), + DEVMETHOD(device_probe, amdsbwd_probe), + DEVMETHOD(device_attach, amdsbwd_attach), + DEVMETHOD(device_detach, amdsbwd_detach), +#if 0 + DEVMETHOD(device_shutdown, amdsbwd_detach), +#endif + {0, 0} +}; + +static devclass_t amdsbwd_devclass; +static driver_t amdsbwd_driver = { + "amdsbwd", + amdsbwd_methods, + sizeof(struct amdsbwd_softc) +}; + +DRIVER_MODULE(amdsbwd, isa, amdsbwd_driver, amdsbwd_devclass, NULL, NULL); + + +static uint8_t +pmio_read(struct resource *res, uint8_t reg) +{ + bus_write_1(res, 0, reg); /* Index */ + return (bus_read_1(res, 1)); /* Data */ +} + +static void +pmio_write(struct resource *res, uint8_t reg, uint8_t val) +{ + bus_write_1(res, 0, reg); /* Index */ + bus_write_1(res, 1, val); /* Data */ +} + +static uint32_t +wdctrl_read(struct amdsbwd_softc *sc) +{ + return (bus_read_4(sc->res_ctrl, 0)); +} + +static void +wdctrl_write(struct amdsbwd_softc *sc, uint32_t val) +{ + bus_write_4(sc->res_ctrl, 0, val); +} + +static __unused uint32_t +wdcount_read(struct amdsbwd_softc *sc) +{ + return (bus_read_4(sc->res_count, 0)); +} + +static void +wdcount_write(struct amdsbwd_softc *sc, uint32_t val) +{ + bus_write_4(sc->res_count, 0, val); +} + +static void +amdsbwd_tmr_enable(struct amdsbwd_softc *sc) +{ + uint32_t val; + + val = wdctrl_read(sc); + val |= AMDSB_WD_RUN; + wdctrl_write(sc, val); + sc->active = 1; + amdsbwd_verbose_printf(sc->dev, "timer enabled\n"); +} + +static void +amdsbwd_tmr_disable(struct amdsbwd_softc *sc) +{ + uint32_t val; + + val = wdctrl_read(sc); + val &= ~AMDSB_WD_RUN; + wdctrl_write(sc, val); + sc->active = 0; + amdsbwd_verbose_printf(sc->dev, "timer disabled\n"); +} + +static void +amdsbwd_tmr_reload(struct amdsbwd_softc *sc) +{ + uint32_t val; + + val = wdctrl_read(sc); + val |= AMDSB_WD_RELOAD; + wdctrl_write(sc, val); +} + +static void +amdsbwd_tmr_set(struct amdsbwd_softc *sc, uint16_t timeout) +{ + + timeout &= AMDSB_WD_COUNT_MASK; + wdcount_write(sc, timeout); + sc->timeout = timeout; + amdsbwd_verbose_printf(sc->dev, "timeout set to %u ticks\n", timeout); +} + +static void +amdsbwd_event(void *arg, unsigned int cmd, int *error) +{ + struct amdsbwd_softc *sc = arg; + unsigned int timeout; + + /* convert from power-of-two-ns to WDT ticks */ + cmd &= WD_INTERVAL; + if (cmd < WD_TO_1SEC) + cmd = 0; + timeout = ((uint64_t)1 << (cmd - WD_TO_1MS)) / sc->ms_per_tick; + if (timeout > sc->max_ticks) + timeout = sc->max_ticks; + if (cmd) { + if (timeout != sc->timeout) { + amdsbwd_tmr_set(sc, timeout); + if (!sc->active) + amdsbwd_tmr_enable(sc); + } + amdsbwd_tmr_reload(sc); + *error = 0; + } else { + if (sc->active) + amdsbwd_tmr_disable(sc); + } +} + +static void +amdsbwd_identify(driver_t *driver, device_t parent) +{ + device_t child; + device_t smb_dev; + + if (resource_disabled("amdsbwd", 0)) + return; + if (device_find_child(parent, "amdsbwd", -1) != NULL) + return; + + /* + * Try to identify SB600/SB7xx by PCI Device ID of SMBus device + * that should be present at bus 0, device 20, function 0. + */ + smb_dev = pci_find_bsf(0, 20, 0); + if (smb_dev == NULL) + return; + if (pci_get_devid(smb_dev) != AMDSB7xx_SMBUS_DEVID) + return; + + child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "amdsbwd", -1); + if (child == NULL) + device_printf(parent, "add amdsbwd child failed\n"); +} + +static int +amdsbwd_probe(device_t dev) +{ + struct resource *res; + uint32_t addr; + uint32_t val; + int rid; + int rc; + int i; + + /* Do not claim some ISA PnP device by accident. */ + if (isa_get_logicalid(dev) != 0) + return (ENXIO); + + rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, AMDSB_PMIO_INDEX, + AMDSB_PMIO_WIDTH); + if (rc != 0) { + device_printf(dev, "bus_set_resource for IO failed\n"); + return (ENXIO); + } + rid = 0; + res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0ul, ~0ul, + AMDSB_PMIO_WIDTH, RF_ACTIVE | RF_SHAREABLE); + if (res == NULL) { + device_printf(dev, "bus_alloc_resource for IO failed\n"); + return (ENXIO); + } + + /* Report cause of previous reset for user's convenience. */ + val = pmio_read(res, AMDSB_PM_RESET_STATUS0); + if (val != 0) + amdsbwd_verbose_printf(dev, "ResetStatus0 = %#04x\n", val); + val = pmio_read(res, AMDSB_PM_RESET_STATUS1); + if (val != 0) + amdsbwd_verbose_printf(dev, "ResetStatus1 = %#04x\n", val); + if ((val & AMDSB_WD_RST_STS) != 0) + device_printf(dev, "Previous Reset was caused by Watchdog\n"); + + /* Find base address of memory mapped WDT registers. */ + for (addr = 0, i = 0; i < 4; i++) { + addr <<= 8; + addr |= pmio_read(res, AMDSB_PM_WDT_BASE_MSB - i); + } + amdsbwd_verbose_printf(dev, "memory base address = %#010x\n", addr); + rc = bus_set_resource(dev, SYS_RES_MEMORY, 0, addr + AMDSB_WD_CTRL, + AMDSB_WDIO_REG_WIDTH); + if (rc != 0) { + device_printf(dev, "bus_set_resource for control failed\n"); + return (ENXIO); + } + rc = bus_set_resource(dev, SYS_RES_MEMORY, 1, addr + AMDSB_WD_COUNT, + AMDSB_WDIO_REG_WIDTH); + if (rc != 0) { + device_printf(dev, "bus_set_resource for count failed\n"); + return (ENXIO); + } + + /* Set watchdog timer tick to 10ms. */ + val = pmio_read(res, AMDSB_PM_WDT_CTRL); + val &= ~AMDSB_WDT_RES_MASK; + val |= AMDSB_WDT_RES_10MS; + pmio_write(res, AMDSB_PM_WDT_CTRL, val); + + /* Enable watchdog device (in stopped state). */ + val = pmio_read(res, AMDSB_PM_WDT_CTRL); + val &= ~AMDSB_WDT_DISABLE; + pmio_write(res, AMDSB_PM_WDT_CTRL, val); + + /* + * XXX TODO: Ensure that watchdog decode is enabled + * (register 0x41, bit 3). + */ + bus_release_resource(dev, SYS_RES_IOPORT, rid, res); + bus_delete_resource(dev, SYS_RES_IOPORT, rid); + + device_set_desc(dev, "AMD SB600/SB7xx Watchdog Timer"); + return (0); +} + +static int +amdsbwd_attach_sb(device_t dev, struct amdsbwd_softc *sc) +{ + sc->max_ticks = UINT16_MAX; + sc->ms_per_tick = 10; + sc->rid_ctrl = 0; + sc->rid_count = 1; + + sc->res_ctrl = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->rid_ctrl, RF_ACTIVE); + if (sc->res_ctrl == NULL) { + device_printf(dev, "bus_alloc_resource for ctrl failed\n"); + return (ENXIO); + } + sc->res_count = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->rid_count, RF_ACTIVE); + if (sc->res_count == NULL) { + device_printf(dev, "bus_alloc_resource for count failed\n"); + return (ENXIO); + } + return (0); +} + +static int +amdsbwd_attach(device_t dev) +{ + struct amdsbwd_softc *sc; + int rc; + + sc = device_get_softc(dev); + sc->dev = dev; + + rc = amdsbwd_attach_sb(dev, sc); + if (rc != 0) + goto fail; + + /* Setup initial state of Watchdog Control. */ + wdctrl_write(sc, AMDSB_WD_FIRED); + + if (wdctrl_read(sc) & AMDSB_WD_DISABLE) { + device_printf(dev, "watchdog hardware is disabled\n"); + goto fail; + } + + sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, amdsbwd_event, sc, + EVENTHANDLER_PRI_ANY); + + return (0); + +fail: + amdsbwd_detach(dev); + return (ENXIO); +} + +static int +amdsbwd_detach(device_t dev) +{ + struct amdsbwd_softc *sc; + + sc = device_get_softc(dev); + if (sc->ev_tag != NULL) + EVENTHANDLER_DEREGISTER(watchdog_list, sc->ev_tag); + + if (sc->active) + amdsbwd_tmr_disable(sc); + + if (sc->res_ctrl != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ctrl, + sc->res_ctrl); + + if (sc->res_count != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_count, + sc->res_count); + + return (0); +} + Modified: head/sys/i386/conf/NOTES ============================================================================== --- head/sys/i386/conf/NOTES Mon Nov 30 11:11:08 2009 (r199968) +++ head/sys/i386/conf/NOTES Mon Nov 30 11:44:03 2009 (r199969) @@ -785,8 +785,10 @@ hint.pcf.0.irq="5" # Hardware watchdog timers: # # ichwd: Intel ICH watchdog timer +# amdsbwd: AMD SB7xx watchdog timer # device ichwd +device amdsbwd # # Temperature sensors: Modified: head/sys/modules/Makefile ============================================================================== --- head/sys/modules/Makefile Mon Nov 30 11:11:08 2009 (r199968) +++ head/sys/modules/Makefile Mon Nov 30 11:44:03 2009 (r199969) @@ -21,6 +21,7 @@ SUBDIR= ${_3dfx} \ alc \ ale \ ${_amd} \ + ${_amdsbwd} \ ${_amdtemp} \ amr \ ${_an} \ @@ -416,6 +417,7 @@ _zfs= zfs _aac= aac _acpi= acpi _ahb= ahb +_amdsbwd= amdsbwd _amdtemp= amdtemp _arcmsr= arcmsr _asmc= asmc @@ -472,6 +474,7 @@ _aac= aac _acpi= acpi _agp= agp _an= an +_amdsbwd= amdsbwd _amdtemp= amdtemp _arcmsr= arcmsr _asmc= asmc Added: head/sys/modules/amdsbwd/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/modules/amdsbwd/Makefile Mon Nov 30 11:44:03 2009 (r199969) @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/amdsbwd +KMOD = amdsbwd +SRCS = amdsbwd.c +SRCS += device_if.h bus_if.h pci_if.h isa_if.h + +.include