Module Name: src
Committed By: jakllsch
Date: Fri Jul 23 00:43:21 UTC 2010
Modified Files:
src/sys/arch/amd64/conf: GENERIC
src/sys/arch/i386/conf: GENERIC
src/sys/arch/x86/pci: files.pci i82802reg.h ichlpcib.c pchb.c pchbvar.h
Added Files:
src/sys/arch/x86/pci: fwhrng.c
Removed Files:
src/sys/arch/x86/pci: pchb_rnd.c
Log Message:
Almost entirely rework Intel Firmware Hub random number generator support.
This introduces fwhrng(4) which attaches via ichlpcib(4), replacing
the rnd(4) support in pchb(4).
To generate a diff of this commit:
cvs rdiff -u -r1.282 -r1.283 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.987 -r1.988 src/sys/arch/i386/conf/GENERIC
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/x86/pci/files.pci
cvs rdiff -u -r0 -r1.1 src/sys/arch/x86/pci/fwhrng.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/pci/i82802reg.h
cvs rdiff -u -r1.24 -r1.25 src/sys/arch/x86/pci/ichlpcib.c
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/x86/pci/pchb.c
cvs rdiff -u -r1.9 -r0 src/sys/arch/x86/pci/pchb_rnd.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/x86/pci/pchbvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.282 src/sys/arch/amd64/conf/GENERIC:1.283
--- src/sys/arch/amd64/conf/GENERIC:1.282 Sun Jul 18 09:29:11 2010
+++ src/sys/arch/amd64/conf/GENERIC Fri Jul 23 00:43:20 2010
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.282 2010/07/18 09:29:11 jruoho Exp $
+# $NetBSD: GENERIC,v 1.283 2010/07/23 00:43:20 jakllsch Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.282 $"
+#ident "GENERIC-$Revision: 1.283 $"
maxusers 64 # estimated number of users
@@ -336,8 +336,9 @@
#amdpcib* at pci? dev ? function ? # AMD 8111 PCI-ISA w/ HPET
#hpet* at amdpcib?
-ichlpcib* at pci? dev ? function ? # Intel ICH PCI-ISA w/ timecounter,
- # watchdog and Speedstep support.
+ichlpcib* at pci? dev ? function ? # Intel ICH PCI-LPC w/ timecounter,
+ # watchdog and Speedstep and HPET
+fwhrng* at ichlpcib? # Intel 82802 FWH Random Number Generator
#hpet* at ichlpcib?
aapic* at pci? dev ? function ? # AMD 8131 IO apic
Index: src/sys/arch/i386/conf/GENERIC
diff -u src/sys/arch/i386/conf/GENERIC:1.987 src/sys/arch/i386/conf/GENERIC:1.988
--- src/sys/arch/i386/conf/GENERIC:1.987 Sun Jul 18 09:29:12 2010
+++ src/sys/arch/i386/conf/GENERIC Fri Jul 23 00:43:20 2010
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.987 2010/07/18 09:29:12 jruoho Exp $
+# $NetBSD: GENERIC,v 1.988 2010/07/23 00:43:20 jakllsch Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.987 $"
+#ident "GENERIC-$Revision: 1.988 $"
maxusers 64 # estimated number of users
@@ -457,8 +457,9 @@
# PCI bridges
#amdpcib* at pci? dev ? function ? # AMD 8111 PCI-ISA w/ HPET
#hpet* at amdpcib?
-ichlpcib* at pci? dev ? function ? # Intel ICH PCI-ISA w/ timecounter,
+ichlpcib* at pci? dev ? function ? # Intel ICH PCI-LPC w/ timecounter,
# watchdog, SpeedStep and HPET
+fwhrng* at ichlpcib? # Intel 82802 FWH Random Number Generator
#hpet* at ichlpcib?
gcscpcib* at pci? dev ? function ? # AMD CS5535/CS5536 PCI-ISA w/
gpio* at gcscpcib? # timecounter, watchdog and GPIO
Index: src/sys/arch/x86/pci/files.pci
diff -u src/sys/arch/x86/pci/files.pci:1.9 src/sys/arch/x86/pci/files.pci:1.10
--- src/sys/arch/x86/pci/files.pci:1.9 Fri May 14 18:11:25 2010
+++ src/sys/arch/x86/pci/files.pci Fri Jul 23 00:43:21 2010
@@ -1,4 +1,4 @@
-# $NetBSD: files.pci,v 1.9 2010/05/14 18:11:25 phx Exp $
+# $NetBSD: files.pci,v 1.10 2010/07/23 00:43:21 jakllsch Exp $
device aapic
attach aapic at pci
@@ -11,7 +11,6 @@
agp_intel, agp_sis, agp_via
attach pchb at pci
file arch/x86/pci/pchb.c pchb needs-flag
-file arch/x86/pci/pchb_rnd.c pchb & rnd
# PCI-ISA bridges
device pcib: isabus
@@ -32,9 +31,14 @@
file arch/x86/pci/amdtemp.c amdtemp
# PCI-LPC bridges
+define fwhichbus {}
define hpetichbus {}
-device ichlpcib: acpipmtimer, isabus, sysmon_wdog, hpetichbus, gpiobus
+device ichlpcib: acpipmtimer, isabus, sysmon_wdog, fwhichbus, hpetichbus, gpiobus
attach ichlpcib at pci
attach hpet at hpetichbus with ichlpcib_hpet
file arch/x86/pci/ichlpcib.c ichlpcib
+
+device fwhrng
+attach fwhrng at fwhichbus
+file arch/x86/pci/fwhrng.c fwhrng needs-flag
Index: src/sys/arch/x86/pci/i82802reg.h
diff -u src/sys/arch/x86/pci/i82802reg.h:1.2 src/sys/arch/x86/pci/i82802reg.h:1.3
--- src/sys/arch/x86/pci/i82802reg.h:1.2 Tue Nov 3 01:19:35 2009
+++ src/sys/arch/x86/pci/i82802reg.h Fri Jul 23 00:43:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: i82802reg.h,v 1.2 2009/11/03 01:19:35 snj Exp $ */
+/* $NetBSD: i82802reg.h,v 1.3 2010/07/23 00:43:21 jakllsch Exp $ */
/*
* Copyright (c) 2000 Michael Shalayeff
@@ -34,33 +34,42 @@
*/
/*
- * unfortunatelly FWH does not show up in the pci device scan, 10x intel.
- * so all we do is probe for it in the pchb driver at the following address.
+ * MMIO bases and sizes
*/
-#define I82802_IOBASE 0xffb00000
-#define I82802_IOSIZE 0x00100000
-
-/*
- * FWH registers
- * (table 4-4)
- */
-#define I82802_BLOCK_LK 0xf0002
-#define I82802_MINUS01_LK 0xe0002
-#define I82802_MINUS02_LK 0xd0002
-#define I82802_MINUS03_LK 0xc0002
-#define I82802_MINUS04_LK 0xb0002
-#define I82802_MINUS05_LK 0xa0002
-#define I82802_MINUS06_LK 0x90002
-#define I82802_MINUS07_LK 0x80002
-#define I82802_MINUS08_LK 0x70002
-#define I82802_MINUS09_LK 0x60002
-#define I82802_MINUS10_LK 0x50002
-#define I82802_MINUS11_LK 0x40002
-#define I82802_MINUS12_LK 0x30002
-#define I82802_MINUS13_LK 0x20002
-#define I82802_MINUS14_LK 0x10002
-#define I82802_MINUS15_LK 0x00002
-#define I82802_FGPI_REG 0xc0100
+#define I82802AC_REGBASE 0xffb00000
+#define I82802AC_MEMBASE 0xfff00000
+#define I82802AC_WINSIZE 0x00100000
+
+#define I82802_MFG 0x89
+#define I82802AB_ID 0xad
+#define I82802AC_ID 0xac
+
+/*
+ * Intel FWH registers
+ */
+#define I82802_T_BLOCK_LK 0xf0002
+#define I82802_T_MINUS01_LK 0xe0002
+#define I82802_T_MINUS02_LK 0xd0002
+#define I82802_T_MINUS03_LK 0xc0002
+#define I82802_T_MINUS04_LK 0xb0002
+#define I82802_T_MINUS05_LK 0xa0002
+#define I82802_T_MINUS06_LK 0x90002
+#define I82802_T_MINUS07_LK 0x80002
+
+#define I82802_T_MINUS08_LK 0x70002
+#define I82802_T_MINUS09_LK 0x60002
+#define I82802_T_MINUS10_LK 0x50002
+#define I82802_T_MINUS11_LK 0x40002
+#define I82802_T_MINUS12_LK 0x30002
+#define I82802_T_MINUS13_LK 0x20002
+#define I82802_T_MINUS14_LK 0x10002
+#define I82802_T_MINUS15_LK 0x00002
+
+#define I82802_GPI_REG 0xc0100
+
+#define I82802_RNG_HSR 0xc015f /* Hardware Status */
+#define I82802_RNG_DSR 0xc0160 /* Data Status */
+#define I82802_RNG_DR 0xc0161 /* Data */
/*
* T_BLOCK_LK and T_MINUS_* (block locking registers)
@@ -71,30 +80,18 @@
#define I82802_BLR_WL 0x01
/*
- * Register Based Locking Value Definitions
- * (tabe 4-6)
- */
-#define I82802_LV_FULL 0x00
-#define I82802_LV_WRITE 0x01
-#define I82802_LV_DOWN 0x02
-#define I82802_LV_READ 0x04
-
-/*
* General Purpose Inputs Register
* (table 4-7)
- */
-#define I82802_FGPI_PIN4 0x10 /* PLCC-30/T SOP-7 */
-#define I82802_FGPI_PIN3 0x08 /* PLCC-30/T SOP-15 */
-#define I82802_FGPI_PIN2 0x04 /* PLCC-30/T SOP-16 */
-#define I82802_FGPI_PIN1 0x02 /* PLCC-30/T SOP-17 */
-#define I82802_FGPI_PIN0 0x01 /* PLCC-30/T SOP-18 */
+ */ /* PLCC32/TSOP40 pin # */
+#define I82802_GPI_REG_FGPI4 0x10 /* 30 / 7 */
+#define I82802_GPI_REG_FGPI3 0x08 /* 3 / 15 */
+#define I82802_GPI_REG_FGPI2 0x04 /* 4 / 16 */
+#define I82802_GPI_REG_FGPI1 0x02 /* 5 / 17 */
+#define I82802_GPI_REG_FGPI0 0x01 /* 6 / 18 */
/*
* RNG registers
*/
-#define I82802_RNG_HWST 0xc015f
-#define I82802_RNG_HWST_PRESENT 0x40
-#define I82802_RNG_HWST_ENABLE 0x01
-#define I82802_RNG_RNGST 0xc0160
-#define I82802_RNG_RNGST_DATAV 0x01
-#define I82802_RNG_DATA 0xc0161
+#define I82802_RNG_HSR_PRESENT 0x40
+#define I82802_RNG_HSR_ENABLE 0x01
+#define I82802_RNG_DSR_VALID 0x01
Index: src/sys/arch/x86/pci/ichlpcib.c
diff -u src/sys/arch/x86/pci/ichlpcib.c:1.24 src/sys/arch/x86/pci/ichlpcib.c:1.25
--- src/sys/arch/x86/pci/ichlpcib.c:1.24 Wed Feb 24 22:37:55 2010
+++ src/sys/arch/x86/pci/ichlpcib.c Fri Jul 23 00:43:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: ichlpcib.c,v 1.24 2010/02/24 22:37:55 dyoung Exp $ */
+/* $NetBSD: ichlpcib.c,v 1.25 2010/07/23 00:43:21 jakllsch Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.24 2010/02/24 22:37:55 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ichlpcib.c,v 1.25 2010/07/23 00:43:21 jakllsch Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -65,6 +65,7 @@
#include "hpet.h"
#include "pcibvar.h"
#include "gpio.h"
+#include "fwhrng.h"
#define LPCIB_GPIO_NPINS 64
@@ -102,6 +103,10 @@
gpio_pin_t sc_gpio_pins[LPCIB_GPIO_NPINS];
#endif
+#if NFWHRNG > 0
+ device_t sc_fwhbus;
+#endif
+
/* Speedstep */
pcireg_t sc_pmcon_orig;
@@ -156,6 +161,11 @@
static void lpcib_gpio_pin_ctl(void *, int, int);
#endif
+#if NFWHRNG > 0
+static void lpcib_fwh_configure(device_t);
+static int lpcib_fwh_unconfigure(device_t, int);
+#endif
+
struct lpcib_softc *speedstep_cookie; /* XXX */
CFATTACH_DECL2_NEW(ichlpcib, sizeof(struct lpcib_softc),
@@ -291,6 +301,10 @@
lpcib_gpio_configure(self);
#endif
+#if NFWHRNG > 0
+ lpcib_fwh_configure(self);
+#endif
+
/* Install power handler */
if (!pmf_device_register1(self, lpcib_suspend, lpcib_resume,
lpcib_shutdown))
@@ -303,6 +317,12 @@
struct lpcib_softc *sc = device_private(self);
uint32_t val;
+#if NFWHRNG > 0
+ if (sc->sc_fwhbus == child) {
+ sc->sc_fwhbus = NULL;
+ return;
+ }
+#endif
#if NGPIO > 0
if (sc->sc_gpiobus == child) {
sc->sc_gpiobus = NULL;
@@ -354,6 +374,11 @@
struct lpcib_softc *sc = device_private(self);
#endif
+#if NFWHRNG > 0
+ if (ifattr_match(ifattr, "fwhichbus") && sc->sc_fwhbus == NULL)
+ lpcib_fwh_configure(self);
+#endif
+
#if NHPET > 0
if (ifattr_match(ifattr, "hpetichbus") && sc->sc_hpetbus == NULL)
lpcib_hpet_configure(self);
@@ -375,6 +400,11 @@
pmf_device_deregister(self);
+#if NFWHRNG > 0
+ if ((rc = lpcib_fwh_unconfigure(self, flags)) != 0)
+ return rc;
+#endif
+
#if NHPET > 0
if ((rc = lpcib_hpet_unconfigure(self, flags)) != 0)
return rc;
@@ -1206,3 +1236,45 @@
mutex_exit(&sc->sc_gpio_mtx);
}
#endif
+
+#if NFWHRNG > 0
+static void
+lpcib_fwh_configure(device_t self)
+{
+ struct lpcib_softc *sc = device_private(self);
+
+ pcireg_t pr;
+
+ if (sc->sc_has_rcba) {
+ /*
+ * Very unlikely to find a 82802 on a ICH6 or newer.
+ * Also the write enable register moved at that point.
+ */
+ return;
+ } else {
+ /* Enable FWH write to identify FWH. */
+ pr = pci_conf_read(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
+ 0x4c);
+ pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag,
+ 0x4c, pr|__BIT(16));
+ }
+
+ sc->sc_fwhbus = config_found_ia(self, "fwhichbus", NULL, NULL);
+
+ /* disable write */
+ pci_conf_write(sc->sc_pcib.sc_pc, sc->sc_pcib.sc_tag, 0x4c, pr);
+}
+
+static int
+lpcib_fwh_unconfigure(device_t self, int flags)
+{
+ struct lpcib_softc *sc = device_private(self);
+ int rc;
+
+ if (sc->sc_fwhbus != NULL &&
+ (rc = config_detach(sc->sc_fwhbus, flags)) != 0)
+ return rc;
+
+ return 0;
+}
+#endif
Index: src/sys/arch/x86/pci/pchb.c
diff -u src/sys/arch/x86/pci/pchb.c:1.22 src/sys/arch/x86/pci/pchb.c:1.23
--- src/sys/arch/x86/pci/pchb.c:1.22 Wed Jun 16 03:35:01 2010
+++ src/sys/arch/x86/pci/pchb.c Fri Jul 23 00:43:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: pchb.c,v 1.22 2010/06/16 03:35:01 riz Exp $ */
+/* $NetBSD: pchb.c,v 1.23 2010/07/23 00:43:21 jakllsch Exp $ */
/*-
* Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.22 2010/06/16 03:35:01 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pchb.c,v 1.23 2010/07/23 00:43:21 jakllsch Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -409,13 +409,6 @@
break;
}
-#if NRND > 0
- /*
- * Attach a random number generator, if there is one.
- */
- pchb_attach_rnd(sc, pa);
-#endif
-
if (!pmf_device_register(self, pchb_suspend, pchb_resume))
aprint_error_dev(self, "couldn't establish power handler\n");
@@ -450,21 +443,12 @@
pchbdetach(device_t self, int flags)
{
int rc;
-#if NRND > 0
- struct pchb_softc *sc = device_private(self);
-#endif
if ((rc = config_detach_children(self, flags)) != 0)
return rc;
pmf_device_deregister(self);
-#if NRND > 0
- /*
- * Attach a random number generator, if there is one.
- */
- pchb_detach_rnd(sc);
-#endif
return 0;
}
Index: src/sys/arch/x86/pci/pchbvar.h
diff -u src/sys/arch/x86/pci/pchbvar.h:1.5 src/sys/arch/x86/pci/pchbvar.h:1.6
--- src/sys/arch/x86/pci/pchbvar.h:1.5 Mon Apr 28 20:23:40 2008
+++ src/sys/arch/x86/pci/pchbvar.h Fri Jul 23 00:43:21 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: pchbvar.h,v 1.5 2008/04/28 20:23:40 martin Exp $ */
+/* $NetBSD: pchbvar.h,v 1.6 2010/07/23 00:43:21 jakllsch Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -41,16 +41,6 @@
pci_chipset_tag_t sc_pc;
pcitag_t sc_tag;
- bus_space_tag_t sc_st;
- bus_space_handle_t sc_sh;
-
- struct callout sc_rnd_ch;
- rndsource_element_t sc_rnd_source;
-
- int sc_rnd_i;
- uint32_t sc_rnd_ax;
- bool sc_rnd_attached;
-
pcireg_t sc_pciconfext[48];
};
Added files:
Index: src/sys/arch/x86/pci/fwhrng.c
diff -u /dev/null src/sys/arch/x86/pci/fwhrng.c:1.1
--- /dev/null Fri Jul 23 00:43:22 2010
+++ src/sys/arch/x86/pci/fwhrng.c Fri Jul 23 00:43:21 2010
@@ -0,0 +1,253 @@
+/* $NetBSD: fwhrng.c,v 1.1 2010/07/23 00:43:21 jakllsch Exp $ */
+
+/*
+ * Copyright (c) 2000 Michael Shalayeff
+ * 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 ``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 HIS RELATIVES 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 MIND, 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.
+ *
+ * from OpenBSD: pchb.c,v 1.23 2000/10/23 20:07:30 deraadt Exp
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: fwhrng.c,v 1.1 2010/07/23 00:43:21 jakllsch Exp $");
+
+#include "rnd.h"
+
+#if NRND == 0
+#error fwhrng requires rnd pseudo-device
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/time.h>
+#include <sys/rnd.h>
+
+#include <machine/bus.h>
+
+#include <arch/x86/pci/i82802reg.h>
+
+struct fwhrng_softc {
+ device_t sc_dev;
+
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+
+ struct callout sc_rnd_ch;
+ rndsource_element_t sc_rnd_source;
+
+ int sc_rnd_i;
+ uint32_t sc_rnd_ax;
+};
+
+static int fwhrng_match(device_t, cfdata_t, void *);
+static void fwhrng_attach(device_t, device_t, void *);
+static int fwhrng_detach(device_t, int);
+
+static void fwhrng_callout(void *v);
+
+#define FWHRNG_RETRIES 1000
+#define FWHRNG_MIN_SAMPLES 10
+
+CFATTACH_DECL_NEW(fwhrng, sizeof(struct fwhrng_softc),
+ fwhrng_match, fwhrng_attach, fwhrng_detach, NULL);
+
+static int
+fwhrng_match(device_t parent, cfdata_t match, void *aux)
+{
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ int ret;
+ uint8_t id0, id1, data0, data1;
+
+ ret = 0;
+
+ bst = x86_bus_space_mem;
+
+ /* read chip ID */
+ if (bus_space_map(bst, I82802AC_MEMBASE, I82802AC_WINSIZE, 0, &bsh))
+ return 0;
+
+ bus_space_write_1(bst, bsh, 0, 0xff); /* reset */
+ data0 = bus_space_read_1(bst, bsh, 0);
+ data1 = bus_space_read_1(bst, bsh, 1);
+ bus_space_write_1(bst, bsh, 0, 0x90); /* enter read id */
+ id0 = bus_space_read_1(bst, bsh, 0);
+ id1 = bus_space_read_1(bst, bsh, 1);
+ bus_space_write_1(bst, bsh, 0, 0xff); /* reset */
+
+ bus_space_unmap(bst, bsh, I82802AC_WINSIZE);
+
+ aprint_debug_dev(parent, "fwh: data %02x,%02x, id %02x,%02x\n",
+ data0, data1, id0, id1);
+
+ /* unlikely to have these match if we actually read the ID */
+ if ((id0 == data0) && (id1 == data1))
+ return 0;
+
+ /* check for chips with RNG */
+ if (!(id0 == I82802_MFG))
+ return 0;
+ if (!((id1 == I82802AB_ID) || (id1 == I82802AC_ID)))
+ return 0;
+
+ /* check for RNG presence */
+ if (bus_space_map(bst, I82802AC_REGBASE, I82802AC_WINSIZE, 0, &bsh))
+ return 0;
+ data0 = bus_space_read_1(bst, bsh, I82802_RNG_HSR);
+ bus_space_unmap(bst, bsh, I82802AC_WINSIZE);
+ if ((data0 & I82802_RNG_HSR_PRESENT) == I82802_RNG_HSR_PRESENT)
+ return 1;
+
+ return 0;
+}
+
+static void
+fwhrng_attach(device_t parent, device_t self, void *aux)
+{
+ struct fwhrng_softc *sc;
+ int i, j, count_ff;
+ uint8_t reg8;
+
+ sc = device_private(self);
+ sc->sc_dev = self;
+
+ aprint_naive("\n");
+ aprint_normal(": Intel Firmware Hub Random Number Generator\n");
+
+ sc->sc_st = x86_bus_space_mem;
+
+ if (bus_space_map(sc->sc_st, I82802AC_REGBASE, I82802AC_WINSIZE, 0,
+ &sc->sc_sh) != 0) {
+ aprint_error_dev(self, "unable to map registers\n");
+ return;
+ }
+
+ /* Enable the RNG. */
+ reg8 = bus_space_read_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR);
+ bus_space_write_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR,
+ reg8 | I82802_RNG_HSR_ENABLE);
+ reg8 = bus_space_read_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR);
+ if ((reg8 & I82802_RNG_HSR_ENABLE) == 0) {
+ aprint_error_dev(self, "unable to enable\n");
+ bus_space_unmap(sc->sc_st, sc->sc_sh, I82802AC_WINSIZE);
+ return;
+ }
+
+ /* Check to see if we can read data from the RNG. */
+ count_ff = 0;
+ for (j = 0; j < FWHRNG_MIN_SAMPLES; ++j) {
+ for (i = 0; i < FWHRNG_RETRIES; i++) {
+ reg8 = bus_space_read_1(sc->sc_st, sc->sc_sh,
+ I82802_RNG_DSR);
+ if (!(reg8 & I82802_RNG_DSR_VALID)) {
+ delay(10);
+ continue;
+ }
+ reg8 = bus_space_read_1(sc->sc_st, sc->sc_sh,
+ I82802_RNG_DR);
+ break;
+ }
+ if (i == FWHRNG_RETRIES) {
+ bus_space_unmap(sc->sc_st, sc->sc_sh, I82802AC_WINSIZE);
+ aprint_verbose_dev(sc->sc_dev,
+ "timeout reading test samples, RNG disabled.\n");
+ return;
+ }
+ if (reg8 == 0xff)
+ ++count_ff;
+ }
+
+ if (count_ff == FWHRNG_MIN_SAMPLES) {
+ /* Disable the RNG. */
+ reg8 = bus_space_read_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR);
+ bus_space_write_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR,
+ reg8 & ~I82802_RNG_HSR_ENABLE);
+ bus_space_unmap(sc->sc_st, sc->sc_sh, I82802AC_WINSIZE);
+ aprint_error_dev(sc->sc_dev,
+ "returns constant 0xff stream, RNG disabled.\n");
+ return;
+ }
+
+ /*
+ * Should test entropy source to ensure
+ * that it passes the Statistical Random
+ * Number Generator Tests in section 4.11.1,
+ * FIPS PUB 140-1.
+ *
+ * http://csrc.nist.gov/fips/fips1401.htm
+ */
+
+ aprint_debug_dev(sc->sc_dev, "random number generator enabled\n");
+
+ callout_init(&sc->sc_rnd_ch, 0);
+ /* FWH is polled for entropy, so no estimate is available. */
+ rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
+ RND_TYPE_RNG, RND_FLAG_NO_ESTIMATE);
+ sc->sc_rnd_i = sizeof(sc->sc_rnd_ax);
+ fwhrng_callout(sc);
+
+ return;
+}
+
+static int
+fwhrng_detach(device_t self, int flags)
+{
+ struct fwhrng_softc *sc;
+ uint8_t reg8;
+
+ sc = device_private(self);
+
+ rnd_detach_source(&sc->sc_rnd_source);
+
+ callout_stop(&sc->sc_rnd_ch);
+ callout_destroy(&sc->sc_rnd_ch);
+
+ /* Disable the RNG. */
+ reg8 = bus_space_read_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR);
+ bus_space_write_1(sc->sc_st, sc->sc_sh, I82802_RNG_HSR,
+ reg8 & ~I82802_RNG_HSR_ENABLE);
+
+ bus_space_unmap(sc->sc_st, sc->sc_sh, I82802AC_WINSIZE);
+
+ return 0;
+}
+
+static void
+fwhrng_callout(void *v)
+{
+ struct fwhrng_softc *sc = v;
+
+ if ((bus_space_read_1(sc->sc_st, sc->sc_sh, I82802_RNG_DSR) &
+ I82802_RNG_DSR_VALID) != 0) {
+ sc->sc_rnd_ax = (sc->sc_rnd_ax << NBBY) |
+ bus_space_read_1(sc->sc_st, sc->sc_sh, I82802_RNG_DR);
+ if (--sc->sc_rnd_i == 0) {
+ sc->sc_rnd_i = sizeof(sc->sc_rnd_ax);
+ rnd_add_data(&sc->sc_rnd_source, &sc->sc_rnd_ax,
+ sizeof(sc->sc_rnd_ax),
+ sizeof(sc->sc_rnd_ax) * NBBY);
+ }
+ }
+ callout_reset(&sc->sc_rnd_ch, 1, fwhrng_callout, sc);
+}