Lines 42-62
Link Here
|
42 |
#include <sys/kernel.h> |
42 |
#include <sys/kernel.h> |
43 |
#include <sys/module.h> |
43 |
#include <sys/module.h> |
44 |
#include <sys/proc.h> |
44 |
#include <sys/proc.h> |
45 |
#include <sys/rman.h> |
|
|
46 |
#include <sys/timeet.h> |
45 |
#include <sys/timeet.h> |
47 |
|
46 |
|
48 |
#include <isa/rtc.h> |
47 |
#include <isa/rtc.h> |
|
|
48 |
#include <machine/intr_machdep.h> |
49 |
#include "clock_if.h" |
50 |
#include "atrtcvar.h" |
51 |
|
49 |
#ifdef DEV_ISA |
52 |
#ifdef DEV_ISA |
50 |
#include <isa/isareg.h> |
53 |
#include <isa/isareg.h> |
51 |
#include <isa/isavar.h> |
54 |
#include <isa/isavar.h> |
52 |
#endif |
55 |
#endif |
53 |
#include <machine/intr_machdep.h> |
|
|
54 |
#include "clock_if.h" |
55 |
|
56 |
|
56 |
#define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0) |
57 |
#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) |
58 |
#define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0) |
58 |
|
59 |
|
59 |
int atrtcclock_disable = 0; |
60 |
#define IO_DELAY() (void)inb(0x84) |
|
|
61 |
#define IO_RTC_ADDR (IO_RTC + 0) |
62 |
#define IO_RTC_DATA (IO_RTC + 1) |
60 |
|
63 |
|
61 |
static int rtc_reg = -1; |
64 |
static int rtc_reg = -1; |
62 |
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; |
65 |
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF; |
Lines 73-82
Link Here
|
73 |
|
76 |
|
74 |
RTC_LOCK; |
77 |
RTC_LOCK; |
75 |
if (rtc_reg != reg) { |
78 |
if (rtc_reg != reg) { |
76 |
inb(0x84); |
79 |
IO_DELAY(); |
77 |
outb(IO_RTC, reg); |
80 |
outb(IO_RTC, reg); |
78 |
rtc_reg = reg; |
81 |
rtc_reg = reg; |
79 |
inb(0x84); |
82 |
IO_DELAY(); |
80 |
} |
83 |
} |
81 |
val = inb(IO_RTC + 1); |
84 |
val = inb(IO_RTC + 1); |
82 |
RTC_UNLOCK; |
85 |
RTC_UNLOCK; |
Lines 89-101
Link Here
|
89 |
|
92 |
|
90 |
RTC_LOCK; |
93 |
RTC_LOCK; |
91 |
if (rtc_reg != reg) { |
94 |
if (rtc_reg != reg) { |
92 |
inb(0x84); |
95 |
IO_DELAY(); |
93 |
outb(IO_RTC, reg); |
96 |
outb(IO_RTC, reg); |
94 |
rtc_reg = reg; |
97 |
rtc_reg = reg; |
95 |
inb(0x84); |
98 |
IO_DELAY(); |
96 |
} |
99 |
} |
97 |
outb(IO_RTC + 1, val); |
100 |
outb(IO_RTC + 1, val); |
98 |
inb(0x84); |
101 |
IO_DELAY(); |
99 |
RTC_UNLOCK; |
102 |
RTC_UNLOCK; |
100 |
} |
103 |
} |
101 |
|
104 |
|
Lines 105-111
Link Here
|
105 |
return(bcd2bin(rtcin(port))); |
108 |
return(bcd2bin(rtcin(port))); |
106 |
} |
109 |
} |
107 |
|
110 |
|
108 |
static void |
111 |
void |
109 |
atrtc_start(void) |
112 |
atrtc_start(void) |
110 |
{ |
113 |
{ |
111 |
|
114 |
|
Lines 155-169
Link Here
|
155 |
* RTC driver for subr_rtc |
158 |
* RTC driver for subr_rtc |
156 |
*/ |
159 |
*/ |
157 |
|
160 |
|
158 |
struct atrtc_softc { |
161 |
int |
159 |
int port_rid, intr_rid; |
|
|
160 |
struct resource *port_res; |
161 |
struct resource *intr_res; |
162 |
void *intr_handler; |
163 |
struct eventtimer et; |
164 |
}; |
165 |
|
166 |
static int |
167 |
rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period) |
162 |
rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period) |
168 |
{ |
163 |
{ |
169 |
|
164 |
|
Lines 172-178
Link Here
|
172 |
return (0); |
167 |
return (0); |
173 |
} |
168 |
} |
174 |
|
169 |
|
175 |
static int |
170 |
int |
176 |
rtc_stop(struct eventtimer *et) |
171 |
rtc_stop(struct eventtimer *et) |
177 |
{ |
172 |
{ |
178 |
|
173 |
|
Lines 201-207
Link Here
|
201 |
* Stat clock ticks can still be lost, causing minor loss of accuracy |
196 |
* Stat clock ticks can still be lost, causing minor loss of accuracy |
202 |
* in the statistics, but the stat clock will no longer stop. |
197 |
* in the statistics, but the stat clock will no longer stop. |
203 |
*/ |
198 |
*/ |
204 |
static int |
199 |
int |
205 |
rtc_intr(void *arg) |
200 |
rtc_intr(void *arg) |
206 |
{ |
201 |
{ |
207 |
struct atrtc_softc *sc = (struct atrtc_softc *)arg; |
202 |
struct atrtc_softc *sc = (struct atrtc_softc *)arg; |
Lines 215-300
Link Here
|
215 |
return(flag ? FILTER_HANDLED : FILTER_STRAY); |
210 |
return(flag ? FILTER_HANDLED : FILTER_STRAY); |
216 |
} |
211 |
} |
217 |
|
212 |
|
218 |
/* |
213 |
int |
219 |
* Attach to the ISA PnP descriptors for the timer and realtime clock. |
|
|
220 |
*/ |
221 |
static struct isa_pnp_id atrtc_ids[] = { |
222 |
{ 0x000bd041 /* PNP0B00 */, "AT realtime clock" }, |
223 |
{ 0 } |
224 |
}; |
225 |
|
226 |
static int |
227 |
atrtc_probe(device_t dev) |
228 |
{ |
229 |
int result; |
230 |
|
231 |
result = ISA_PNP_PROBE(device_get_parent(dev), dev, atrtc_ids); |
232 |
/* ENOENT means no PnP-ID, device is hinted. */ |
233 |
if (result == ENOENT) { |
234 |
device_set_desc(dev, "AT realtime clock"); |
235 |
return (BUS_PROBE_LOW_PRIORITY); |
236 |
} |
237 |
return (result); |
238 |
} |
239 |
|
240 |
static int |
241 |
atrtc_attach(device_t dev) |
242 |
{ |
243 |
struct atrtc_softc *sc; |
244 |
u_long s; |
245 |
int i; |
246 |
|
247 |
sc = device_get_softc(dev); |
248 |
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, |
249 |
IO_RTC, IO_RTC + 1, 2, RF_ACTIVE); |
250 |
if (sc->port_res == NULL) |
251 |
device_printf(dev, "Warning: Couldn't map I/O.\n"); |
252 |
atrtc_start(); |
253 |
clock_register(dev, 1000000); |
254 |
bzero(&sc->et, sizeof(struct eventtimer)); |
255 |
if (!atrtcclock_disable && |
256 |
(resource_int_value(device_get_name(dev), device_get_unit(dev), |
257 |
"clock", &i) != 0 || i != 0)) { |
258 |
sc->intr_rid = 0; |
259 |
while (bus_get_resource(dev, SYS_RES_IRQ, sc->intr_rid, |
260 |
&s, NULL) == 0 && s != 8) |
261 |
sc->intr_rid++; |
262 |
sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ, |
263 |
&sc->intr_rid, 8, 8, 1, RF_ACTIVE); |
264 |
if (sc->intr_res == NULL) { |
265 |
device_printf(dev, "Can't map interrupt.\n"); |
266 |
return (0); |
267 |
} else if ((bus_setup_intr(dev, sc->intr_res, INTR_TYPE_CLK, |
268 |
rtc_intr, NULL, sc, &sc->intr_handler))) { |
269 |
device_printf(dev, "Can't setup interrupt.\n"); |
270 |
return (0); |
271 |
} else { |
272 |
/* Bind IRQ to BSP to avoid live migration. */ |
273 |
bus_bind_intr(dev, sc->intr_res, 0); |
274 |
} |
275 |
sc->et.et_name = "RTC"; |
276 |
sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_POW2DIV; |
277 |
sc->et.et_quality = 0; |
278 |
sc->et.et_frequency = 32768; |
279 |
sc->et.et_min_period = 0x00080000; |
280 |
sc->et.et_max_period = 0x80000000; |
281 |
sc->et.et_start = rtc_start; |
282 |
sc->et.et_stop = rtc_stop; |
283 |
sc->et.et_priv = dev; |
284 |
et_register(&sc->et); |
285 |
} |
286 |
return(0); |
287 |
} |
288 |
|
289 |
static int |
290 |
atrtc_resume(device_t dev) |
291 |
{ |
292 |
|
293 |
atrtc_restore(); |
294 |
return(0); |
295 |
} |
296 |
|
297 |
static int |
298 |
atrtc_settime(device_t dev __unused, struct timespec *ts) |
214 |
atrtc_settime(device_t dev __unused, struct timespec *ts) |
299 |
{ |
215 |
{ |
300 |
struct clocktime ct; |
216 |
struct clocktime ct; |
Lines 322-328
Link Here
|
322 |
return (0); |
238 |
return (0); |
323 |
} |
239 |
} |
324 |
|
240 |
|
325 |
static int |
241 |
int |
326 |
atrtc_gettime(device_t dev, struct timespec *ts) |
242 |
atrtc_gettime(device_t dev, struct timespec *ts) |
327 |
{ |
243 |
{ |
328 |
struct clocktime ct; |
244 |
struct clocktime ct; |
Lines 362-395
Link Here
|
362 |
return (clock_ct_to_ts(&ct, ts)); |
278 |
return (clock_ct_to_ts(&ct, ts)); |
363 |
} |
279 |
} |
364 |
|
280 |
|
365 |
static device_method_t atrtc_methods[] = { |
|
|
366 |
/* Device interface */ |
367 |
DEVMETHOD(device_probe, atrtc_probe), |
368 |
DEVMETHOD(device_attach, atrtc_attach), |
369 |
DEVMETHOD(device_detach, bus_generic_detach), |
370 |
DEVMETHOD(device_shutdown, bus_generic_shutdown), |
371 |
DEVMETHOD(device_suspend, bus_generic_suspend), |
372 |
/* XXX stop statclock? */ |
373 |
DEVMETHOD(device_resume, atrtc_resume), |
374 |
|
375 |
/* clock interface */ |
376 |
DEVMETHOD(clock_gettime, atrtc_gettime), |
377 |
DEVMETHOD(clock_settime, atrtc_settime), |
378 |
|
379 |
{ 0, 0 } |
380 |
}; |
381 |
|
382 |
static driver_t atrtc_driver = { |
383 |
"atrtc", |
384 |
atrtc_methods, |
385 |
sizeof(struct atrtc_softc), |
386 |
}; |
387 |
|
388 |
static devclass_t atrtc_devclass; |
389 |
|
390 |
DRIVER_MODULE(atrtc, isa, atrtc_driver, atrtc_devclass, 0, 0); |
391 |
DRIVER_MODULE(atrtc, acpi, atrtc_driver, atrtc_devclass, 0, 0); |
392 |
|
393 |
#include "opt_ddb.h" |
281 |
#include "opt_ddb.h" |
394 |
#ifdef DDB |
282 |
#ifdef DDB |
395 |
#include <ddb/ddb.h> |
283 |
#include <ddb/ddb.h> |