Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


timer fixes
[palacios.git] / palacios / src / devices / 8254.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <devices/8254.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_time.h>
23 #include <palacios/vmm_util.h>
24 #include <palacios/vmm_intr.h>
25
26
27
28 #ifndef DEBUG_PIT
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34
35 // constants
36 #define OSC_HZ 1193182
37
38
39 /* The 8254 has three counters and one control port */
40 #define CHANNEL0_PORT 0x40
41 #define CHANNEL1_PORT 0x41
42 #define CHANNEL2_PORT 0x42
43 #define COMMAND_PORT 0x43
44
45
46 #define PIT_INTR_NUM 0
47
48 /* The order of these typedefs is important because the numerical values correspond to the 
49  * values coming from the io ports
50  */
51 typedef enum {NOT_RUNNING, PENDING, RUNNING} channel_run_state_t;
52 typedef enum {NOT_WAITING, WAITING_LOBYTE, WAITING_HIBYTE} channel_access_state_t;
53 typedef enum {LATCH_COUNT, LOBYTE_ONLY, HIBYTE_ONLY, LOBYTE_HIBYTE} channel_access_mode_t;
54 typedef enum {IRQ_ON_TERM_CNT, ONE_SHOT, RATE_GEN, SQR_WAVE, SW_STROBE, HW_STROBE} channel_op_mode_t;
55
56
57 struct channel {
58   channel_access_mode_t access_mode;
59   channel_access_state_t access_state;
60   channel_run_state_t run_state;
61
62   channel_op_mode_t op_mode;
63
64
65   // Time til interrupt trigger 
66
67   ushort_t counter;
68   ushort_t reload_value;
69
70   ushort_t latched_value;
71   
72   enum {NOTLATCHED, LATCHED} latch_state;
73
74   enum {LSB, MSB} read_state;
75
76   uint_t output_pin : 1;
77   uint_t gate_input_pin : 1;
78 };
79
80
81 struct pit {
82
83   ullong_t pit_counter;
84   ullong_t pit_reload;
85
86
87   struct channel ch_0;
88   struct channel ch_1;
89   struct channel ch_2;
90 };
91
92
93 struct pit_cmd_word {
94   uint_t bcd_mode    : 1;
95   uint_t op_mode     : 3;
96   uint_t access_mode : 2;
97   uint_t channel     : 2;
98 };
99
100 struct pit_rdb_cmd_word {
101   uint_t rsvd         : 1; // SBZ
102   uint_t ch_0         : 1;
103   uint_t ch_1         : 1;
104   uint_t ch_2         : 1;
105   uint_t latch_status : 1;
106   uint_t latch_count  : 1;
107   uint_t readback_cmd : 2; // Must Be 0x3
108 };
109
110 struct pit_rdb_status_word {
111   uint_t bcd_mode     : 1;
112   uint_t op_mode      : 3;
113   uint_t access_mode  : 2;
114   uint_t null_count   : 1;
115   uint_t pin_state    : 1; 
116 };
117
118
119
120 /* 
121  * This should call out to handle_SQR_WAVE_tics, etc... 
122  */
123 // Returns true if the the output signal changed state
124 static int handle_crystal_tics(struct vm_device * dev, struct channel * ch, uint_t oscillations) {
125   uint_t channel_cycles = 0;
126   uint_t output_changed = 0;
127   
128   // PrintDebug("8254 PIT: %d crystal tics\n", oscillations);
129   if (ch->run_state == PENDING) {
130     oscillations--;
131     ch->counter = ch->reload_value;
132
133     if (ch->op_mode == SQR_WAVE) {
134       ch->counter -= ch->counter % 2;
135     }
136
137     ch->run_state = RUNNING;
138   } else if (ch->run_state != RUNNING) {
139     return output_changed;
140   }
141
142   /*
143   PrintDebug("8254 PIT: Channel Run State = %d, counter=", ch->run_state);
144   PrintTraceLL(ch->counter);
145   PrintDebug("\n");
146   */
147   if (ch->op_mode == SQR_WAVE) {
148     oscillations *= 2;
149   }
150
151   if (ch->counter > oscillations) {
152     ch->counter -= oscillations;
153     return output_changed;
154   } else {
155     ushort_t reload_val = ch->reload_value; 
156
157     // TODO: Check this....
158     // Is this correct???
159     if (reload_val == 0) {
160       reload_val = 1;
161     }
162
163     oscillations -= ch->counter;
164     ch->counter = 0;
165     channel_cycles = 1;
166
167     if (ch->op_mode == SQR_WAVE) {
168       reload_val -= reload_val % 2;
169     }
170
171     channel_cycles += oscillations / reload_val;
172     oscillations = oscillations % reload_val;
173
174     ch->counter = reload_val - oscillations;
175   }
176
177   //  PrintDebug("8254 PIT: Channel Cycles: %d\n", channel_cycles);
178   
179
180
181   switch (ch->op_mode) {
182   case IRQ_ON_TERM_CNT:
183     if ((channel_cycles > 0) && (ch->output_pin == 0)) {
184       ch->output_pin = 1; 
185       output_changed = 1;
186     }
187     break;
188   case ONE_SHOT:
189     if ((channel_cycles > 0) && (ch->output_pin == 0)) {
190       ch->output_pin = 1; 
191       output_changed = 1;
192     }
193     break;
194   case RATE_GEN:
195     // See the data sheet: we ignore the output pin cycle...
196     if (channel_cycles > 0) {
197       output_changed = 1;
198     }
199     break;
200   case SQR_WAVE:
201     ch->output_pin = (ch->output_pin + 1) % 2;
202
203     if (ch->output_pin == 1) {
204       output_changed = 1;
205     }
206
207     break;
208   case SW_STROBE:
209     return -1;
210     break;
211   case HW_STROBE:
212     return -1;
213     break;
214   default:
215     break;
216   }
217
218   return output_changed;
219 }
220                                 
221
222
223 static void pit_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
224   struct vm_device * dev = (struct vm_device *)private_data;
225   struct pit * state = (struct pit *)dev->private_data;
226   //  ullong_t tmp_ctr = state->pit_counter;
227   ullong_t tmp_cycles;
228   uint_t oscillations = 0;
229
230
231   /*
232     PrintDebug("updating cpu_cycles=");
233     PrintTraceLL(cpu_cycles);
234     PrintDebug("\n");
235     
236     PrintDebug("pit_counter=");
237     PrintTraceLL(state->pit_counter);
238     PrintDebug("\n");
239     
240     PrintDebug("pit_reload=");
241     PrintTraceLL(state->pit_reload);
242     PrintDebug("\n");
243   */
244
245   if (state->pit_counter > cpu_cycles) {
246     // Easy...
247     state->pit_counter -= cpu_cycles;
248   } else {
249     ushort_t reload_val = state->pit_reload;
250     // Take off the first part
251     cpu_cycles -= state->pit_counter;
252     state->pit_counter = 0;
253     oscillations = 1;
254     
255     if (cpu_cycles > state->pit_reload) {
256       // how many full oscillations
257       
258       // PrintError("cpu_cycles = %p, reload = %p...\n", 
259       //         (void *)(addr_t)cpu_cycles, 
260       //         (void *)(addr_t)state->pit_reload);
261
262       // How do we check for a one shot....
263       if (state->pit_reload == 0) {
264         reload_val = 1;
265       }
266
267       tmp_cycles = cpu_cycles;
268
269       
270 #ifdef __V3_64BIT__
271       cpu_cycles = tmp_cycles / state->pit_reload;
272       tmp_cycles = tmp_cycles % state->pit_reload;
273 #else
274       cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
275 #endif
276         
277       oscillations += tmp_cycles;
278     }
279
280     // update counter with remainder (mod reload)
281     state->pit_counter = state->pit_reload - cpu_cycles;    
282
283     //PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
284     if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) {
285       // raise interrupt
286       PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n");
287       v3_raise_irq(dev->vm, 0);
288     }
289
290     //handle_crystal_tics(dev, &(state->ch_1), oscillations);
291     //handle_crystal_tics(dev, &(state->ch_2), oscillations);
292   }
293   
294
295
296  
297   return;
298 }
299
300
301
302 /* This should call out to handle_SQR_WAVE_write, etc...
303  */
304 static int handle_channel_write(struct channel * ch, char val) {
305
306     switch (ch->access_state) {      
307     case WAITING_HIBYTE:
308       {
309         ushort_t tmp_val = ((ushort_t)val) << 8;
310         ch->reload_value &= 0x00ff;
311         ch->reload_value |= tmp_val;
312         
313
314         if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
315           ch->run_state = PENDING;  
316         }
317         
318         if (ch->access_mode == LOBYTE_HIBYTE) {
319           ch->access_state = WAITING_LOBYTE;
320         }
321
322         PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);        
323         PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
324         break;
325       }
326     case WAITING_LOBYTE:
327       ch->reload_value &= 0xff00;
328       ch->reload_value |= val;
329       
330       if (ch->access_mode == LOBYTE_HIBYTE) {
331         ch->access_state = WAITING_HIBYTE;
332       } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
333         ch->run_state = PENDING;
334       }
335       
336       PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);
337       PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
338       break;
339     default:
340       return -1;
341     }
342     
343
344     switch (ch->op_mode) {
345     case IRQ_ON_TERM_CNT:
346       ch->output_pin = 0;
347       break;
348     case ONE_SHOT:
349       ch->output_pin = 1;
350       break;
351     case RATE_GEN:
352       ch->output_pin = 1;
353       break;
354     case SQR_WAVE:
355       ch->output_pin = 1;
356       break;
357     default:
358       return -1;
359       break;
360     }
361
362
363   return 0;
364 }
365
366
367 static int handle_channel_read(struct channel * ch, char * val) {
368
369   ushort_t * myval;
370
371   if (ch->latch_state == NOTLATCHED) { 
372     myval = &(ch->counter);
373   } else {
374     myval = &(ch->latched_value);
375   }
376
377   if (ch->read_state == LSB) { 
378     *val = ((char*)myval)[0];  // little endian
379     ch->read_state = MSB;
380   } else {
381     *val = ((char*)myval)[1];
382     ch->read_state = LSB;
383     if (ch->latch_state == LATCHED) { 
384       ch->latch_state = NOTLATCHED;
385     }
386   }
387
388   return 0;
389
390 }
391
392
393
394
395
396 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
397   ch->op_mode = cmd.op_mode;
398   ch->access_mode = cmd.access_mode;
399
400
401
402
403   switch (cmd.access_mode) {
404   case LATCH_COUNT:
405     if (ch->latch_state == NOTLATCHED) { 
406       ch->latched_value = ch->counter;
407       ch->latch_state = LATCHED;
408     }
409     break;
410   case HIBYTE_ONLY:
411     ch->access_state = WAITING_HIBYTE;
412     break;
413   case LOBYTE_ONLY: 
414   case LOBYTE_HIBYTE:
415     ch->access_state = WAITING_LOBYTE;
416     break;
417   }
418
419
420   switch (cmd.op_mode) {
421   case IRQ_ON_TERM_CNT:
422     ch->output_pin = 0;
423     break;
424   case ONE_SHOT: 
425     ch->output_pin = 1;
426     break;
427   case RATE_GEN: 
428     ch->output_pin = 1;
429     break;
430   case SQR_WAVE:
431     ch->output_pin = 1;
432     break;
433   default:
434     return -1;
435   }
436
437   return 0;
438     
439 }
440
441
442
443
444 static int pit_read_channel(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
445   struct pit * state = (struct pit *)dev->private_data;
446   char * val = (char *)dst;
447
448   if (length != 1) {
449     PrintError("8254 PIT: Invalid Read Write length \n");
450     return -1;
451   }
452
453   PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
454
455   switch (port) {
456   case CHANNEL0_PORT: 
457     if (handle_channel_read(&(state->ch_0), val) == -1) {
458       return -1;
459     }
460     break;
461   case CHANNEL1_PORT:
462     if (handle_channel_read(&(state->ch_1), val) == -1) {
463       return -1;
464     }
465     break;
466   case CHANNEL2_PORT:
467     if (handle_channel_read(&(state->ch_2), val) == -1) {
468       return -1;
469     }
470     break;
471   default:
472     PrintError("8254 PIT: Read from invalid port (%d)\n", port);
473     return -1;
474   }
475
476   return length;
477 }
478
479
480
481 static int pit_write_channel(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
482   struct pit * state = (struct pit *)dev->private_data;
483   char val = *(char *)src;
484
485   if (length != 1) {
486     PrintError("8254 PIT: Invalid Write Length\n");
487     return -1;
488   }
489
490   PrintDebug("8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src);
491
492
493   switch (port) {
494   case CHANNEL0_PORT:
495     if (handle_channel_write(&(state->ch_0), val) == -1) {
496       return -1;
497     } 
498     break;
499   case CHANNEL1_PORT:
500     if (handle_channel_write(&(state->ch_1), val) == -1) {
501       return -1;
502     }
503     break;
504   case CHANNEL2_PORT:
505     if (handle_channel_write(&(state->ch_2), val) == -1) {
506       return -1;
507     }
508     break;
509   default:
510     PrintError("8254 PIT: Write to invalid port (%d)\n", port);
511     return -1;
512   }
513
514   return length;
515 }
516
517
518
519
520 static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
521   struct pit * state = (struct pit *)dev->private_data;
522   struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
523
524   PrintDebug("8254 PIT: Write to PIT Command port\n");
525   PrintDebug("8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
526   if (length != 1) {
527     PrintError("8254 PIT: Write of Invalid length to command port\n");
528     return -1;
529   }
530
531   switch (cmd->channel) {
532   case 0:
533     if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
534       return -1;
535     }
536     break;
537   case 1:
538     if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
539       return -1;
540     }
541     break;
542   case 2:
543     if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
544       return -1;
545     }
546     break;
547   case 3:
548     // Read Back command
549     return -1;
550     break;
551   default:
552     break;
553   }
554
555
556   return length;
557 }
558
559
560
561
562 static struct vm_timer_ops timer_ops = {
563   .update_time = pit_update_time,
564 };
565
566
567 static void init_channel(struct channel * ch) {
568   ch->run_state = NOT_RUNNING;
569   ch->access_state = NOT_WAITING;
570   ch->access_mode = 0;
571   ch->op_mode = 0;
572
573   ch->counter = 0;
574   ch->reload_value = 0;
575   ch->output_pin = 0;
576   ch->gate_input_pin = 0;
577
578   ch->latched_value = 0;
579   ch->latch_state = NOTLATCHED;
580   ch->read_state = LSB;
581
582   return;
583 }
584
585
586 static int pit_init(struct vm_device * dev) {
587   struct pit * state = (struct pit *)dev->private_data;
588   uint_t cpu_khz = V3_CPU_KHZ();
589   ullong_t reload_val = (ullong_t)cpu_khz * 1000;
590
591   v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
592   v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
593   v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
594   v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
595
596 #ifdef DEBUG_PIT
597   PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
598   PrintTraceLL(reload_val);
599   PrintDebug("\n");
600 #endif
601
602   v3_add_timer(dev->vm, &timer_ops, dev);
603
604   // Get cpu frequency and calculate the global pit oscilattor counter/cycle
605
606   do_divll(reload_val, OSC_HZ);
607   state->pit_counter = reload_val;
608   state->pit_reload = reload_val;
609
610
611
612   init_channel(&(state->ch_0));
613   init_channel(&(state->ch_1));
614   init_channel(&(state->ch_2));
615
616 #ifdef DEBUG_PIT
617   PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
618   PrintTraceLL(state->pit_counter);
619   PrintDebug("\n");
620 #endif
621
622   return 0;
623 }
624
625 static int pit_deinit(struct vm_device * dev) {
626
627   return 0;
628 }
629
630
631 static struct vm_device_ops dev_ops = {
632   .init = pit_init,
633   .deinit = pit_deinit,
634   .reset = NULL,
635   .start = NULL,
636   .stop = NULL,
637
638 };
639
640
641 struct vm_device * v3_create_pit() {
642   struct pit * pit_state = NULL;
643   pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
644   V3_ASSERT(pit_state != NULL);
645
646   struct vm_device * dev = v3_create_device("PIT", &dev_ops, pit_state);
647   
648   return dev;
649 }