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.


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