kernel: Use hashdestroy() to free hash tables allocated with hashinit().
[dragonfly.git] / usr.bin / doscmd / cmos.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1992, 1993, 1996
3 * Berkeley Software Design, Inc. 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 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Berkeley Software
16 * Design, Inc.
17 *
18 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * BSDI cmos.c,v 2.3 1996/04/08 19:32:20 bostic Exp
1de703da
MD
31 *
32 * $FreeBSD: src/usr.bin/doscmd/cmos.c,v 1.2.2.2 2002/04/25 11:04:50 tg Exp $
33 * $DragonFly: src/usr.bin/doscmd/cmos.c,v 1.2 2003/06/17 04:29:25 dillon Exp $
984263bc
MD
34 */
35
984263bc
MD
36#include "doscmd.h"
37
38#define ALARM_ON ((unsigned char) 0x20)
39#define FAST_TIMER ((unsigned char) 0x40)
40#define SEC_SIZE 1
41#define MIN_SIZE 60
42#define HOUR_SIZE (MIN_SIZE * 60)
43#define DAY_SIZE (HOUR_SIZE * 24)
44#define YEAR_DAY 365
45
46#define SEC_MS 1000000
47#define FAST_TICK_BSD 0x3D00
48
49#define Jan 31
50#define Feb 28
51#define Mar 31
52#define Apr 30
53#define May 31
54#define Jun 30
55#define Jul 31
56#define Aug 31
57#define Sep 31
58#define Oct 31
59#define Nov 30
60#define Dec 31
61
62static unsigned char cmos_last_port_70 = 0;
63static unsigned char cmos_data[0x40] = {
64 0x00, /* 0x00 Current Second */
65 0x00, /* 0x01 Alarm Second */
66 0x00, /* 0x02 Current minute */
67 0x00, /* 0x03 Alarm minute */
68 0x00, /* 0x04 Current hour */
69 0x00, /* 0x05 Alarm hour */
70 0x00, /* 0x06 Current week day */
71 0x00, /* 0x07 Current day */
72 0x00, /* 0x08 Current month */
73 0x00, /* 0x09 Current year */
74 0x26, /* 0x0A Status register A */
75 0x02, /* 0x0B Status register B */
76 0x00, /* 0x0C Status register C */
77 0x80, /* 0x0D Status register D */
78 0x00, /* 0x0E Diagnostic status */
79 0x00, /* 0x0F Shutdown Code */
80 0x00, /* 0x10 Drive types (1 FDHD disk) */
81 0x00, /* 0x11 Fixed disk 0 type */
82 0x00, /* 0x12 Fixed disk 1 type */
83 0x00,
84 0x00, /* Installed equipment */
85};
86
87int day_in_year [12] = {
88 0, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov
89};
90
91/* consumed by dos.c */
92time_t delta_clock = 0;
93
94/* locals */
95static struct timeval fast_clock;
96static int fast_tick;
97
98static struct timeval glob_clock;
99static int cmos_alarm_time = 0;
100static int cmos_alarm_daytime = 0;
101
102static inline int
103day_in_mon_year(int mon, int year)
104{
105 return day_in_year[mon] + (mon > 2 && (year % 4 == 0));
106}
107
108static inline int
109to_BCD (int n)
110{
111 n &= 0xFF;
112 return n%10 + ((n/10)<<4);
113}
114
115static inline int
116from_BCD (int n)
117{
118 n &= 0xFF;
119 return (n & 0xF) + (n >> 4) * 10;
120}
121
122/*
123** inb() from clock ports.
124**
125** 0x70 is scratchpad/register select
126** 0x71 is data
127*/
128static unsigned char
129cmos_inb(int portnum)
130{
a62ce081 131 unsigned char ret_val = 0;
984263bc
MD
132 int cmos_reg;
133 struct timezone tz;
a62ce081 134 struct tm tm = { .tm_sec = 0 };
984263bc
MD
135 time_t now;
136
137 switch (portnum) {
138 case 0x70:
139 ret_val = cmos_last_port_70;
140 break;
141 case 0x71:
142 cmos_reg = cmos_last_port_70 & 0x3f;
143 if (cmos_reg < 0xa) {
144 gettimeofday(&glob_clock, &tz);
145 now = glob_clock.tv_sec + delta_clock;
146 tm = *localtime(&now);
147 }
148 switch (cmos_reg) {
149 case 0:
150 ret_val = to_BCD(tm.tm_sec);
151 break;
152 case 2:
153 ret_val = to_BCD(tm.tm_min);
154 break;
155 case 4:
156 ret_val = to_BCD(tm.tm_hour);
157 break;
158 case 6:
159 ret_val = to_BCD(tm.tm_wday);
160 break;
161 case 7:
162 ret_val = to_BCD(tm.tm_mday);
163 break;
164 case 8:
165 ret_val = to_BCD(tm.tm_mon + 1);
166 break;
167 case 9:
168 ret_val = to_BCD((tm.tm_year + 1900) % 100);
169 break;
170 default:
171 ret_val = cmos_data[cmos_reg];
172 break;
173 }
174 break;
175 }
176 return (ret_val);
177}
178
179static void
180cmos_outb(int portnum, unsigned char byte)
181{
182 int cmos_reg;
183 int year;
184 int time00;
185 struct timezone tz;
a62ce081 186 struct tm tm = { .tm_sec = 0 };
984263bc
MD
187 time_t now;
188
189 switch (portnum) {
190 case 0x70:
191 cmos_last_port_70 = byte;
192 break;
193 case 0x71:
194 cmos_reg = cmos_last_port_70 & 0x3f;
195 if (cmos_reg < 0xa) {
196 gettimeofday(&glob_clock, &tz);
197 now = glob_clock.tv_sec + delta_clock;
198 tm = *localtime(&now);
199 }
200 switch (cmos_reg) {
201 case 0:
202 delta_clock += SEC_SIZE * (from_BCD(byte) - tm.tm_sec);
203 break;
204 case 1:
205 cmos_alarm_daytime +=
206 SEC_SIZE * (from_BCD(byte) - from_BCD(cmos_data[1]));
207 break;
208 case 2:
209 delta_clock += MIN_SIZE * (from_BCD(byte) - tm.tm_min);
210 break;
211 case 3:
212 cmos_alarm_daytime +=
213 MIN_SIZE * (from_BCD(byte) - from_BCD(cmos_data[3]));
214 break;
215 case 4:
216 delta_clock += HOUR_SIZE * (from_BCD(byte) - tm.tm_hour);
217 break;
218 case 5:
219 cmos_alarm_daytime +=
220 HOUR_SIZE * (from_BCD(byte) - from_BCD(cmos_data[5]));
221 break;
222 case 7:
223 delta_clock += DAY_SIZE * (from_BCD(byte) - tm.tm_mday);
224 break;
225 case 8:
226 delta_clock += DAY_SIZE *
227 (day_in_mon_year(from_BCD(byte), tm.tm_year) -
228 day_in_mon_year(tm.tm_mon + 1, tm.tm_year));
229 break;
230 case 9:
231 year = from_BCD(byte);
232 delta_clock += DAY_SIZE * (YEAR_DAY * (year - tm.tm_year)
233 + (year/4 - tm.tm_year/4));
234 break;
235 case 0xB:
236 cmos_data[0xc] = byte;
237 if (byte & ALARM_ON) {
238 debug(D_ALWAYS, "Alarm turned on\n");
239 time00 = glob_clock.tv_sec + delta_clock -
240 (tm.tm_sec + MIN_SIZE * tm.tm_min
241 + HOUR_SIZE * tm.tm_hour);
242 cmos_alarm_time = time00 + cmos_alarm_daytime;
243 if (cmos_alarm_time < (glob_clock.tv_sec + delta_clock))
244 cmos_alarm_time += DAY_SIZE;
245 }
246 if (byte & FAST_TIMER) {
247 debug(D_ALWAYS, "Fast timer turned on\n");
248 fast_clock = glob_clock;
249 fast_tick = 0;
250 }
251 break;
252 }
253 cmos_data[cmos_reg] = byte;
254 break;
255 }
256}
257
258
259void
260cmos_init(void)
261{
262 int numflops = 0;
263 int checksum = 0;
264 int i;
265
266 cmos_data[0x0e] = 0;
267
268 numflops = nfloppies;
269 cmos_data[0x10] = (search_floppy(0) << 4) | search_floppy(1);
270
271 if (numflops) /* floppy drives present + numflops */
272 cmos_data[0x14] = ((numflops - 1) << 6) | 1;
273
274 cmos_data[0x15] = 0x80; /* base memory 640k */
275 cmos_data[0x16] = 0x2;
276 for (i=0x10; i<=0x2d; i++)
277 checksum += cmos_data[i];
278 cmos_data[0x2e] = checksum >>8; /* High byte */
279 cmos_data[0x2f] = checksum & 0xFF; /* Low byte */
280
281 cmos_data[0x32] = 0x19; /* Century in BCD ; temporary */
282
283 for (i = 1; i < 12; i++){
284 day_in_year[i] += day_in_year[i-1];
285 }
286
287 define_input_port_handler(0x70, cmos_inb);
288 define_input_port_handler(0x71, cmos_inb);
289 define_output_port_handler(0x70, cmos_outb);
290 define_output_port_handler(0x71, cmos_outb);
291}