This source file includes following definitions.
- piixpcib_int15_gsic_call
- piixpcib_set_ownership
- piixpcib_configure_speedstep
- piixpcib_match
- piixpcib_attach
- piixpcib_getset_state
- piixpcib_setperf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/device.h>
65 #include <sys/sysctl.h>
66
67 #include <machine/bus.h>
68
69 #include <dev/pci/pcireg.h>
70 #include <dev/pci/pcivar.h>
71 #include <dev/pci/pcidevs.h>
72
73 #include <machine/cpu.h>
74 #include <machine/cpufunc.h>
75 #include <machine/kvm86.h>
76
77
78 #define PIIXPCIB_ISGE 0x47534943
79 #define PIIXPCIB_IST_CALL 0x0000e980
80 #define PIIXPCIB_GSIC_CMD 0x82
81 #define PIIXPCIB_DEFAULT_COMMAND \
82 ((PIIXPCIB_ISGE & 0xffffff00) | (PIIXPCIB_GSIC_CMD & 0xff))
83
84 #define PIIXPCIB_DEFAULT_SMI_PORT 0xb2
85 #define PIIXPCIB_DEFAULT_SMI_DATA 0xb3
86
87 #define PIIXPCIB_GETSTATE 1
88 #define PIIXPCIB_SETSTATE 2
89 #define PIIXPCIB_SPEEDSTEP_HIGH 0
90 #define PIIXPCIB_SPEEDSTEP_LOW 1
91
92 struct piixpcib_softc {
93 struct device sc_dev;
94
95 int sc_sig;
96 int sc_smi_port;
97 int sc_smi_data;
98 int sc_command;
99 int sc_flags;
100
101 int state;
102 };
103
104 int piixpcib_match(struct device *, void *, void *);
105 void piixpcib_attach(struct device *, struct device *, void *);
106
107 void piixpcib_setperf(int);
108 int piixpcib_cpuspeed(int *);
109
110 int piixpcib_set_ownership(struct piixpcib_softc *);
111 int piixpcib_configure_speedstep(struct piixpcib_softc *);
112 int piixpcib_getset_state(struct piixpcib_softc *, int *, int);
113 void piixpcib_int15_gsic_call(struct piixpcib_softc *);
114
115
116 extern void pcibattach(struct device *, struct device *, void *);
117
118
119 #if !defined(SMALL_KERNEL) && defined(I686_CPU)
120 extern void p3_update_cpuspeed(void);
121 #endif
122
123 struct cfattach piixpcib_ca = {
124 sizeof(struct piixpcib_softc),
125 piixpcib_match,
126 piixpcib_attach
127 };
128
129 struct cfdriver piixpcib_cd = {
130 NULL, "piixpcib", DV_DULL
131 };
132
133 struct piixpcib_softc *piixpcib_sc;
134 extern int setperf_prio;
135
136 const struct pci_matchid piixpcib_devices[] = {
137 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82371AB_ISA},
138 { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82440MX_PM},
139 };
140
141 void
142 piixpcib_int15_gsic_call(struct piixpcib_softc *sc)
143 {
144 struct kvm86regs regs;
145 int cmd;
146
147 memset(®s, 0, sizeof(struct kvm86regs));
148 regs.eax = PIIXPCIB_IST_CALL;
149 regs.edx = PIIXPCIB_ISGE;
150 kvm86_simplecall(0x15, ®s);
151
152 if (regs.eax == PIIXPCIB_ISGE) {
153 sc->sc_sig = regs.eax;
154 sc->sc_smi_port = regs.ebx & 0xff;
155
156 cmd = (regs.ebx >> 16) & 0xff;
157
158 if (cmd == 0x80)
159 cmd = PIIXPCIB_GSIC_CMD;
160 sc->sc_command = (sc->sc_sig & 0xffffff00) | (cmd & 0xff);
161
162 sc->sc_smi_data = regs.ecx;
163 sc->sc_flags = regs.edx;
164 }
165 }
166
167 int
168 piixpcib_set_ownership(struct piixpcib_softc *sc)
169 {
170 int rv;
171 paddr_t pmagic;
172 char magic[] = "Copyright (c) 1999 Intel Corporation";
173
174 pmap_extract(pmap_kernel(), (vaddr_t)magic, &pmagic);
175
176 __asm __volatile(
177 "movl $0, %%edi\n\t"
178 "out %%al, (%%dx)\n"
179 : "=D" (rv)
180 : "a" (sc->sc_command),
181 "b" (0),
182 "c" (0),
183 "d" (sc->sc_smi_port),
184 "S" (pmagic)
185 );
186
187 return (rv ? ENXIO : 0);
188 }
189
190 int
191 piixpcib_configure_speedstep(struct piixpcib_softc *sc)
192 {
193 int rv;
194
195 sc->sc_sig = -1;
196
197
198 sc->sc_smi_port = PIIXPCIB_DEFAULT_SMI_PORT;
199 sc->sc_smi_data = PIIXPCIB_DEFAULT_SMI_DATA;
200 sc->sc_command = PIIXPCIB_DEFAULT_COMMAND;
201 sc->sc_flags = 0;
202
203 piixpcib_int15_gsic_call(sc);
204
205
206 if (sc->sc_sig != PIIXPCIB_ISGE)
207 return ENODEV;
208
209 if (piixpcib_set_ownership(sc) != 0) {
210 printf(": unable to claim ownership from BIOS, "
211 "SpeedStep disabled");
212 return ENXIO;
213 }
214
215 rv = piixpcib_getset_state(sc, &sc->state, PIIXPCIB_GETSTATE);
216 if (rv != 0) {
217 printf(": cannot determine CPU power state, "
218 "SpeedStep disabled");
219 return ENXIO;
220 }
221
222
223 piixpcib_sc = sc;
224
225 return 0;
226 }
227
228 int
229 piixpcib_match(struct device *parent, void *match, void *aux)
230 {
231 if (pci_matchbyid((struct pci_attach_args *)aux, piixpcib_devices,
232 sizeof(piixpcib_devices) / sizeof(piixpcib_devices[0])))
233 return (2);
234 return (0);
235 }
236
237 void
238 piixpcib_attach(struct device *parent, struct device *self, void *aux)
239 {
240 struct piixpcib_softc *sc = (struct piixpcib_softc *)self;
241
242 if (setperf_prio < 2) {
243
244 if (piixpcib_configure_speedstep(sc) == 0) {
245 printf(": SpeedStep");
246
247
248 cpu_setperf = piixpcib_setperf;
249 setperf_prio = 2;
250 }
251 }
252
253
254 pcibattach(parent, self, aux);
255 }
256
257 int
258 piixpcib_getset_state(struct piixpcib_softc *sc, int *state, int function)
259 {
260 int new_state;
261 int rv;
262 int eax;
263
264 #ifdef DIAGNOSTIC
265 if (function != PIIXPCIB_GETSTATE &&
266 function != PIIXPCIB_SETSTATE) {
267 printf("%s: %s called with invalid function %d\n",
268 sc->sc_dev.dv_xname, __func__, function);
269 return EINVAL;
270 }
271 #endif
272
273 __asm __volatile(
274 "movl $0, %%edi\n\t"
275 "out %%al, (%%dx)\n"
276 : "=a" (eax),
277 "=b" (new_state),
278 "=D" (rv)
279 : "a" (sc->sc_command),
280 "b" (function),
281 "c" (*state),
282 "d" (sc->sc_smi_port),
283 "S" (0)
284 );
285
286 *state = new_state & 1;
287
288 switch (function) {
289 case PIIXPCIB_GETSTATE:
290 if (eax)
291 return ENXIO;
292 break;
293 case PIIXPCIB_SETSTATE:
294 if (rv)
295 return ENXIO;
296 break;
297 }
298
299 return 0;
300 }
301
302 void
303 piixpcib_setperf(int level)
304 {
305 struct piixpcib_softc *sc;
306 int new_state;
307 int tries, rv, s;
308
309 sc = piixpcib_sc;
310
311 #ifdef DIAGNOSTIC
312 if (sc == NULL) {
313 printf("%s: no cookie", __func__);
314 return;
315 }
316 #endif
317
318
319 if (level <= 50)
320 new_state = PIIXPCIB_SPEEDSTEP_LOW;
321 else
322 new_state = PIIXPCIB_SPEEDSTEP_HIGH;
323
324 if (sc->state == new_state)
325 return;
326
327 tries = 5;
328 s = splhigh();
329
330 do {
331 rv = piixpcib_getset_state(sc, &new_state,
332 PIIXPCIB_SETSTATE);
333 if (rv)
334 delay(200);
335 } while (rv && --tries);
336
337 splx(s);
338
339 #ifdef DIAGNOSTIC
340 if (rv)
341 printf("%s: setting CPU power state failed",
342 sc->sc_dev.dv_xname);
343 #endif
344
345 sc->state = new_state;
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367 delay(200);
368 #if !defined(SMALL_KERNEL) && defined(I686_CPU)
369 p3_update_cpuspeed();
370 #endif
371 }