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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 16 by dpavlin, Mon Oct 8 16:19:01 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_mc146818.c,v 1.75 2005/10/09 22:21:31 debug Exp $   *  $Id: dev_mc146818.c,v 1.99 2007/06/15 19:57:33 debug Exp $
29   *     *  
30   *  MC146818 real-time clock, used by many different machines types.   *  COMMENT: MC146818 real-time clock
31     *
32   *  (DS1687 as used in some other machines is also similar to the MC146818.)   *  (DS1687 as used in some other machines is also similar to the MC146818.)
33   *   *
34   *  This device contains Date/time, the machine's ethernet address (on   *  This device contains Date/time, the machine's ethernet address (on
# Line 48  Line 49 
49  #include "machine.h"  #include "machine.h"
50  #include "memory.h"  #include "memory.h"
51  #include "misc.h"  #include "misc.h"
52    #include "timer.h"
53    
54  #include "mc146818reg.h"  #include "mc146818reg.h"
55    
56    
57  #define to_bcd(x)       ( ((x)/10) * 16 + ((x)%10) )  #define to_bcd(x)       ( ((x)/10) * 16 + ((x)%10) )
58    #define from_bcd(x)     ( ((x)>>4) * 10 + ((x)&15) )
59    
60  /*  #define MC146818_DEBUG  */  /*  #define MC146818_DEBUG  */
61    
62  #define TICK_SHIFT      14  #define MC146818_TICK_SHIFT     14
63    
64    
65  /*  256 on DECstation, SGI uses reg at 72*4 as the Century  */  /*  256 on DECstation, SGI uses reg at 72*4 as the Century  */
66  #define N_REGISTERS     1024  #define N_REGISTERS     1024
67  struct mc_data {  struct mc_data {
68          int     access_style;          int             access_style;
69          int     last_addr;          int             last_addr;
   
         int     register_choice;  
         int     reg[N_REGISTERS];  
         int     addrdiv;  
70    
71          int     use_bcd;          int             register_choice;
72            int             reg[N_REGISTERS];
73            int             addrdiv;
74    
75            int             use_bcd;
76    
77            int             timebase_hz;
78            int             interrupt_hz;
79            int             old_interrupt_hz;
80            struct interrupt irq;
81            struct timer    *timer;
82            volatile int    pending_timer_interrupts;
83    
84            int             previous_second;
85            int             n_seconds_elapsed;
86            int             uip_threshold;
87    
88          int     timebase_hz;          int             ugly_netbsd_prep_hack_done;
89          int     interrupt_hz;          int             ugly_netbsd_prep_hack_sec;
90          int     irq_nr;  };
91    
         int     previous_second;  
92    
93          int     interrupt_every_x_cycles;  /*
94          int     cycles_left_until_interrupt;   *  Ugly hack to fool NetBSD/prep to accept the clock.  (See mcclock_isa_match
95  };   *  in NetBSD's arch/prep/isa/mcclock_isa.c for details.)
96     */
97    #define NETBSD_HACK_INIT                0
98    #define NETBSD_HACK_FIRST_1             1
99    #define NETBSD_HACK_FIRST_2             2
100    #define NETBSD_HACK_SECOND_1            3
101    #define NETBSD_HACK_SECOND_2            4
102    #define NETBSD_HACK_DONE                5
103    
104    
105  /*  /*
106   *  recalc_interrupt_cycle():   *  timer_tick():
107   *   *
108   *  If automatic_clock_adjustment is turned on, then emulated_hz is modified   *  Called d->interrupt_hz times per (real-world) second.
  *  dynamically.  We have to recalculate how often interrupts are to be  
  *  triggered.  
109   */   */
110  static void recalc_interrupt_cycle(struct cpu *cpu, struct mc_data *d)  static void timer_tick(struct timer *timer, void *extra)
111  {  {
112          int64_t emulated_hz = cpu->machine->emulated_hz;          struct mc_data *d = (struct mc_data *) extra;
113  #if 0          d->pending_timer_interrupts ++;
         static int warning_printed = 0;  
   
         /*  
          *  A hack to make Ultrix run, even on very fast host machines.  
          *  
          *  (Ultrix was probably never meant to be run on machines with  
          *  faster CPUs than around 33 MHz or so.)  
          */  
         if (d->access_style == MC146818_DEC && emulated_hz > 30000000) {  
                 if (!warning_printed) {  
                         fatal("\n*********************************************"  
                             "**********************************\n\n   Your hos"  
                             "t machine is too fast! The emulated CPU speed wil"  
                             "l be limited to\n   30 MHz, and clocks inside the"  
                             " emulated environment might go faster than\n   in"  
                             " the real world.  You have been warned.\n\n******"  
                             "*************************************************"  
                             "************************\n\n");  
                         warning_printed = 1;  
                 }  
   
                 emulated_hz = 30000000;  
         }  
 #endif  
   
         if (d->interrupt_hz > 0)  
                 d->interrupt_every_x_cycles =  
                     emulated_hz / d->interrupt_hz;  
         else  
                 d->interrupt_every_x_cycles = 0;  
114  }  }
115    
116    
117  /*  DEVICE_TICK(mc146818)
  *  dev_mc146818_tick():  
  */  
 void dev_mc146818_tick(struct cpu *cpu, void *extra)  
118  {  {
119          struct mc_data *d = extra;          struct mc_data *d = extra;
120            int pti = d->pending_timer_interrupts;
121    
122          if (d == NULL)          if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) && pti > 0) {
123                  return;  #if 0
124                    /*  For debugging, to see how much the interrupts are
125          recalc_interrupt_cycle(cpu, d);                      lagging behind the real clock:  */
126                    {
127          if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) &&                          static int x = 0;
128               d->interrupt_every_x_cycles > 0) {                          if (++x == 1) {
129                  d->cycles_left_until_interrupt -= (1 << TICK_SHIFT);                                  x = 0;
130                                    printf("%i ", pti);
131                  if (d->cycles_left_until_interrupt < 0 ||                                  fflush(stdout);
132                      d->cycles_left_until_interrupt >=                          }
133                      d->interrupt_every_x_cycles) {                  }
134                          /*  debug("[ rtc interrupt (every %i cycles) ]\n",  #endif
                             d->interrupt_every_x_cycles);  */  
                         cpu_interrupt(cpu, d->irq_nr);  
135    
136                          d->reg[MC_REGC * 4] |= MC_REGC_PF;                  INTERRUPT_ASSERT(d->irq);
137    
138                          /*  Reset the cycle countdown:  */                  d->reg[MC_REGC * 4] |= MC_REGC_PF;
                         while (d->cycles_left_until_interrupt < 0)  
                                 d->cycles_left_until_interrupt +=  
                                     d->interrupt_every_x_cycles;  
                 }  
139          }          }
140    
141          if (d->reg[MC_REGC * 4] & MC_REGC_UF ||          if (d->reg[MC_REGC * 4] & MC_REGC_UF ||
# Line 171  void dev_mc146818_tick(struct cpu *cpu, Line 151  void dev_mc146818_tick(struct cpu *cpu,
151   *  It seems like JAZZ machines accesses the mc146818 by writing one byte to   *  It seems like JAZZ machines accesses the mc146818 by writing one byte to
152   *  0x90000070 and then reading or writing another byte at 0x......0004000.   *  0x90000070 and then reading or writing another byte at 0x......0004000.
153   */   */
154  int dev_mc146818_jazz_access(struct cpu *cpu, struct memory *mem,  DEVICE_ACCESS(mc146818_jazz)
         uint64_t relative_addr, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
155  {  {
156          struct mc_data *d = extra;          struct mc_data *d = extra;
157    
# Line 226  static void mc146818_update_time(struct Line 204  static void mc146818_update_time(struct
204           *  Special hacks for emulating the behaviour of various machines:           *  Special hacks for emulating the behaviour of various machines:
205           */           */
206          switch (d->access_style) {          switch (d->access_style) {
207            case MC146818_ALGOR:
208                    /*
209                     *  NetBSD/evbmips sources indicate that the Algor year base
210                     *  is 1920. This makes the time work with NetBSD in Malta
211                     *  emulation. However, for Linux, commenting out this line
212                     *  works better.  (TODO: Find a way to make both work?)
213                     */
214                    d->reg[4 * MC_YEAR] += 80;
215                    break;
216          case MC146818_ARC_NEC:          case MC146818_ARC_NEC:
217                  d->reg[4 * MC_YEAR] += (0x18 - 104);                  d->reg[4 * MC_YEAR] += (0x18 - 104);
218                  break;                  break;
# Line 289  static void mc146818_update_time(struct Line 276  static void mc146818_update_time(struct
276  }  }
277    
278    
279  /*  DEVICE_ACCESS(mc146818)
  *  dev_mc146818_access():  
  *  
  *  TODO: This access function only handles 8-bit accesses!  
  */  
 int dev_mc146818_access(struct cpu *cpu, struct memory *mem,  
         uint64_t r, unsigned char *data, size_t len,  
         int writeflag, void *extra)  
280  {  {
281            struct mc_data *d = extra;
282          struct tm *tmp;          struct tm *tmp;
283          time_t timet;          time_t timet;
284          struct mc_data *d = extra;          size_t i;
285          int i, relative_addr = r;  
286            /*  NOTE/TODO: This access function only handles 8-bit accesses!  */
287    
288          relative_addr /= d->addrdiv;          relative_addr /= d->addrdiv;
289    
290          /*  Different ways of accessing the registers:  */          /*  Different ways of accessing the registers:  */
291          switch (d->access_style) {          switch (d->access_style) {
292            case MC146818_ALGOR:
293          case MC146818_CATS:          case MC146818_CATS:
294          case MC146818_PC_CMOS:          case MC146818_PC_CMOS:
295                  if ((relative_addr & 1) == 0x00) {                  if ((relative_addr & 1) == 0x00) {
# Line 351  int dev_mc146818_access(struct cpu *cpu, Line 334  int dev_mc146818_access(struct cpu *cpu,
334                   *  should be ignored. It works _almost_ as DEC, if offsets are                   *  should be ignored. It works _almost_ as DEC, if offsets are
335                   *  divided by 0x40.                   *  divided by 0x40.
336                   */                   */
337                    break;
338            case MC146818_PMPPC:
339                    relative_addr *= 4;
340                    break;
341          default:          default:
342                  ;                  ;
343          }          }
# Line 360  int dev_mc146818_access(struct cpu *cpu, Line 347  int dev_mc146818_access(struct cpu *cpu,
347                  fatal("[ mc146818: write to addr=0x%04x (len %i): ",                  fatal("[ mc146818: write to addr=0x%04x (len %i): ",
348                      (int)relative_addr, (int)len);                      (int)relative_addr, (int)len);
349                  for (i=0; i<len; i++)                  for (i=0; i<len; i++)
350                          fatal("%02x ", data[i]);                          fatal("0x%02x ", data[i]);
351                  fatal("]\n");                  fatal("]\n");
352          }          }
353  #endif  #endif
# Line 373  int dev_mc146818_access(struct cpu *cpu, Line 360  int dev_mc146818_access(struct cpu *cpu,
360           *  Linux on at least sgimips and evbmips (Malta) wants the UIP bit           *  Linux on at least sgimips and evbmips (Malta) wants the UIP bit
361           *  in REGA to be updated once a second.           *  in REGA to be updated once a second.
362           */           */
363          timet = time(NULL);          if (relative_addr == MC_REGA*4 || relative_addr == MC_REGC*4) {
364          tmp = gmtime(&timet);                  timet = time(NULL);
365          d->reg[MC_REGC * 4] &= ~MC_REGC_UF;                  tmp = gmtime(&timet);
366                    d->reg[MC_REGC * 4] &= ~MC_REGC_UF;
367                    if (tmp->tm_sec != d->previous_second) {
368                            d->n_seconds_elapsed ++;
369                            d->previous_second = tmp->tm_sec;
370                    }
371                    if (d->n_seconds_elapsed > d->uip_threshold) {
372                            d->n_seconds_elapsed = 0;
373    
374          if (tmp->tm_sec != d->previous_second) {                          d->reg[MC_REGA * 4] |= MC_REGA_UIP;
                 d->reg[MC_REGA * 4] &= ~MC_REGA_UIP;  
375    
376                  d->reg[MC_REGC * 4] |= MC_REGC_UF;                          d->reg[MC_REGC * 4] |= MC_REGC_UF;
377                  d->reg[MC_REGC * 4] |= MC_REGC_IRQF;                          d->reg[MC_REGC * 4] |= MC_REGC_IRQF;
                 d->previous_second = tmp->tm_sec;  
378    
379                  /*  For some reason, some Linux/DECstation KN04 kernels want                          /*  For some reason, some Linux/DECstation KN04
380                      the PF (periodic flag) bit set, even though interrupts                              kernels want the PF (periodic flag) bit set,
381                      are not enabled?  */                              even though interrupts are not enabled?  */
382                  d->reg[MC_REGC * 4] |= MC_REGC_PF;                          d->reg[MC_REGC * 4] |= MC_REGC_PF;
383          } else                  } else
384                  d->reg[MC_REGA * 4] |= MC_REGA_UIP;                          d->reg[MC_REGA * 4] &= ~MC_REGA_UIP;
385            }
386    
387          /*  RTC data is in either BCD format or binary:  */          /*  RTC data is in either BCD format or binary:  */
388          if (d->use_bcd)          if (d->use_bcd)
# Line 439  int dev_mc146818_access(struct cpu *cpu, Line 432  int dev_mc146818_access(struct cpu *cpu,
432                          case MC_RATE_8_Hz:      d->interrupt_hz = 8;    break;                          case MC_RATE_8_Hz:      d->interrupt_hz = 8;    break;
433                          case MC_RATE_4_Hz:      d->interrupt_hz = 4;    break;                          case MC_RATE_4_Hz:      d->interrupt_hz = 4;    break;
434                          case MC_RATE_2_Hz:      d->interrupt_hz = 2;    break;                          case MC_RATE_2_Hz:      d->interrupt_hz = 2;    break;
435                          default:                          default:/*  debug("[ mc146818: unimplemented "
                                 /*  debug("[ mc146818: unimplemented "  
436                                      "MC_REGA RS: %i ]\n",                                      "MC_REGA RS: %i ]\n",
437                                      data[0] & MC_REGA_RSMASK);  */                                      data[0] & MC_REGA_RSMASK);  */
438                                  ;                                  ;
439                          }                          }
440    
441                          recalc_interrupt_cycle(cpu, d);                          if (d->interrupt_hz != d->old_interrupt_hz) {
442                                    debug("[ rtc changed to interrupt at %i Hz ]\n",
443                          d->cycles_left_until_interrupt =                                      d->interrupt_hz);
444                                  d->interrupt_every_x_cycles;  
445                                    d->old_interrupt_hz = d->interrupt_hz;
446    
447                                    if (d->timer == NULL)
448                                            d->timer = timer_add(d->interrupt_hz,
449                                                timer_tick, d);
450                                    else
451                                            timer_update_frequency(d->timer,
452                                                d->interrupt_hz);
453                            }
454    
455                          d->reg[MC_REGA * 4] =                          d->reg[MC_REGA * 4] =
456                              data[0] & (MC_REGA_RSMASK | MC_REGA_DVMASK);                              data[0] & (MC_REGA_RSMASK | MC_REGA_DVMASK);
   
                         debug("[ rtc set to interrupt every %i:th cycle ]\n",  
                             d->interrupt_every_x_cycles);  
457                          break;                          break;
458                  case MC_REGB*4:                  case MC_REGB*4:
                         if (((data[0] ^ d->reg[MC_REGB*4]) & MC_REGB_PIE))  
                                 d->cycles_left_until_interrupt =  
                                     d->interrupt_every_x_cycles;  
459                          d->reg[MC_REGB*4] = data[0];                          d->reg[MC_REGB*4] = data[0];
460                          if (!(data[0] & MC_REGB_PIE)) {                          if (!(data[0] & MC_REGB_PIE)) {
461                                  cpu_interrupt_ack(cpu, d->irq_nr);                                  INTERRUPT_DEASSERT(d->irq);
                                 /*  d->cycles_left_until_interrupt =  
                                     d->interrupt_every_x_cycles;  */  
462                          }                          }
463    
464                          /*  debug("[ mc146818: write to MC_REGB, data[0] "                          /*  debug("[ mc146818: write to MC_REGB, data[0] "
465                              "= 0x%02x ]\n", data[0]);  */                              "= 0x%02x ]\n", data[0]);  */
466                          break;                          break;
# Line 478  int dev_mc146818_access(struct cpu *cpu, Line 472  int dev_mc146818_access(struct cpu *cpu,
472                  case 0x128:                  case 0x128:
473                          d->reg[relative_addr] = data[0];                          d->reg[relative_addr] = data[0];
474                          if (data[0] & 8) {                          if (data[0] & 8) {
475                                    int j;
476    
477                                  /*  Used on SGI to power off the machine.  */                                  /*  Used on SGI to power off the machine.  */
478                                  fatal("[ md146818: power off ]\n");                                  fatal("[ md146818: power off ]\n");
479                                  for (i=0; i<cpu->machine->ncpus; i++)                                  for (j=0; j<cpu->machine->ncpus; j++)
480                                          cpu->machine->cpus[i]->running = 0;                                          cpu->machine->cpus[j]->running = 0;
481                                  cpu->machine->                                  cpu->machine->
482                                      exit_without_entering_debugger = 1;                                      exit_without_entering_debugger = 1;
483                          }                          }
# Line 506  int dev_mc146818_access(struct cpu *cpu, Line 502  int dev_mc146818_access(struct cpu *cpu,
502                  case 0x15:                  case 0x15:
503                          break;                          break;
504                  case 4 * MC_SEC:                  case 4 * MC_SEC:
505                            if (d->ugly_netbsd_prep_hack_done < NETBSD_HACK_DONE) {
506                                    d->ugly_netbsd_prep_hack_done ++;
507                                    switch (d->ugly_netbsd_prep_hack_done) {
508                                    case NETBSD_HACK_FIRST_1:
509                                            d->ugly_netbsd_prep_hack_sec =
510                                                from_bcd(d->reg[relative_addr]);
511                                            break;
512                                    case NETBSD_HACK_FIRST_2:
513                                            d->reg[relative_addr] = to_bcd(
514                                                d->ugly_netbsd_prep_hack_sec);
515                                            break;
516                                    case NETBSD_HACK_SECOND_1:
517                                    case NETBSD_HACK_SECOND_2:
518                                            d->reg[relative_addr] = to_bcd((1 +
519                                                d->ugly_netbsd_prep_hack_sec) % 60);
520                                            break;
521                                    }
522                            }
523                  case 4 * MC_MIN:                  case 4 * MC_MIN:
524                  case 4 * MC_HOUR:                  case 4 * MC_HOUR:
525                  case 4 * MC_DOW:                  case 4 * MC_DOW:
# Line 522  int dev_mc146818_access(struct cpu *cpu, Line 536  int dev_mc146818_access(struct cpu *cpu,
536                          if (d->reg[MC_REGB * 4] & MC_REGB_SET)                          if (d->reg[MC_REGB * 4] & MC_REGB_SET)
537                                  break;                                  break;
538    
539                          mc146818_update_time(d);                          if (d->ugly_netbsd_prep_hack_done >= NETBSD_HACK_DONE)
540                                    mc146818_update_time(d);
541                            break;
542                    case 4 * MC_REGA:
543                          break;                          break;
544                  case 4 * MC_REGC:       /*  Interrupt ack.  */                  case 4 * MC_REGC:       /*  Interrupt ack.  */
545                          /*  NOTE: Acking is done below, _after_ the                          /*  NOTE: Acking is done below, _after_ the
546                              register has been read.  */                              register has been read.  */
547                          break;                          break;
548                  default:                  default:debug("[ mc146818: read from relative_addr = "
                         debug("[ mc146818: read from relative_addr = "  
549                              "%04x ]\n", (int)relative_addr);                              "%04x ]\n", (int)relative_addr);
                         ;  
550                  }                  }
551    
552                  data[0] = d->reg[relative_addr];                  data[0] = d->reg[relative_addr];
553    
554                  if (relative_addr == MC_REGC*4) {                  if (relative_addr == MC_REGC*4) {
555                          cpu_interrupt_ack(cpu, d->irq_nr);                          INTERRUPT_DEASSERT(d->irq);
556                          /*  d->cycles_left_until_interrupt =  
557                              d->interrupt_every_x_cycles;  */                          /*
558                             *  Acknowledging an interrupt decreases the
559                             *  number of pending "real world" timer ticks.
560                             */
561                            if (d->reg[MC_REGC * 4] & MC_REGC_PF &&
562                                d->pending_timer_interrupts > 0)
563                                    d->pending_timer_interrupts --;
564    
565                          d->reg[MC_REGC * 4] = 0x00;                          d->reg[MC_REGC * 4] = 0x00;
566                  }                  }
567          }          }
# Line 549  int dev_mc146818_access(struct cpu *cpu, Line 571  int dev_mc146818_access(struct cpu *cpu,
571                  fatal("[ mc146818: read from addr=0x%04x (len %i): ",                  fatal("[ mc146818: read from addr=0x%04x (len %i): ",
572                      (int)relative_addr, (int)len);                      (int)relative_addr, (int)len);
573                  for (i=0; i<len; i++)                  for (i=0; i<len; i++)
574                          fatal("%02x ", data[i]);                          fatal("0x%02x ", data[i]);
575                  fatal("]\n");                  fatal("]\n");
576          }          }
577  #endif  #endif
# Line 565  int dev_mc146818_access(struct cpu *cpu, Line 587  int dev_mc146818_access(struct cpu *cpu,
587   *  so it contains both rtc related stuff and the station's Ethernet address.   *  so it contains both rtc related stuff and the station's Ethernet address.
588   */   */
589  void dev_mc146818_init(struct machine *machine, struct memory *mem,  void dev_mc146818_init(struct machine *machine, struct memory *mem,
590          uint64_t baseaddr, int irq_nr, int access_style, int addrdiv)          uint64_t baseaddr, char *irq_path, int access_style, int addrdiv)
591  {  {
592          unsigned char ether_address[6];          unsigned char ether_address[6];
593          int i, dev_len;          int i, dev_len;
594          struct mc_data *d;          struct mc_data *d;
595    
596          d = malloc(sizeof(struct mc_data));          CHECK_ALLOCATION(d = malloc(sizeof(struct mc_data)));
         if (d == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
   
597          memset(d, 0, sizeof(struct mc_data));          memset(d, 0, sizeof(struct mc_data));
598          d->irq_nr        = irq_nr;  
599          d->access_style  = access_style;          d->access_style  = access_style;
600          d->addrdiv       = addrdiv;          d->addrdiv       = addrdiv;
601    
602          /*  Only SGIs and PCs use BCD format (?)  */          INTERRUPT_CONNECT(irq_path, d->irq);
603    
604          d->use_bcd = 0;          d->use_bcd = 0;
605          if (access_style == MC146818_SGI || access_style == MC146818_PC_CMOS)          switch (access_style) {
606            case MC146818_SGI:
607            case MC146818_PC_CMOS:
608            case MC146818_PMPPC:
609                  d->use_bcd = 1;                  d->use_bcd = 1;
610            }
611    
612            if (machine->machine_type != MACHINE_PREP) {
613                    /*  NetBSD/prep has a really ugly clock detection code;
614                        no other machines/OSes don't need this.  */
615                    d->ugly_netbsd_prep_hack_done = NETBSD_HACK_DONE;
616            }
617    
618          if (access_style == MC146818_DEC) {          if (access_style == MC146818_DEC) {
619          /*  Station Ethernet Address, on DECstation 3100:  */                  /*  Station Ethernet Address, on DECstation 3100:  */
620          for (i=0; i<6; i++)                  for (i=0; i<6; i++)
621                  ether_address[i] = 0x10 * (i+1);                          ether_address[i] = 0x10 * (i+1);
622    
623                  d->reg[0x01] = ether_address[0];                  d->reg[0x01] = ether_address[0];
624                  d->reg[0x05] = ether_address[1];                  d->reg[0x05] = ether_address[1];
# Line 625  void dev_mc146818_init(struct machine *m Line 653  void dev_mc146818_init(struct machine *m
653                  d->reg[0xf8] = 1;                  d->reg[0xf8] = 1;
654          }          }
655    
656            /*
657             *  uip_threshold should ideally be 1, but when Linux polls the UIP bit
658             *  it looses speed. This hack gives Linux the impression that the cpu
659             *  is uip_threshold times faster than the slow clock it would
660             *  otherwise detect.
661             *
662             *  TODO:  Find out if this messes up Sprite emulation; if so, then
663             *         this hack has to be removed.
664             */
665            d->uip_threshold = 8;
666    
667          if (access_style == MC146818_ARC_JAZZ)          if (access_style == MC146818_ARC_JAZZ)
668                  memory_device_register(mem, "mc146818_jazz", 0x90000070ULL,                  memory_device_register(mem, "mc146818_jazz", 0x90000070ULL,
669                      1, dev_mc146818_jazz_access, d, MEM_DEFAULT, NULL);                      1, dev_mc146818_jazz_access, d, DM_DEFAULT, NULL);
670    
671          dev_len = DEV_MC146818_LENGTH;          dev_len = DEV_MC146818_LENGTH;
672          switch (access_style) {          switch (access_style) {
# Line 641  void dev_mc146818_init(struct machine *m Line 680  void dev_mc146818_init(struct machine *m
680    
681          memory_device_register(mem, "mc146818", baseaddr,          memory_device_register(mem, "mc146818", baseaddr,
682              dev_len * addrdiv, dev_mc146818_access,              dev_len * addrdiv, dev_mc146818_access,
683              d, MEM_DEFAULT, NULL);              d, DM_DEFAULT, NULL);
684    
685          mc146818_update_time(d);          mc146818_update_time(d);
686    
687          machine_add_tickfunction(machine, dev_mc146818_tick, d, TICK_SHIFT);          machine_add_tickfunction(machine, dev_mc146818_tick, d,
688                MC146818_TICK_SHIFT);
689  }  }
690    

Legend:
Removed from v.16  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26