Index: share/man/man4/atrtc.4 =================================================================== --- share/man/man4/atrtc.4 +++ share/man/man4/atrtc.4 @@ -33,13 +33,18 @@ .Sh SYNOPSIS This driver is a mandatory part of i386/amd64 kernels. .Pp -The following tunable is settable from the +The following tunables are settable from the .Xr loader 8 : .Bl -ohang .It Va hint.atrtc. Ns Ar X Ns Va .clock controls event timers functionality support. Setting to 0, disables it. Default value is 1. +.It Va hw.atrtc.enable +Forces enabling or disabling of the device(s). +Setting to 0 disables it, setting to 1 enables it, bypassing any platform +configuration hints. +Default value is -1 (autodetect). .El .Sh DESCRIPTION This driver uses RTC hardware to supply kernel with time-of-day clock Index: sys/x86/isa/atrtc.c =================================================================== --- sys/x86/isa/atrtc.c +++ sys/x86/isa/atrtc.c @@ -32,6 +32,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_acpi.h" #include "opt_isa.h" #include @@ -55,6 +56,10 @@ #include #include "clock_if.h" +#ifdef DEV_ACPI +#include +#endif + /* * clock_lock protects low-level access to individual hardware registers. * atrtc_time_lock protects the entire sequence of accessing multiple registers @@ -63,6 +68,10 @@ #define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0) #define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0) +/* Force RTC enabled/disabled. */ +static int atrtc_enabled = -1; +TUNABLE_INT("hw.atrtc.enabled", &atrtc_enabled); + struct mtx atrtc_time_lock; MTX_SYSINIT(atrtc_lock_init, &atrtc_time_lock, "atrtc", MTX_DEF); @@ -241,11 +250,43 @@ { 0 } }; +static bool +atrtc_acpi_disabled(void) +{ +#ifdef DEV_ACPI + ACPI_TABLE_FADT *fadt; + vm_paddr_t physaddr; + uint16_t flags; + + physaddr = acpi_find_table(ACPI_SIG_FADT); + if (physaddr == 0) + return (false); + + fadt = acpi_map_table(physaddr, ACPI_SIG_FADT); + if (fadt == NULL) { + printf("at_rtc: unable to map FADT ACPI table\n"); + return (false); + } + + flags = fadt->BootFlags; + acpi_unmap_table(fadt); + + if (flags & ACPI_FADT_NO_CMOS_RTC) + return (true); +#endif + + return (false); +} + static int atrtc_probe(device_t dev) { int result; - + + if ((atrtc_enabled == -1 && atrtc_acpi_disabled()) || + (atrtc_enabled == 0)) + return (ENXIO); + result = ISA_PNP_PROBE(device_get_parent(dev), dev, atrtc_ids); /* ENOENT means no PnP-ID, device is hinted. */ if (result == ENOENT) {