/[gxemul]/trunk/src/devices/dev_mc146818.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/devices/dev_mc146818.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17973 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


1 /*
2 * Copyright (C) 2003-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
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 *
28 * $Id: dev_mc146818.c,v 1.69 2005/05/20 07:42:12 debug Exp $
29 *
30 * MC146818 real-time clock, used by many different machines types.
31 * (DS1687 as used in some SGI machines is similar to MC146818.)
32 *
33 * This device contains Date/time, the machine's ethernet address (on
34 * DECstation 3100), and can cause periodic (hardware) interrupts.
35 *
36 * NOTE: Many register offsets are multiplied by 4 in this code; this is
37 * because I originally wrote it for DECstation 3100 emulation, where the
38 * registered are spaced that way.
39 */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <time.h>
45
46 #include "cpu.h"
47 #include "devices.h"
48 #include "machine.h"
49 #include "memory.h"
50 #include "misc.h"
51
52 #include "mc146818reg.h"
53
54
55 #define to_bcd(x) ( ((x)/10) * 16 + ((x)%10) )
56
57 /* #define MC146818_DEBUG */
58
59 #define TICK_STEPS_SHIFT 14
60
61
62 /* 256 on DECstation, SGI uses reg at 72*4 as the Century */
63 #define N_REGISTERS 1024
64 struct mc_data {
65 int access_style;
66 int last_addr;
67
68 int register_choice;
69 int reg[N_REGISTERS];
70 int addrdiv;
71
72 int use_bcd;
73
74 int timebase_hz;
75 int interrupt_hz;
76 int irq_nr;
77
78 int previous_second;
79
80 int interrupt_every_x_cycles;
81 int cycles_left_until_interrupt;
82 };
83
84
85 /*
86 * recalc_interrupt_cycle():
87 *
88 * If automatic_clock_adjustment is turned on, then emulated_hz is modified
89 * dynamically. We have to recalculate how often interrupts are to be
90 * triggered.
91 */
92 static void recalc_interrupt_cycle(struct cpu *cpu, struct mc_data *d)
93 {
94 int64_t emulated_hz = cpu->machine->emulated_hz;
95 #if 0
96 static int warning_printed = 0;
97
98 /*
99 * A hack to make Ultrix run, even on very fast host machines.
100 *
101 * (Ultrix was probably never meant to be run on machines with
102 * faster CPUs than around 33 MHz or so.)
103 */
104 if (d->access_style == MC146818_DEC && emulated_hz > 30000000) {
105 if (!warning_printed) {
106 fatal("\n*********************************************"
107 "**********************************\n\n Your hos"
108 "t machine is too fast! The emulated CPU speed wil"
109 "l be limited to\n 30 MHz, and clocks inside the"
110 " emulated environment might go faster than\n in"
111 " the real world. You have been warned.\n\n******"
112 "*************************************************"
113 "************************\n\n");
114 warning_printed = 1;
115 }
116
117 emulated_hz = 30000000;
118 }
119 #endif
120
121 if (d->interrupt_hz > 0)
122 d->interrupt_every_x_cycles =
123 emulated_hz / d->interrupt_hz;
124 else
125 d->interrupt_every_x_cycles = 0;
126 }
127
128
129 /*
130 * dev_mc146818_tick():
131 */
132 void dev_mc146818_tick(struct cpu *cpu, void *extra)
133 {
134 struct mc_data *d = extra;
135
136 if (d == NULL)
137 return;
138
139 recalc_interrupt_cycle(cpu, d);
140
141 if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) &&
142 d->interrupt_every_x_cycles > 0) {
143 d->cycles_left_until_interrupt -=
144 (1 << TICK_STEPS_SHIFT);
145
146 if (d->cycles_left_until_interrupt < 0 ||
147 d->cycles_left_until_interrupt >=
148 d->interrupt_every_x_cycles) {
149 /* debug("[ rtc interrupt (every %i cycles) ]\n",
150 d->interrupt_every_x_cycles); */
151 cpu_interrupt(cpu, d->irq_nr);
152
153 d->reg[MC_REGC * 4] |= MC_REGC_PF;
154
155 /* Reset the cycle countdown: */
156 while (d->cycles_left_until_interrupt < 0)
157 d->cycles_left_until_interrupt +=
158 d->interrupt_every_x_cycles;
159 }
160 }
161
162 if (d->reg[MC_REGC * 4] & MC_REGC_UF ||
163 d->reg[MC_REGC * 4] & MC_REGC_AF ||
164 d->reg[MC_REGC * 4] & MC_REGC_PF)
165 d->reg[MC_REGC * 4] |= MC_REGC_IRQF;
166 }
167
168
169 /*
170 * dev_mc146818_jazz_access():
171 *
172 * It seems like JAZZ machines accesses the mc146818 by writing one byte to
173 * 0x90000070 and then reading or writing another byte at 0x......0004000.
174 */
175 int dev_mc146818_jazz_access(struct cpu *cpu, struct memory *mem,
176 uint64_t relative_addr, unsigned char *data, size_t len,
177 int writeflag, void *extra)
178 {
179 struct mc_data *d = extra;
180
181 #ifdef MC146818_DEBUG
182 if (writeflag == MEM_WRITE) {
183 int i;
184 fatal("[ mc146818_jazz: write to addr=0x%04x: ",
185 (int)relative_addr);
186 for (i=0; i<len; i++)
187 fatal("%02x ", data[i]);
188 fatal("]\n");
189 } else
190 fatal("[ mc146818_jazz: read from addr=0x%04x ]\n",
191 (int)relative_addr);
192 #endif
193
194 if (writeflag == MEM_WRITE) {
195 d->last_addr = data[0];
196 return 1;
197 } else {
198 data[0] = d->last_addr;
199 return 1;
200 }
201 }
202
203
204 /*
205 * mc146818_update_time():
206 *
207 * This function updates the MC146818 registers by reading
208 * the host's clock.
209 */
210 static void mc146818_update_time(struct mc_data *d)
211 {
212 struct tm *tmp;
213 time_t timet;
214
215 timet = time(NULL);
216 tmp = gmtime(&timet);
217
218 d->reg[4 * MC_SEC] = tmp->tm_sec;
219 d->reg[4 * MC_MIN] = tmp->tm_min;
220 d->reg[4 * MC_HOUR] = tmp->tm_hour;
221 d->reg[4 * MC_DOW] = tmp->tm_wday + 1;
222 d->reg[4 * MC_DOM] = tmp->tm_mday;
223 d->reg[4 * MC_MONTH] = tmp->tm_mon + 1;
224 d->reg[4 * MC_YEAR] = tmp->tm_year;
225
226 switch (d->access_style) {
227 case MC146818_ARC_NEC:
228 d->reg[4 * MC_YEAR] += (0x18 - 104);
229 break;
230 case MC146818_SGI:
231 /*
232 * NetBSD/sgimips assumes data in BCD format.
233 * Also, IRIX stores the year value in a weird
234 * format, according to ../arch/sgimips/sgimips/clockvar.h
235 * in NetBSD:
236 *
237 * "If year < 1985, store (year - 1970), else
238 * (year - 1940). This matches IRIX semantics."
239 *
240 * Another rule: It seems that a real SGI IP32 box
241 * uses the value 5 for the year 2005.
242 */
243 d->reg[4 * MC_YEAR] =
244 d->reg[4 * MC_YEAR] >= 100 ?
245 (d->reg[4 * MC_YEAR] - 100) :
246 (
247 d->reg[4 * MC_YEAR] < 85 ?
248 (d->reg[4 * MC_YEAR] - 30 + 40)
249 : (d->reg[4 * MC_YEAR] - 40)
250 );
251
252 /* Century: */
253 d->reg[72 * 4] = 19 + (tmp->tm_year / 100);
254
255 break;
256 case MC146818_DEC:
257 /*
258 * DECstations must have 72 or 73 in the
259 * Year field, or Ultrix screems. (Weird.)
260 */
261 d->reg[4 * MC_YEAR] = 72;
262
263 /*
264 * Linux on DECstation stores the year in register 63,
265 * but no other DECstation OS does? (Hm.)
266 */
267 d->reg[4 * 63] = tmp->tm_year - 100;
268 break;
269 }
270
271 if (d->use_bcd) {
272 d->reg[4 * MC_SEC] = to_bcd(d->reg[4 * MC_SEC]);
273 d->reg[4 * MC_MIN] = to_bcd(d->reg[4 * MC_MIN]);
274 d->reg[4 * MC_HOUR] = to_bcd(d->reg[4 * MC_HOUR]);
275 d->reg[4 * MC_DOW] = to_bcd(d->reg[4 * MC_DOW]);
276 d->reg[4 * MC_DOM] = to_bcd(d->reg[4 * MC_DOM]);
277 d->reg[4 * MC_MONTH] = to_bcd(d->reg[4 * MC_MONTH]);
278 d->reg[4 * MC_YEAR] = to_bcd(d->reg[4 * MC_YEAR]);
279
280 /* Used by Linux on DECstation: (Hm) */
281 d->reg[4 * 63] = to_bcd(d->reg[4 * 63]);
282
283 /* Used on SGI: */
284 d->reg[4 * 72] = to_bcd(d->reg[4 * 72]);
285 }
286 }
287
288
289 /*
290 * dev_mc146818_access():
291 *
292 * TODO: This access function only handles 8-bit accesses!
293 */
294 int dev_mc146818_access(struct cpu *cpu, struct memory *mem,
295 uint64_t r, unsigned char *data, size_t len,
296 int writeflag, void *extra)
297 {
298 struct tm *tmp;
299 time_t timet;
300 struct mc_data *d = extra;
301 int i, relative_addr = r;
302
303 relative_addr /= d->addrdiv;
304
305 /* Different ways of accessing the registers: */
306 switch (d->access_style) {
307 case MC146818_PC_CMOS:
308 if (relative_addr == 0x70 || relative_addr == 0x00) {
309 if (writeflag == MEM_WRITE) {
310 d->last_addr = data[0];
311 return 1;
312 } else {
313 data[0] = d->last_addr;
314 return 1;
315 }
316 } else if (relative_addr == 0x71 || relative_addr == 0x01)
317 relative_addr = d->last_addr * 4;
318 else {
319 fatal("[ mc146818: not accessed as an "
320 "MC146818_PC_CMOS device! ]\n");
321 }
322 break;
323 case MC146818_ARC_NEC:
324 if (relative_addr == 0x01) {
325 if (writeflag == MEM_WRITE) {
326 d->last_addr = data[0];
327 return 1;
328 } else {
329 data[0] = d->last_addr;
330 return 1;
331 }
332 } else if (relative_addr == 0x00)
333 relative_addr = d->last_addr * 4;
334 else {
335 fatal("[ mc146818: not accessed as an "
336 "MC146818_ARC_NEC device! ]\n");
337 }
338 break;
339 case MC146818_ARC_JAZZ:
340 /* See comment for dev_mc146818_jazz_access(). */
341 relative_addr = d->last_addr * 4;
342 break;
343 case MC146818_DEC:
344 case MC146818_SGI:
345 /*
346 * This device was originally written for DECstation
347 * emulation, so no changes are necessary for that access
348 * style.
349 *
350 * SGI access bytes 0x0..0xd at offsets 0x0yz..0xdyz, where yz
351 * should be ignored. It works _almost_ as DEC, if offsets are
352 * divided by 0x40.
353 */
354 default:
355 ;
356 }
357
358 #ifdef MC146818_DEBUG
359 if (writeflag == MEM_WRITE) {
360 fatal("[ mc146818: write to addr=0x%04x (len %i): ",
361 (int)relative_addr, (int)len);
362 for (i=0; i<len; i++)
363 fatal("%02x ", data[i]);
364 fatal("]\n");
365 }
366 #endif
367
368 /*
369 * For some reason, Linux/sgimips relies on the UIP bit to go
370 * on and off. Without this code, booting Linux takes forever:
371 */
372 d->reg[MC_REGA * 4] &= ~MC_REGA_UIP;
373 #if 1
374 /* TODO: solve this more nicely */
375 if ((random() & 0xff) == 0)
376 d->reg[MC_REGA * 4] ^= MC_REGA_UIP;
377 #endif
378
379 /*
380 * Sprite seens to wants UF interrupt status, once every second, or
381 * it hangs forever during bootup. (These do not cause interrupts,
382 * but it is good enough... Sprite polls this, iirc.)
383 */
384 timet = time(NULL);
385 tmp = gmtime(&timet);
386 d->reg[MC_REGC * 4] &= ~MC_REGC_UF;
387 if (tmp->tm_sec != d->previous_second) {
388 d->reg[MC_REGC * 4] |= MC_REGC_UF;
389 d->reg[MC_REGC * 4] |= MC_REGC_IRQF;
390 d->previous_second = tmp->tm_sec;
391
392 /* For some reason, some Linux/DECstation KN04 kernels want
393 the PF (periodic flag) bit set, even though interrupts
394 are not enabled? */
395 d->reg[MC_REGC * 4] |= MC_REGC_PF;
396 }
397
398 /* RTC data is in either BCD format or binary: */
399 if (d->use_bcd) {
400 d->reg[MC_REGB * 4] &= ~(1 << 2);
401 } else {
402 d->reg[MC_REGB * 4] |= (1 << 2);
403 }
404
405 /* RTC date/time is always Valid: */
406 d->reg[MC_REGD * 4] |= MC_REGD_VRT;
407
408 if (writeflag == MEM_WRITE) {
409 /* WRITE: */
410 switch (relative_addr) {
411 case MC_REGA*4:
412 if ((data[0] & MC_REGA_DVMASK) == MC_BASE_32_KHz)
413 d->timebase_hz = 32000;
414 if ((data[0] & MC_REGA_DVMASK) == MC_BASE_1_MHz)
415 d->timebase_hz = 1000000;
416 if ((data[0] & MC_REGA_DVMASK) == MC_BASE_4_MHz)
417 d->timebase_hz = 4000000;
418 switch (data[0] & MC_REGA_RSMASK) {
419 case MC_RATE_NONE:
420 d->interrupt_hz = 0;
421 break;
422 case MC_RATE_1:
423 if (d->timebase_hz == 32000)
424 d->interrupt_hz = 256;
425 else
426 d->interrupt_hz = 32768;
427 break;
428 case MC_RATE_2:
429 if (d->timebase_hz == 32000)
430 d->interrupt_hz = 128;
431 else
432 d->interrupt_hz = 16384;
433 break;
434 case MC_RATE_8192_Hz: d->interrupt_hz = 8192; break;
435 case MC_RATE_4096_Hz: d->interrupt_hz = 4096; break;
436 case MC_RATE_2048_Hz: d->interrupt_hz = 2048; break;
437 case MC_RATE_1024_Hz: d->interrupt_hz = 1024; break;
438 case MC_RATE_512_Hz: d->interrupt_hz = 512; break;
439 case MC_RATE_256_Hz: d->interrupt_hz = 256; break;
440 case MC_RATE_128_Hz: d->interrupt_hz = 128; break;
441 case MC_RATE_64_Hz: d->interrupt_hz = 64; break;
442 case MC_RATE_32_Hz: d->interrupt_hz = 32; break;
443 case MC_RATE_16_Hz: d->interrupt_hz = 16; break;
444 case MC_RATE_8_Hz: d->interrupt_hz = 8; break;
445 case MC_RATE_4_Hz: d->interrupt_hz = 4; break;
446 case MC_RATE_2_Hz: d->interrupt_hz = 2; break;
447 default:
448 /* debug("[ mc146818: unimplemented "
449 "MC_REGA RS: %i ]\n",
450 data[0] & MC_REGA_RSMASK); */
451 ;
452 }
453
454 recalc_interrupt_cycle(cpu, d);
455
456 d->cycles_left_until_interrupt =
457 d->interrupt_every_x_cycles;
458
459 d->reg[MC_REGA * 4] =
460 data[0] & (MC_REGA_RSMASK | MC_REGA_DVMASK);
461
462 debug("[ rtc set to interrupt every %i:th cycle ]\n",
463 d->interrupt_every_x_cycles);
464 break;
465 case MC_REGB*4:
466 if (((data[0] ^ d->reg[MC_REGB*4]) & MC_REGB_PIE))
467 d->cycles_left_until_interrupt =
468 d->interrupt_every_x_cycles;
469 d->reg[MC_REGB*4] = data[0];
470 if (!(data[0] & MC_REGB_PIE)) {
471 cpu_interrupt_ack(cpu, d->irq_nr);
472 /* d->cycles_left_until_interrupt =
473 d->interrupt_every_x_cycles; */
474 }
475 /* debug("[ mc146818: write to MC_REGB, data[0] "
476 "= 0x%02x ]\n", data[0]); */
477 break;
478 case MC_REGC*4:
479 d->reg[MC_REGC * 4] = data[0];
480 debug("[ mc146818: write to MC_REGC, data[0] = "
481 "0x%02x ]\n", data[0]);
482 break;
483 case 0x128:
484 d->reg[relative_addr] = data[0];
485 if (data[0] & 8) {
486 /* Used on SGI to power off the machine. */
487 fatal("[ md146818: power off ]\n");
488 for (i=0; i<cpu->machine->ncpus; i++)
489 cpu->machine->cpus[i]->running = 0;
490 cpu->machine->
491 exit_without_entering_debugger = 1;
492 }
493 break;
494 default:
495 d->reg[relative_addr] = data[0];
496
497 debug("[ mc146818: unimplemented write to "
498 "relative_addr = %08lx: ", (long)relative_addr);
499 for (i=0; i<len; i++)
500 debug("%02x ", data[i]);
501 debug("]\n");
502 }
503 } else {
504 /* READ: */
505 switch (relative_addr) {
506 case 0x01: /* Station's ethernet address (6 bytes) */
507 case 0x05: /* (on DECstation 3100) */
508 case 0x09:
509 case 0x0d:
510 case 0x11:
511 case 0x15:
512 break;
513 case 4 * MC_SEC:
514 case 4 * MC_MIN:
515 case 4 * MC_HOUR:
516 case 4 * MC_DOW:
517 case 4 * MC_DOM:
518 case 4 * MC_MONTH:
519 case 4 * MC_YEAR:
520 case 4 * 63: /* 63 is used by Linux on DECstation */
521 case 4 * 72: /* 72 is Century, on SGI (DS1687) */
522 /*
523 * If the SET bit is set, then we don't automatically
524 * update the values. Otherwise, we update them by
525 * reading from the host's clock:
526 */
527 if (d->reg[MC_REGB * 4] & MC_REGB_SET)
528 break;
529
530 mc146818_update_time(d);
531 break;
532 case 4 * MC_REGC: /* Interrupt ack. */
533 /* NOTE: Acking is done below, _after_ the
534 register has been read. */
535 break;
536 default:
537 debug("[ mc146818: read from relative_addr = "
538 "%04x ]\n", (int)relative_addr);
539 ;
540 }
541
542 data[0] = d->reg[relative_addr];
543
544 if (relative_addr == MC_REGC*4) {
545 cpu_interrupt_ack(cpu, d->irq_nr);
546 /* d->cycles_left_until_interrupt =
547 d->interrupt_every_x_cycles; */
548 d->reg[MC_REGC * 4] = 0x00;
549 }
550 }
551
552 #ifdef MC146818_DEBUG
553 if (writeflag == MEM_READ) {
554 fatal("[ mc146818: read from addr=0x%04x (len %i): ",
555 (int)relative_addr, (int)len);
556 for (i=0; i<len; i++)
557 fatal("%02x ", data[i]);
558 fatal("]\n");
559 }
560 #endif
561
562 return 1;
563 }
564
565
566 /*
567 * dev_mc146818_init():
568 *
569 * This needs to work for both DECstation emulation and other machine types,
570 * so it contains both rtc related stuff and the station's Ethernet address.
571 */
572 void dev_mc146818_init(struct machine *machine, struct memory *mem,
573 uint64_t baseaddr, int irq_nr, int access_style, int addrdiv)
574 {
575 unsigned char ether_address[6];
576 int i, dev_len;
577 struct mc_data *d;
578
579 d = malloc(sizeof(struct mc_data));
580 if (d == NULL) {
581 fprintf(stderr, "out of memory\n");
582 exit(1);
583 }
584
585 memset(d, 0, sizeof(struct mc_data));
586 d->irq_nr = irq_nr;
587 d->access_style = access_style;
588 d->addrdiv = addrdiv;
589
590 /* Only SGIs and PCs use BCD format (?) */
591 d->use_bcd = 0;
592 if (access_style == MC146818_SGI || access_style == MC146818_PC_CMOS)
593 d->use_bcd = 1;
594
595 if (access_style == MC146818_DEC) {
596 /* Station Ethernet Address, on DECstation 3100: */
597 for (i=0; i<6; i++)
598 ether_address[i] = 0x10 * (i+1);
599
600 d->reg[0x01] = ether_address[0];
601 d->reg[0x05] = ether_address[1];
602 d->reg[0x09] = ether_address[2];
603 d->reg[0x0d] = ether_address[3];
604 d->reg[0x11] = ether_address[4];
605 d->reg[0x15] = ether_address[5];
606 /* TODO: 19, 1d, 21, 25 = checksum bytes 1,2,2,1 resp. */
607 d->reg[0x29] = ether_address[5];
608 d->reg[0x2d] = ether_address[4];
609 d->reg[0x31] = ether_address[3];
610 d->reg[0x35] = ether_address[2];
611 d->reg[0x39] = ether_address[1];
612 d->reg[0x3d] = ether_address[1];
613 d->reg[0x41] = ether_address[0];
614 d->reg[0x45] = ether_address[1];
615 d->reg[0x49] = ether_address[2];
616 d->reg[0x4d] = ether_address[3];
617 d->reg[0x51] = ether_address[4];
618 d->reg[0x55] = ether_address[5];
619 /* TODO: 59, 5d = checksum bytes 1,2 resp. */
620 d->reg[0x61] = 0xff;
621 d->reg[0x65] = 0x00;
622 d->reg[0x69] = 0x55;
623 d->reg[0x6d] = 0xaa;
624 d->reg[0x71] = 0xff;
625 d->reg[0x75] = 0x00;
626 d->reg[0x79] = 0x55;
627 d->reg[0x7d] = 0xaa;
628
629 /* Battery valid, for DECstations */
630 d->reg[0xf8] = 1;
631 }
632
633 if (access_style == MC146818_ARC_JAZZ)
634 memory_device_register(mem, "mc146818_jazz", 0x90000070ULL,
635 1, dev_mc146818_jazz_access, d, MEM_DEFAULT, NULL);
636
637 dev_len = DEV_MC146818_LENGTH;
638 switch (access_style) {
639 case MC146818_PC_CMOS:
640 dev_len = 2;
641 break;
642 case MC146818_SGI:
643 dev_len = 0x400;
644 }
645
646 memory_device_register(mem, "mc146818", baseaddr,
647 dev_len * addrdiv, dev_mc146818_access,
648 d, MEM_DEFAULT, NULL);
649
650 mc146818_update_time(d);
651
652 machine_add_tickfunction(machine, dev_mc146818_tick,
653 d, TICK_STEPS_SHIFT);
654 }
655

  ViewVC Help
Powered by ViewVC 1.1.26