Annotation of sys/arch/amd64/pci/pchb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pchb.c,v 1.10 2007/07/04 21:30:48 ckuethe Exp $ */
2: /* $NetBSD: pchb.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
3: /*
4: * Copyright (c) 2000 Michael Shalayeff
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
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.
15: *
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.
27: */
28: /*-
29: * Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc.
30: * All rights reserved.
31: *
32: * This code is derived from software contributed to The NetBSD Foundation
33: * by Jason R. Thorpe.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the NetBSD
46: * Foundation, Inc. and its contributors.
47: * 4. Neither the name of The NetBSD Foundation nor the names of its
48: * contributors may be used to endorse or promote products derived
49: * from this software without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
52: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
55: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61: * POSSIBILITY OF SUCH DAMAGE.
62: */
63:
64: #include <sys/types.h>
65: #include <sys/param.h>
66: #include <sys/systm.h>
67: #include <sys/device.h>
68: #include <sys/timeout.h>
69:
70: #include <machine/bus.h>
71:
72: #include <dev/pci/pcivar.h>
73: #include <dev/pci/pcireg.h>
74: #include <dev/pci/pcidevs.h>
75:
76: #include <dev/rndvar.h>
77:
78: #include <dev/ic/i82802reg.h>
79:
80: #define PCISET_BRIDGETYPE_MASK 0x3
81: #define PCISET_TYPE_COMPAT 0x1
82: #define PCISET_TYPE_AUX 0x2
83:
84: #define PCISET_BUSCONFIG_REG 0x48
85: #define PCISET_BRIDGE_NUMBER(reg) (((reg) >> 8) & 0xff)
86: #define PCISET_PCI_BUS_NUMBER(reg) (((reg) >> 16) & 0xff)
87:
88: /* XXX should be in dev/ic/i82443reg.h */
89: #define I82443BX_SDRAMC_REG 0x76
90:
91: /* XXX should be in dev/ic/i82424{reg.var}.h */
92: #define I82424_CPU_BCTL_REG 0x53
93: #define I82424_PCI_BCTL_REG 0x54
94:
95: #define I82424_BCTL_CPUMEM_POSTEN 0x01
96: #define I82424_BCTL_CPUPCI_POSTEN 0x02
97: #define I82424_BCTL_PCIMEM_BURSTEN 0x01
98: #define I82424_BCTL_PCI_BURSTEN 0x02
99:
100: /* XXX should be in dev/ic/amd64htreg.h */
101: #define AMD64HT_LDT0_BUS 0x94
102: #define AMD64HT_LDT0_TYPE 0x98
103: #define AMD64HT_LDT1_BUS 0xb4
104: #define AMD64HT_LDT1_TYPE 0xb8
105: #define AMD64HT_LDT2_BUS 0xd4
106: #define AMD64HT_LDT2_TYPE 0xd8
107:
108: #define AMD64HT_NUM_LDT 3
109:
110: #define AMD64HT_LDT_TYPE_MASK 0x0000001f
111: #define AMD64HT_LDT_INIT_COMPLETE 0x00000002
112: #define AMD64HT_LDT_NC 0x00000004
113:
114: #define AMD64HT_LDT_SEC_BUS_NUM(reg) (((reg) >> 8) & 0xff)
115:
116: struct pchb_softc {
117: struct device sc_dev;
118:
119: bus_space_tag_t sc_bt;
120: bus_space_handle_t sc_bh;
121:
122: int sc_rnd_i;
123: u_int32_t sc_rnd_ax;
124: struct timeout sc_rnd_to;
125: };
126:
127: int pchbmatch(struct device *, void *, void *);
128: void pchbattach(struct device *, struct device *, void *);
129:
130: int pchb_print(void *, const char *);
131: void pchb_rnd(void *);
132: void pchb_amd64ht_attach (struct device *, struct pci_attach_args *, int);
133:
134: struct cfattach pchb_ca = {
135: sizeof(struct pchb_softc), pchbmatch, pchbattach,
136: };
137:
138: struct cfdriver pchb_cd = {
139: NULL, "pchb", DV_DULL
140: };
141:
142: int
143: pchbmatch(struct device *parent, void *match, void *aux)
144: {
145: struct pci_attach_args *pa = aux;
146:
147: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
148: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) {
149: return (1);
150: }
151:
152: return (0);
153: }
154:
155: void
156: pchbattach(struct device *parent, struct device *self, void *aux)
157: {
158: struct pchb_softc *sc = (struct pchb_softc *)self;
159: struct pci_attach_args *pa = aux;
160: struct timeval tv1, tv2;
161: int i, r;
162:
163: switch (PCI_VENDOR(pa->pa_id)) {
164: case PCI_VENDOR_AMD:
165: switch (PCI_PRODUCT(pa->pa_id)) {
166: case PCI_PRODUCT_AMD_AMD64_HT:
167: for (i = 0; i < AMD64HT_NUM_LDT; i++)
168: pchb_amd64ht_attach(self, pa, i);
169: break;
170: }
171: break;
172: case PCI_VENDOR_INTEL:
173: #ifdef PCIAGP
174: pciagp_set_pchb(pa);
175: #endif
176: switch (PCI_PRODUCT(pa->pa_id)) {
177: case PCI_PRODUCT_INTEL_82915G_HB:
178: case PCI_PRODUCT_INTEL_82925X_HB:
179: case PCI_PRODUCT_INTEL_82945GP_MCH:
180: case PCI_PRODUCT_INTEL_82955X_HB:
181: sc->sc_bt = pa->pa_memt;
182: if (bus_space_map(sc->sc_bt, I82802_IOBASE,
183: I82802_IOSIZE, 0, &sc->sc_bh)) {
184: break;
185: }
186:
187: /* probe and init rng */
188: if (!(bus_space_read_1(sc->sc_bt, sc->sc_bh,
189: I82802_RNG_HWST) & I82802_RNG_HWST_PRESENT)) {
190: break;
191: }
192:
193: /* enable RNG */
194: bus_space_write_1(sc->sc_bt, sc->sc_bh,
195: I82802_RNG_HWST,
196: bus_space_read_1(sc->sc_bt, sc->sc_bh,
197: I82802_RNG_HWST) | I82802_RNG_HWST_ENABLE);
198:
199: /* see if we can read anything */
200: for (i = 1000; i-- &&
201: !(bus_space_read_1(sc->sc_bt,sc->sc_bh,
202: I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV);)
203: DELAY(10);
204:
205: if (!(bus_space_read_1(sc->sc_bt, sc->sc_bh,
206: I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV)) {
207: break;
208: }
209:
210: r = bus_space_read_1(sc->sc_bt, sc->sc_bh,
211: I82802_RNG_DATA);
212:
213: /* benchmark the RNG */
214: microtime(&tv1);
215: for (i = 8 * 1024; i--; ) {
216: while(!(bus_space_read_1(sc->sc_bt, sc->sc_bh,
217: I82802_RNG_RNGST) & I82802_RNG_RNGST_DATAV))
218: ;
219: r = bus_space_read_1(sc->sc_bt, sc->sc_bh,
220: I82802_RNG_DATA);
221: }
222: microtime(&tv2);
223:
224: timersub(&tv2, &tv1, &tv1);
225: if (tv1.tv_sec)
226: tv1.tv_usec += 1000000 * tv1.tv_sec;
227: printf(": rng active");
228: if (tv1.tv_usec != 0)
229: printf(", %dKb/sec",
230: 8 * 1000000 / tv1.tv_usec);
231:
232: timeout_set(&sc->sc_rnd_to, pchb_rnd, sc);
233: sc->sc_rnd_i = 4;
234: pchb_rnd(sc);
235: break;
236: }
237: break;
238: }
239: printf("\n");
240: }
241:
242: int
243: pchb_print(void *aux, const char *pnp)
244: {
245: struct pcibus_attach_args *pba = aux;
246:
247: if (pnp)
248: printf("%s at %s", pba->pba_busname, pnp);
249: printf(" bus %d", pba->pba_bus);
250: return (UNCONF);
251: }
252:
253: void
254: pchb_amd64ht_attach(struct device *self, struct pci_attach_args *pa, int i)
255: {
256: struct pcibus_attach_args pba;
257: pcireg_t type, bus;
258: int reg;
259:
260: reg = AMD64HT_LDT0_TYPE + i * 0x20;
261: type = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
262: if ((type & AMD64HT_LDT_INIT_COMPLETE) == 0 ||
263: (type & AMD64HT_LDT_NC) == 0)
264: return;
265:
266: reg = AMD64HT_LDT0_BUS + i * 0x20;
267: bus = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
268: if (AMD64HT_LDT_SEC_BUS_NUM(bus) > 0) {
269: pba.pba_busname = "pci";
270: pba.pba_iot = pa->pa_iot;
271: pba.pba_memt = pa->pa_memt;
272: pba.pba_dmat = pa->pa_dmat;
273: pba.pba_bus = AMD64HT_LDT_SEC_BUS_NUM(bus);
274: pba.pba_bridgetag = NULL;
275: pba.pba_pc = pa->pa_pc;
276: config_found(self, &pba, pchb_print);
277: }
278: }
279:
280: /*
281: * Should do FIPS testing as per:
282: * http://csrc.nist.gov/publications/fips/fips140-1/fips1401.pdf
283: */
284: void
285: pchb_rnd(void *v)
286: {
287: struct pchb_softc *sc = v;
288:
289: /*
290: * Don't wait for data to be ready. If it's not there, we'll check
291: * next time.
292: */
293: if ((bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_RNGST) &
294: I82802_RNG_RNGST_DATAV)) {
295:
296: sc->sc_rnd_ax = (sc->sc_rnd_ax << 8) |
297: bus_space_read_1(sc->sc_bt, sc->sc_bh, I82802_RNG_DATA);
298:
299: if (!sc->sc_rnd_i--) {
300: sc->sc_rnd_i = 4;
301: add_true_randomness(sc->sc_rnd_ax);
302: }
303: }
304:
305: timeout_add(&sc->sc_rnd_to, 1);
306: }
CVSweb