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.


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