/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 5 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 dpavlin 4 /*
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