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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26