View | Details | Raw Unified | Return to bug 207419 | Differences between
and this patch

Collapse All | Expand All

(-)sys/conf/files.i386 (-2 / +4 lines)
Lines 577-584 Link Here
577
x86/iommu/intel_quirks.c	optional acpi acpi_dmar pci
577
x86/iommu/intel_quirks.c	optional acpi acpi_dmar pci
578
x86/iommu/intel_utils.c		optional acpi acpi_dmar pci
578
x86/iommu/intel_utils.c		optional acpi acpi_dmar pci
579
x86/isa/atpic.c			optional atpic
579
x86/isa/atpic.c			optional atpic
580
x86/isa/atrtc.c			standard
580
x86/isa/atrtc.c			standard native
581
x86/isa/clock.c			standard
581
x86/isa/atrtc_isa.c		standard isa atrtc
582
#x86/isa/atrtc_acpi.c		optional atrtc acpi
583
x86/isa/clock.c			optional native
582
x86/isa/elcr.c			optional atpic | apic
584
x86/isa/elcr.c			optional atpic | apic
583
x86/isa/isa.c			optional isa
585
x86/isa/isa.c			optional isa
584
x86/isa/isa_dma.c		optional isa
586
x86/isa/isa_dma.c		optional isa
(-)sys/conf/files.amd64 (+2 lines)
Lines 583-588 Link Here
583
x86/iommu/intel_utils.c		optional	acpi acpi_dmar pci
583
x86/iommu/intel_utils.c		optional	acpi acpi_dmar pci
584
x86/isa/atpic.c			optional	atpic isa
584
x86/isa/atpic.c			optional	atpic isa
585
x86/isa/atrtc.c			standard
585
x86/isa/atrtc.c			standard
586
x86/isa/atrtc_isa.c		standard	
587
x86/isa/atrtc_acpi.c		standard
586
x86/isa/clock.c			standard
588
x86/isa/clock.c			standard
587
x86/isa/elcr.c			optional	atpic isa | mptable
589
x86/isa/elcr.c			optional	atpic isa | mptable
588
x86/isa/isa.c			standard
590
x86/isa/isa.c			standard
(-)sys/x86/isa/atrtc.c (-130 / +18 lines)
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>
(-)sys/x86/isa/atrtc_acpi.c (+131 lines)
Line 0 Link Here
1
#include <sys/cdefs.h>
2
#include <sys/param.h>
3
#include <sys/systm.h>
4
#include <sys/bus.h>
5
#include <sys/clock.h>
6
#include <sys/lock.h>
7
#include <sys/mutex.h>
8
#include <sys/kernel.h>
9
#include <sys/module.h>
10
#include <contrib/dev/acpica/include/acpi.h>
11
#include <contrib/dev/acpica/include/accommon.h>
12
#include <dev/acpica/acpivar.h>
13
#include <isa/rtc.h>
14
15
#include "atrtc_acpi.h"
16
#include "opt_acpi.h"
17
18
struct atrtc_acpi_stuff {
19
	ACPI_HANDLE acpi_handle;	/* Handle of the PNP0B00 node */
20
	int acpi_handle_registered;	/* 0 = acpi_handle not registered */
21
};
22
23
static void
24
acpi_cmos_read(ACPI_PHYSICAL_ADDRESS address, UINT8 *buf, UINT32 buflen)
25
{
26
	UINT32 offset;
27
28
	for (offset = 0; offset < buflen; ++offset) {
29
		buf[offset] = rtcin(address + offset) & 0xff;
30
	}
31
}
32
33
static void
34
acpi_cmos_write(ACPI_PHYSICAL_ADDRESS address, const UINT8 *buf, UINT32 buflen)
35
{
36
	UINT32 offset;
37
38
	for (offset = 0; offset < buflen; ++offset) {
39
		writertc(address + offset, buf[offset]);
40
	}
41
}
42
43
static int
44
acpi_check_rtc_access(int is_read, u_long addr, u_long len)
45
{
46
	int retval = 1;	/* Success */
47
48
	if (is_read) {
49
		/* Reading 0x0C will muck with interrupts */
50
		if (addr + len - 1 >= 0x0C && addr <= 0x0c)
51
			retval = 0;
52
	} else {
53
		/* Allow single-byte writes to alarm registers and
54
		 * addr >= 0x30, else deny.
55
		 */
56
		if (!((len == 1 && (addr <= 5 && (addr & 1))) || addr >= 0x30))
57
			retval = 0;
58
	}
59
	return retval;
60
}
61
62
static ACPI_STATUS
63
acpi_rtc_cmos_handler(UINT32 func, ACPI_PHYSICAL_ADDRESS addr,
64
    UINT32 bitwidth, UINT64 *value, void *context, void *region_context)
