/[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 4 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 12 by dpavlin, Mon Oct 8 16:18:38 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_mc146818.c,v 1.68 2005/02/07 05:51:54 debug Exp $   *  $Id: dev_mc146818.c,v 1.72 2005/08/02 07:56:37 debug Exp $
29   *     *  
30   *  MC146818 real-time clock, used by many different machines types.   *  MC146818 real-time clock, used by many different machines types.
31   *  (DS1687 as used in some SGI machines is similar to MC146818.)   *  (DS1687 as used in some SGI machines is similar to MC146818.)
# Line 56  Line 56 
56    
57  /*  #define MC146818_DEBUG  */  /*  #define MC146818_DEBUG  */
58    
59  #define TICK_STEPS_SHIFT        14  #define TICK_SHIFT      14
60    
61    
62  /*  256 on DECstation, SGI uses reg at 72*4 as the Century  */  /*  256 on DECstation, SGI uses reg at 72*4 as the Century  */
# Line 140  void dev_mc146818_tick(struct cpu *cpu, Line 140  void dev_mc146818_tick(struct cpu *cpu,
140    
141          if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) &&          if ((d->reg[MC_REGB * 4] & MC_REGB_PIE) &&
142               d->interrupt_every_x_cycles > 0) {               d->interrupt_every_x_cycles > 0) {
143                  d->cycles_left_until_interrupt -=                  d->cycles_left_until_interrupt -= (1 << TICK_SHIFT);
                     (1 << TICK_STEPS_SHIFT);  
144    
145                  if (d->cycles_left_until_interrupt < 0 ||                  if (d->cycles_left_until_interrupt < 0 ||
146                      d->cycles_left_until_interrupt >=                      d->cycles_left_until_interrupt >=
# Line 366  int dev_mc146818_access(struct cpu *cpu, Line 365  int dev_mc146818_access(struct cpu *cpu,
365  #endif  #endif
366    
367          /*          /*
368           *  For some reason, Linux/sgimips relies on the UIP bit to go           *  Sprite seems to wants UF interrupt status, once every second, or
          *  on and off. Without this code, booting Linux takes forever:  
          */  
         d->reg[MC_REGA * 4] &= ~MC_REGA_UIP;  
 #if 1  
         /*  TODO:  solve this more nicely  */  
         if ((random() & 0xff) == 0)  
                 d->reg[MC_REGA * 4] ^= MC_REGA_UIP;  
 #endif  
   
         /*  
          *  Sprite seens to wants UF interrupt status, once every second, or  
369           *  it hangs forever during bootup.  (These do not cause interrupts,           *  it hangs forever during bootup.  (These do not cause interrupts,
370           *  but it is good enough... Sprite polls this, iirc.)           *  but it is good enough... Sprite polls this, iirc.)
371             *
372             *  Linux on at least sgimips and evbmips (Malta) wants the UIP bit
373             *  in REGA to be updated once a second.
374           */           */
375          timet = time(NULL);          timet = time(NULL);
376          tmp = gmtime(&timet);          tmp = gmtime(&timet);
377          d->reg[MC_REGC * 4] &= ~MC_REGC_UF;          d->reg[MC_REGC * 4] &= ~MC_REGC_UF;
378    
379          if (tmp->tm_sec != d->previous_second) {          if (tmp->tm_sec != d->previous_second) {
380                    d->reg[MC_REGA * 4] &= ~MC_REGA_UIP;
381    
382                  d->reg[MC_REGC * 4] |= MC_REGC_UF;                  d->reg[MC_REGC * 4] |= MC_REGC_UF;
383                  d->reg[MC_REGC * 4] |= MC_REGC_IRQF;                  d->reg[MC_REGC * 4] |= MC_REGC_IRQF;
384                  d->previous_second = tmp->tm_sec;                  d->previous_second = tmp->tm_sec;
# Line 393  int dev_mc146818_access(struct cpu *cpu, Line 387  int dev_mc146818_access(struct cpu *cpu,
387                      the PF (periodic flag) bit set, even though interrupts                      the PF (periodic flag) bit set, even though interrupts
388                      are not enabled?  */                      are not enabled?  */
389                  d->reg[MC_REGC * 4] |= MC_REGC_PF;                  d->reg[MC_REGC * 4] |= MC_REGC_PF;
390          }          } else
391                    d->reg[MC_REGA * 4] |= MC_REGA_UIP;
392    
393          /*  RTC data is in either BCD format or binary:  */          /*  RTC data is in either BCD format or binary:  */
394          if (d->use_bcd) {          if (d->use_bcd)
395                  d->reg[MC_REGB * 4] &= ~(1 << 2);                  d->reg[MC_REGB * 4] &= ~(1 << 2);
396          } else {          else
397                  d->reg[MC_REGB * 4] |= (1 << 2);                  d->reg[MC_REGB * 4] |= (1 << 2);
         }  
398    
399          /*  RTC date/time is always Valid:  */          /*  RTC date/time is always Valid:  */
400          d->reg[MC_REGD * 4] |= MC_REGD_VRT;          d->reg[MC_REGD * 4] |= MC_REGD_VRT;
# Line 587  void dev_mc146818_init(struct machine *m Line 581  void dev_mc146818_init(struct machine *m
581          d->access_style  = access_style;          d->access_style  = access_style;
582          d->addrdiv       = addrdiv;          d->addrdiv       = addrdiv;
583    
584            /*  Only SGIs and PCs use BCD format (?)  */
585            d->use_bcd = 0;
586            if (access_style == MC146818_SGI || access_style == MC146818_PC_CMOS)
587                    d->use_bcd = 1;
588    
589            if (access_style == MC146818_DEC) {
590          /*  Station Ethernet Address, on DECstation 3100:  */          /*  Station Ethernet Address, on DECstation 3100:  */
591          for (i=0; i<6; i++)          for (i=0; i<6; i++)
592                  ether_address[i] = 0x10 * (i+1);                  ether_address[i] = 0x10 * (i+1);
593    
594          d->reg[0x01] = ether_address[0];                  d->reg[0x01] = ether_address[0];
595          d->reg[0x05] = ether_address[1];                  d->reg[0x05] = ether_address[1];
596          d->reg[0x09] = ether_address[2];                  d->reg[0x09] = ether_address[2];
597          d->reg[0x0d] = ether_address[3];                  d->reg[0x0d] = ether_address[3];
598          d->reg[0x11] = ether_address[4];                  d->reg[0x11] = ether_address[4];
599          d->reg[0x15] = ether_address[5];                  d->reg[0x15] = ether_address[5];
600          /*  TODO:  19, 1d, 21, 25 = checksum bytes 1,2,2,1 resp. */                  /*  TODO:  19, 1d, 21, 25 = checksum bytes 1,2,2,1 resp. */
601          d->reg[0x29] = ether_address[5];                  d->reg[0x29] = ether_address[5];
602          d->reg[0x2d] = ether_address[4];                  d->reg[0x2d] = ether_address[4];
603          d->reg[0x31] = ether_address[3];                  d->reg[0x31] = ether_address[3];
604          d->reg[0x35] = ether_address[2];                  d->reg[0x35] = ether_address[2];
605          d->reg[0x39] = ether_address[1];                  d->reg[0x39] = ether_address[1];
606          d->reg[0x3d] = ether_address[1];                  d->reg[0x3d] = ether_address[1];
607          d->reg[0x41] = ether_address[0];                  d->reg[0x41] = ether_address[0];
608          d->reg[0x45] = ether_address[1];                  d->reg[0x45] = ether_address[1];
609          d->reg[0x49] = ether_address[2];                  d->reg[0x49] = ether_address[2];
610          d->reg[0x4d] = ether_address[3];                  d->reg[0x4d] = ether_address[3];
611          d->reg[0x51] = ether_address[4];                  d->reg[0x51] = ether_address[4];
612          d->reg[0x55] = ether_address[5];                  d->reg[0x55] = ether_address[5];
613          /*  TODO:  59, 5d = checksum bytes 1,2 resp. */                  /*  TODO:  59, 5d = checksum bytes 1,2 resp. */
614          d->reg[0x61] = 0xff;                  d->reg[0x61] = 0xff;
615          d->reg[0x65] = 0x00;                  d->reg[0x65] = 0x00;
616          d->reg[0x69] = 0x55;                  d->reg[0x69] = 0x55;
617          d->reg[0x6d] = 0xaa;                  d->reg[0x6d] = 0xaa;
618          d->reg[0x71] = 0xff;                  d->reg[0x71] = 0xff;
619          d->reg[0x75] = 0x00;                  d->reg[0x75] = 0x00;
620          d->reg[0x79] = 0x55;                  d->reg[0x79] = 0x55;
621          d->reg[0x7d] = 0xaa;                  d->reg[0x7d] = 0xaa;
622    
         /*  Only SGI uses BCD format (?)  */  
         d->use_bcd = 0;  
         if (access_style == MC146818_SGI)  
                 d->use_bcd = 1;  
   
         if (access_style == MC146818_DEC) {  
623                  /*  Battery valid, for DECstations  */                  /*  Battery valid, for DECstations  */
624                  d->reg[0xf8] = 1;                  d->reg[0xf8] = 1;
625          }          }
# Line 649  void dev_mc146818_init(struct machine *m Line 643  void dev_mc146818_init(struct machine *m
643    
644          mc146818_update_time(d);          mc146818_update_time(d);
645    
646          machine_add_tickfunction(machine, dev_mc146818_tick,          machine_add_tickfunction(machine, dev_mc146818_tick, d, TICK_SHIFT);
             d, TICK_STEPS_SHIFT);  
647  }  }
648    

Legend:
Removed from v.4  
changed lines
  Added in v.12

  ViewVC Help
Powered by ViewVC 1.1.26