/[gxemul]/trunk/src/devices/dev_8253.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_8253.c

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

revision 31 by dpavlin, Mon Oct 8 16:20:40 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_8253.c,v 1.14 2006/07/24 19:08:17 debug Exp $   *  $Id: dev_8253.c,v 1.16 2006/08/22 15:13:03 debug Exp $
29   *   *
30   *  Intel 8253/8254 Programmable Interval Timer   *  Intel 8253/8254 Programmable Interval Timer
31   *   *
32   *  TODO: The timers don't really count down. Fix this when there is a generic   *  TODO/NOTE:
33   *  clock framework; also split counter[] into reset value and current value.   *      The timers don't really count down. Timer 0 causes clock interrupts
34     *      at a specific frequency, but reading the counter register would not
35     *      result in anything meaningful.
36     *
37     *  (Split counter[] into reset value and current value.)
38   */   */
39    
40  #include <stdio.h>  #include <stdio.h>
# Line 39  Line 43 
43    
44  #include "cpu.h"  #include "cpu.h"
45  #include "device.h"  #include "device.h"
 #include "devices.h"  
46  #include "emul.h"  #include "emul.h"
47  #include "machine.h"  #include "machine.h"
48  #include "memory.h"  #include "memory.h"
49  #include "misc.h"  #include "misc.h"
50    #include "timer.h"
51    
52  #include "i8253reg.h"  #include "i8253reg.h"
53    
54    
55  /*  #define debug fatal  */  #define debug fatal
56    
57  #define DEV_8253_LENGTH         4  #define DEV_8253_LENGTH         4
58  #define TICK_SHIFT              14  #define TICK_SHIFT              14
# Line 57  Line 61 
61  struct pit8253_data {  struct pit8253_data {
62          int             in_use;          int             in_use;
63    
         int             irq0_nr;  
64          int             counter_select;          int             counter_select;
65          uint8_t         mode_byte;          uint8_t         mode_byte;
66    
67          int             mode[3];          int             mode[3];
68          int             counter[3];          int             counter[3];
69    
70            int             hz[3];
71    
72            struct timer    *timer0;
73            int             irq0_nr;
74            int             pending_interrupts_timer0;
75  };  };
76    
77    
78    static void timer0_tick(struct timer *t, void *extra)
79    {
80            struct pit8253_data *d = (struct pit8253_data *) extra;
81            d->pending_interrupts_timer0 ++;
82    
83    #if 0
84            printf("%i ", d->pending_interrupts_timer0); fflush(stdout);
85    #endif
86    }
87    
88    
89  DEVICE_TICK(8253)  DEVICE_TICK(8253)
90  {  {
91          struct pit8253_data *d = (struct pit8253_data *) extra;          struct pit8253_data *d = (struct pit8253_data *) extra;
# Line 76  DEVICE_TICK(8253) Line 96  DEVICE_TICK(8253)
96          switch (d->mode[0] & 0x0e) {          switch (d->mode[0] & 0x0e) {
97    
98          case I8253_TIMER_INTTC:          case I8253_TIMER_INTTC:
99                  /*  TODO: Correct frequency!  */                  if (d->pending_interrupts_timer0 > 0)
100                  cpu_interrupt(cpu, d->irq0_nr);                          cpu_interrupt(cpu, d->irq0_nr);
101                  break;                  break;
102    
103            case I8253_TIMER_SQWAVE:
104          case I8253_TIMER_RATEGEN:          case I8253_TIMER_RATEGEN:
105                  break;                  break;
106    
# Line 99  DEVICE_ACCESS(8253) Line 120  DEVICE_ACCESS(8253)
120    
121          d->in_use = 1;          d->in_use = 1;
122    
         /*  TODO: ack somewhere else  */  
         cpu_interrupt_ack(cpu, d->irq0_nr);  
   
123          switch (relative_addr) {          switch (relative_addr) {
124    
125          case I8253_TIMER_CNTR0:          case I8253_TIMER_CNTR0:
# Line 117  DEVICE_ACCESS(8253) Line 135  DEVICE_ACCESS(8253)
135                          case I8253_TIMER_MSB:                          case I8253_TIMER_MSB:
136                                  d->counter[relative_addr] &= 0x00ff;                                  d->counter[relative_addr] &= 0x00ff;
137                                  d->counter[relative_addr] |= ((idata&0xff)<<8);                                  d->counter[relative_addr] |= ((idata&0xff)<<8);
138                                    if (d->counter[relative_addr] != 0)
139                                            d->hz[relative_addr] =
140                                                I8253_TIMER_FREQ / (float)
141                                                d->counter[relative_addr] + 0.5;
142                                    else
143                                            d->hz[relative_addr] = 0;
144                                  debug("[ 8253: counter %i set to %i (%i Hz) "                                  debug("[ 8253: counter %i set to %i (%i Hz) "
145                                      "]\n", relative_addr, d->counter[                                      "]\n", relative_addr, d->counter[
146                                      relative_addr], (int)(I8253_TIMER_FREQ /                                      relative_addr], d->hz[relative_addr]);
147                                      (float)d->counter[relative_addr] + 0.5));                                  switch (relative_addr) {
148                                    case 0: if (d->timer0 == NULL)
149                                                    d->timer0 = timer_add(
150                                                        d->hz[0], timer0_tick, d);
151                                            else
152                                                    timer_update_frequency(
153                                                        d->timer0, d->hz[0]);
154                                            break;
155                                    case 1: fatal("TODO: DMA refresh?\n");
156                                            exit(1);
157                                    case 2: fatal("TODO: 8253 tone generation?\n");
158                                            break;
159                                    }
160                                  break;                                  break;
161                          default:fatal("[ 8253: huh? writing to counter"                          default:fatal("[ 8253: huh? writing to counter"
162                                      " %i but neither from msb nor lsb? ]\n",                                      " %i but neither from msb nor lsb? ]\n",
# Line 219  DEVINIT(8253) Line 255  DEVINIT(8253)
255          d->mode[1] = I8253_TIMER_RATEGEN;          d->mode[1] = I8253_TIMER_RATEGEN;
256          d->mode[2] = I8253_TIMER_RATEGEN;          d->mode[2] = I8253_TIMER_RATEGEN;
257    
258            devinit->machine->isa_pic_data.pending_timer_interrupts =
259                &d->pending_interrupts_timer0;
260    
261          memory_device_register(devinit->machine->memory, devinit->name,          memory_device_register(devinit->machine->memory, devinit->name,
262              devinit->addr, DEV_8253_LENGTH, dev_8253_access, (void *)d,              devinit->addr, DEV_8253_LENGTH, dev_8253_access, (void *)d,
263              DM_DEFAULT, NULL);              DM_DEFAULT, NULL);

Legend:
Removed from v.31  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26