/[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 16 - (show annotations)
Mon Oct 8 16:19:01 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 17859 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.988 2005/10/11 03:53:57 debug Exp $

==============  RELEASE 0.3.6  ==============

20051008	The bug was not because of faulty ARM documentation after all,
		but it was related to those parts of the code.
		Fixing the RTC (dev_mc146818) to work with CATS.
20051009	Rewriting the R() function; now there are 8192 automatically
		generated smaller functions doing the same thing, but hopefully
		faster. This also fixes some bugs which were triggered when
		trying to compile GXemul inside itself. :-)
		Adding a dummy dev_lpt.
20051010	Small hack to not update virtual translation tables if memory
		accesses are done with the NO_EXCEPTION flag; a time reduction
		of almost a factor 2 for a full NetBSD/cats install. :-)
20051011	Passing -A as the default boot arg for CATS (works fine with
		OpenBSD/cats).

==============  RELEASE 0.3.6.1  ==============


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.75 2005/10/09 22:21:31 debug Exp $
29 *
30 * MC146818 real-time clock, used by many different machines types.
31 * (DS1687 as used in some other machines is also similar to the 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_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 -= (1 << TICK_SHIFT);
144
145 if (d->cycles_left_until_interrupt < 0 ||
146 d->cycles_left_until_interrupt >=
147 d->interrupt_every_x_cycles) {
148 /* debug("[ rtc interrupt (every %i cycles) ]\n",
149 d->interrupt_every_x_cycles); */
150 cpu_interrupt(cpu, d->irq_nr);
151
152 d->reg[MC_REGC * 4] |= MC_REGC_PF;
153
154 /* Reset the cycle countdown: */
155 while (d->cycles_left_until_interrupt < 0)
156 d->cycles_left_until_interrupt +=
157 d->interrupt_every_x_cycles;
158 }
159 }
160
161 if (d->reg[MC_REGC * 4] & MC_REGC_UF ||
162 d->reg[MC_REGC * 4] & MC_REGC_AF ||
163 d->reg[MC_REGC * 4] & MC_REGC_PF)
164 d->reg[MC_REGC * 4] |= MC_REGC_IRQF;
165 }
166
167
168 /*
169 * dev_mc146818_jazz_access():
170 *
171 * It seems like JAZZ machines accesses the mc146818 by writing one byte to
172 * 0x90000070 and then reading or writing another byte at 0x......0004000.
173 */
174 int dev_mc146818_jazz_access(struct cpu *cpu, struct memory *mem,
175 uint64_t relative_addr, unsigned char *data, size_t len,
176 int writeflag, void *extra)
177 {
178 struct mc_data *d = extra;
179
180 #ifdef MC146818_DEBUG
181 if (writeflag == MEM_WRITE) {
182 int i;
183 fatal("[ mc146818_jazz: write to addr=0x%04x: ",
184 (int)relative_addr);
185 for (i=0; i<len; i++)
186 fatal("%02x ", data[i]);
187 fatal("]\n");
188 } else
189 fatal("[ mc146818_jazz: read from addr=0x%04x ]\n",
190 (int)relative_addr);
191 #endif
192
193 if (writeflag == MEM_WRITE) {
194 d->last_addr = data[0];
195 return 1;
196 } else {
197 data[0] = d->last_addr;
198 return 1;
199 }
200 }
201
202
203 /*
204 * mc146818_update_time():
205 *
206 * This function updates the MC146818 registers by reading
207 * the host's clock.
208 */
209 static void mc146818_update_time(struct mc_data *d)
210 {
211 struct tm *tmp;
212 time_t timet;
213
214 timet = time(NULL);
215 tmp = gmtime(&timet);
216
217 d->reg[4 * MC_SEC] = tmp->tm_sec;
218 d->reg[4 * MC_MIN] = tmp->tm_min;
219 d->reg[4 * MC_HOUR] = tmp->tm_hour;
220 d->reg[4 * MC_DOW] = tmp->tm_wday + 1;
221 d->reg[4 * MC_DOM] = tmp->tm_mday;
222 d->reg[4 * MC_MONTH] = tmp->tm_mon + 1;
223 d->reg[4 * MC_YEAR] = tmp->tm_year;
224
225 /*
226 * Special hacks for emulating the behaviour of various machines:
227 */
228 switch (d->access_style) {
229 case MC146818_ARC_NEC:
230 d->reg[4 * MC_YEAR] += (0x18 - 104);
231 break;
232 case MC146818_CATS:
233 d->reg[4 * MC_YEAR] %= 100;
234 break;
235 case MC146818_SGI:
236 /*
237 * NetBSD/sgimips assumes data in BCD format.
238 * Also, IRIX stores the year value in a weird
239 * format, according to ../arch/sgimips/sgimips/clockvar.h
240 * in NetBSD:
241 *
242 * "If year < 1985, store (year - 1970), else
243 * (year - 1940). This matches IRIX semantics."
244 *
245 * Another rule: It seems that a real SGI IP32 box
246 * uses the value 5 for the year 2005.
247 */
248 d->reg[4 * MC_YEAR] =
249 d->reg[4 * MC_YEAR] >= 100 ?
250 (d->reg[4 * MC_YEAR] - 100) :
251 (
252 d->reg[4 * MC_YEAR] < 85 ?
253 (d->reg[4 * MC_YEAR] - 30 + 40)
254 : (d->reg[4 * MC_YEAR] - 40)
255 );
256 /* Century: */
257 d->reg[72 * 4] = 19 + (tmp->tm_year / 100);
258 break;
259 case MC146818_DEC:
260 /*
261 * DECstations must have 72 or 73 in the
262 * Year field, or Ultrix screems. (Weird.)
263 */
264 d->reg[4 * MC_YEAR] = 72;
265
266 /*
267 * Linux on DECstation stores the year in register 63,
268 * but no other DECstation OS does? (Hm.)
269 */
270 d->reg[4 * 63] = tmp->tm_year - 100;
271 break;
272 }
273
274 if (d->use_bcd) {
275 d->reg[4 * MC_SEC] = to_bcd(d->reg[4 * MC_SEC]);
276 d->reg[4 * MC_MIN] = to_bcd(d->reg[4 * MC_MIN]);
277 d->reg[4 * MC_HOUR] = to_bcd(d->reg[4 * MC_HOUR]);
278 d->reg[4 * MC_DOW] = to_bcd(d->reg[4 * MC_DOW]);
279 d->reg[4 * MC_DOM] = to_bcd(d->reg[4 * MC_DOM]);
280 d->reg[4 * MC_MONTH] = to_bcd(d->reg[4 * MC_MONTH]);
281 d->reg[4 * MC_YEAR] = to_bcd(d->reg[4 * MC_YEAR]);
282
283 /* Used by Linux on DECstation: (Hm) */
284 d->reg[4 * 63] = to_bcd(d->reg[4 * 63]);
285
286 /* Used on SGI: */
287 d->reg[4 * 72] = to_bcd(d->reg[4 * 72]);
288 }
289 }
290
291
292 /*
293 * dev_mc146818_access():
294 *
295 * TODO: This access function only handles 8-bit accesses!
296 */
297 int dev_mc146818_access(struct cpu *cpu, struct memory *mem,
298 uint64_t r, unsigned char *data, size_t len,
299 int writeflag, void *extra)
300 {
301 struct tm *tmp;
302 time_t timet;
303 struct mc_data *d = extra;
304 int i, relative_addr = r;
305
306 relative_addr /= d->addrdiv;
307
308 /* Different ways of accessing the registers: */
309 switch (d->access_style) {
310 case MC146818_CATS:
311 case MC146818_PC_CMOS:
312 if ((relative_addr & 1) == 0x00) {
313 if (writeflag == MEM_WRITE) {
314 d->last_addr = data[0];
315 return 1;
316 } else {
317 data[0] = d->last_addr;
318 return 1;
319 }
320 } else
321 relative_addr = d->last_addr * 4;
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 * Sprite seems to wants UF interrupt status, once every second, or
370 * it hangs forever during bootup. (These do not cause interrupts,
371 * but it is good enough... Sprite polls this, iirc.)
372 *
373 * Linux on at least sgimips and evbmips (Malta) wants the UIP bit
374 * in REGA to be updated once a second.
375 */
376 timet = time(NULL);
377 tmp = gmtime(&timet);
378 d->reg[MC_REGC * 4] &= ~MC_REGC_UF;
379
380 if (tmp->tm_sec != d->previous_second) {
381 d->reg[MC_REGA * 4] &= ~MC_REGA_UIP;
382
383 d->reg[MC_REGC * 4] |= MC_REGC_UF;
384 d->reg[MC_REGC * 4] |= MC_REGC_IRQF;
385 d->previous_second = tmp->tm_sec;
386
387 /* For some reason, some Linux/DECstation KN04 kernels want
388 the PF (periodic flag) bit set, even though interrupts
389 are not enabled? */
390 d->reg[MC_REGC * 4] |= MC_REGC_PF;
391 } else
392 d->reg[MC_REGA * 4] |= MC_REGA_UIP;
393
394 /* RTC data is in either BCD format or binary: */
395 if (d->use_bcd)
396 d->reg[MC_REGB * 4] &= ~(1 << 2);
397 else
398 d->reg[MC_REGB * 4] |= (1 << 2);
399
400 /* RTC date/time is always Valid: */
401 d->reg[MC_REGD * 4] |= MC_REGD_VRT;
402
403 if (writeflag == MEM_WRITE) {
404 /* WRITE: */
405 switch (relative_addr) {
406 case MC_REGA*4:
407 if ((data[0] & MC_REGA_DVMASK) == MC_BASE_32_KHz)
408 d->timebase_hz = 32000;
409 if ((data[0] & MC_REGA_DVMASK) == MC_BASE_1_MHz)
410 d->timebase_hz = 1000000;
411 if ((data[0] & MC_REGA_DVMASK) == MC_BASE_4_MHz)
412 d->timebase_hz = 4000000;
413 switch (data[0] & MC_REGA_RSMASK) {
414 case MC_RATE_NONE:
415 d->interrupt_hz = 0;
416 break;
417 case MC_RATE_1:
418 if (d->timebase_hz == 32000)
419 d->interrupt_hz = 256;
420 else
421 d->interrupt_hz = 32768;
422 break;
423 case MC_RATE_2:
424 if (d->timebase_hz == 32000)
425 d->interrupt_hz = 128;
426 else
427 d->interrupt_hz = 16384;
428 break;
429 case MC_RATE_8192_Hz: d->interrupt_hz = 8192; break;
430 case MC_RATE_4096_Hz: d->interrupt_hz = 4096; break;
431 case MC_RATE_2048_Hz: d->interrupt_hz = 2048; break;
432 case MC_RATE_1024_Hz: d->interrupt_hz = 1024; break;
433 case MC_RATE_512_Hz: d->interrupt_hz = 512; break;
434 case MC_RATE_256_Hz: d->interrupt_hz = 256; break;
435 case MC_RATE_128_Hz: d->interrupt_hz = 128; break;
436 case MC_RATE_64_Hz: d->interrupt_hz = 64; break;
437 case MC_RATE_32_Hz: d->interrupt_hz = 32; break;
438 case MC_RATE_16_Hz: d->interrupt_hz = 16; break;
439 case MC_RATE_8_Hz: d->interrupt_hz = 8; break;
440 case MC_RATE_4_Hz: d->interrupt_hz = 4; break;
441 case MC_RATE_2_Hz: d->interrupt_hz = 2; break;
442 default:
443 /* debug("[ mc146818: unimplemented "
444 "MC_REGA RS: %i ]\n",
445 data[0] & MC_REGA_RSMASK); */
446 ;
447 }
448
449 recalc_interrupt_cycle(cpu, d);
450
451 d->cycles_left_until_interrupt =
452 d->interrupt_every_x_cycles;
453
454 d->reg[MC_REGA * 4] =
455 data[0] & (MC_REGA_RSMASK | MC_REGA_DVMASK);
456
457 debug("[ rtc set to interrupt every %i:th cycle ]\n",
458 d->interrupt_every_x_cycles);
459 break;
460 case MC_REGB*4:
461 if (((data[0] ^ d->reg[MC_REGB*4]) & MC_REGB_PIE))
462 d->cycles_left_until_interrupt =
463 d->interrupt_every_x_cycles;
464 d->reg[MC_REGB*4] = data[0];
465 if (!(data[0] & MC_REGB_PIE)) {
466 cpu_interrupt_ack(cpu, d->irq_nr);
467 /* d->cycles_left_until_interrupt =
468 d->interrupt_every_x_cycles; */
469 }
470 /* debug("[ mc146818: write to MC_REGB, data[0] "
471 "= 0x%02x ]\n", data[0]); */
472 break;
473 case MC_REGC*4:
474 d->reg[MC_REGC * 4] = data[0];
475 debug("[ mc146818: write to MC_REGC, data[0] = "
476 "0x%02x ]\n", data[0]);
477 break;
478 case 0x128:
479 d->reg[relative_addr] = data[0];
480 if (data[0] & 8) {
481 /* Used on SGI to power off the machine. */
482 fatal("[ md146818: power off ]\n");
483 for (i=0; i<cpu->machine->ncpus; i++)
484 cpu->machine->cpus[i]->running = 0;
485 cpu->machine->
486 exit_without_entering_debugger = 1;
487 }
488 break;
489 default:
490 d->reg[relative_addr] = data[0];
491
492 debug("[ mc146818: unimplemented write to "
493 "relative_addr = %08lx: ", (long)relative_addr);
494 for (i=0; i<len; i++)
495 debug("%02x ", data[i]);
496 debug("]\n");
497 }
498 } else {
499 /* READ: */
500 switch (relative_addr) {
501 case 0x01: /* Station's ethernet address (6 bytes) */
502 case 0x05: /* (on DECstation 3100) */
503 case 0x09:
504 case 0x0d:
505 case 0x11:
506 case 0x15:
507 break;
508 case 4 * MC_SEC:
509 case 4 * MC_MIN:
510 case 4 * MC_HOUR:
511 case 4 * MC_DOW:
512 case 4 * MC_DOM:
513 case 4 * MC_MONTH:
514 case 4 * MC_YEAR:
515 case 4 * 63: /* 63 is used by Linux on DECstation */
516 case 4 * 72: /* 72 is Century, on SGI (DS1687) */
517 /*
518 * If the SET bit is set, then we don't automatically
519 * update the values. Otherwise, we update them by
520 * reading from the host's clock:
521 */
522 if (d->reg[MC_REGB * 4] & MC_REGB_SET)
523 break;
524
525 mc146818_update_time(d);
526 break;
527 case 4 * MC_REGC: /* Interrupt ack. */
528 /* NOTE: Acking is done below, _after_ the
529 register has been read. */
530 break;
531 default:
532 debug("[ mc146818: read from relative_addr = "
533 "%04x ]\n", (int)relative_addr);
534 ;
535 }
536
537 data[0] = d->reg[relative_addr];
538
539 if (relative_addr == MC_REGC*4) {
540 cpu_interrupt_ack(cpu, d->irq_nr);
541 /* d->cycles_left_until_interrupt =
542 d->interrupt_every_x_cycles; */
543 d->reg[MC_REGC * 4] = 0x00;
544 }
545 }
546
547 #ifdef MC146818_DEBUG
548 if (writeflag == MEM_READ) {
549 fatal("[ mc146818: read from addr=0x%04x (len %i): ",
550 (int)relative_addr, (int)len);
551 for (i=0; i<len; i++)
552 fatal("%02x ", data[i]);
553 fatal("]\n");
554 }
555 #endif
556
557 return 1;
558 }
559
560
561 /*
562 * dev_mc146818_init():
563 *
564 * This needs to work for both DECstation emulation and other machine types,
565 * so it contains both rtc related stuff and the station's Ethernet address.
566 */
567 void dev_mc146818_init(struct machine *machine, struct memory *mem,
568 uint64_t baseaddr, int irq_nr, int access_style, int addrdiv)
569 {
570 unsigned char ether_address[6];
571 int i, dev_len;
572 struct mc_data *d;
573
574 d = malloc(sizeof(struct mc_data));
575 if (d == NULL) {
576 fprintf(stderr, "out of memory\n");
577 exit(1);
578 }
579
580 memset(d, 0, sizeof(struct mc_data));
581 d->irq_nr = irq_nr;
582 d->access_style = access_style;
583 d->addrdiv = addrdiv;
584
585 /* Only SGIs and PCs use BCD format (?) */
586 d->use_bcd = 0;
587 if (access_style == MC146818_SGI || access_style == MC146818_PC_CMOS)
588 d->use_bcd = 1;
589
590 if (access_style == MC146818_DEC) {
591 /* Station Ethernet Address, on DECstation 3100: */
592 for (i=0; i<6; i++)
593 ether_address[i] = 0x10 * (i+1);
594
595 d->reg[0x01] = ether_address[0];
596 d->reg[0x05] = ether_address[1];
597 d->reg[0x09] = ether_address[2];
598 d->reg[0x0d] = ether_address[3];
599 d->reg[0x11] = ether_address[4];
600 d->reg[0x15] = ether_address[5];
601 /* TODO: 19, 1d, 21, 25 = checksum bytes 1,2,2,1 resp. */
602 d->reg[0x29] = ether_address[5];
603 d->reg[0x2d] = ether_address[4];
604 d->reg[0x31] = ether_address[3];
605 d->reg[0x35] = ether_address[2];
606 d->reg[0x39] = ether_address[1];
607 d->reg[0x3d] = ether_address[1];
608 d->reg[0x41] = ether_address[0];
609 d->reg[0x45] = ether_address[1];
610 d->reg[0x49] = ether_address[2];
611 d->reg[0x4d] = ether_address[3];
612 d->reg[0x51] = ether_address[4];
613 d->reg[0x55] = ether_address[5];
614 /* TODO: 59, 5d = checksum bytes 1,2 resp. */
615 d->reg[0x61] = 0xff;
616 d->reg[0x65] = 0x00;
617 d->reg[0x69] = 0x55;
618 d->reg[0x6d] = 0xaa;
619 d->reg[0x71] = 0xff;
620 d->reg[0x75] = 0x00;
621 d->reg[0x79] = 0x55;
622 d->reg[0x7d] = 0xaa;
623
624 /* Battery valid, for DECstations */
625 d->reg[0xf8] = 1;
626 }
627
628 if (access_style == MC146818_ARC_JAZZ)
629 memory_device_register(mem, "mc146818_jazz", 0x90000070ULL,
630 1, dev_mc146818_jazz_access, d, MEM_DEFAULT, NULL);
631
632 dev_len = DEV_MC146818_LENGTH;
633 switch (access_style) {
634 case MC146818_CATS:
635 case MC146818_PC_CMOS:
636 dev_len = 2;
637 break;
638 case MC146818_SGI:
639 dev_len = 0x400;
640 }
641
642 memory_device_register(mem, "mc146818", baseaddr,
643 dev_len * addrdiv, dev_mc146818_access,
644 d, MEM_DEFAULT, NULL);
645
646 mc146818_update_time(d);
647
648 machine_add_tickfunction(machine, dev_mc146818_tick, d, TICK_SHIFT);
649 }
650

  ViewVC Help
Powered by ViewVC 1.1.26