1 /* $NetBSD: pchb_rnd.c,v 1.8 2008/03/04 15:33:06 cube Exp $ */
4 * Copyright (c) 2000 Michael Shalayeff
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
28 * from OpenBSD: pchb.c,v 1.23 2000/10/23 20:07:30 deraadt Exp
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: pchb_rnd.c,v 1.8 2008/03/04 15:33:06 cube Exp $");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
39 #include <machine/bus.h>
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcidevs.h>
45 #include <arch/x86/pci/i82802reg.h>
46 #include <arch/x86/pci/pchbvar.h>
48 static void pchb_rnd_callout(void *v
);
50 #define PCHB_RNG_RETRIES 1000
51 #define PCHB_RNG_MIN_SAMPLES 10
54 pchb_detach_rnd(struct pchb_softc
*sc
)
58 if (!sc
->sc_rnd_attached
)
61 /* pch is polled for entropy, so no estimate is available. */
62 rnd_detach_source(&sc
->sc_rnd_source
);
64 callout_stop(&sc
->sc_rnd_ch
);
65 callout_destroy(&sc
->sc_rnd_ch
);
67 /* Disable the RNG. */
68 reg8
= bus_space_read_1(sc
->sc_st
, sc
->sc_sh
, I82802_RNG_HWST
);
69 bus_space_write_1(sc
->sc_st
, sc
->sc_sh
, I82802_RNG_HWST
,
70 reg8
& ~I82802_RNG_HWST_ENABLE
);
72 bus_space_unmap(sc
->sc_st
, sc
->sc_sh
, I82802_IOSIZE
);
74 sc
->sc_rnd_attached
= false;
78 pchb_attach_rnd(struct pchb_softc
*sc
, struct pci_attach_args
*pa
)
83 if (PCI_VENDOR(pa
->pa_id
) != PCI_VENDOR_INTEL
)
86 switch (PCI_PRODUCT(pa
->pa_id
)) {
88 /* Old chipsets which only support IA32 CPUs. */
89 case PCI_PRODUCT_INTEL_82810E_MCH
:
90 case PCI_PRODUCT_INTEL_82810_DC100_MCH
:
91 case PCI_PRODUCT_INTEL_82810_MCH
:
92 case PCI_PRODUCT_INTEL_82815_DC100_HUB
:
93 case PCI_PRODUCT_INTEL_82815_NOAGP_HUB
:
94 case PCI_PRODUCT_INTEL_82815_NOGRAPH_HUB
:
95 case PCI_PRODUCT_INTEL_82815_FULL_HUB
:
96 case PCI_PRODUCT_INTEL_82820_MCH
:
97 case PCI_PRODUCT_INTEL_82840_HB
:
98 case PCI_PRODUCT_INTEL_82845_HB
:
99 case PCI_PRODUCT_INTEL_82850_HB
:
100 case PCI_PRODUCT_INTEL_82860_HB
:
101 case PCI_PRODUCT_INTEL_82865_HB
:
102 case PCI_PRODUCT_INTEL_82875P_HB
:
103 #endif /* defined((__i386__) */
104 /* New chipsets which support EM64T CPUs. */
105 case PCI_PRODUCT_INTEL_82915G_HB
:
106 case PCI_PRODUCT_INTEL_82915GM_HB
:
107 case PCI_PRODUCT_INTEL_82925X_HB
:
108 case PCI_PRODUCT_INTEL_82945P_MCH
:
109 case PCI_PRODUCT_INTEL_82955X_HB
:
115 sc
->sc_st
= pa
->pa_memt
;
116 if (bus_space_map(sc
->sc_st
, I82802_IOBASE
, I82802_IOSIZE
, 0,
119 * Unable to map control registers, punt,
120 * but don't bother issuing a warning.
125 reg8
= bus_space_read_1(sc
->sc_st
, sc
->sc_sh
,
127 if ((reg8
& I82802_RNG_HWST_PRESENT
) == 0) {
129 * Random number generator is not present.
131 bus_space_unmap(sc
->sc_st
, sc
->sc_sh
, I82802_IOSIZE
);
135 /* Enable the RNG. */
136 bus_space_write_1(sc
->sc_st
, sc
->sc_sh
,
137 I82802_RNG_HWST
, reg8
| I82802_RNG_HWST_ENABLE
);
138 reg8
= bus_space_read_1(sc
->sc_st
, sc
->sc_sh
, I82802_RNG_HWST
);
139 if ((reg8
& I82802_RNG_HWST_ENABLE
) == 0) {
141 * Couldn't enable the RNG.
143 bus_space_unmap(sc
->sc_st
, sc
->sc_sh
, I82802_IOSIZE
);
147 /* Check to see if we can read data from the RNG. */
149 for (j
= 0; j
< PCHB_RNG_MIN_SAMPLES
; ++j
) {
150 for (i
= 0; i
< PCHB_RNG_RETRIES
; i
++) {
151 reg8
= bus_space_read_1(sc
->sc_st
, sc
->sc_sh
,
153 if (!(reg8
& I82802_RNG_RNGST_DATAV
)) {
157 reg8
= bus_space_read_1(sc
->sc_st
, sc
->sc_sh
,
161 if (i
== PCHB_RNG_RETRIES
) {
162 bus_space_unmap(sc
->sc_st
, sc
->sc_sh
, I82802_IOSIZE
);
163 aprint_verbose_dev(sc
->sc_dev
,
164 "timeout reading test samples, RNG disabled.\n");
171 if (count_ff
== PCHB_RNG_MIN_SAMPLES
) {
172 bus_space_unmap(sc
->sc_st
, sc
->sc_sh
, I82802_IOSIZE
);
173 aprint_verbose_dev(sc
->sc_dev
,
174 "returns constant 0xff stream, RNG disabled.\n");
179 * Should test entropy source to ensure
180 * that it passes the Statistical Random
181 * Number Generator Tests in section 4.11.1,
184 * http://csrc.nist.gov/fips/fips1401.htm
187 aprint_normal_dev(sc
->sc_dev
, "random number generator enabled\n");
189 callout_init(&sc
->sc_rnd_ch
, 0);
190 /* pch is polled for entropy, so no estimate is available. */
191 rnd_attach_source(&sc
->sc_rnd_source
, device_xname(sc
->sc_dev
),
192 RND_TYPE_RNG
, RND_FLAG_NO_ESTIMATE
);
193 sc
->sc_rnd_i
= sizeof(sc
->sc_rnd_ax
);
194 pchb_rnd_callout(sc
);
195 sc
->sc_rnd_attached
= true;
199 pchb_rnd_callout(void *v
)
201 struct pchb_softc
*sc
= v
;
203 if ((bus_space_read_1(sc
->sc_st
, sc
->sc_sh
, I82802_RNG_RNGST
) &
204 I82802_RNG_RNGST_DATAV
) != 0) {
205 sc
->sc_rnd_ax
= (sc
->sc_rnd_ax
<< NBBY
) |
206 bus_space_read_1(sc
->sc_st
, sc
->sc_sh
, I82802_RNG_DATA
);
207 if (--sc
->sc_rnd_i
== 0) {
208 sc
->sc_rnd_i
= sizeof(sc
->sc_rnd_ax
);
209 rnd_add_data(&sc
->sc_rnd_source
, &sc
->sc_rnd_ax
,
210 sizeof(sc
->sc_rnd_ax
),
211 sizeof(sc
->sc_rnd_ax
) * NBBY
);
214 callout_reset(&sc
->sc_rnd_ch
, 1, pchb_rnd_callout
, sc
);