View | Details | Raw Unified | Return to bug 170705
Collapse All | Expand All

(-)sys/isa/rtc.h (+1 lines)
Lines 117-122 extern int atrtcclock_disable; Link Here
117
int	rtcin(int reg);
117
int	rtcin(int reg);
118
void	atrtc_restore(void);
118
void	atrtc_restore(void);
119
void	writertc(int reg, u_char val);
119
void	writertc(int reg, u_char val);
120
void	atrtc_nmi_enable(int enable);
120
#endif
121
#endif
121
122
122
#endif /* _I386_ISA_RTC_H_ */
123
#endif /* _I386_ISA_RTC_H_ */
(-)sys/x86/isa/atrtc.c (-17 / +74 lines)
Lines 55-82 __FBSDID("$FreeBSD: src/sys/x86/isa/atrt Link Here
55
#define	RTC_LOCK	mtx_lock_spin(&clock_lock)
55
#define	RTC_LOCK	mtx_lock_spin(&clock_lock)
56
#define	RTC_UNLOCK	mtx_unlock_spin(&clock_lock)
56
#define	RTC_UNLOCK	mtx_unlock_spin(&clock_lock)
57
57
58
/* atrtcclock_disable is set to 1 by apm_attach() or by hint.atrtc.0.clock=0 */
58
int	atrtcclock_disable = 0;
59
int	atrtcclock_disable = 0;
59
60
60
static	int	rtc_reg = -1;
61
static int use_iodelay = 0;     /* set from hint.atrtc.0.use_iodelay */
61
static	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
62
62
static	u_char	rtc_statusb = RTCSB_24HR;
63
#define RTC_REINDEX_REQUIRED  0xffU
64
#define NMI_ENABLE_BIT        0x80U
65
66
static u_char nmi_enable;
67
static u_char rtc_reg     = RTC_REINDEX_REQUIRED;
68
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
69
static u_char rtc_statusb = RTCSB_24HR;
70
71
/*
72
 * Delay after writing to IO_RTC[+1] registers.  Modern hardware doesn't
73
 * require this expensive delay, so it's a tuneable that's disabled by default.
74
 */
75
static __inline void
76
rtc_iodelay(void)
77
{
78
	if (use_iodelay)
79
		inb(0x84);
80
}
63
81
64
/*
82
/*
65
 * RTC support routines
83
 * RTC support routines
84
 *
85
 * Most rtc chipsets let you write a value into the index register and then each
86
 * read of the IO register obtains a new value from the indexed location. Others
87
 * behave as if they latch the indexed value when you write to the index, and
88
 * repeated reads keep returning the same value until you write to the index
89
 * register again.  atrtc_start() probes for this behavior and leaves rtc_reg
90
 * set to RTC_REINDEX_REQUIRED if reads keep returning the same value.
66
 */
91
 */
67
92
93
static __inline void
94
rtcindex(u_char reg)
95
{
96
	if (rtc_reg != reg) {
97
		if (rtc_reg != RTC_REINDEX_REQUIRED)
98
			rtc_reg = reg;
99
		outb(IO_RTC, reg | nmi_enable);
100
		rtc_iodelay();
101
	}
102
}
103
68
int
104
int
69
rtcin(int reg)
105
rtcin(int reg)
70
{
106
{
71
	u_char val;
107
	u_char val;
72
108
73
	RTC_LOCK;
109
	RTC_LOCK;
74
	if (rtc_reg != reg) {
110
	rtcindex(reg);
75
		inb(0x84);
76
		outb(IO_RTC, reg);
77
		rtc_reg = reg;
78
		inb(0x84);
79
	}
80
	val = inb(IO_RTC + 1);
111
	val = inb(IO_RTC + 1);
81
	RTC_UNLOCK;
112
	RTC_UNLOCK;
82
	return (val);
113
	return (val);
Lines 87-100 writertc(int reg, u_char val) Link Here
87
{
118
{
88
119
89
	RTC_LOCK;
120
	RTC_LOCK;
90
	if (rtc_reg != reg) {
121
	rtcindex(reg);
91
		inb(0x84);
92
		outb(IO_RTC, reg);
93
		rtc_reg = reg;
94
		inb(0x84);
95
	}
96
	outb(IO_RTC + 1, val);
122
	outb(IO_RTC + 1, val);
97
	inb(0x84);
123
	rtc_iodelay();
98
	RTC_UNLOCK;
124
	RTC_UNLOCK;
99
}
125
}
100
126
Lines 104-115 readrtc(int port) Link Here
104
	return(bcd2bin(rtcin(port)));
130
	return(bcd2bin(rtcin(port)));
105
}
131
}
106
132
133
/*
134
 * At start, probe read-without-reindex behavior.  Reading RTC_INTR clears it;
135
 * read until it has a non-zero value, then read it again without re-writing the
136
 * index register. If 2nd read returns a different value it's safe to cache the
137
 * current index with this chipset; enable by changing rtc_reg to current index.
138
 */
107
static void
139
static void
108
atrtc_start(void)
140
atrtc_start(void)
109
{
141
{
142
	int status;
110
143
111
	writertc(RTC_STATUSA, rtc_statusa);
144
	writertc(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_8192);
112
	writertc(RTC_STATUSB, RTCSB_24HR);
145
	writertc(RTC_STATUSB, RTCSB_24HR);
146
147
	RTC_LOCK;
148
	do {
149
		rtcindex(RTC_INTR);
150
		status = inb(IO_RTC+1);
151
	} while (status == 0);
152
153
	if (status != inb(IO_RTC+1))
154
		rtc_reg = RTC_INTR;
155
	RTC_UNLOCK;
156
157
	writertc(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_NOPROF);
113
}
158
}
114
159
115
static void
160
static void
Lines 139-144 atrtc_disable_intr(void) Link Here
139
}
184
}
140
185
141
void
186
void
187
atrtc_nmi_enable(int enable)
188
{
189
	/* Must not write to 0x70 without a following read or write of 0x71 on
190
	 * some chipsets, so do a read.  Also, must access a register other than
191
	 * the current rtc_reg to force rtcin to push a change out to 0x70.
192
	 */
193
	nmi_enable = enable ? NMI_ENABLE_BIT : 0x00;
194
	rtcin((rtc_reg == RTC_STATUSA) ? RTC_STATUSB : RTC_STATUSA);
195
}
196
197
void
142
atrtc_restore(void)
198
atrtc_restore(void)
143
{
199
{
144
200
Lines 249-254 atrtc_attach(device_t dev) Link Here
249
	    IO_RTC, IO_RTC + 1, 2, RF_ACTIVE);
305
	    IO_RTC, IO_RTC + 1, 2, RF_ACTIVE);
250
	if (sc->port_res == NULL)
306
	if (sc->port_res == NULL)
251
		device_printf(dev, "Warning: Couldn't map I/O.\n");
307
		device_printf(dev, "Warning: Couldn't map I/O.\n");
308
	resource_int_value("atrtc", 0, "use_iodelay", &use_iodelay);
252
	atrtc_start();
309
	atrtc_start();
253
	clock_register(dev, 1000000);
310
	clock_register(dev, 1000000);
254
	bzero(&sc->et, sizeof(struct eventtimer));
311
	bzero(&sc->et, sizeof(struct eventtimer));

Return to bug 170705