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