Home | History | Annotate | Line # | Download | only in pci
ichlpcib.c revision 1.43.4.5.2.1
      1  1.43.4.5.2.1     skrll /*	$NetBSD: ichlpcib.c,v 1.43.4.5.2.1 2017/01/18 08:46:26 skrll Exp $	*/
      2           1.1   xtraeme 
      3           1.1   xtraeme /*-
      4           1.1   xtraeme  * Copyright (c) 2004 The NetBSD Foundation, Inc.
      5           1.1   xtraeme  * All rights reserved.
      6           1.1   xtraeme  *
      7           1.1   xtraeme  * This code is derived from software contributed to The NetBSD Foundation
      8           1.1   xtraeme  * by Minoura Makoto and Matthew R. Green.
      9           1.1   xtraeme  *
     10           1.1   xtraeme  * Redistribution and use in source and binary forms, with or without
     11           1.1   xtraeme  * modification, are permitted provided that the following conditions
     12           1.1   xtraeme  * are met:
     13           1.1   xtraeme  * 1. Redistributions of source code must retain the above copyright
     14           1.1   xtraeme  *    notice, this list of conditions and the following disclaimer.
     15           1.1   xtraeme  * 2. Redistributions in binary form must reproduce the above copyright
     16           1.1   xtraeme  *    notice, this list of conditions and the following disclaimer in the
     17           1.1   xtraeme  *    documentation and/or other materials provided with the distribution.
     18           1.1   xtraeme  *
     19           1.1   xtraeme  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20           1.1   xtraeme  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21           1.1   xtraeme  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22           1.1   xtraeme  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23           1.1   xtraeme  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24           1.1   xtraeme  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25           1.1   xtraeme  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26           1.1   xtraeme  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27           1.1   xtraeme  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28           1.1   xtraeme  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29           1.1   xtraeme  * POSSIBILITY OF SUCH DAMAGE.
     30           1.1   xtraeme  */
     31           1.1   xtraeme 
     32           1.1   xtraeme /*
     33           1.1   xtraeme  * Intel I/O Controller Hub (ICHn) LPC Interface Bridge driver
     34           1.1   xtraeme  *
     35           1.1   xtraeme  *  LPC Interface Bridge is basically a pcib (PCI-ISA Bridge), but has
     36           1.1   xtraeme  *  some power management and monitoring functions.
     37           1.1   xtraeme  *  Currently we support the watchdog timer, SpeedStep (on some systems)
     38           1.1   xtraeme  *  and the power management timer.
     39           1.1   xtraeme  */
     40           1.1   xtraeme 
     41           1.1   xtraeme #include <sys/cdefs.h>
     42  1.43.4.5.2.1     skrll __KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.43.4.5.2.1 2017/01/18 08:46:26 skrll Exp $");
     43           1.1   xtraeme 
     44           1.1   xtraeme #include <sys/types.h>
     45           1.1   xtraeme #include <sys/param.h>
     46           1.1   xtraeme #include <sys/systm.h>
     47           1.1   xtraeme #include <sys/device.h>
     48           1.1   xtraeme #include <sys/sysctl.h>
     49           1.6  jmcneill #include <sys/timetc.h>
     50          1.20  jakllsch #include <sys/gpio.h>
     51          1.32    dyoung #include <sys/bus.h>
     52           1.1   xtraeme 
     53           1.1   xtraeme #include <dev/pci/pcivar.h>
     54           1.1   xtraeme #include <dev/pci/pcireg.h>
     55           1.1   xtraeme #include <dev/pci/pcidevs.h>
     56           1.1   xtraeme 
     57          1.20  jakllsch #include <dev/gpio/gpiovar.h>
     58           1.1   xtraeme #include <dev/sysmon/sysmonvar.h>
     59           1.1   xtraeme 
     60           1.6  jmcneill #include <dev/ic/acpipmtimer.h>
     61           1.1   xtraeme #include <dev/ic/i82801lpcreg.h>
     62          1.31    jruoho #include <dev/ic/i82801lpcvar.h>
     63           1.6  jmcneill #include <dev/ic/hpetreg.h>
     64           1.6  jmcneill #include <dev/ic/hpetvar.h>
     65           1.6  jmcneill 
     66          1.12    martin #include "pcibvar.h"
     67          1.20  jakllsch #include "gpio.h"
     68          1.25  jakllsch #include "fwhrng.h"
     69          1.20  jakllsch 
     70          1.20  jakllsch #define LPCIB_GPIO_NPINS 64
     71           1.1   xtraeme 
     72           1.1   xtraeme struct lpcib_softc {
     73          1.12    martin 	/* we call pcibattach() which assumes this starts like this: */
     74          1.12    martin 	struct pcib_softc	sc_pcib;
     75           1.1   xtraeme 
     76           1.6  jmcneill 	struct pci_attach_args	sc_pa;
     77           1.6  jmcneill 	int			sc_has_rcba;
     78           1.6  jmcneill 	int			sc_has_ich5_hpet;
     79           1.6  jmcneill 
     80           1.6  jmcneill 	/* RCBA */
     81           1.6  jmcneill 	bus_space_tag_t		sc_rcbat;
     82           1.6  jmcneill 	bus_space_handle_t	sc_rcbah;
     83           1.6  jmcneill 	pcireg_t		sc_rcba_reg;
     84           1.6  jmcneill 
     85           1.1   xtraeme 	/* Watchdog variables. */
     86           1.1   xtraeme 	struct sysmon_wdog	sc_smw;
     87           1.1   xtraeme 	bus_space_tag_t		sc_iot;
     88           1.1   xtraeme 	bus_space_handle_t	sc_ioh;
     89          1.19    dyoung 	bus_size_t		sc_iosize;
     90           1.6  jmcneill 
     91           1.6  jmcneill 	/* HPET variables. */
     92           1.6  jmcneill 	uint32_t		sc_hpet_reg;
     93           1.6  jmcneill 
     94          1.20  jakllsch #if NGPIO > 0
     95          1.20  jakllsch 	device_t		sc_gpiobus;
     96          1.20  jakllsch 	kmutex_t		sc_gpio_mtx;
     97          1.20  jakllsch 	bus_space_tag_t		sc_gpio_iot;
     98          1.20  jakllsch 	bus_space_handle_t	sc_gpio_ioh;
     99          1.20  jakllsch 	bus_size_t		sc_gpio_ios;
    100          1.20  jakllsch 	struct gpio_chipset_tag	sc_gpio_gc;
    101          1.20  jakllsch 	gpio_pin_t		sc_gpio_pins[LPCIB_GPIO_NPINS];
    102          1.20  jakllsch #endif
    103          1.20  jakllsch 
    104          1.25  jakllsch #if NFWHRNG > 0
    105          1.25  jakllsch 	device_t		sc_fwhbus;
    106          1.25  jakllsch #endif
    107          1.25  jakllsch 
    108          1.16     joerg 	/* Speedstep */
    109          1.16     joerg 	pcireg_t		sc_pmcon_orig;
    110          1.16     joerg 
    111           1.1   xtraeme 	/* Power management */
    112           1.7  drochner 	pcireg_t		sc_pirq[2];
    113           1.6  jmcneill 	pcireg_t		sc_pmcon;
    114           1.6  jmcneill 	pcireg_t		sc_fwhsel2;
    115          1.19    dyoung 
    116          1.19    dyoung 	/* Child devices */
    117          1.19    dyoung 	device_t		sc_hpetbus;
    118          1.19    dyoung 	acpipmtimer_t		sc_pmtimer;
    119          1.19    dyoung 	pcireg_t		sc_acpi_cntl;
    120          1.19    dyoung 
    121          1.19    dyoung 	struct sysctllog	*sc_log;
    122           1.1   xtraeme };
    123           1.1   xtraeme 
    124           1.9   xtraeme static int lpcibmatch(device_t, cfdata_t, void *);
    125           1.9   xtraeme static void lpcibattach(device_t, device_t, void *);
    126          1.19    dyoung static int lpcibdetach(device_t, int);
    127          1.19    dyoung static void lpcibchilddet(device_t, device_t);
    128          1.19    dyoung static int lpcibrescan(device_t, const char *, const int *);
    129          1.24    dyoung static bool lpcib_suspend(device_t, const pmf_qual_t *);
    130          1.24    dyoung static bool lpcib_resume(device_t, const pmf_qual_t *);
    131          1.16     joerg static bool lpcib_shutdown(device_t, int);
    132           1.1   xtraeme 
    133           1.9   xtraeme static void pmtimer_configure(device_t);
    134          1.19    dyoung static int pmtimer_unconfigure(device_t, int);
    135           1.1   xtraeme 
    136           1.9   xtraeme static void tcotimer_configure(device_t);
    137          1.19    dyoung static int tcotimer_unconfigure(device_t, int);
    138           1.1   xtraeme static int tcotimer_setmode(struct sysmon_wdog *);
    139           1.1   xtraeme static int tcotimer_tickle(struct sysmon_wdog *);
    140           1.1   xtraeme static void tcotimer_stop(struct lpcib_softc *);
    141           1.1   xtraeme static void tcotimer_start(struct lpcib_softc *);
    142           1.1   xtraeme static void tcotimer_status_reset(struct lpcib_softc *);
    143           1.9   xtraeme static int  tcotimer_disable_noreboot(device_t);
    144           1.1   xtraeme 
    145           1.9   xtraeme static void speedstep_configure(device_t);
    146          1.19    dyoung static void speedstep_unconfigure(device_t);
    147           1.1   xtraeme static int speedstep_sysctl_helper(SYSCTLFN_ARGS);
    148           1.1   xtraeme 
    149           1.9   xtraeme static void lpcib_hpet_configure(device_t);
    150          1.19    dyoung static int lpcib_hpet_unconfigure(device_t, int);
    151           1.6  jmcneill 
    152          1.20  jakllsch #if NGPIO > 0
    153          1.20  jakllsch static void lpcib_gpio_configure(device_t);
    154          1.20  jakllsch static int lpcib_gpio_unconfigure(device_t, int);
    155          1.20  jakllsch static int lpcib_gpio_pin_read(void *, int);
    156          1.20  jakllsch static void lpcib_gpio_pin_write(void *, int, int);
    157          1.20  jakllsch static void lpcib_gpio_pin_ctl(void *, int, int);
    158          1.20  jakllsch #endif
    159          1.20  jakllsch 
    160          1.25  jakllsch #if NFWHRNG > 0
    161          1.25  jakllsch static void lpcib_fwh_configure(device_t);
    162          1.25  jakllsch static int lpcib_fwh_unconfigure(device_t, int);
    163          1.25  jakllsch #endif
    164          1.25  jakllsch 
    165           1.1   xtraeme struct lpcib_softc *speedstep_cookie;	/* XXX */
    166           1.1   xtraeme 
    167          1.19    dyoung CFATTACH_DECL2_NEW(ichlpcib, sizeof(struct lpcib_softc),
    168          1.19    dyoung     lpcibmatch, lpcibattach, lpcibdetach, NULL, lpcibrescan, lpcibchilddet);
    169           1.1   xtraeme 
    170           1.6  jmcneill static struct lpcib_device {
    171           1.6  jmcneill 	pcireg_t vendor, product;
    172           1.6  jmcneill 	int has_rcba;
    173           1.6  jmcneill 	int has_ich5_hpet;
    174           1.6  jmcneill } lpcib_devices[] = {
    175          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_LPC, 1, 0 },
    176          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3420_LPC, 1, 0 },
    177          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3450_LPC, 1, 0 },
    178          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6300ESB_LPC, 1, 0 },
    179          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_63XXESB_LPC, 1, 0 },
    180           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_LPC, 0, 0 },
    181          1.27  jakllsch 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_LPC, 0, 0 },
    182           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_LPC, 0, 0 },
    183           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BAM_LPC, 0, 0 },
    184           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_LPC, 0, 0 },
    185           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CAM_LPC, 0, 0 },
    186           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_LPC, 0, 0 },
    187          1.30   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DBM_LPC, 0, 0 },
    188          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801E_LPC, 0, 1 },
    189           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_LPC, 0, 1 },
    190           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FB_LPC, 1, 0 },
    191           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FBM_LPC, 1, 0 },
    192           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801G_LPC, 1, 0 },
    193           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GBM_LPC, 1, 0 },
    194          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GH_LPC, 1, 0 },
    195           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GHM_LPC, 1, 0 },
    196           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_LPC, 1, 0 },
    197           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HEM_LPC, 1, 0 },
    198           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HH_LPC, 1, 0 },
    199           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HO_LPC, 1, 0 },
    200           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801HBM_LPC, 1, 0 },
    201          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IB_LPC, 1, 0 },
    202           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IH_LPC, 1, 0 },
    203          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IM_LPC, 1, 0 },
    204           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IO_LPC, 1, 0 },
    205           1.6  jmcneill 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IR_LPC, 1, 0 },
    206          1.17     njoly 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801IEM_LPC, 1, 0 },
    207          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JD_LPC, 1, 0 },
    208          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JDO_LPC, 1, 0 },
    209          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JIB_LPC, 1, 0 },
    210          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JIR_LPC, 1, 0 },
    211          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C202_LPC, 1, 0 },
    212          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C204_LPC, 1, 0 },
    213          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C206_LPC, 1, 0 },
    214          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C216_LPC, 1, 0 },
    215          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_NM10_LPC, 1, 0 },
    216          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H55_LPC, 1, 0 },
    217          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H57_LPC, 1, 0 },
    218          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM55_LPC, 1, 0 },
    219          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM57_LPC, 1, 0 },
    220          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_P55_LPC, 1, 0 },
    221          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PM55_LPC, 1, 0 },
    222          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q57_LPC, 1, 0 },
    223          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QM57_LPC, 1, 0 },
    224          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QS57_LPC, 1, 0 },
    225          1.36   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_B65_LPC, 1, 0 },
    226          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H61_LPC, 1, 0 },
    227          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H67_LPC, 1, 0 },
    228          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM65_LPC, 1, 0 },
    229          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM67_LPC, 1, 0 },
    230          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_P67_LPC, 1, 0 },
    231          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q65_LPC, 1, 0 },
    232          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q67_LPC, 1, 0 },
    233          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QM67_LPC, 1, 0 },
    234          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QS67_LPC, 1, 0 },
    235          1.35   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_UM67_LPC, 1, 0 },
    236          1.43   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z68_LPC, 1, 0 },
    237          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_B75_LPC, 1, 0 },
    238          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H77_LPC, 1, 0 },
    239          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM70_LPC, 1, 0 },
    240          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM75_LPC, 1, 0 },
    241          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM76_LPC, 1, 0 },
    242          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_HM77_LPC, 1, 0 },
    243          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_QM77_LPC, 1, 0 },
    244          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_QS77_LPC, 1, 0 },
    245          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_MOBILE_UM77_LPC, 1, 0 },
    246          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_NM70_LPC, 1, 0 },
    247          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q75_LPC, 1, 0 },
    248          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q77_LPC, 1, 0 },
    249          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z75_LPC, 1, 0 },
    250          1.37   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z77_LPC, 1, 0 },
    251          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z87_LPC, 1, 0 },
    252          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z85_LPC, 1, 0 },
    253          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM86_LPC, 1, 0 },
    254          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H87_LPC, 1, 0 },
    255          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_HM87_LPC, 1, 0 },
    256          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q85_LPC, 1, 0 },
    257          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Q87_LPC, 1, 0 },
    258          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_QM87_LPC, 1, 0 },
    259          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_B85_LPC, 1, 0 },
    260      1.43.4.4       snj 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H97_LPC, 1, 0 },
    261      1.43.4.4       snj 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_Z97_LPC, 1, 0 },
    262      1.43.4.4       snj 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X99_LPC, 1, 0 },
    263      1.43.4.4       snj 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X99_LPC_2, 1, 0 },
    264  1.43.4.5.2.1     skrll 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE5G_M_LPC_4, 1, 0 },
    265  1.43.4.5.2.1     skrll 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE5G_M_LPC_7, 1, 0 },
    266          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C222_LPC, 1, 0 },
    267          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C224_LPC, 1, 0 },
    268          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C226_LPC, 1, 0 },
    269          1.39   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_H81_LPC, 1, 0 },
    270          1.38  riastrad 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_LPC, 1, 0 },
    271      1.43.4.3    martin 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_DH89XXCC_LPC, 1, 0 },
    272      1.43.4.3    martin 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_DH89XXCL_LPC, 1, 0 },
    273          1.42   msaitoh #if 0
    274          1.41   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_1, 1, 0 },
    275          1.41   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_2, 1, 0 },
    276          1.41   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_3, 1, 0 },
    277          1.41   msaitoh 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C2000_PCU_4, 1, 0 },
    278          1.42   msaitoh #endif
    279          1.14     joerg 
    280           1.6  jmcneill 	{ 0, 0, 0, 0 },
    281           1.6  jmcneill };
    282           1.6  jmcneill 
    283           1.1   xtraeme /*
    284      1.43.4.5       snj  * Allow user to enable GPIO functionality if they really need it.  The
    285      1.43.4.5       snj  * vast majority of systems with an ICH should not expose GPIO to the
    286      1.43.4.5       snj  * kernel or user.  In at least one instance the gpio_resume() handler
    287      1.43.4.5       snj  * on ICH GPIO was found to sabotage S3 suspend/resume.
    288      1.43.4.5       snj  */
    289      1.43.4.5       snj int	ichlpcib_gpio_disable = 1;
    290      1.43.4.5       snj 
    291      1.43.4.5       snj /*
    292           1.1   xtraeme  * Autoconf callbacks.
    293           1.1   xtraeme  */
    294           1.1   xtraeme static int
    295           1.9   xtraeme lpcibmatch(device_t parent, cfdata_t match, void *aux)
    296           1.1   xtraeme {
    297           1.1   xtraeme 	struct pci_attach_args *pa = aux;
    298           1.6  jmcneill 	struct lpcib_device *lpcib_dev;
    299           1.1   xtraeme 
    300           1.1   xtraeme 	/* We are ISA bridge, of course */
    301           1.1   xtraeme 	if (PCI_CLASS(pa->pa_class) != PCI_CLASS_BRIDGE ||
    302           1.1   xtraeme 	    PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_BRIDGE_ISA)
    303           1.1   xtraeme 		return 0;
    304           1.1   xtraeme 
    305           1.6  jmcneill 	for (lpcib_dev = lpcib_devices; lpcib_dev->vendor; ++lpcib_dev) {
    306           1.6  jmcneill 		if (PCI_VENDOR(pa->pa_id) == lpcib_dev->vendor &&
    307           1.6  jmcneill 		    PCI_PRODUCT(pa->pa_id) == lpcib_dev->product)
    308           1.1   xtraeme 			return 10;
    309           1.1   xtraeme 	}
    310           1.1   xtraeme 
    311           1.1   xtraeme 	return 0;
    312           1.1   xtraeme }
    313           1.1   xtraeme 
    314           1.1   xtraeme static void
    315           1.9   xtraeme lpcibattach(device_t parent, device_t self, void *aux)
    316           1.1   xtraeme {
    317           1.1   xtraeme 	struct pci_attach_args *pa = aux;
    318           1.6  jmcneill 	struct lpcib_softc *sc = device_private(self);
    319           1.6  jmcneill 	struct lpcib_device *lpcib_dev;
    320      1.43.4.2    martin 	pcireg_t pmbase;
    321           1.1   xtraeme 
    322           1.6  jmcneill 	sc->sc_pa = *pa;
    323           1.6  jmcneill 
    324           1.6  jmcneill 	for (lpcib_dev = lpcib_devices; lpcib_dev->vendor; ++lpcib_dev) {
    325           1.6  jmcneill 		if (PCI_VENDOR(pa->pa_id) != lpcib_dev->vendor ||
    326           1.6  jmcneill 		    PCI_PRODUCT(pa->pa_id) != lpcib_dev->product)
    327           1.6  jmcneill 			continue;
    328           1.6  jmcneill 		sc->sc_has_rcba = lpcib_dev->has_rcba;
    329           1.6  jmcneill 		sc->sc_has_ich5_hpet = lpcib_dev->has_ich5_hpet;
    330           1.6  jmcneill 		break;
    331           1.6  jmcneill 	}
    332           1.1   xtraeme 
    333           1.1   xtraeme 	pcibattach(parent, self, aux);
    334           1.1   xtraeme 
    335           1.1   xtraeme 	/*
    336           1.1   xtraeme 	 * Part of our I/O registers are used as ACPI PM regs.
    337           1.1   xtraeme 	 * Since our ACPI subsystem accesses the I/O space directly so far,
    338           1.1   xtraeme 	 * we do not have to bother bus_space I/O map confliction.
    339      1.43.4.1    martin 	 *
    340      1.43.4.1    martin 	 * The PMBASE register is alike PCI BAR but not completely compatible
    341      1.43.4.1    martin 	 * with it. The PMBASE define the base address and the type but
    342      1.43.4.2    martin 	 * not describe the size. The value of the register may be lower
    343      1.43.4.2    martin 	 * than LPCIB_PCI_PM_SIZE. It makes impossible to use
    344      1.43.4.2    martin 	 * pci_mapreg_submap() because the function does range check.
    345           1.1   xtraeme 	 */
    346      1.43.4.2    martin 	sc->sc_iot = pa->pa_iot;
    347      1.43.4.2    martin 	pmbase = pci_conf_read(pa->pa_pc, pa->pa_tag, LPCIB_PCI_PMBASE);
    348      1.43.4.2    martin 	if (bus_space_map(sc->sc_iot, PCI_MAPREG_IO_ADDR(pmbase),
    349      1.43.4.2    martin 	    LPCIB_PCI_PM_SIZE, 0, &sc->sc_ioh) != 0) {
    350      1.43.4.2    martin 		aprint_error_dev(self,
    351      1.43.4.2    martin 	    	"can't map power management i/o space\n");
    352           1.1   xtraeme 		return;
    353           1.1   xtraeme 	}
    354           1.1   xtraeme 
    355          1.16     joerg 	sc->sc_pmcon_orig = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    356          1.16     joerg 	    LPCIB_PCI_GEN_PMCON_1);
    357          1.16     joerg 
    358           1.6  jmcneill 	/* For ICH6 and later, always enable RCBA */
    359           1.6  jmcneill 	if (sc->sc_has_rcba) {
    360           1.6  jmcneill 		pcireg_t rcba;
    361           1.6  jmcneill 
    362           1.6  jmcneill 		sc->sc_rcbat = sc->sc_pa.pa_memt;
    363           1.6  jmcneill 
    364          1.12    martin 		rcba = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    365          1.12    martin 		     LPCIB_RCBA);
    366           1.6  jmcneill 		if ((rcba & LPCIB_RCBA_EN) == 0) {
    367          1.40  jakllsch 			aprint_error_dev(self, "RCBA is not enabled\n");
    368           1.6  jmcneill 			return;
    369           1.6  jmcneill 		}
    370           1.6  jmcneill 		rcba &= ~LPCIB_RCBA_EN;
    371           1.6  jmcneill 
    372           1.6  jmcneill 		if (bus_space_map(sc->sc_rcbat, rcba, LPCIB_RCBA_SIZE, 0,
    373           1.6  jmcneill 				  &sc->sc_rcbah)) {
    374          1.40  jakllsch 			aprint_error_dev(self, "RCBA could not be mapped\n");
    375           1.6  jmcneill 			return;
    376           1.6  jmcneill 		}
    377           1.6  jmcneill 	}
    378           1.6  jmcneill 
    379           1.1   xtraeme 	/* Set up the power management timer. */
    380           1.9   xtraeme 	pmtimer_configure(self);
    381           1.1   xtraeme 
    382           1.1   xtraeme 	/* Set up the TCO (watchdog). */
    383           1.9   xtraeme 	tcotimer_configure(self);
    384           1.1   xtraeme 
    385           1.1   xtraeme 	/* Set up SpeedStep. */
    386           1.9   xtraeme 	speedstep_configure(self);
    387           1.1   xtraeme 
    388           1.6  jmcneill 	/* Set up HPET. */
    389           1.9   xtraeme 	lpcib_hpet_configure(self);
    390           1.6  jmcneill 
    391          1.20  jakllsch #if NGPIO > 0
    392          1.20  jakllsch 	/* Set up GPIO */
    393          1.20  jakllsch 	lpcib_gpio_configure(self);
    394          1.20  jakllsch #endif
    395          1.20  jakllsch 
    396          1.25  jakllsch #if NFWHRNG > 0
    397          1.25  jakllsch 	lpcib_fwh_configure(self);
    398          1.25  jakllsch #endif
    399          1.25  jakllsch 
    400           1.6  jmcneill 	/* Install power handler */
    401          1.16     joerg 	if (!pmf_device_register1(self, lpcib_suspend, lpcib_resume,
    402          1.16     joerg 	    lpcib_shutdown))
    403           1.6  jmcneill 		aprint_error_dev(self, "couldn't establish power handler\n");
    404           1.6  jmcneill }
    405           1.6  jmcneill 
    406          1.19    dyoung static void
    407          1.19    dyoung lpcibchilddet(device_t self, device_t child)
    408          1.19    dyoung {
    409          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
    410          1.19    dyoung 	uint32_t val;
    411          1.19    dyoung 
    412          1.25  jakllsch #if NFWHRNG > 0
    413          1.25  jakllsch 	if (sc->sc_fwhbus == child) {
    414          1.25  jakllsch 		sc->sc_fwhbus = NULL;
    415          1.25  jakllsch 		return;
    416          1.25  jakllsch 	}
    417          1.25  jakllsch #endif
    418          1.21  jakllsch #if NGPIO > 0
    419          1.20  jakllsch 	if (sc->sc_gpiobus == child) {
    420          1.20  jakllsch 		sc->sc_gpiobus = NULL;
    421          1.20  jakllsch 		return;
    422          1.20  jakllsch 	}
    423          1.21  jakllsch #endif
    424          1.19    dyoung 	if (sc->sc_hpetbus != child) {
    425          1.19    dyoung 		pcibchilddet(self, child);
    426          1.19    dyoung 		return;
    427          1.19    dyoung 	}
    428          1.19    dyoung 	sc->sc_hpetbus = NULL;
    429          1.19    dyoung 	if (sc->sc_has_ich5_hpet) {
    430          1.19    dyoung 		val = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    431          1.19    dyoung 		    LPCIB_PCI_GEN_CNTL);
    432          1.19    dyoung 		switch (val & LPCIB_ICH5_HPTC_WIN_MASK) {
    433          1.19    dyoung 		case LPCIB_ICH5_HPTC_0000:
    434          1.19    dyoung 		case LPCIB_ICH5_HPTC_1000:
    435          1.19    dyoung 		case LPCIB_ICH5_HPTC_2000:
    436          1.19    dyoung 		case LPCIB_ICH5_HPTC_3000:
    437          1.19    dyoung 			break;
    438          1.19    dyoung 		default:
    439          1.19    dyoung 			return;
    440          1.19    dyoung 		}
    441          1.19    dyoung 		val &= ~LPCIB_ICH5_HPTC_EN;
    442          1.19    dyoung 		pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    443          1.19    dyoung 		    LPCIB_PCI_GEN_CNTL, val);
    444          1.19    dyoung 	} else if (sc->sc_has_rcba) {
    445          1.19    dyoung 		val = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah,
    446          1.19    dyoung 		    LPCIB_RCBA_HPTC);
    447          1.19    dyoung 		switch (val & LPCIB_RCBA_HPTC_WIN_MASK) {
    448          1.19    dyoung 		case LPCIB_RCBA_HPTC_0000:
    449          1.19    dyoung 		case LPCIB_RCBA_HPTC_1000:
    450          1.19    dyoung 		case LPCIB_RCBA_HPTC_2000:
    451          1.19    dyoung 		case LPCIB_RCBA_HPTC_3000:
    452          1.19    dyoung 			break;
    453          1.19    dyoung 		default:
    454          1.19    dyoung 			return;
    455          1.19    dyoung 		}
    456          1.19    dyoung 		val &= ~LPCIB_RCBA_HPTC_EN;
    457          1.19    dyoung 		bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC,
    458          1.19    dyoung 		    val);
    459          1.19    dyoung 	}
    460          1.19    dyoung }
    461          1.19    dyoung 
    462          1.19    dyoung static int
    463          1.19    dyoung lpcibrescan(device_t self, const char *ifattr, const int *locators)
    464          1.19    dyoung {
    465          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
    466          1.19    dyoung 
    467          1.25  jakllsch #if NFWHRNG > 0
    468          1.25  jakllsch 	if (ifattr_match(ifattr, "fwhichbus") && sc->sc_fwhbus == NULL)
    469          1.25  jakllsch 		lpcib_fwh_configure(self);
    470          1.25  jakllsch #endif
    471          1.25  jakllsch 
    472          1.19    dyoung 	if (ifattr_match(ifattr, "hpetichbus") && sc->sc_hpetbus == NULL)
    473          1.19    dyoung 		lpcib_hpet_configure(self);
    474          1.19    dyoung 
    475          1.20  jakllsch #if NGPIO > 0
    476          1.20  jakllsch 	if (ifattr_match(ifattr, "gpiobus") && sc->sc_gpiobus == NULL)
    477          1.20  jakllsch 		lpcib_gpio_configure(self);
    478          1.20  jakllsch #endif
    479          1.20  jakllsch 
    480          1.19    dyoung 	return pcibrescan(self, ifattr, locators);
    481          1.19    dyoung }
    482          1.19    dyoung 
    483          1.19    dyoung static int
    484          1.19    dyoung lpcibdetach(device_t self, int flags)
    485          1.19    dyoung {
    486          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
    487          1.19    dyoung 	int rc;
    488          1.19    dyoung 
    489          1.19    dyoung 	pmf_device_deregister(self);
    490          1.19    dyoung 
    491          1.25  jakllsch #if NFWHRNG > 0
    492          1.25  jakllsch 	if ((rc = lpcib_fwh_unconfigure(self, flags)) != 0)
    493          1.25  jakllsch 		return rc;
    494          1.25  jakllsch #endif
    495          1.25  jakllsch 
    496          1.19    dyoung 	if ((rc = lpcib_hpet_unconfigure(self, flags)) != 0)
    497          1.19    dyoung 		return rc;
    498          1.19    dyoung 
    499          1.20  jakllsch #if NGPIO > 0
    500          1.20  jakllsch 	if ((rc = lpcib_gpio_unconfigure(self, flags)) != 0)
    501          1.20  jakllsch 		return rc;
    502          1.20  jakllsch #endif
    503          1.20  jakllsch 
    504          1.19    dyoung 	/* Set up SpeedStep. */
    505          1.19    dyoung 	speedstep_unconfigure(self);
    506          1.19    dyoung 
    507          1.19    dyoung 	if ((rc = tcotimer_unconfigure(self, flags)) != 0)
    508          1.19    dyoung 		return rc;
    509          1.19    dyoung 
    510          1.19    dyoung 	if ((rc = pmtimer_unconfigure(self, flags)) != 0)
    511          1.19    dyoung 		return rc;
    512          1.19    dyoung 
    513          1.19    dyoung 	if (sc->sc_has_rcba)
    514          1.19    dyoung 		bus_space_unmap(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_SIZE);
    515          1.19    dyoung 
    516          1.19    dyoung 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize);
    517          1.19    dyoung 
    518          1.19    dyoung 	return pcibdetach(self, flags);
    519          1.19    dyoung }
    520          1.19    dyoung 
    521           1.6  jmcneill static bool
    522          1.16     joerg lpcib_shutdown(device_t dv, int howto)
    523          1.16     joerg {
    524          1.16     joerg 	struct lpcib_softc *sc = device_private(dv);
    525          1.16     joerg 
    526          1.16     joerg 	pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    527          1.16     joerg 	    LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig);
    528          1.16     joerg 
    529          1.16     joerg 	return true;
    530          1.16     joerg }
    531          1.16     joerg 
    532          1.16     joerg static bool
    533          1.24    dyoung lpcib_suspend(device_t dv, const pmf_qual_t *qual)
    534           1.6  jmcneill {
    535           1.6  jmcneill 	struct lpcib_softc *sc = device_private(dv);
    536          1.12    martin 	pci_chipset_tag_t pc = sc->sc_pcib.sc_pc;
    537          1.12    martin 	pcitag_t tag = sc->sc_pcib.sc_tag;
    538           1.6  jmcneill 
    539           1.6  jmcneill 	/* capture PIRQ routing control registers */
    540           1.6  jmcneill 	sc->sc_pirq[0] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQA_ROUT);
    541           1.7  drochner 	sc->sc_pirq[1] = pci_conf_read(pc, tag, LPCIB_PCI_PIRQE_ROUT);
    542           1.6  jmcneill 
    543           1.6  jmcneill 	sc->sc_pmcon = pci_conf_read(pc, tag, LPCIB_PCI_GEN_PMCON_1);
    544           1.6  jmcneill 	sc->sc_fwhsel2 = pci_conf_read(pc, tag, LPCIB_PCI_GEN_STA);
    545           1.6  jmcneill 
    546           1.6  jmcneill 	if (sc->sc_has_rcba) {
    547           1.6  jmcneill 		sc->sc_rcba_reg = pci_conf_read(pc, tag, LPCIB_RCBA);
    548           1.6  jmcneill 		sc->sc_hpet_reg = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah,
    549           1.6  jmcneill 		    LPCIB_RCBA_HPTC);
    550           1.6  jmcneill 	} else if (sc->sc_has_ich5_hpet) {
    551           1.6  jmcneill 		sc->sc_hpet_reg = pci_conf_read(pc, tag, LPCIB_PCI_GEN_CNTL);
    552           1.6  jmcneill 	}
    553           1.6  jmcneill 
    554           1.6  jmcneill 	return true;
    555           1.6  jmcneill }
    556           1.6  jmcneill 
    557           1.6  jmcneill static bool
    558          1.24    dyoung lpcib_resume(device_t dv, const pmf_qual_t *qual)
    559           1.6  jmcneill {
    560           1.6  jmcneill 	struct lpcib_softc *sc = device_private(dv);
    561          1.12    martin 	pci_chipset_tag_t pc = sc->sc_pcib.sc_pc;
    562          1.12    martin 	pcitag_t tag = sc->sc_pcib.sc_tag;
    563           1.6  jmcneill 
    564           1.6  jmcneill 	/* restore PIRQ routing control registers */
    565           1.6  jmcneill 	pci_conf_write(pc, tag, LPCIB_PCI_PIRQA_ROUT, sc->sc_pirq[0]);
    566           1.7  drochner 	pci_conf_write(pc, tag, LPCIB_PCI_PIRQE_ROUT, sc->sc_pirq[1]);
    567           1.6  jmcneill 
    568           1.6  jmcneill 	pci_conf_write(pc, tag, LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon);
    569           1.6  jmcneill 	pci_conf_write(pc, tag, LPCIB_PCI_GEN_STA, sc->sc_fwhsel2);
    570           1.6  jmcneill 
    571           1.6  jmcneill 	if (sc->sc_has_rcba) {
    572           1.6  jmcneill 		pci_conf_write(pc, tag, LPCIB_RCBA, sc->sc_rcba_reg);
    573           1.6  jmcneill 		bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC,
    574           1.6  jmcneill 		    sc->sc_hpet_reg);
    575           1.6  jmcneill 	} else if (sc->sc_has_ich5_hpet) {
    576           1.6  jmcneill 		pci_conf_write(pc, tag, LPCIB_PCI_GEN_CNTL, sc->sc_hpet_reg);
    577           1.6  jmcneill 	}
    578           1.1   xtraeme 
    579           1.6  jmcneill 	return true;
    580           1.1   xtraeme }
    581           1.1   xtraeme 
    582           1.1   xtraeme /*
    583           1.1   xtraeme  * Initialize the power management timer.
    584           1.1   xtraeme  */
    585           1.1   xtraeme static void
    586           1.9   xtraeme pmtimer_configure(device_t self)
    587           1.1   xtraeme {
    588           1.9   xtraeme 	struct lpcib_softc *sc = device_private(self);
    589           1.1   xtraeme 	pcireg_t control;
    590           1.1   xtraeme 
    591           1.1   xtraeme 	/*
    592           1.1   xtraeme 	 * Check if power management I/O space is enabled and enable the ACPI_EN
    593           1.1   xtraeme 	 * bit if it's disabled.
    594           1.1   xtraeme 	 */
    595          1.12    martin 	control = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    596          1.12    martin 	    LPCIB_PCI_ACPI_CNTL);
    597          1.19    dyoung 	sc->sc_acpi_cntl = control;
    598           1.1   xtraeme 	if ((control & LPCIB_PCI_ACPI_CNTL_EN) == 0) {
    599           1.1   xtraeme 		control |= LPCIB_PCI_ACPI_CNTL_EN;
    600          1.12    martin 		pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    601          1.12    martin 		    LPCIB_PCI_ACPI_CNTL, control);
    602           1.1   xtraeme 	}
    603           1.1   xtraeme 
    604           1.1   xtraeme 	/* Attach our PM timer with the generic acpipmtimer function */
    605          1.19    dyoung 	sc->sc_pmtimer = acpipmtimer_attach(self, sc->sc_iot, sc->sc_ioh,
    606           1.1   xtraeme 	    LPCIB_PM1_TMR, 0);
    607           1.1   xtraeme }
    608           1.1   xtraeme 
    609          1.19    dyoung static int
    610          1.19    dyoung pmtimer_unconfigure(device_t self, int flags)
    611          1.19    dyoung {
    612          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
    613          1.19    dyoung 	int rc;
    614          1.19    dyoung 
    615          1.19    dyoung 	if (sc->sc_pmtimer != NULL &&
    616          1.19    dyoung 	    (rc = acpipmtimer_detach(sc->sc_pmtimer, flags)) != 0)
    617          1.19    dyoung 		return rc;
    618          1.19    dyoung 
    619          1.19    dyoung 	pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    620          1.19    dyoung 	    LPCIB_PCI_ACPI_CNTL, sc->sc_acpi_cntl);
    621          1.19    dyoung 
    622          1.19    dyoung 	return 0;
    623          1.19    dyoung }
    624          1.19    dyoung 
    625           1.1   xtraeme /*
    626           1.1   xtraeme  * Initialize the watchdog timer.
    627           1.1   xtraeme  */
    628           1.1   xtraeme static void
    629           1.9   xtraeme tcotimer_configure(device_t self)
    630           1.1   xtraeme {
    631           1.9   xtraeme 	struct lpcib_softc *sc = device_private(self);
    632           1.1   xtraeme 	uint32_t ioreg;
    633           1.1   xtraeme 	unsigned int period;
    634           1.1   xtraeme 
    635          1.13      yamt 	/* Explicitly stop the TCO timer. */
    636          1.13      yamt 	tcotimer_stop(sc);
    637          1.13      yamt 
    638          1.13      yamt 	/*
    639          1.13      yamt 	 * Enable TCO timeout SMI only if the hardware reset does not
    640          1.13      yamt 	 * work. We don't know what the SMBIOS does.
    641          1.13      yamt 	 */
    642          1.13      yamt 	ioreg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LPCIB_SMI_EN);
    643          1.13      yamt 	ioreg &= ~LPCIB_SMI_EN_TCO_EN;
    644          1.13      yamt 
    645           1.1   xtraeme 	/*
    646           1.4   xtraeme 	 * Clear the No Reboot (NR) bit. If this fails, enabling the TCO_EN bit
    647           1.1   xtraeme 	 * in the SMI_EN register is the last chance.
    648           1.1   xtraeme 	 */
    649           1.9   xtraeme 	if (tcotimer_disable_noreboot(self)) {
    650           1.1   xtraeme 		ioreg |= LPCIB_SMI_EN_TCO_EN;
    651          1.13      yamt 	}
    652          1.13      yamt 	if ((ioreg & LPCIB_SMI_EN_GBL_SMI_EN) != 0) {
    653           1.1   xtraeme 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, LPCIB_SMI_EN, ioreg);
    654           1.1   xtraeme 	}
    655           1.1   xtraeme 
    656           1.1   xtraeme 	/* Reset the watchdog status registers. */
    657           1.1   xtraeme 	tcotimer_status_reset(sc);
    658           1.1   xtraeme 
    659           1.1   xtraeme 	/*
    660           1.1   xtraeme 	 * Register the driver with the sysmon watchdog framework.
    661           1.1   xtraeme 	 */
    662           1.9   xtraeme 	sc->sc_smw.smw_name = device_xname(self);
    663           1.1   xtraeme 	sc->sc_smw.smw_cookie = sc;
    664           1.1   xtraeme 	sc->sc_smw.smw_setmode = tcotimer_setmode;
    665           1.1   xtraeme 	sc->sc_smw.smw_tickle = tcotimer_tickle;
    666           1.6  jmcneill 	if (sc->sc_has_rcba)
    667           1.1   xtraeme 		period = LPCIB_TCOTIMER2_MAX_TICK;
    668           1.1   xtraeme 	else
    669           1.1   xtraeme 		period = LPCIB_TCOTIMER_MAX_TICK;
    670           1.1   xtraeme 	sc->sc_smw.smw_period = lpcib_tcotimer_tick_to_second(period);
    671           1.1   xtraeme 
    672           1.1   xtraeme 	if (sysmon_wdog_register(&sc->sc_smw)) {
    673           1.9   xtraeme 		aprint_error_dev(self, "unable to register TCO timer"
    674           1.9   xtraeme 		       "as a sysmon watchdog device.\n");
    675           1.1   xtraeme 		return;
    676           1.1   xtraeme 	}
    677           1.1   xtraeme 
    678           1.9   xtraeme 	aprint_verbose_dev(self, "TCO (watchdog) timer configured.\n");
    679           1.1   xtraeme }
    680           1.1   xtraeme 
    681          1.19    dyoung static int
    682          1.19    dyoung tcotimer_unconfigure(device_t self, int flags)
    683          1.19    dyoung {
    684          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
    685          1.19    dyoung 	int rc;
    686          1.19    dyoung 
    687          1.19    dyoung 	if ((rc = sysmon_wdog_unregister(&sc->sc_smw)) != 0) {
    688          1.19    dyoung 		if (rc == ERESTART)
    689          1.19    dyoung 			rc = EINTR;
    690          1.19    dyoung 		return rc;
    691          1.19    dyoung 	}
    692          1.19    dyoung 
    693          1.19    dyoung 	/* Explicitly stop the TCO timer. */
    694          1.19    dyoung 	tcotimer_stop(sc);
    695          1.19    dyoung 
    696          1.19    dyoung 	/* XXX Set No Reboot? */
    697          1.19    dyoung 
    698          1.19    dyoung 	return 0;
    699          1.19    dyoung }
    700          1.19    dyoung 
    701          1.19    dyoung 
    702           1.1   xtraeme /*
    703           1.1   xtraeme  * Sysmon watchdog callbacks.
    704           1.1   xtraeme  */
    705           1.1   xtraeme static int
    706           1.1   xtraeme tcotimer_setmode(struct sysmon_wdog *smw)
    707           1.1   xtraeme {
    708           1.1   xtraeme 	struct lpcib_softc *sc = smw->smw_cookie;
    709           1.1   xtraeme 	unsigned int period;
    710           1.1   xtraeme 	uint16_t ich6period = 0;
    711          1.18    bouyer 	uint8_t ich5period = 0;
    712           1.1   xtraeme 
    713           1.1   xtraeme 	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
    714           1.1   xtraeme 		/* Stop the TCO timer. */
    715           1.1   xtraeme 		tcotimer_stop(sc);
    716           1.1   xtraeme 	} else {
    717           1.1   xtraeme 		/*
    718           1.6  jmcneill 		 * ICH6 or newer are limited to 2s min and 613s max.
    719           1.1   xtraeme 		 * ICH5 or older are limited to 4s min and 39s max.
    720           1.1   xtraeme 		 */
    721          1.18    bouyer 		period = lpcib_tcotimer_second_to_tick(smw->smw_period);
    722           1.6  jmcneill 		if (sc->sc_has_rcba) {
    723          1.18    bouyer 			if (period < LPCIB_TCOTIMER2_MIN_TICK ||
    724          1.18    bouyer 			    period > LPCIB_TCOTIMER2_MAX_TICK)
    725           1.6  jmcneill 				return EINVAL;
    726           1.6  jmcneill 		} else {
    727          1.18    bouyer 			if (period < LPCIB_TCOTIMER_MIN_TICK ||
    728          1.18    bouyer 			    period > LPCIB_TCOTIMER_MAX_TICK)
    729           1.1   xtraeme 				return EINVAL;
    730           1.1   xtraeme 		}
    731           1.5   xtraeme 
    732           1.1   xtraeme 		/* Stop the TCO timer, */
    733           1.1   xtraeme 		tcotimer_stop(sc);
    734           1.1   xtraeme 
    735           1.1   xtraeme 		/* set the timeout, */
    736           1.6  jmcneill 		if (sc->sc_has_rcba) {
    737           1.1   xtraeme 			/* ICH6 or newer */
    738           1.1   xtraeme 			ich6period = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
    739           1.1   xtraeme 						      LPCIB_TCO_TMR2);
    740           1.1   xtraeme 			ich6period &= 0xfc00;
    741           1.1   xtraeme 			bus_space_write_2(sc->sc_iot, sc->sc_ioh,
    742           1.1   xtraeme 					  LPCIB_TCO_TMR2, ich6period | period);
    743           1.1   xtraeme 		} else {
    744           1.1   xtraeme 			/* ICH5 or older */
    745          1.18    bouyer 			ich5period = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
    746           1.1   xtraeme 						   LPCIB_TCO_TMR);
    747          1.18    bouyer 			ich5period &= 0xc0;
    748           1.1   xtraeme 			bus_space_write_1(sc->sc_iot, sc->sc_ioh,
    749          1.18    bouyer 					  LPCIB_TCO_TMR, ich5period | period);
    750           1.1   xtraeme 		}
    751           1.1   xtraeme 
    752           1.1   xtraeme 		/* and start/reload the timer. */
    753           1.1   xtraeme 		tcotimer_start(sc);
    754           1.1   xtraeme 		tcotimer_tickle(smw);
    755           1.1   xtraeme 	}
    756           1.1   xtraeme 
    757           1.1   xtraeme 	return 0;
    758           1.1   xtraeme }
    759           1.1   xtraeme 
    760           1.1   xtraeme static int
    761           1.1   xtraeme tcotimer_tickle(struct sysmon_wdog *smw)
    762           1.1   xtraeme {
    763           1.1   xtraeme 	struct lpcib_softc *sc = smw->smw_cookie;
    764           1.1   xtraeme 
    765           1.1   xtraeme 	/* any value is allowed */
    766           1.6  jmcneill 	if (sc->sc_has_rcba)
    767           1.6  jmcneill 		bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO_RLD, 1);
    768           1.6  jmcneill 	else
    769           1.1   xtraeme 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_TCO_RLD, 1);
    770           1.1   xtraeme 
    771           1.1   xtraeme 	return 0;
    772           1.1   xtraeme }
    773           1.1   xtraeme 
    774           1.1   xtraeme static void
    775           1.1   xtraeme tcotimer_stop(struct lpcib_softc *sc)
    776           1.1   xtraeme {
    777           1.1   xtraeme 	uint16_t ioreg;
    778           1.1   xtraeme 
    779           1.1   xtraeme 	ioreg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT);
    780           1.1   xtraeme 	ioreg |= LPCIB_TCO1_CNT_TCO_TMR_HLT;
    781           1.1   xtraeme 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT, ioreg);
    782           1.1   xtraeme }
    783           1.1   xtraeme 
    784           1.1   xtraeme static void
    785           1.1   xtraeme tcotimer_start(struct lpcib_softc *sc)
    786           1.1   xtraeme {
    787           1.1   xtraeme 	uint16_t ioreg;
    788           1.1   xtraeme 
    789           1.1   xtraeme 	ioreg = bus_space_read_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT);
    790           1.1   xtraeme 	ioreg &= ~LPCIB_TCO1_CNT_TCO_TMR_HLT;
    791           1.1   xtraeme 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_CNT, ioreg);
    792           1.1   xtraeme }
    793           1.1   xtraeme 
    794           1.1   xtraeme static void
    795           1.1   xtraeme tcotimer_status_reset(struct lpcib_softc *sc)
    796           1.1   xtraeme {
    797           1.1   xtraeme 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO1_STS,
    798           1.1   xtraeme 			  LPCIB_TCO1_STS_TIMEOUT);
    799           1.1   xtraeme 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO2_STS,
    800           1.1   xtraeme 			  LPCIB_TCO2_STS_BOOT_STS);
    801           1.1   xtraeme 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, LPCIB_TCO2_STS,
    802           1.1   xtraeme 			  LPCIB_TCO2_STS_SECONDS_TO_STS);
    803           1.1   xtraeme }
    804           1.1   xtraeme 
    805           1.1   xtraeme /*
    806           1.4   xtraeme  * Clear the No Reboot (NR) bit, this enables reboots when the timer
    807           1.4   xtraeme  * reaches the timeout for the second time.
    808           1.1   xtraeme  */
    809           1.1   xtraeme static int
    810           1.9   xtraeme tcotimer_disable_noreboot(device_t self)
    811           1.1   xtraeme {
    812           1.9   xtraeme 	struct lpcib_softc *sc = device_private(self);
    813           1.1   xtraeme 
    814           1.6  jmcneill 	if (sc->sc_has_rcba) {
    815           1.6  jmcneill 		uint32_t status;
    816           1.6  jmcneill 
    817           1.9   xtraeme 		status = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah,
    818           1.9   xtraeme 		    LPCIB_GCS_OFFSET);
    819           1.6  jmcneill 		status &= ~LPCIB_GCS_NO_REBOOT;
    820           1.9   xtraeme 		bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah,
    821           1.9   xtraeme 		    LPCIB_GCS_OFFSET, status);
    822           1.9   xtraeme 		status = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah,
    823           1.9   xtraeme 		    LPCIB_GCS_OFFSET);
    824           1.6  jmcneill 		if (status & LPCIB_GCS_NO_REBOOT)
    825           1.6  jmcneill 			goto error;
    826           1.6  jmcneill 	} else {
    827           1.6  jmcneill 		pcireg_t pcireg;
    828           1.6  jmcneill 
    829          1.35   msaitoh 		pcireg = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    830           1.1   xtraeme 				       LPCIB_PCI_GEN_STA);
    831           1.1   xtraeme 		if (pcireg & LPCIB_PCI_GEN_STA_NO_REBOOT) {
    832           1.1   xtraeme 			/* TCO timeout reset is disabled; try to enable it */
    833           1.1   xtraeme 			pcireg &= ~LPCIB_PCI_GEN_STA_NO_REBOOT;
    834          1.12    martin 			pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    835           1.1   xtraeme 				       LPCIB_PCI_GEN_STA, pcireg);
    836           1.1   xtraeme 			if (pcireg & LPCIB_PCI_GEN_STA_NO_REBOOT)
    837           1.1   xtraeme 				goto error;
    838           1.1   xtraeme 		}
    839           1.1   xtraeme 	}
    840           1.1   xtraeme 
    841           1.1   xtraeme 	return 0;
    842           1.1   xtraeme error:
    843           1.9   xtraeme 	aprint_error_dev(self, "TCO timer reboot disabled by hardware; "
    844           1.9   xtraeme 	    "hope SMBIOS properly handles it.\n");
    845           1.1   xtraeme 	return EINVAL;
    846           1.1   xtraeme }
    847           1.1   xtraeme 
    848           1.1   xtraeme 
    849           1.1   xtraeme /*
    850           1.1   xtraeme  * Intel ICH SpeedStep support.
    851           1.1   xtraeme  */
    852           1.1   xtraeme #define SS_READ(sc, reg) \
    853           1.1   xtraeme 	bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (reg))
    854           1.1   xtraeme #define SS_WRITE(sc, reg, val) \
    855           1.1   xtraeme 	bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
    856           1.1   xtraeme 
    857           1.1   xtraeme /*
    858           1.1   xtraeme  * Linux driver says that SpeedStep on older chipsets cause
    859           1.1   xtraeme  * lockups on Dell Inspiron 8000 and 8100.
    860          1.15       mrg  * It should also not be enabled on systems with the 82855GM
    861          1.15       mrg  * Hub, which typically have an EST-enabled CPU.
    862           1.1   xtraeme  */
    863           1.1   xtraeme static int
    864          1.29    dyoung speedstep_bad_hb_check(const struct pci_attach_args *pa)
    865           1.1   xtraeme {
    866           1.1   xtraeme 
    867           1.1   xtraeme 	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82815_FULL_HUB &&
    868           1.1   xtraeme 	    PCI_REVISION(pa->pa_class) < 5)
    869           1.1   xtraeme 		return 1;
    870           1.1   xtraeme 
    871          1.15       mrg 	if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_82855GM_MCH)
    872          1.15       mrg 		return 1;
    873          1.15       mrg 
    874           1.1   xtraeme 	return 0;
    875           1.1   xtraeme }
    876           1.1   xtraeme 
    877           1.1   xtraeme static void
    878           1.9   xtraeme speedstep_configure(device_t self)
    879           1.1   xtraeme {
    880           1.9   xtraeme 	struct lpcib_softc *sc = device_private(self);
    881           1.1   xtraeme 	const struct sysctlnode	*node, *ssnode;
    882           1.1   xtraeme 	int rv;
    883           1.1   xtraeme 
    884           1.1   xtraeme 	/* Supported on ICH2-M, ICH3-M and ICH4-M.  */
    885          1.30   msaitoh 	if (PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801DBM_LPC ||
    886           1.6  jmcneill 	    PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801CAM_LPC ||
    887           1.6  jmcneill 	    (PCI_PRODUCT(sc->sc_pa.pa_id) == PCI_PRODUCT_INTEL_82801BAM_LPC &&
    888           1.6  jmcneill 	     pci_find_device(&sc->sc_pa, speedstep_bad_hb_check) == 0)) {
    889          1.19    dyoung 		pcireg_t pmcon;
    890           1.1   xtraeme 
    891           1.1   xtraeme 		/* Enable SpeedStep if it isn't already enabled. */
    892          1.12    martin 		pmcon = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    893           1.1   xtraeme 				      LPCIB_PCI_GEN_PMCON_1);
    894           1.1   xtraeme 		if ((pmcon & LPCIB_PCI_GEN_PMCON_1_SS_EN) == 0)
    895          1.12    martin 			pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    896           1.1   xtraeme 				       LPCIB_PCI_GEN_PMCON_1,
    897           1.1   xtraeme 				       pmcon | LPCIB_PCI_GEN_PMCON_1_SS_EN);
    898           1.1   xtraeme 
    899           1.1   xtraeme 		/* Put in machdep.speedstep_state (0 for low, 1 for high). */
    900          1.19    dyoung 		if ((rv = sysctl_createv(&sc->sc_log, 0, NULL, &node,
    901           1.1   xtraeme 		    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
    902           1.1   xtraeme 		    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0)
    903           1.1   xtraeme 			goto err;
    904           1.1   xtraeme 
    905           1.1   xtraeme 		/* CTLFLAG_ANYWRITE? kernel option like EST? */
    906          1.19    dyoung 		if ((rv = sysctl_createv(&sc->sc_log, 0, &node, &ssnode,
    907           1.1   xtraeme 		    CTLFLAG_READWRITE, CTLTYPE_INT, "speedstep_state", NULL,
    908           1.1   xtraeme 		    speedstep_sysctl_helper, 0, NULL, 0, CTL_CREATE,
    909           1.1   xtraeme 		    CTL_EOL)) != 0)
    910           1.1   xtraeme 			goto err;
    911           1.1   xtraeme 
    912           1.1   xtraeme 		/* XXX save the sc for IO tag/handle */
    913           1.1   xtraeme 		speedstep_cookie = sc;
    914           1.9   xtraeme 		aprint_verbose_dev(self, "SpeedStep enabled\n");
    915           1.1   xtraeme 	}
    916           1.1   xtraeme 
    917           1.1   xtraeme 	return;
    918           1.1   xtraeme 
    919           1.1   xtraeme err:
    920           1.1   xtraeme 	aprint_normal("%s: sysctl_createv failed (rv = %d)\n", __func__, rv);
    921           1.1   xtraeme }
    922           1.1   xtraeme 
    923          1.19    dyoung static void
    924          1.19    dyoung speedstep_unconfigure(device_t self)
    925          1.19    dyoung {
    926          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
    927          1.19    dyoung 
    928          1.19    dyoung 	sysctl_teardown(&sc->sc_log);
    929          1.19    dyoung 	pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
    930          1.19    dyoung 	    LPCIB_PCI_GEN_PMCON_1, sc->sc_pmcon_orig);
    931          1.19    dyoung 
    932          1.19    dyoung 	speedstep_cookie = NULL;
    933          1.19    dyoung }
    934          1.19    dyoung 
    935           1.1   xtraeme /*
    936           1.1   xtraeme  * get/set the SpeedStep state: 0 == low power, 1 == high power.
    937           1.1   xtraeme  */
    938           1.1   xtraeme static int
    939           1.1   xtraeme speedstep_sysctl_helper(SYSCTLFN_ARGS)
    940           1.1   xtraeme {
    941           1.1   xtraeme 	struct sysctlnode	node;
    942           1.1   xtraeme 	struct lpcib_softc 	*sc = speedstep_cookie;
    943           1.1   xtraeme 	uint8_t			state, state2;
    944           1.1   xtraeme 	int			ostate, nstate, s, error = 0;
    945           1.1   xtraeme 
    946           1.1   xtraeme 	/*
    947           1.1   xtraeme 	 * We do the dance with spl's to avoid being at high ipl during
    948           1.1   xtraeme 	 * sysctl_lookup() which can both copyin and copyout.
    949           1.1   xtraeme 	 */
    950           1.1   xtraeme 	s = splserial();
    951           1.1   xtraeme 	state = SS_READ(sc, LPCIB_PM_SS_CNTL);
    952           1.1   xtraeme 	splx(s);
    953           1.1   xtraeme 	if ((state & LPCIB_PM_SS_STATE_LOW) == 0)
    954           1.1   xtraeme 		ostate = 1;
    955           1.1   xtraeme 	else
    956           1.1   xtraeme 		ostate = 0;
    957           1.1   xtraeme 	nstate = ostate;
    958           1.1   xtraeme 
    959           1.1   xtraeme 	node = *rnode;
    960           1.1   xtraeme 	node.sysctl_data = &nstate;
    961           1.1   xtraeme 
    962           1.1   xtraeme 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    963           1.1   xtraeme 	if (error || newp == NULL)
    964           1.1   xtraeme 		goto out;
    965           1.1   xtraeme 
    966           1.1   xtraeme 	/* Only two states are available */
    967           1.1   xtraeme 	if (nstate != 0 && nstate != 1) {
    968           1.1   xtraeme 		error = EINVAL;
    969           1.1   xtraeme 		goto out;
    970           1.1   xtraeme 	}
    971           1.1   xtraeme 
    972           1.1   xtraeme 	s = splserial();
    973           1.1   xtraeme 	state2 = SS_READ(sc, LPCIB_PM_SS_CNTL);
    974           1.1   xtraeme 	if ((state2 & LPCIB_PM_SS_STATE_LOW) == 0)
    975           1.1   xtraeme 		ostate = 1;
    976           1.1   xtraeme 	else
    977           1.1   xtraeme 		ostate = 0;
    978           1.1   xtraeme 
    979           1.1   xtraeme 	if (ostate != nstate) {
    980           1.1   xtraeme 		uint8_t cntl;
    981           1.1   xtraeme 
    982           1.1   xtraeme 		if (nstate == 0)
    983           1.1   xtraeme 			state2 |= LPCIB_PM_SS_STATE_LOW;
    984           1.1   xtraeme 		else
    985           1.1   xtraeme 			state2 &= ~LPCIB_PM_SS_STATE_LOW;
    986           1.1   xtraeme 
    987           1.1   xtraeme 		/*
    988           1.1   xtraeme 		 * Must disable bus master arbitration during the change.
    989           1.1   xtraeme 		 */
    990           1.1   xtraeme 		cntl = SS_READ(sc, LPCIB_PM_CTRL);
    991           1.1   xtraeme 		SS_WRITE(sc, LPCIB_PM_CTRL, cntl | LPCIB_PM_SS_CNTL_ARB_DIS);
    992           1.1   xtraeme 		SS_WRITE(sc, LPCIB_PM_SS_CNTL, state2);
    993           1.1   xtraeme 		SS_WRITE(sc, LPCIB_PM_CTRL, cntl);
    994           1.1   xtraeme 	}
    995           1.1   xtraeme 	splx(s);
    996           1.1   xtraeme out:
    997           1.1   xtraeme 	return error;
    998           1.1   xtraeme }
    999           1.6  jmcneill 
   1000           1.6  jmcneill static void
   1001           1.9   xtraeme lpcib_hpet_configure(device_t self)
   1002           1.6  jmcneill {
   1003           1.9   xtraeme 	struct lpcib_softc *sc = device_private(self);
   1004          1.31    jruoho 	struct lpcib_hpet_attach_args arg;
   1005           1.6  jmcneill 	uint32_t hpet_reg, val;
   1006           1.6  jmcneill 
   1007           1.6  jmcneill 	if (sc->sc_has_ich5_hpet) {
   1008          1.12    martin 		val = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
   1009           1.9   xtraeme 		    LPCIB_PCI_GEN_CNTL);
   1010           1.6  jmcneill 		switch (val & LPCIB_ICH5_HPTC_WIN_MASK) {
   1011           1.6  jmcneill 		case LPCIB_ICH5_HPTC_0000:
   1012           1.6  jmcneill 			hpet_reg = LPCIB_ICH5_HPTC_0000_BASE;
   1013           1.6  jmcneill 			break;
   1014           1.6  jmcneill 		case LPCIB_ICH5_HPTC_1000:
   1015           1.6  jmcneill 			hpet_reg = LPCIB_ICH5_HPTC_1000_BASE;
   1016           1.6  jmcneill 			break;
   1017           1.6  jmcneill 		case LPCIB_ICH5_HPTC_2000:
   1018           1.6  jmcneill 			hpet_reg = LPCIB_ICH5_HPTC_2000_BASE;
   1019           1.6  jmcneill 			break;
   1020           1.6  jmcneill 		case LPCIB_ICH5_HPTC_3000:
   1021           1.6  jmcneill 			hpet_reg = LPCIB_ICH5_HPTC_3000_BASE;
   1022           1.6  jmcneill 			break;
   1023           1.6  jmcneill 		default:
   1024           1.6  jmcneill 			return;
   1025           1.6  jmcneill 		}
   1026           1.6  jmcneill 		val |= sc->sc_hpet_reg | LPCIB_ICH5_HPTC_EN;
   1027          1.12    martin 		pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
   1028           1.9   xtraeme 		    LPCIB_PCI_GEN_CNTL, val);
   1029           1.6  jmcneill 	} else if (sc->sc_has_rcba) {
   1030           1.6  jmcneill 		val = bus_space_read_4(sc->sc_rcbat, sc->sc_rcbah,
   1031           1.6  jmcneill 		    LPCIB_RCBA_HPTC);
   1032           1.6  jmcneill 		switch (val & LPCIB_RCBA_HPTC_WIN_MASK) {
   1033           1.6  jmcneill 		case LPCIB_RCBA_HPTC_0000:
   1034           1.6  jmcneill 			hpet_reg = LPCIB_RCBA_HPTC_0000_BASE;
   1035           1.6  jmcneill 			break;
   1036           1.6  jmcneill 		case LPCIB_RCBA_HPTC_1000:
   1037           1.6  jmcneill 			hpet_reg = LPCIB_RCBA_HPTC_1000_BASE;
   1038           1.6  jmcneill 			break;
   1039           1.6  jmcneill 		case LPCIB_RCBA_HPTC_2000:
   1040           1.6  jmcneill 			hpet_reg = LPCIB_RCBA_HPTC_2000_BASE;
   1041           1.6  jmcneill 			break;
   1042           1.6  jmcneill 		case LPCIB_RCBA_HPTC_3000:
   1043           1.6  jmcneill 			hpet_reg = LPCIB_RCBA_HPTC_3000_BASE;
   1044           1.6  jmcneill 			break;
   1045           1.6  jmcneill 		default:
   1046           1.6  jmcneill 			return;
   1047           1.6  jmcneill 		}
   1048           1.6  jmcneill 		val |= LPCIB_RCBA_HPTC_EN;
   1049           1.6  jmcneill 		bus_space_write_4(sc->sc_rcbat, sc->sc_rcbah, LPCIB_RCBA_HPTC,
   1050           1.6  jmcneill 		    val);
   1051           1.6  jmcneill 	} else {
   1052           1.6  jmcneill 		/* No HPET here */
   1053           1.6  jmcneill 		return;
   1054           1.6  jmcneill 	}
   1055           1.6  jmcneill 
   1056           1.6  jmcneill 	arg.hpet_mem_t = sc->sc_pa.pa_memt;
   1057           1.6  jmcneill 	arg.hpet_reg = hpet_reg;
   1058           1.6  jmcneill 
   1059          1.19    dyoung 	sc->sc_hpetbus = config_found_ia(self, "hpetichbus", &arg, NULL);
   1060          1.19    dyoung }
   1061          1.19    dyoung 
   1062          1.19    dyoung static int
   1063          1.19    dyoung lpcib_hpet_unconfigure(device_t self, int flags)
   1064          1.19    dyoung {
   1065          1.19    dyoung 	struct lpcib_softc *sc = device_private(self);
   1066          1.19    dyoung 	int rc;
   1067          1.19    dyoung 
   1068          1.19    dyoung 	if (sc->sc_hpetbus != NULL &&
   1069          1.19    dyoung 	    (rc = config_detach(sc->sc_hpetbus, flags)) != 0)
   1070          1.19    dyoung 		return rc;
   1071          1.19    dyoung 
   1072          1.19    dyoung 	return 0;
   1073           1.6  jmcneill }
   1074          1.20  jakllsch 
   1075          1.20  jakllsch #if NGPIO > 0
   1076          1.20  jakllsch static void
   1077          1.20  jakllsch lpcib_gpio_configure(device_t self)
   1078          1.20  jakllsch {
   1079          1.20  jakllsch 	struct lpcib_softc *sc = device_private(self);
   1080          1.20  jakllsch 	struct gpiobus_attach_args gba;
   1081          1.20  jakllsch 	pcireg_t gpio_cntl;
   1082          1.20  jakllsch 	uint32_t use, io, bit;
   1083          1.20  jakllsch 	int pin, shift, base_reg, cntl_reg, reg;
   1084      1.43.4.1    martin 	int rv;
   1085          1.20  jakllsch 
   1086      1.43.4.5       snj 	if (ichlpcib_gpio_disable != 0)
   1087      1.43.4.5       snj 		return;
   1088      1.43.4.5       snj 
   1089          1.20  jakllsch 	/* this implies ICH >= 6, and thus different mapreg */
   1090          1.20  jakllsch 	if (sc->sc_has_rcba) {
   1091          1.20  jakllsch 		base_reg = LPCIB_PCI_GPIO_BASE_ICH6;
   1092          1.20  jakllsch 		cntl_reg = LPCIB_PCI_GPIO_CNTL_ICH6;
   1093          1.20  jakllsch 	} else {
   1094          1.20  jakllsch 		base_reg = LPCIB_PCI_GPIO_BASE;
   1095          1.20  jakllsch 		cntl_reg = LPCIB_PCI_GPIO_CNTL;
   1096          1.20  jakllsch 	}
   1097          1.20  jakllsch 
   1098          1.20  jakllsch 	gpio_cntl = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
   1099          1.20  jakllsch 				  cntl_reg);
   1100          1.20  jakllsch 
   1101          1.20  jakllsch 	/* Is GPIO enabled? */
   1102          1.20  jakllsch 	if ((gpio_cntl & LPCIB_PCI_GPIO_CNTL_EN) == 0)
   1103          1.20  jakllsch 		return;
   1104      1.43.4.1    martin 	/*
   1105      1.43.4.1    martin 	 * The GPIO_BASE register is alike PCI BAR but not completely
   1106      1.43.4.1    martin 	 * compatible with it. The PMBASE define the base address and the type
   1107      1.43.4.2    martin 	 * but not describe the size. The value of the register may be lower
   1108      1.43.4.2    martin 	 * than LPCIB_PCI_GPIO_SIZE. It makes impossible to use
   1109      1.43.4.2    martin 	 * pci_mapreg_submap() because the function does range check.
   1110      1.43.4.1    martin 	 */
   1111      1.43.4.2    martin 	sc->sc_gpio_iot = sc->sc_pa.pa_iot;
   1112      1.43.4.2    martin 	reg = pci_conf_read(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag, base_reg);
   1113      1.43.4.2    martin 	rv = bus_space_map(sc->sc_gpio_iot, PCI_MAPREG_IO_ADDR(reg),
   1114      1.43.4.2    martin 	    LPCIB_PCI_GPIO_SIZE, 0, &sc->sc_gpio_ioh);
   1115      1.43.4.1    martin 	if (rv != 0) {
   1116      1.43.4.1    martin 		aprint_error_dev(self, "can't map general purpose i/o space(rv = %d)\n", rv);
   1117          1.20  jakllsch 		return;
   1118          1.20  jakllsch 	}
   1119          1.20  jakllsch 
   1120          1.20  jakllsch 	mutex_init(&sc->sc_gpio_mtx, MUTEX_DEFAULT, IPL_NONE);
   1121          1.20  jakllsch 
   1122          1.20  jakllsch 	for (pin = 0; pin < LPCIB_GPIO_NPINS; pin++) {
   1123          1.20  jakllsch 		sc->sc_gpio_pins[pin].pin_num = pin;
   1124          1.20  jakllsch 
   1125          1.20  jakllsch 		/* Read initial state */
   1126          1.20  jakllsch 		reg = (pin < 32) ? LPCIB_GPIO_GPIO_USE_SEL : LPCIB_GPIO_GPIO_USE_SEL2;
   1127          1.20  jakllsch 		use = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
   1128          1.20  jakllsch 		reg = (pin < 32) ? LPCIB_GPIO_GP_IO_SEL : LPCIB_GPIO_GP_IO_SEL;
   1129          1.20  jakllsch 		io = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, 4);
   1130          1.20  jakllsch 		shift = pin % 32;
   1131          1.20  jakllsch 		bit = __BIT(shift);
   1132          1.20  jakllsch 
   1133          1.20  jakllsch 		if ((use & bit) != 0) {
   1134          1.20  jakllsch 			sc->sc_gpio_pins[pin].pin_caps =
   1135          1.20  jakllsch 			    GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
   1136          1.20  jakllsch 			if (pin < 32)
   1137          1.20  jakllsch 				sc->sc_gpio_pins[pin].pin_caps |=
   1138          1.20  jakllsch 				    GPIO_PIN_PULSATE;
   1139          1.20  jakllsch 			if ((io & bit) != 0)
   1140          1.20  jakllsch 				sc->sc_gpio_pins[pin].pin_flags =
   1141          1.20  jakllsch 				    GPIO_PIN_INPUT;
   1142          1.20  jakllsch 			else
   1143          1.20  jakllsch 				sc->sc_gpio_pins[pin].pin_flags =
   1144          1.20  jakllsch 				    GPIO_PIN_OUTPUT;
   1145          1.20  jakllsch 		} else
   1146          1.20  jakllsch 			sc->sc_gpio_pins[pin].pin_caps = 0;
   1147          1.20  jakllsch 
   1148          1.20  jakllsch 		if (lpcib_gpio_pin_read(sc, pin) == 0)
   1149          1.20  jakllsch 			sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
   1150          1.20  jakllsch 		else
   1151          1.20  jakllsch 			sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
   1152          1.20  jakllsch 
   1153          1.20  jakllsch 	}
   1154          1.20  jakllsch 
   1155          1.20  jakllsch 	/* Create controller tag */
   1156          1.20  jakllsch 	sc->sc_gpio_gc.gp_cookie = sc;
   1157          1.20  jakllsch 	sc->sc_gpio_gc.gp_pin_read = lpcib_gpio_pin_read;
   1158          1.20  jakllsch 	sc->sc_gpio_gc.gp_pin_write = lpcib_gpio_pin_write;
   1159          1.20  jakllsch 	sc->sc_gpio_gc.gp_pin_ctl = lpcib_gpio_pin_ctl;
   1160          1.20  jakllsch 
   1161          1.20  jakllsch 	memset(&gba, 0, sizeof(gba));
   1162          1.20  jakllsch 
   1163          1.20  jakllsch 	gba.gba_gc = &sc->sc_gpio_gc;
   1164          1.20  jakllsch 	gba.gba_pins = sc->sc_gpio_pins;
   1165          1.20  jakllsch 	gba.gba_npins = LPCIB_GPIO_NPINS;
   1166          1.20  jakllsch 
   1167          1.20  jakllsch 	sc->sc_gpiobus = config_found_ia(self, "gpiobus", &gba, gpiobus_print);
   1168          1.20  jakllsch }
   1169          1.20  jakllsch 
   1170          1.20  jakllsch static int
   1171          1.20  jakllsch lpcib_gpio_unconfigure(device_t self, int flags)
   1172          1.20  jakllsch {
   1173          1.20  jakllsch 	struct lpcib_softc *sc = device_private(self);
   1174          1.20  jakllsch 	int rc;
   1175          1.20  jakllsch 
   1176          1.20  jakllsch 	if (sc->sc_gpiobus != NULL &&
   1177          1.20  jakllsch 	    (rc = config_detach(sc->sc_gpiobus, flags)) != 0)
   1178          1.20  jakllsch 		return rc;
   1179          1.20  jakllsch 
   1180          1.20  jakllsch 	mutex_destroy(&sc->sc_gpio_mtx);
   1181          1.20  jakllsch 
   1182          1.20  jakllsch 	bus_space_unmap(sc->sc_gpio_iot, sc->sc_gpio_ioh, sc->sc_gpio_ios);
   1183          1.20  jakllsch 
   1184          1.20  jakllsch 	return 0;
   1185          1.20  jakllsch }
   1186          1.20  jakllsch 
   1187          1.20  jakllsch static int
   1188          1.20  jakllsch lpcib_gpio_pin_read(void *arg, int pin)
   1189          1.20  jakllsch {
   1190          1.20  jakllsch 	struct lpcib_softc *sc = arg;
   1191          1.20  jakllsch 	uint32_t data;
   1192          1.20  jakllsch 	int reg, shift;
   1193          1.20  jakllsch 
   1194          1.20  jakllsch 	reg = (pin < 32) ? LPCIB_GPIO_GP_LVL : LPCIB_GPIO_GP_LVL2;
   1195          1.20  jakllsch 	shift = pin % 32;
   1196          1.20  jakllsch 
   1197          1.20  jakllsch 	mutex_enter(&sc->sc_gpio_mtx);
   1198          1.20  jakllsch 	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
   1199          1.20  jakllsch 	mutex_exit(&sc->sc_gpio_mtx);
   1200          1.20  jakllsch 
   1201          1.20  jakllsch 	return (__SHIFTOUT(data, __BIT(shift)) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
   1202          1.20  jakllsch }
   1203          1.20  jakllsch 
   1204          1.20  jakllsch static void
   1205          1.20  jakllsch lpcib_gpio_pin_write(void *arg, int pin, int value)
   1206          1.20  jakllsch {
   1207          1.20  jakllsch 	struct lpcib_softc *sc = arg;
   1208          1.20  jakllsch 	uint32_t data;
   1209          1.20  jakllsch 	int reg, shift;
   1210          1.20  jakllsch 
   1211          1.20  jakllsch 	reg = (pin < 32) ? LPCIB_GPIO_GP_LVL : LPCIB_GPIO_GP_LVL2;
   1212          1.20  jakllsch 	shift = pin % 32;
   1213          1.20  jakllsch 
   1214          1.20  jakllsch 	mutex_enter(&sc->sc_gpio_mtx);
   1215          1.20  jakllsch 
   1216          1.20  jakllsch 	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
   1217          1.20  jakllsch 
   1218          1.20  jakllsch 	if(value)
   1219          1.20  jakllsch 		data |= __BIT(shift);
   1220          1.20  jakllsch 	else
   1221          1.20  jakllsch 		data &= ~__BIT(shift);
   1222          1.20  jakllsch 
   1223          1.20  jakllsch 	bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data);
   1224          1.20  jakllsch 
   1225          1.20  jakllsch 	mutex_exit(&sc->sc_gpio_mtx);
   1226          1.20  jakllsch }
   1227          1.20  jakllsch 
   1228          1.20  jakllsch static void
   1229          1.20  jakllsch lpcib_gpio_pin_ctl(void *arg, int pin, int flags)
   1230          1.20  jakllsch {
   1231          1.20  jakllsch 	struct lpcib_softc *sc = arg;
   1232          1.20  jakllsch 	uint32_t data;
   1233          1.20  jakllsch 	int reg, shift;
   1234          1.20  jakllsch 
   1235          1.20  jakllsch 	shift = pin % 32;
   1236          1.20  jakllsch 	reg = (pin < 32) ? LPCIB_GPIO_GP_IO_SEL : LPCIB_GPIO_GP_IO_SEL2;
   1237          1.20  jakllsch 
   1238          1.20  jakllsch 	mutex_enter(&sc->sc_gpio_mtx);
   1239          1.20  jakllsch 
   1240          1.20  jakllsch 	data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
   1241          1.20  jakllsch 
   1242          1.20  jakllsch 	if (flags & GPIO_PIN_OUTPUT)
   1243          1.20  jakllsch 		data &= ~__BIT(shift);
   1244          1.20  jakllsch 
   1245          1.20  jakllsch 	if (flags & GPIO_PIN_INPUT)
   1246          1.20  jakllsch 		data |= __BIT(shift);
   1247          1.20  jakllsch 
   1248          1.20  jakllsch 	bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data);
   1249          1.20  jakllsch 
   1250          1.20  jakllsch 
   1251          1.20  jakllsch 	if (pin < 32) {
   1252          1.20  jakllsch 		reg = LPCIB_GPIO_GPO_BLINK;
   1253          1.20  jakllsch 		data = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg);
   1254          1.20  jakllsch 
   1255          1.20  jakllsch 		if (flags & GPIO_PIN_PULSATE)
   1256          1.20  jakllsch 			data |= __BIT(shift);
   1257          1.20  jakllsch 		else
   1258          1.20  jakllsch 			data &= ~__BIT(shift);
   1259          1.20  jakllsch 
   1260          1.20  jakllsch 		bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, reg, data);
   1261          1.20  jakllsch 	}
   1262          1.20  jakllsch 
   1263          1.20  jakllsch 	mutex_exit(&sc->sc_gpio_mtx);
   1264          1.20  jakllsch }
   1265          1.20  jakllsch #endif
   1266          1.25  jakllsch 
   1267          1.25  jakllsch #if NFWHRNG > 0
   1268          1.25  jakllsch static void
   1269          1.25  jakllsch lpcib_fwh_configure(device_t self)
   1270          1.25  jakllsch {
   1271          1.26  jakllsch 	struct lpcib_softc *sc;
   1272          1.26  jakllsch 	pcireg_t pr;
   1273          1.25  jakllsch 
   1274          1.26  jakllsch 	sc = device_private(self);
   1275          1.25  jakllsch 
   1276          1.25  jakllsch 	if (sc->sc_has_rcba) {
   1277          1.25  jakllsch 		/*
   1278          1.25  jakllsch 		 * Very unlikely to find a 82802 on a ICH6 or newer.
   1279          1.25  jakllsch 		 * Also the write enable register moved at that point.
   1280          1.25  jakllsch 		 */
   1281          1.25  jakllsch 		return;
   1282          1.25  jakllsch 	} else {
   1283          1.25  jakllsch 		/* Enable FWH write to identify FWH. */
   1284          1.25  jakllsch 		pr = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
   1285          1.26  jakllsch 		    LPCIB_PCI_BIOS_CNTL);
   1286          1.25  jakllsch 		pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
   1287          1.26  jakllsch 		    LPCIB_PCI_BIOS_CNTL, pr|LPCIB_PCI_BIOS_CNTL_BWE);
   1288          1.25  jakllsch 	}
   1289          1.25  jakllsch 
   1290          1.25  jakllsch 	sc->sc_fwhbus = config_found_ia(self, "fwhichbus", NULL, NULL);
   1291          1.25  jakllsch 
   1292          1.26  jakllsch 	/* restore previous write enable setting */
   1293          1.26  jakllsch 	pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
   1294          1.26  jakllsch 	    LPCIB_PCI_BIOS_CNTL, pr);
   1295          1.25  jakllsch }
   1296          1.25  jakllsch 
   1297          1.25  jakllsch static int
   1298          1.25  jakllsch lpcib_fwh_unconfigure(device_t self, int flags)
   1299          1.25  jakllsch {
   1300          1.25  jakllsch 	struct lpcib_softc *sc = device_private(self);
   1301          1.25  jakllsch 	int rc;
   1302          1.25  jakllsch 
   1303          1.25  jakllsch 	if (sc->sc_fwhbus != NULL &&
   1304          1.25  jakllsch 	    (rc = config_detach(sc->sc_fwhbus, flags)) != 0)
   1305          1.25  jakllsch 		return rc;
   1306          1.25  jakllsch 
   1307          1.25  jakllsch 	return 0;
   1308          1.25  jakllsch }
   1309          1.25  jakllsch #endif
   1310