/[gxemul]/upstream/0.3.3.2/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 /upstream/0.3.3.2/src/devices/dev_mc146818.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show annotations)
Mon Oct 8 16:18:22 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 17973 byte(s)
0.3.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.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