Attachment 'atrtc.c-20140829.patch'
Download 1 Index: sys/x86/isa/atrtc.c
2 ===================================================================
3 --- sys/x86/isa/atrtc.c (revision 268728)
4 +++ sys/x86/isa/atrtc.c (working copy)
5 @@ -31,6 +31,7 @@
6 __FBSDID("$FreeBSD$");
7
8 #include "opt_isa.h"
9 +#include "opt_acpi.h"
10
11 #include <sys/param.h>
12 #include <sys/systm.h>
13 @@ -53,12 +54,19 @@
14 #include <machine/intr_machdep.h>
15 #include "clock_if.h"
16
17 +#include <contrib/dev/acpica/include/acpi.h>
18 +#include <contrib/dev/acpica/include/accommon.h>
19 +#include <dev/acpica/acpivar.h>
20 +
21 #define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0)
22 #define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0)
23
24 +#define IO_DELAY() (void)inb(0x84)
25 +#define IO_RTC_ADDR (IO_RTC + 0)
26 +#define IO_RTC_DATA (IO_RTC + 1)
27 +
28 int atrtcclock_disable = 0;
29
30 -static int rtc_reg = -1;
31 static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
32 static u_char rtc_statusb = RTCSB_24HR;
33
34 @@ -66,39 +74,52 @@
35 * RTC support routines
36 */
37
38 -int
39 -rtcin(int reg)
40 +static void
41 +acpi_cmos_read(ACPI_PHYSICAL_ADDRESS address, UINT8 *buf, UINT32 buflen)
42 {
43 - u_char val;
44 + UINT32 offset;
45
46 RTC_LOCK;
47 - if (rtc_reg != reg) {
48 - inb(0x84);
49 - outb(IO_RTC, reg);
50 - rtc_reg = reg;
51 - inb(0x84);
52 + for (offset = 0; offset < buflen; ++offset) {
53 + IO_DELAY();
54 + outb(IO_RTC_ADDR, ((address + offset) | 0x80) & 0xFF);
55 + IO_DELAY();
56 + buf[offset] = inb(IO_RTC_DATA);
57 }
58 - val = inb(IO_RTC + 1);
59 RTC_UNLOCK;
60 - return (val);
61 }
62
63 -void
64 -writertc(int reg, u_char val)
65 +static void
66 +acpi_cmos_write(ACPI_PHYSICAL_ADDRESS address, const UINT8 *buf, UINT32 buflen)
67 {
68 + UINT32 offset;
69
70 RTC_LOCK;
71 - if (rtc_reg != reg) {
72 - inb(0x84);
73 - outb(IO_RTC, reg);
74 - rtc_reg = reg;
75 - inb(0x84);
76 + for (offset = 0; offset < buflen; ++offset) {
77 + IO_DELAY();
78 + outb(IO_RTC_ADDR, ((address + offset) | 0x80) & 0xFF);
79 + IO_DELAY();
80 + outb(IO_RTC_DATA, buf[offset]);
81 }
82 - outb(IO_RTC + 1, val);
83 - inb(0x84);
84 + IO_DELAY();
85 RTC_UNLOCK;
86 }
87
88 +int
89 +rtcin(int reg)
90 +{
91 + u_char val;
92 +
93 + acpi_cmos_read(reg & 0xFF, &val, 1);
94 + return (val);
95 +}
96 +
97 +void
98 +writertc(int reg, u_char val)
99 +{
100 + acpi_cmos_write(reg & 0xFF, &val, 1);
101 +}
102 +
103 static __inline int
104 readrtc(int port)
105 {
106 @@ -144,7 +165,6 @@
107 {
108
109 /* Restore all of the RTC's "status" (actually, control) registers. */
110 - rtcin(RTC_STATUSA); /* dummy to get rtc_reg set */
111 writertc(RTC_STATUSB, RTCSB_24HR);
112 writertc(RTC_STATUSA, rtc_statusa);
113 writertc(RTC_STATUSB, rtc_statusb);
114 @@ -161,9 +181,58 @@
115 struct resource *intr_res;
116 void *intr_handler;
117 struct eventtimer et;
118 + ACPI_HANDLE acpi_handle; /* Handle of the PNP0B00 node */
119 };
120
121 static int
122 +acpi_check_rtc_byteaccess(int is_read, u_long addr)
123 +{
124 + int retval = 1; /* Success */
125 +
126 + if (is_read) {
127 + /* Reading 0x0C will muck with interrupts */
128 + if (addr == 0x0C)
129 + retval = 0;
130 + } else {
131 + /* No writing RTC control regs */
132 + if (addr >= 0x0A && addr <= 0x0D)
133 + retval = 0;
134 + }
135 + return retval;
136 +}
137 +
138 +static ACPI_STATUS
139 +acpi_rtc_cmos_handler(UINT32 function, ACPI_PHYSICAL_ADDRESS address,
140 + UINT32 width, UINT64 *value, void *context, void *region_context)
141 +{
142 + struct atrtc_softc *sc;
143 +
144 + sc = (struct atrtc_softc *)context;
145 + if (!value || !sc)
146 + return AE_BAD_PARAMETER;
147 + if (width > 32 || (width & 0x07) || address >= 64)
148 + return AE_BAD_PARAMETER;
149 + if (!acpi_check_rtc_byteaccess(function == ACPI_READ, address))
150 + return AE_BAD_PARAMETER;
151 +
152 + switch (function) {
153 + case ACPI_READ:
154 + acpi_cmos_read(address, (UINT8 *)value, width >> 3);
155 + break;
156 + case ACPI_WRITE:
157 + acpi_cmos_write(address, (const UINT8 *)value,
158 + width >> 3);
159 + break;
160 + default:
161 + return AE_BAD_PARAMETER;
162 + }
163 + printf("%s: %-5s%02u address=%04lx value=%08x\n",
164 + __FUNCTION__, function == ACPI_READ ? "READ" : "WRITE", width >> 3,
165 + address, *((UINT32 *)value));
166 + return AE_OK;
167 +}
168 +
169 +static int
170 rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
171 {
172
173 @@ -245,10 +314,17 @@
174 int i;
175
176 sc = device_get_softc(dev);
177 + sc->acpi_handle = acpi_get_handle(dev);
178 sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
179 IO_RTC, IO_RTC + 1, 2, RF_ACTIVE);
180 if (sc->port_res == NULL)
181 device_printf(dev, "Warning: Couldn't map I/O.\n");
182 + if (ACPI_FAILURE(AcpiInstallAddressSpaceHandler(sc->acpi_handle,
183 + ACPI_ADR_SPACE_CMOS, acpi_rtc_cmos_handler, NULL, sc)))
184 + {
185 + device_printf(dev, "Error registering ACPI CMOS address space handler.\n");
186 + return 0;
187 + }
188 atrtc_start();
189 clock_register(dev, 1000000);
190 bzero(&sc->et, sizeof(struct eventtimer));
191 @@ -286,6 +362,15 @@
192 return(0);
193 }
194
195 +static int atrtc_detach(device_t dev)
196 +{
197 + struct atrtc_softc *sc;
198 +
199 + sc = device_get_softc(dev);
200 + AcpiRemoveAddressSpaceHandler(sc->acpi_handle, ACPI_ADR_SPACE_CMOS, acpi_rtc_cmos_handler);
201 + return bus_generic_detach(dev);
202 +}
203 +
204 static int
205 atrtc_resume(device_t dev)
206 {
207 @@ -366,7 +451,7 @@
208 /* Device interface */
209 DEVMETHOD(device_probe, atrtc_probe),
210 DEVMETHOD(device_attach, atrtc_attach),
211 - DEVMETHOD(device_detach, bus_generic_detach),
212 + DEVMETHOD(device_detach, atrtc_detach),
213 DEVMETHOD(device_shutdown, bus_generic_shutdown),
214 DEVMETHOD(device_suspend, bus_generic_suspend),
215 /* XXX stop statclock? */
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.