mp_clock.c revision 52121
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $FreeBSD: head/sys/i386/i386/mp_clock.c 52121 1999-10-11 14:50:03Z peter $
10 *
11 */
12
13/* #include "opt_bus.h" */
14/* #include "opt_pci.h" */
15/* #include "opt_smp.h" */
16
17#include <sys/param.h>
18#include <sys/systm.h>
19#include <sys/time.h>
20#include <sys/kernel.h>
21#include <sys/sysctl.h>
22#include <sys/bus.h>
23
24#include <pci/pcivar.h>
25
26static unsigned piix_get_timecount(struct timecounter *tc);
27
28static u_int32_t piix_timecounter_address;
29static u_int piix_freq = 14318182/4;
30
31static struct timecounter piix_timecounter = {
32	piix_get_timecount,
33	0,
34	0xffffff,
35	0,
36	"PIIX"
37};
38
39SYSCTL_OPAQUE(_debug, OID_AUTO, piix_timecounter, CTLFLAG_RD,
40	&piix_timecounter, sizeof(piix_timecounter), "S,timecounter", "");
41
42static int
43sysctl_machdep_piix_freq SYSCTL_HANDLER_ARGS
44{
45	int error;
46	u_int freq;
47
48	if (piix_timecounter.tc_frequency == 0)
49		return (EOPNOTSUPP);
50	freq = piix_freq;
51	error = sysctl_handle_int(oidp, &freq, sizeof(freq), req);
52	if (error == 0 && req->newptr != NULL) {
53		piix_freq = freq;
54		piix_timecounter.tc_frequency = piix_freq;
55		update_timecounter(&piix_timecounter);
56	}
57	return (error);
58}
59
60SYSCTL_PROC(_machdep, OID_AUTO, piix_freq, CTLTYPE_INT | CTLFLAG_RW,
61    0, sizeof(u_int), sysctl_machdep_piix_freq, "I", "");
62
63static unsigned
64piix_get_timecount(struct timecounter *tc)
65{
66	return (inl(piix_timecounter_address));
67}
68
69static int
70piix_probe (device_t dev)
71{
72	u_int32_t	d;
73
74	switch (pci_get_devid(dev)) {
75	case 0x71138086:
76		d = pci_read_config(dev, 0x4, 2);
77		if (!(d & 1))
78			return 0;	/* IO space not mapped */
79		d = pci_read_config(dev, 0x40, 4);
80		piix_timecounter_address = (d & 0xffc0) + 8;
81		piix_timecounter.tc_frequency = piix_freq;
82		init_timecounter(&piix_timecounter);
83		return (ENXIO);
84	};
85	return (ENXIO);
86}
87
88static int
89piix_attach (device_t dev)
90{
91
92	return 0;
93}
94
95static device_method_t piix_methods[] = {
96	/* Device interface */
97	DEVMETHOD(device_probe,		piix_probe),
98	DEVMETHOD(device_attach,	piix_attach),
99	{ 0, 0 }
100};
101
102static driver_t piix_driver = {
103	"piix",
104	piix_methods,
105	1,
106};
107
108static devclass_t piix_devclass;
109
110DRIVER_MODULE(piix, pci, piix_driver, piix_devclass, 0, 0);
111