|
Lines 31-36
Link Here
|
| 31 |
__FBSDID("$FreeBSD$"); |
31 |
__FBSDID("$FreeBSD$"); |
| 32 |
|
32 |
|
| 33 |
#include "opt_isa.h" |
33 |
#include "opt_isa.h" |
|
|
34 |
#include "opt_acpi.h" |
| 34 |
|
35 |
|
| 35 |
#include <sys/param.h> |
36 |
#include <sys/param.h> |
| 36 |
#include <sys/systm.h> |
37 |
#include <sys/systm.h> |
|
Lines 53-67
__FBSDID("$FreeBSD$");
Link Here
|
| 53 |
#include <machine/intr_machdep.h> |
54 |
#include <machine/intr_machdep.h> |
| 54 |
#include "clock_if.h" |
55 |
#include "clock_if.h" |
| 55 |
|
56 |
|
|
|
57 |
#include <contrib/dev/acpica/include/acpi.h> |
| 58 |
#include <contrib/dev/acpica/include/accommon.h> |
| 59 |
#include <dev/acpica/acpivar.h> |
| 60 |
|
| 56 |
#define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0) |
61 |
#define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0) |
| 57 |
#define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0) |
62 |
#define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0) |
| 58 |
|
63 |
|
|
|
64 |
#define IO_DELAY() (void)inb(0x84) |
| 65 |
#define IO_RTC_ADDR (IO_RTC + 0) |
| 66 |
#define IO_RTC_DATA (IO_RTC + 1) |
| 67 |
|
| 59 |
int atrtcclock_disable = 0; |
68 |
int atrtcclock_disable = 0; |
| 60 |
|
69 |
|
| 61 |
static int rtc_reg = -1; |
70 |
static int rtc_reg = -1; |
| 62 |
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; |
71 |
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; |
| 63 |
static u_char rtc_statusb = RTCSB_24HR; |
72 |
static u_char rtc_statusb = RTCSB_24HR; |
| 64 |
|
73 |
|
|
|
74 |
#ifndef ATRTC_VERBOSE |
| 75 |
#define ATRTC_VERBOSE 1 |
| 76 |
#endif |
| 77 |
|
| 78 |
static unsigned int atrtc_verbose = ATRTC_VERBOSE; |
| 79 |
SYSCTL_UINT(_debug, OID_AUTO, atrtc_verbose, CTLFLAG_RWTUN, |
| 80 |
&atrtc_verbose, 0, "AT-RTC Debug Level (0-2)"); |
| 81 |
#define ATRTC_DBG_PRINTF(level, format, ...) \ |
| 82 |
if (atrtc_verbose >= level) printf(format, ##__VA_ARGS__) |
| 83 |
|
| 65 |
/* |
84 |
/* |
| 66 |
* RTC support routines |
85 |
* RTC support routines |
| 67 |
*/ |
86 |
*/ |
|
Lines 73-82
rtcin(int reg)
Link Here
|
| 73 |
|
92 |
|
| 74 |
RTC_LOCK; |
93 |
RTC_LOCK; |
| 75 |
if (rtc_reg != reg) { |
94 |
if (rtc_reg != reg) { |
| 76 |
inb(0x84); |
95 |
IO_DELAY(); |
| 77 |
outb(IO_RTC, reg); |
96 |
outb(IO_RTC, reg); |
| 78 |
rtc_reg = reg; |
97 |
rtc_reg = reg; |
| 79 |
inb(0x84); |
98 |
IO_DELAY(); |
| 80 |
} |
99 |
} |
| 81 |
val = inb(IO_RTC + 1); |
100 |
val = inb(IO_RTC + 1); |
| 82 |
RTC_UNLOCK; |
101 |
RTC_UNLOCK; |
|
Lines 89-104
writertc(int reg, u_char val)
Link Here
|
| 89 |
|
108 |
|
| 90 |
RTC_LOCK; |
109 |
RTC_LOCK; |
| 91 |
if (rtc_reg != reg) { |
110 |
if (rtc_reg != reg) { |
| 92 |
inb(0x84); |
111 |
IO_DELAY(); |
| 93 |
outb(IO_RTC, reg); |
112 |
outb(IO_RTC, reg); |
| 94 |
rtc_reg = reg; |
113 |
rtc_reg = reg; |
| 95 |
inb(0x84); |
114 |
IO_DELAY(); |
| 96 |
} |
115 |
} |
| 97 |
outb(IO_RTC + 1, val); |
116 |
outb(IO_RTC + 1, val); |
| 98 |
inb(0x84); |
117 |
IO_DELAY(); |
| 99 |
RTC_UNLOCK; |
118 |
RTC_UNLOCK; |
| 100 |
} |
119 |
} |
| 101 |
|
120 |
|
|
|
121 |
static void |
| 122 |
acpi_cmos_read(ACPI_PHYSICAL_ADDRESS address, UINT8 *buf, UINT32 buflen) |
| 123 |
{ |
| 124 |
UINT32 offset; |
| 125 |
|
| 126 |
for (offset = 0; offset < buflen; ++offset) { |
| 127 |
buf[offset] = rtcin(address + offset) & 0xff; |
| 128 |
} |
| 129 |
} |
| 130 |
|
| 131 |
static void |
| 132 |
acpi_cmos_write(ACPI_PHYSICAL_ADDRESS address, const UINT8 *buf, UINT32 buflen) |
| 133 |
{ |
| 134 |
UINT32 offset; |
| 135 |
|
| 136 |
for (offset = 0; offset < buflen; ++offset) { |
| 137 |
writertc(address + offset, buf[offset]); |
| 138 |
} |
| 139 |
} |
| 140 |
|
| 102 |
static __inline int |
141 |
static __inline int |
| 103 |
readrtc(int port) |
142 |
readrtc(int port) |
| 104 |
{ |
143 |
{ |
|
Lines 161-169
struct atrtc_softc {
Link Here
|
| 161 |
struct resource *intr_res; |
200 |
struct resource *intr_res; |
| 162 |
void *intr_handler; |
201 |
void *intr_handler; |
| 163 |
struct eventtimer et; |
202 |
struct eventtimer et; |
|
|
203 |
ACPI_HANDLE acpi_handle; /* Handle of the PNP0B00 node */ |
| 204 |
int acpi_handle_registered; /* 0 = acpi_handle not registered */ |
| 164 |
}; |
205 |
}; |
| 165 |
|
206 |
|
| 166 |
static int |
207 |
static int |
|
|
208 |
acpi_check_rtc_access(int is_read, u_long addr, u_long len) |
| 209 |
{ |
| 210 |
int retval = 1; /* Success */ |
| 211 |
|
| 212 |
if (is_read) { |
| 213 |
/* Reading 0x0C will muck with interrupts */ |
| 214 |
if (addr + len - 1 >= 0x0C && addr <= 0x0c) |
| 215 |
retval = 0; |
| 216 |
} else { |
| 217 |
/* Allow single-byte writes to alarm registers and |
| 218 |
* addr >= 0x30, else deny. |
| 219 |
*/ |
| 220 |
if (!((len == 1 && (addr <= 5 && (addr & 1))) || addr >= 0x30)) |
| 221 |
retval = 0; |
| 222 |
} |
| 223 |
return retval; |
| 224 |
} |
| 225 |
|
| 226 |
static ACPI_STATUS |
| 227 |
acpi_rtc_cmos_handler(UINT32 func, ACPI_PHYSICAL_ADDRESS addr, |
| 228 |
UINT32 bitwidth, UINT64 *value, void *context, void *region_context) |
| 229 |
{ |
| 230 |
struct atrtc_softc *sc; |
| 231 |
UINT32 bytewidth = bitwidth >> 3; |
| 232 |
|
| 233 |
sc = (struct atrtc_softc *)context; |
| 234 |
if (!value || !sc) { |
| 235 |
ATRTC_DBG_PRINTF(1, "NULL parameter.\n"); |
| 236 |
return AE_BAD_PARAMETER; |
| 237 |
} |
| 238 |
if (bitwidth == 0 || bitwidth > 32 || (bitwidth & 0x07) || |
| 239 |
addr + bytewidth - 1 > 63) { |
| 240 |
ATRTC_DBG_PRINTF(1, |
| 241 |
"Invalid bitwidth (%u) or addr (0x%08lx).\n", |
| 242 |
bitwidth, addr); |
| 243 |
return AE_BAD_PARAMETER; |
| 244 |
} |
| 245 |
if (!acpi_check_rtc_access(func == ACPI_READ, addr, bytewidth)) { |
| 246 |
ATRTC_DBG_PRINTF(1, "Bad CMOS %s access at addr 0x%08lx.\n", |
| 247 |
func == ACPI_READ ? "read" : "write", addr); |
| 248 |
return AE_BAD_PARAMETER; |
| 249 |
} |
| 250 |
|
| 251 |
switch (func) { |
| 252 |
case ACPI_READ: |
| 253 |
acpi_cmos_read(addr, (UINT8 *)value, bytewidth); |
| 254 |
break; |
| 255 |
case ACPI_WRITE: |
| 256 |
acpi_cmos_write(addr, (const UINT8 *)value, bytewidth); |
| 257 |
break; |
| 258 |
default: |
| 259 |
ATRTC_DBG_PRINTF(1, "Invalid function: %d.\n", func); |
| 260 |
return AE_BAD_PARAMETER; |
| 261 |
} |
| 262 |
ATRTC_DBG_PRINTF(1, "%-5s%02u addr=%04lx val=%08x\n", |
| 263 |
func == ACPI_READ ? "READ" : "WRITE", bytewidth, |
| 264 |
addr, *((UINT32 *)value)); |
| 265 |
return AE_OK; |
| 266 |
} |
| 267 |
|
| 268 |
static int |
| 167 |
rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period) |
269 |
rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period) |
| 168 |
{ |
270 |
{ |
| 169 |
|
271 |
|
|
Lines 245-254
atrtc_attach(device_t dev)
Link Here
|
| 245 |
int i; |
347 |
int i; |
| 246 |
|
348 |
|
| 247 |
sc = device_get_softc(dev); |
349 |
sc = device_get_softc(dev); |
|
|
350 |
sc->acpi_handle = acpi_get_handle(dev); |
| 248 |
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, |
351 |
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, |
| 249 |
IO_RTC, IO_RTC + 1, 2, RF_ACTIVE); |
352 |
IO_RTC, IO_RTC + 1, 2, RF_ACTIVE); |
| 250 |
if (sc->port_res == NULL) |
353 |
if (sc->port_res == NULL) |
| 251 |
device_printf(dev, "Warning: Couldn't map I/O.\n"); |
354 |
device_printf(dev, "Warning: Couldn't map I/O.\n"); |
|
|
355 |
if (ACPI_FAILURE(AcpiInstallAddressSpaceHandler(sc->acpi_handle, |
| 356 |
ACPI_ADR_SPACE_CMOS, |
| 357 |
acpi_rtc_cmos_handler, NULL, sc))) |
| 358 |
{ |
| 359 |
device_printf(dev, "Warning: Couldn't register ACPI CMOS address space handler.\n"); |
| 360 |
/* I assume the softc was memset() to 0? */ |
| 361 |
} else |
| 362 |
sc->acpi_handle_registered = 1; |
| 252 |
atrtc_start(); |
363 |
atrtc_start(); |
| 253 |
clock_register(dev, 1000000); |
364 |
clock_register(dev, 1000000); |
| 254 |
bzero(&sc->et, sizeof(struct eventtimer)); |
365 |
bzero(&sc->et, sizeof(struct eventtimer)); |
|
Lines 286-291
atrtc_attach(device_t dev)
Link Here
|
| 286 |
return(0); |
397 |
return(0); |
| 287 |
} |
398 |
} |
| 288 |
|
399 |
|
|
|
400 |
static int atrtc_detach(device_t dev) |
| 401 |
{ |
| 402 |
struct atrtc_softc *sc; |
| 403 |
|
| 404 |
sc = device_get_softc(dev); |
| 405 |
if (sc->acpi_handle_registered) |
| 406 |
AcpiRemoveAddressSpaceHandler(sc->acpi_handle, |
| 407 |
ACPI_ADR_SPACE_CMOS, acpi_rtc_cmos_handler); |
| 408 |
return bus_generic_detach(dev); |
| 409 |
} |
| 410 |
|
| 289 |
static int |
411 |
static int |
| 290 |
atrtc_resume(device_t dev) |
412 |
atrtc_resume(device_t dev) |
| 291 |
{ |
413 |
{ |
|
Lines 366-372
static device_method_t atrtc_methods[] = {
Link Here
|
| 366 |
/* Device interface */ |
488 |
/* Device interface */ |
| 367 |
DEVMETHOD(device_probe, atrtc_probe), |
489 |
DEVMETHOD(device_probe, atrtc_probe), |
| 368 |
DEVMETHOD(device_attach, atrtc_attach), |
490 |
DEVMETHOD(device_attach, atrtc_attach), |
| 369 |
DEVMETHOD(device_detach, bus_generic_detach), |
491 |
DEVMETHOD(device_detach, atrtc_detach), |
| 370 |
DEVMETHOD(device_shutdown, bus_generic_shutdown), |
492 |
DEVMETHOD(device_shutdown, bus_generic_shutdown), |
| 371 |
DEVMETHOD(device_suspend, bus_generic_suspend), |
493 |
DEVMETHOD(device_suspend, bus_generic_suspend), |
| 372 |
/* XXX stop statclock? */ |
494 |
/* XXX stop statclock? */ |