65
{
66
	device_t dev;
67
	struct atrtc_softc *sc;
68
	UINT32 bytewidth = bitwidth >> 3;
69
70
	dev = (device_t)context;
71
	sc = device_get_softc(dev);
72
	if (!value || !sc) {
73
		printf("NULL parameter.\n");
74
		return AE_BAD_PARAMETER;
75
	}
76
	if (bitwidth == 0 || bitwidth > 32 || (bitwidth & 0x07) ||
77
			addr + bytewidth - 1 > 63) {
78
		printf("Invalid bitwidth (%u) or addr (0x%08lx).\n", bitwidth,
79
				addr);
80
		return AE_BAD_PARAMETER;
81
	}
82
	if (!acpi_check_rtc_access(func == ACPI_READ, addr, bytewidth)) {
83
		printf("Bad CMOS %s access at addr 0x%08lx.\n",
84
			func == ACPI_READ ? "read" : "write", addr);
85
		return AE_BAD_PARAMETER;
86
	}
87
88
	switch (func) {
89
		case ACPI_READ:
90
			acpi_cmos_read(addr, (UINT8 *)value, bytewidth);
91
			break;
92
		case ACPI_WRITE:
93
			acpi_cmos_write(addr, (const UINT8 *)value, bytewidth);
94
			break;
95
		default:
96
			printf("Invalid function: %d.\n", func);
97
			return AE_BAD_PARAMETER;
98
	}
99
	if (bootverbose)
100
		printf("%-5s%02u addr=%04lx val=%08x\n",
101
			func == ACPI_READ ? "READ" : "WRITE", bytewidth,
102
			addr, *((UINT32 *)value));
103
	return AE_OK;
104
}
105
106
static devclass_t atrtc_acpi_devclass;
107
static ACPI_HANDLE acpi_handle = NULL;
108
109
DRIVER_MODULE(atrtc, acpi, atrtc_driver, atrtc_acpi_devclass, 0, 0);
110
111
int atrtc_acpi_register(device_t dev)
112
{
113
	ACPI_HANDLE acpi_handle = acpi_get_handle(dev);
114
	int retval;
115
116
	if ((retval = ACPI_FAILURE(AcpiInstallAddressSpaceHandler(acpi_handle,
117
					ACPI_ADR_SPACE_CMOS,
118
					acpi_rtc_cmos_handler, NULL, dev))))
119
	{
120
		device_printf(dev, "Warning: Couldn't register ACPI CMOS address space handler.\n");
121
	}
122
	return retval ? -1 : 0;
123
}
124
125
int atrtc_acpi_unregister(device_t dev)
126
{
127
	if (acpi_handle)
128
		AcpiRemoveAddressSpaceHandler(acpi_handle,
129
				ACPI_ADR_SPACE_CMOS, acpi_rtc_cmos_handler);
130
	return 0;
131
}
(-)sys/x86/isa/atrtc_acpi.h (+50 lines)
Line 0 Link Here
1
/*-
2
 * Copyright (c) 1990 The Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 4. Neither the name of the University nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * $FreeBSD$
30
 */
31
32
33
#ifndef _X86_ISA_ATRTC_ACPI_H_
34
#define	_X86_ISA_ATRTC_ACPI_H_
35
36
#include <sys/cdefs.h>
37
__FBSDID("$FreeBSD$");
38
39
#include <sys/types.h>
40
#include <sys/param.h>
41
#include <sys/systm.h>
42
#include <sys/bus.h>
43
44
45
int	atrtc_acpi_register(device_t dev);
46
int	atrtc_acpi_unregister(device_t dev);
47
48
driver_t atrtc_driver;
49
50
#endif /* !_X86_ISA_ATRTC_ACPI_H_ */
(-)sys/x86/isa/atrtc_isa.c (+178 lines)
Line 0 Link Here
1
/*-
2
 * Copyright (c) 2008 Poul-Henning Kamp
3
 * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD$
28
 */
29
30
#include <sys/cdefs.h>
31
__FBSDID("$FreeBSD$");
32
33
#include <sys/types.h>
34
35
#include <sys/param.h>
36
#include <sys/systm.h>
37
#include <sys/bus.h>
38
#include <sys/clock.h>
39
#include <sys/lock.h>
40
#include <sys/mutex.h>
41
#include <sys/kdb.h>
42
#include <sys/kernel.h>
43
#include <sys/module.h>
44
#include <sys/proc.h>
45
#include <sys/timeet.h>
46
#include <sys/rman.h>
47
48
#include <isa/isavar.h>
49
#include <isa/isareg.h>
50
#include <isa/rtc.h>
51
#include <machine/intr_machdep.h>
52
#include <machine/resource.h>
53
54
#include "clock_if.h"
55
#include "atrtcvar.h"
56
#include "atrtc_acpi.h"
57
58
59
int atrtcclock_disable = 0;
60
61
static int atrtc_isa_probe(device_t dev);
62
63
/*
64
 * Attach to the ISA PnP descriptors for the timer and realtime clock.
65
 */
