1 /* $NetBSD: clock.c,v 1.13 2014/11/17 02:15:48 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: clock.c 1.18 91/01/21$ 37 * 38 * @(#)clock.c 8.2 (Berkeley) 1/12/94 39 */ 40 41 #include <sys/param.h> 42 43 #include <net/if_ether.h> 44 #include <netinet/in.h> 45 #include <netinet/in_systm.h> 46 47 #include <hp300/stand/common/hilreg.h> 48 49 #include <hp300/dev/frodoreg.h> /* for APCI offsets */ 50 #include <hp300/dev/intioreg.h> /* for frodo offsets */ 51 #include <dev/ic/mc146818reg.h> 52 #include <dev/clock_subr.h> 53 54 #include <lib/libsa/stand.h> 55 #include <lib/libsa/net.h> 56 #include <hp300/stand/common/samachdep.h> 57 58 #define FEBRUARY 2 59 60 #define BBC_SET_REG 0xe0 61 #define BBC_WRITE_REG 0xc2 62 #define BBC_READ_REG 0xc3 63 #define NUM_BBC_REGS 12 64 65 #define range_test(n, l, h) if ((n) < (l) || (n) > (h)) return false 66 #define bbc_to_decimal(a,b) (bbc_registers[a] * 10 + bbc_registers[b]) 67 68 static uint8_t bbc_registers[13]; 69 static struct hil_dev *bbcaddr = BBCADDR; 70 71 static volatile uint8_t *mcclock = 72 (volatile uint8_t *)(INTIOBASE + FRODO_BASE + FRODO_CALENDAR); 73 74 static bool clock_to_gmt(satime_t *); 75 76 static void read_bbc(void); 77 static uint8_t read_bbc_reg(int); 78 static uint8_t mc_read(u_int); 79 80 satime_t 81 getsecs(void) 82 { 83 static bool clockinited = false; 84 satime_t timbuf = 0; 85 86 if (!clock_to_gmt(&timbuf) && !clockinited) 87 printf("WARNING: bad date in battery clock\n"); 88 clockinited = true; 89 90 /* Battery clock does not store usec's, so forget about it. */ 91 return timbuf; 92 } 93 94 static bool 95 clock_to_gmt(satime_t *timbuf) 96 { 97 int i; 98 satime_t tmp; 99 int year, month, day, hour, min, sec; 100 101 if (machineid == HP_425 && mmuid == MMUID_425_E) { 102 /* 425e uses mcclock on the frodo utility chip */ 103 while ((mc_read(MC_REGA) & MC_REGA_UIP) != 0) 104 continue; 105 sec = mc_read(MC_SEC); 106 min = mc_read(MC_MIN); 107 hour = mc_read(MC_HOUR); 108 day = mc_read(MC_DOM); 109 month = mc_read(MC_MONTH); 110 year = mc_read(MC_YEAR) + 1900; 111 } else { 112 /* Use the traditional HIL bbc for all other models */ 113 read_bbc(); 114 115 sec = bbc_to_decimal(1, 0); 116 min = bbc_to_decimal(3, 2); 117 118 /* 119 * Hours are different for some reason. Makes no sense really. 120 */ 121 hour = ((bbc_registers[5] & 0x03) * 10) + bbc_registers[4]; 122 day = bbc_to_decimal(8, 7); 123 month = bbc_to_decimal(10, 9); 124 year = bbc_to_decimal(12, 11) + 1900; 125 } 126 127 if (year < POSIX_BASE_YEAR) 128 year += 100; 129 130 #ifdef CLOCK_DEBUG 131 printf("clock todr: %u/%u/%u %u:%u:%u\n", 132 year, month, day, hour, min, sec); 133 #endif 134 135 range_test(hour, 0, 23); 136 range_test(day, 1, 31); 137 range_test(month, 1, 12); 138 139 tmp = 0; 140 141 for (i = POSIX_BASE_YEAR; i < year; i++) 142 tmp += days_per_year(i); 143 if (is_leap_year(year) && month > FEBRUARY) 144 tmp++; 145 146 for (i = 1; i < month; i++) 147 tmp += days_in_month(i); 148 149 tmp += (day - 1); 150 tmp = ((tmp * 24 + hour) * 60 + min) * 60 + sec; 151 152 *timbuf = tmp; 153 return true; 154 } 155 156 static void 157 read_bbc(void) 158 { 159 int i; 160 bool read_okay; 161 162 read_okay = false; 163 while (!read_okay) { 164 read_okay = true; 165 for (i = 0; i <= NUM_BBC_REGS; i++) 166 bbc_registers[i] = read_bbc_reg(i); 167 for (i = 0; i <= NUM_BBC_REGS; i++) 168 if (bbc_registers[i] != read_bbc_reg(i)) 169 read_okay = false; 170 } 171 } 172 173 static uint8_t 174 read_bbc_reg(int reg) 175 { 176 uint8_t data = reg; 177 178 if (bbcaddr != NULL) { 179 #if 0 180 send_hil_cmd(bbcaddr, BBC_SET_REG, &data, 1, NULL); 181 send_hil_cmd(bbcaddr, BBC_READ_REG, NULL, 0, &data); 182 #else 183 HILWAIT(bbcaddr); 184 bbcaddr->hil_cmd = BBC_SET_REG; 185 HILWAIT(bbcaddr); 186 bbcaddr->hil_data = data; 187 HILWAIT(bbcaddr); 188 bbcaddr->hil_cmd = BBC_READ_REG; 189 HILDATAWAIT(bbcaddr); 190 data = bbcaddr->hil_data; 191 #endif 192 } 193 return data; 194 } 195 196 uint8_t 197 mc_read(u_int reg) 198 { 199 uint8_t datum; 200 201 mcclock[0] = (uint8_t)reg; 202 datum = mcclock[1 << 2]; /* frodo chip has 4 byte stride */ 203 204 return datum; 205 } 206