/[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 4 - (show annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17901 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.2  ==============


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.68 2005/02/07 05:51:54 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 /* Station Ethernet Address, on DECstation 3100: */
591 for (i=0; i<6; i++)
592 ether_address[i] = 0x10 * (i+1);
593
594 d->reg[0x01] = ether_address[0];
595 d->reg[0x05] = ether_address[1];
596 d->reg[0x09] = ether_address[2];
597 d->reg[0x0d] = ether_address[3];
598 d->reg[0x11] = ether_address[4];
599 d->reg[0x15] = ether_address[5];
600 /* TODO: 19, 1d, 21, 25 = checksum bytes 1,2,2,1 resp. */
601 d->reg[0x29] = ether_address[5];
602 d->reg[0x2d] = ether_address[4];
603 d->reg[0x31] = ether_address[3];
604 d->reg[0x35] = ether_address[2];
605 d->reg[0x39] = ether_address[1];
606 d->reg[0x3d] = ether_address[1];
607 d->reg[0x41] = ether_address[0];
608 d->reg[0x45] = ether_address[1];
609 d->reg[0x49] = ether_address[2];
610 d->reg[0x4d] = ether_address[3];
611 d->reg[0x51] = ether_address[4];
612 d->reg[0x55] = ether_address[5];
613 /* TODO: 59, 5d = checksum bytes 1,2 resp. */
614 d->reg[0x61] = 0xff;
615 d->reg[0x65] = 0x00;
616 d->reg[0x69] = 0x55;
617 d->reg[0x6d] = 0xaa;
618 d->reg[0x71] = 0xff;
619 d->reg[0x75] = 0x00;
620 d->reg[0x79] = 0x55;
621 d->reg[0x7d] = 0xaa;
622
623 /* Only SGI uses BCD format (?) */
624 d->use_bcd = 0;
625 if (access_style == MC146818_SGI)
626 d->use_bcd = 1;
627
628 if (access_style == MC146818_DEC) {
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