66
static struct isa_pnp_id atrtc_ids[] = {
67
	{ 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
68
	{ 0 }
69
};
70
71
static int
72
atrtc_isa_probe(device_t dev)
73
{
74
	int result;
75
	
76
	result = ISA_PNP_PROBE(device_get_parent(dev), dev, atrtc_ids);
77
	/* ENOENT means no PnP-ID, device is hinted. */
78
	if (result == ENOENT) {
79
		device_set_desc(dev, "AT realtime clock");
80
		return (BUS_PROBE_LOW_PRIORITY);
81
	}
82
	return (result);
83
}
84
85
static int
86
atrtc_isa_attach(device_t dev)
87
{
88
	struct atrtc_softc *sc;
89
	u_long s;
90
	int i;
91
92
	sc = device_get_softc(dev);
93
	sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
94
	    IO_RTC, IO_RTC + 1, 2, RF_ACTIVE);
95
	if (sc->port_res == NULL)
96
		device_printf(dev, "Warning: Couldn't map I/O.\n");
97
	atrtc_start();
98
	clock_register(dev, 1000000);
99
	bzero(&sc->et, sizeof(struct eventtimer));
100
	if (!atrtcclock_disable &&
101
	    (resource_int_value(device_get_name(dev), device_get_unit(dev),
102
	     "clock", &i) != 0 || i != 0)) {
103
		sc->intr_rid = 0;
104
		while (bus_get_resource(dev, SYS_RES_IRQ, sc->intr_rid,
105
		    &s, NULL) == 0 && s != 8)
106
			sc->intr_rid++;
107
		sc->intr_res = bus_alloc_resource(dev, SYS_RES_IRQ,
108
		    &sc->intr_rid, 8, 8, 1, RF_ACTIVE);
109
		if (sc->intr_res == NULL) {
110
			device_printf(dev, "Can't map interrupt.\n");
111
			return (0);
112
		} else if ((bus_setup_intr(dev, sc->intr_res, INTR_TYPE_CLK,
113
		    rtc_intr, NULL, sc, &sc->intr_handler))) {
114
			device_printf(dev, "Can't setup interrupt.\n");
115
			return (0);
116
		} else { 
117
			/* Bind IRQ to BSP to avoid live migration. */
118
			bus_bind_intr(dev, sc->intr_res, 0);
119
		}
120
		(void)atrtc_acpi_register(dev);
121
		sc->et.et_name = "RTC";
122
		sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_POW2DIV;
123
		sc->et.et_quality = 0;
124
		sc->et.et_frequency = 32768;
125
		sc->et.et_min_period = 0x00080000;
126
		sc->et.et_max_period = 0x80000000;
127
		sc->et.et_start = rtc_start;
128
		sc->et.et_stop = rtc_stop;
129
		sc->et.et_priv = dev;
130
		et_register(&sc->et);
131
	}
132
	return(0);
133
}
134
135
static int atrtc_isa_detach(device_t dev)
136
{
137
	struct atrtc_softc *sc;
138
139
	sc = device_get_softc(dev);
140
	(void)atrtc_acpi_unregister(dev);
141
	return bus_generic_detach(dev);
142
}
143
144
static int
145
atrtc_resume(device_t dev)
146
{
147
148
	atrtc_restore();
149
	return(0);
150
}
151
152
static device_method_t atrtc_methods[] = {
153
	/* Device interface */
154
	DEVMETHOD(device_probe,		atrtc_isa_probe),
155
	DEVMETHOD(device_attach,	atrtc_isa_attach),
156
	DEVMETHOD(device_detach,	atrtc_isa_detach),
157
	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
158
	DEVMETHOD(device_suspend,	bus_generic_suspend),
159
		/* XXX stop statclock? */
160
	DEVMETHOD(device_resume,	atrtc_resume),
161
162
	/* clock interface */
163
	DEVMETHOD(clock_gettime,	atrtc_gettime),
164
	DEVMETHOD(clock_settime,	atrtc_settime),
165
166
	{ 0, 0 }
167
};
168
169
driver_t atrtc_driver = {
170
	"atrtc",
171
	atrtc_methods,
172
	sizeof(struct atrtc_softc),
173
};
174
175
static devclass_t atrtc_isa_devclass;
176
177
DRIVER_MODULE(atrtc, isa, atrtc_driver, atrtc_isa_devclass, 0, 0);
178
(-)sys/x86/isa/atrtcvar.h (+23 lines)
Line 0 Link Here
1
#ifndef ATRTCVAR_H
2
#define ATRTCVAR_H
3
4
#include <sys/types.h>
5
#include <sys/timeet.h>
6
7
struct atrtc_softc {
8
	int port_rid, intr_rid;
9
	struct resource *port_res;
10
	struct resource *intr_res;
11
	void *intr_handler;
12
	struct eventtimer et;
13
};
14
15
int atrtc_gettime(device_t dev, struct timespec *ts);
16
int atrtc_settime(device_t dev __unused, struct timespec *ts);
17
void atrtc_start(void);
18
void atrtc_restore(void);
19
int rtc_start(struct eventtimer *et, sbintime_t first, sbintime_t period);
20
int rtc_stop(struct eventtimer *et);
21
int rtc_intr(void *arg);
22
23
#endif	/* ATRTCVAR_H */

Return to bug 207419