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.


remove extraneous dos linefeeds from scheduling files
[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
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_dev_mgr.h>
23 #include <palacios/vmm_time.h>
24 #include <palacios/vmm_util.h>
25 #include <palacios/vmm_intr.h>
26 #include <palacios/vmm_config.h>
27 #include <palacios/vmm_io.h>
28
29
30 #ifndef V3_CONFIG_DEBUG_PIT
31 #undef PrintDebug
32 #define PrintDebug(fmt, args...)
33 #endif
34
35
36
37 // constants
38 #define OSC_HZ 1193182
39
40
41 /* The 8254 has three counters and one control port */
42 #define CHANNEL0_PORT 0x40
43 #define CHANNEL1_PORT 0x41
44 #define CHANNEL2_PORT 0x42
45 #define COMMAND_PORT 0x43
46 #define SPEAKER_PORT 0x61
47
48
49 #define PIT_INTR_NUM 0
50 #define PIT_SPEAKER_GATE 0x01
51
52 /* The order of these typedefs is important because the numerical values correspond to the 
53  * values coming from the io ports
54  */
55 typedef enum {NOT_RUNNING, PENDING, RUNNING} channel_run_state_t;
56 typedef enum {NOT_WAITING, WAITING_LOBYTE, WAITING_HIBYTE} channel_access_state_t;
57 typedef enum {LATCH_COUNT = 0, LOBYTE_ONLY = 1, HIBYTE_ONLY = 2, LOBYTE_HIBYTE = 3} channel_access_mode_t;
58 typedef enum {IRQ_ON_TERM_CNT = 0, ONE_SHOT = 1, RATE_GEN = 2, SQR_WAVE = 3, SW_STROBE = 4, HW_STROBE = 5} channel_op_mode_t;
59
60
61 struct channel {
62     channel_access_mode_t access_mode;
63     channel_access_state_t access_state;
64     channel_run_state_t run_state;
65
66     channel_op_mode_t op_mode;
67
68
69     // Time til interrupt trigger 
70
71     ushort_t counter;
72     ushort_t reload_value;
73
74     ushort_t latched_value;
75   
76     enum {NOTLATCHED, LATCHED} latch_state;
77
78     enum {LSB, MSB} read_state;
79
80     uint_t output_pin : 1;
81     uint_t gate_input_pin : 1;
82 };
83
84
85 struct pit {
86
87     ullong_t pit_counter;
88     ullong_t pit_reload;
89
90     struct v3_timer * timer;
91
92     struct v3_vm_info * vm;
93
94     struct channel ch_0;
95     struct channel ch_1;
96     struct channel ch_2;
97     uint8_t speaker;
98 };
99
100
101 struct pit_cmd_word {
102     uint_t bcd_mode    : 1;
103     uint_t op_mode     : 3;
104     uint_t access_mode : 2;
105     uint_t channel     : 2;
106 };
107
108 struct pit_rdb_cmd_word {
109     uint_t rsvd         : 1; // SBZ
110     uint_t ch_0         : 1;
111     uint_t ch_1         : 1;
112     uint_t ch_2         : 1;
113     uint_t latch_status : 1;
114     uint_t latch_count  : 1;
115     uint_t readback_cmd : 2; // Must Be 0x3
116 };
117
118 struct pit_rdb_status_word {
119     uint_t bcd_mode     : 1;
120     uint_t op_mode      : 3;
121     uint_t access_mode  : 2;
122     uint_t null_count   : 1;
123     uint_t pin_state    : 1; 
124 };
125
126
127
128 /* 
129  * This should call out to handle_SQR_WAVE_tics, etc... 
130  */
131 // Returns true if the the output signal changed state
132 static int handle_crystal_tics(struct pit * pit, struct channel * ch, uint_t oscillations) {
133     uint_t channel_cycles = 0;
134     uint_t output_changed = 0;
135   
136     //    PrintDebug(info->vm_info, info, "8254 PIT (channel %d): %d crystal tics\n", 
137     //         ch - pit->ch0, oscillations);
138     if (ch->run_state == PENDING) {
139         oscillations--;
140         ch->counter = ch->reload_value;
141
142         if (ch->op_mode == SQR_WAVE) {
143             ch->counter -= ch->counter % 2;
144         }
145
146         ch->run_state = RUNNING;
147     } else if (ch->run_state != RUNNING) {
148         return output_changed;
149     }
150
151     /*
152       PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel Run State = %d, counter=", ch->run_state);
153       PrintTraceLL(ch->counter);
154       PrintDebug(VM_NONE, VCORE_NONE, "\n");
155     */
156     if (ch->op_mode == SQR_WAVE) {
157         oscillations *= 2;
158     }
159
160     if (ch->counter > oscillations) {
161         ch->counter -= oscillations;
162         //PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Counter at %u after %u oscillations.\n", 
163         //   (unsigned int)ch->counter, oscillations);
164         return output_changed;
165     } else {
166         ushort_t reload_val = ch->reload_value; 
167
168         if ((ch->op_mode == SW_STROBE) || (ch->op_mode == IRQ_ON_TERM_CNT)) {
169             reload_val = 0xffff;
170         }
171
172         oscillations -= ch->counter;
173         ch->counter = 0;
174         channel_cycles = 1;
175
176         if (ch->op_mode == SQR_WAVE) {
177             reload_val -= reload_val % 2;
178         }
179
180         if (reload_val == 0) {
181             // This means the value is being set to 0x10000
182             // but due to the tick after the reload, it wraps
183             // down to 0xffff
184             reload_val = 0xffff;
185         }
186
187         channel_cycles += oscillations / reload_val;
188         oscillations = oscillations % reload_val;
189
190         ch->counter = reload_val - oscillations;
191         //      PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Counter reset to %u.\n", 
192         //   (unsigned int)ch->counter);
193
194     }
195
196     //PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel %ld (mode = %u) Cycles: %d\n", 
197                //(ch - &pit->ch_0), ch->op_mode, channel_cycles);
198   
199     switch (ch->op_mode) {
200         case IRQ_ON_TERM_CNT:
201             if (channel_cycles > 0) {
202                 if (ch->output_pin == 0) {
203                     ch->output_pin = 1; 
204                     output_changed = 1;
205                 } else {
206                    // PrintDebug(VM_NONE, VCORE_NONE, "8254: Output not changed in TERM_CNT mode.\n");
207                 }
208             }
209             break;
210         case ONE_SHOT:
211             if (channel_cycles > 0) {
212                 if ((ch->output_pin == 0)) {
213                     ch->output_pin = 1; 
214                     output_changed = 1;
215                 } else {
216                     // PrintDebug(VM_NONE, VCORE_NONE, "8254: Output not changed in ONE_SHOT mode.\n");
217                 }
218             }
219             break;
220         case RATE_GEN:
221             // See the data sheet: we ignore the output pin cycle...
222             if (channel_cycles > 0) {
223                 output_changed = 1;
224             }
225             break;
226         case SQR_WAVE:
227             ch->output_pin = (ch->output_pin + 1) % 2;
228
229             if (ch->output_pin == 1) {
230                 output_changed = 1;
231             }
232
233
234             break;
235         case SW_STROBE:
236
237             if (channel_cycles > 0) {
238                 if (ch->output_pin == 1) {
239                     ch->output_pin = 0;
240                     output_changed = 1;
241                 }
242             }
243             break;
244         case HW_STROBE:
245             PrintError(VM_NONE, VCORE_NONE, "Hardware strobe not implemented\n");
246             return -1;
247             break;
248         default:
249             break;
250     }
251
252     return output_changed;
253 }
254                                 
255
256 #include <palacios/vm_guest.h>
257
258 static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
259     struct pit * state = (struct pit *)private_data;
260     //  ullong_t tmp_ctr = state->pit_counter;
261     ullong_t tmp_cycles;
262     uint_t oscillations = 0;
263
264
265     /*
266       PrintDebug(info->vm_info, info, "updating cpu_cycles=");
267       PrintTraceLL(cpu_cycles);
268       PrintDebug(info->vm_info, info, "\n");
269     
270       PrintDebug(info->vm_info, info, "pit_counter=");
271       PrintTraceLL(state->pit_counter);
272       PrintDebug(info->vm_info, info, "\n");
273     
274       PrintDebug(info->vm_info, info, "pit_reload=");
275       PrintTraceLL(state->pit_reload);
276       PrintDebug(info->vm_info, info, "\n");
277     */
278
279     if (state->pit_counter > cpu_cycles) {
280         // Easy...
281         state->pit_counter -= cpu_cycles;
282     } else {
283         ushort_t reload_val = state->pit_reload;
284         // Take off the first part
285         cpu_cycles -= state->pit_counter;
286         state->pit_counter = 0;
287         oscillations = 1;
288     
289         if (cpu_cycles > state->pit_reload) {
290             // how many full oscillations
291       
292             //PrintError(info->vm_info, info, "cpu_cycles = %p, reload = %p...\n", 
293             //   (void *)(addr_t)cpu_cycles, 
294             //   (void *)(addr_t)state->pit_reload);
295
296             // How do we check for a one shot....
297             if (state->pit_reload == 0) {
298                 reload_val = 1;
299             }
300
301             tmp_cycles = cpu_cycles;
302
303       
304 #ifdef __V3_64BIT__
305             cpu_cycles = tmp_cycles % state->pit_reload;
306             tmp_cycles = tmp_cycles / state->pit_reload;
307 #else
308             cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
309 #endif
310         
311             oscillations += tmp_cycles;
312         }
313
314         // update counter with remainder (mod reload)
315         state->pit_counter = state->pit_reload - cpu_cycles;    
316
317         if (oscillations) {
318             //    PrintDebug(info->vm_info, info, "8254 PIT: Handling %d crystal tics\n", oscillations);
319
320             if (handle_crystal_tics(state, &(state->ch_0), oscillations) == 1) {
321                 // raise interrupt
322                 PrintDebug(info->vm_info, info, "8254 PIT: Injecting Timer interrupt to guest (run_state = %d)\n",
323                            state->ch_0.run_state);
324                 v3_raise_irq(info->vm_info, 0);
325             }
326
327             //handle_crystal_tics(state, &(state->ch_1), oscillations);
328             handle_crystal_tics(state, &(state->ch_2), oscillations);
329         }
330     }
331  
332     return;
333 }
334
335 /* This should call out to handle_SQR_WAVE_write, etc...
336  */
337 static int handle_channel_write(struct channel * ch, char val) {
338
339     switch (ch->access_state) {      
340         case WAITING_HIBYTE:
341             {
342                 ushort_t tmp_val = ((ushort_t)val) << 8;
343                 ch->reload_value &= 0x00ff;
344                 ch->reload_value |= tmp_val;
345         
346
347                 if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
348                     ch->run_state = PENDING;  
349                 }
350         
351                 if (ch->access_mode == LOBYTE_HIBYTE) {
352                     ch->access_state = WAITING_LOBYTE;
353                 }
354
355                 PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: updated channel counter: %d\n", ch->reload_value);   
356                 PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel Run State=%d\n", ch->run_state);
357                 break;
358             }
359         case WAITING_LOBYTE:
360             ch->reload_value &= 0xff00;
361             ch->reload_value |= val;
362       
363             if (ch->access_mode == LOBYTE_HIBYTE) {
364                 ch->access_state = WAITING_HIBYTE;
365             } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
366                 ch->run_state = PENDING;
367             }
368       
369             PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: updated channel counter: %d\n", ch->reload_value);
370             PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Channel Run State=%d\n", ch->run_state);
371             break;
372         default:
373             PrintError(VM_NONE, VCORE_NONE, "Invalid Access state\n");
374             return -1;
375     }
376     
377
378     switch (ch->op_mode) {
379         case IRQ_ON_TERM_CNT:
380             ch->output_pin = 0;
381             break;
382         case ONE_SHOT:
383             ch->output_pin = 1;
384             break;
385         case RATE_GEN:
386             ch->output_pin = 1;
387             break;
388         case SQR_WAVE:
389             ch->output_pin = 1;
390             break;
391         case SW_STROBE:
392             ch->output_pin = 1;
393             break;
394         default:
395             PrintError(VM_NONE, VCORE_NONE, "Invalid OP_MODE: %d\n", ch->op_mode);
396             return -1;
397             break;
398     }
399
400
401     return 0;
402 }
403
404
405 static int handle_channel_read(struct channel * ch, char * val) {
406
407     ushort_t * myval;
408
409     if (ch->latch_state == NOTLATCHED) { 
410         myval = &(ch->counter);
411     } else {
412         myval = &(ch->latched_value);
413     }
414
415     if (ch->read_state == LSB) { 
416         *val = ((char*)myval)[0];  // little endian
417         ch->read_state = MSB;
418     } else {
419         *val = ((char*)myval)[1];
420         ch->read_state = LSB;
421         if (ch->latch_state == LATCHED) { 
422             ch->latch_state = NOTLATCHED;
423         }
424     }
425
426     return 0;
427
428 }
429
430 static int handle_speaker_read(uint8_t *speaker, struct channel * ch, char * val) {
431     *val = *speaker;
432
433     if ((*speaker & PIT_SPEAKER_GATE)) {
434         *val |= (ch->output_pin << 5);
435     }
436     
437     return 0;
438 }
439
440 static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) {
441     *speaker = (val & ~0x20);
442     return 0;
443 }
444
445 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
446
447     if (cmd.op_mode != ch->op_mode) {
448         PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Changing channel from op mode %d to op mode %d.\n", 
449                    ch->op_mode, cmd.op_mode);
450     }
451
452     if (cmd.access_mode != 0) {
453       ch->op_mode = cmd.op_mode;
454     }
455
456     if (cmd.access_mode != ch->access_mode) {
457         PrintDebug(VM_NONE, VCORE_NONE, "8254 PIT: Changing channel from access mode %d to access mode %d.\n", 
458                    ch->access_mode, cmd.access_mode);
459     }
460     ch->access_mode = cmd.access_mode;
461
462     switch (cmd.access_mode) {
463         case LATCH_COUNT:
464             if (ch->latch_state == NOTLATCHED) { 
465                 ch->latched_value = ch->counter;
466                 ch->latch_state = LATCHED;
467             }
468             break;
469         case HIBYTE_ONLY:
470             ch->access_state = WAITING_HIBYTE;
471             break;
472         case LOBYTE_ONLY: 
473         case LOBYTE_HIBYTE:
474             ch->access_state = WAITING_LOBYTE;
475             break;
476     }
477
478
479     switch (cmd.op_mode) {
480         case IRQ_ON_TERM_CNT:
481             ch->output_pin = 0;
482             break;
483         case ONE_SHOT: 
484             ch->output_pin = 1;
485             break;
486         case RATE_GEN: 
487             ch->output_pin = 1;
488             break;
489         case SQR_WAVE:
490             ch->output_pin = 1;
491             break;
492         case SW_STROBE:
493             ch->output_pin = 1;
494             break;
495         default:
496             PrintError(VM_NONE, VCORE_NONE, "Invalid OP_MODE: %d\n", cmd.op_mode);
497             return -1;
498     }
499
500     return 0;
501     
502 }
503
504
505
506
507 static int pit_read_channel(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
508     struct pit * state = (struct pit *)priv_data;
509     char * val = (char *)dst;
510
511     if (length != 1) {
512         PrintError(core->vm_info, core, "8254 PIT: Invalid Read Write length \n");
513         return -1;
514     }
515
516     PrintDebug(core->vm_info, core, "8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
517
518     switch (port) {
519         case CHANNEL0_PORT: 
520             if (handle_channel_read(&(state->ch_0), val) == -1) {
521                 PrintError(core->vm_info, core, "CHANNEL0 read error\n");
522                 return -1;
523             }
524             break;
525         case CHANNEL1_PORT:
526             if (handle_channel_read(&(state->ch_1), val) == -1) {
527                 PrintError(core->vm_info, core, "CHANNEL1 read error\n");
528                 return -1;
529             }
530             break;
531         case CHANNEL2_PORT:
532             if (handle_channel_read(&(state->ch_2), val) == -1) {
533                 PrintError(core->vm_info, core, "CHANNEL2 read error\n");
534                 return -1;
535             }
536             break;
537         case SPEAKER_PORT:
538             if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) {
539                 PrintError(core->vm_info, core, "SPEAKER read error\n");
540                 return -1;
541             }
542             break;
543         default:
544             PrintError(core->vm_info, core, "8254 PIT: Read from invalid port (%d)\n", port);
545             return -1;
546     }
547
548     return length;
549 }
550
551
552
553 static int pit_write_channel(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
554     struct pit * state = (struct pit *)priv_data;
555     char val = *(char *)src;
556
557     if (length != 1) {
558         PrintError(core->vm_info, core, "8254 PIT: Invalid Write Length\n");
559         return -1;
560     }
561
562     PrintDebug(core->vm_info, core, "8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src);
563
564
565     switch (port) {
566         case CHANNEL0_PORT:
567             if (handle_channel_write(&(state->ch_0), val) == -1) {
568                 PrintError(core->vm_info, core, "CHANNEL0 write error\n");
569                 return -1;
570             } 
571             break;
572         case CHANNEL1_PORT:
573             if (handle_channel_write(&(state->ch_1), val) == -1) {
574                 PrintError(core->vm_info, core, "CHANNEL1 write error\n");
575                 return -1;
576             }
577             break;
578         case CHANNEL2_PORT:
579             if (handle_channel_write(&(state->ch_2), val) == -1) {
580                 PrintError(core->vm_info, core, "CHANNEL2 write error\n");      
581                 return -1;
582             }
583             break;
584         case SPEAKER_PORT:
585             if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) {
586                 PrintError(core->vm_info, core, "SPEAKER write error\n");
587                 return -1;
588             }
589             break;
590         default:
591             PrintError(core->vm_info, core, "8254 PIT: Write to invalid port (%d)\n", port);
592             return -1;
593     }
594
595     return length;
596 }
597
598
599
600
601 static int pit_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
602     struct pit * state = (struct pit *)priv_data;
603     struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
604
605     PrintDebug(core->vm_info, core, "8254 PIT: Write to PIT Command port\n");
606     PrintDebug(core->vm_info, core, "8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
607     if (length != 1) {
608         PrintError(core->vm_info, core, "8254 PIT: Write of Invalid length to command port\n");
609         return -1;
610     }
611
612     switch (cmd->channel) {
613         case 0:
614             if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
615                 PrintError(core->vm_info, core, "CHANNEL0 command error\n");
616                 return -1;
617             }
618             break;
619         case 1:
620             if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
621                 PrintError(core->vm_info, core, "CHANNEL1 command error\n");
622                 return -1;
623             }
624             break;
625         case 2:
626             if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
627                 PrintError(core->vm_info, core, "CHANNEL2 command error\n");
628                 return -1;
629             }
630             break;
631         case 3:
632             // Read Back command
633             PrintError(core->vm_info, core, "Read back command not implemented\n");
634             return -1;
635             break;
636         default:
637             break;
638     }
639
640
641     return length;
642 }
643
644
645
646
647 static struct v3_timer_ops timer_ops = {
648     .update_timer = pit_update_timer,
649 };
650
651
652 static void init_channel(struct channel * ch) {
653     ch->run_state = NOT_RUNNING;
654     ch->access_state = NOT_WAITING;
655     ch->access_mode = 0;
656     ch->op_mode = 0;
657
658     ch->counter = 0;
659     ch->reload_value = 0;
660     ch->output_pin = 0;
661     ch->gate_input_pin = 0;
662
663     ch->latched_value = 0;
664     ch->latch_state = NOTLATCHED;
665     ch->read_state = LSB;
666
667     return;
668 }
669
670
671
672
673 static int pit_free(void * private_data) {
674     struct pit * state = (struct pit *)private_data;
675     struct guest_info * info = &(state->vm->cores[0]);
676
677
678     if (state->timer) {
679         v3_remove_timer(info, state->timer);
680     }
681  
682     V3_Free(state);
683     return 0;
684 }
685
686 #ifdef V3_CONFIG_CHECKPOINT
687
688 #include <palacios/vmm_sprintf.h>
689
690 #define KEY_MAX 128
691 #define MAKE_KEY(x) snprintf(key,KEY_MAX,"PIT_CH%d_%s",i,x)
692
693 static int pit_save(struct v3_chkpt_ctx * ctx, void * private_data) {
694     struct pit * pit_state = (struct pit *)private_data; 
695     int i;
696     char key[KEY_MAX];
697
698     V3_CHKPT_SAVE(ctx, "PIT_COUNTER", pit_state->pit_counter,savefailout);
699     V3_CHKPT_SAVE(ctx, "PIT_RELOAD", pit_state->pit_reload,savefailout);
700
701     for (i=0;i<3;i++) {
702       struct channel *c;
703       uint8_t pins;
704
705       if (i==0) { 
706         c=&(pit_state->ch_0);
707       } else if (i==1) { 
708         c=&(pit_state->ch_1);
709       } else {
710         c=&(pit_state->ch_2);
711       }
712       
713       MAKE_KEY("ACCESS_MODE");
714       V3_CHKPT_SAVE(ctx, key, c->access_mode, savefailout);
715       MAKE_KEY("ACCESS_STATE");
716       V3_CHKPT_SAVE(ctx, key, c->access_state, savefailout);
717       MAKE_KEY("RUN_STATE");
718       V3_CHKPT_SAVE(ctx, key, c->run_state, savefailout);
719       MAKE_KEY("OP_MODE");
720       V3_CHKPT_SAVE(ctx, key, c->op_mode, savefailout);
721       MAKE_KEY("COUNTER");
722       V3_CHKPT_SAVE(ctx, key, c->counter, savefailout);
723       MAKE_KEY("RELOAD_VALUE");
724       V3_CHKPT_SAVE(ctx, key, c->reload_value, savefailout);
725       MAKE_KEY("LATCH_STATE");
726       V3_CHKPT_SAVE(ctx, key, c->latch_state, savefailout);
727       MAKE_KEY("READ_STATE");
728       V3_CHKPT_SAVE(ctx, key, c->read_state, savefailout);
729       
730       pins = (c->output_pin) | (c->gate_input_pin << 1);
731       MAKE_KEY("PINS");
732       V3_CHKPT_SAVE(ctx, key, pins, savefailout);
733     }
734     
735     V3_CHKPT_SAVE(ctx, "PIT_SPEAKER", pit_state->speaker,savefailout);
736     
737     return 0;
738
739  savefailout:
740     PrintError(VM_NONE, VCORE_NONE, "Failed to save pit\n");
741     return -1;
742 }
743
744 static int pit_load(struct v3_chkpt_ctx * ctx, void * private_data) {
745     struct pit * pit_state = (struct pit *)private_data;
746     int i;
747     char key[KEY_MAX];
748
749     V3_CHKPT_LOAD(ctx, "PIT_COUNTER", pit_state->pit_counter,loadfailout);
750     V3_CHKPT_LOAD(ctx, "PIT_RELOAD", pit_state->pit_reload,loadfailout);
751
752     for (i=0;i<3;i++) {
753       struct channel *c;
754       uint8_t pins;
755
756       if (i==0) { 
757         c=&(pit_state->ch_0);
758       } else if (i==1) { 
759         c=&(pit_state->ch_1);
760       } else {
761         c=&(pit_state->ch_2);
762       }
763       
764       MAKE_KEY("ACCESS_MODE");
765       V3_CHKPT_LOAD(ctx, key, c->access_mode, loadfailout);
766       MAKE_KEY("ACCESS_STATE");
767       V3_CHKPT_LOAD(ctx, key, c->access_state, loadfailout);
768       MAKE_KEY("RUN_STATE");
769       V3_CHKPT_LOAD(ctx, key, c->run_state, loadfailout);
770       MAKE_KEY("OP_MODE");
771       V3_CHKPT_LOAD(ctx, key, c->op_mode, loadfailout);
772       MAKE_KEY("COUNTER");
773       V3_CHKPT_LOAD(ctx, key, c->counter, loadfailout);
774       MAKE_KEY("RELOAD_VALUE");
775       V3_CHKPT_LOAD(ctx, key, c->reload_value, loadfailout);
776       MAKE_KEY("LATCH_STATE");
777       V3_CHKPT_LOAD(ctx, key, c->latch_state, loadfailout);
778       MAKE_KEY("READ_STATE");
779       V3_CHKPT_LOAD(ctx, key, c->read_state, loadfailout);
780       
781       pins = (c->output_pin) | (c->gate_input_pin << 1);
782       MAKE_KEY("PINS");
783       V3_CHKPT_LOAD(ctx, key, pins, loadfailout);
784     }
785     
786     V3_CHKPT_LOAD(ctx, "PIT_SPEAKER", pit_state->speaker,loadfailout);
787
788     return 0;
789
790  loadfailout:
791     PrintError(VM_NONE, VCORE_NONE, "Failed to load pit\n");
792     return -1;
793 }
794 #endif
795
796 static struct v3_device_ops dev_ops = {
797     .free = (int (*)(void *))pit_free,
798 #ifdef V3_CONFIG_CHECKPOINT
799     .save = pit_save,
800     .load = pit_load,
801 #endif
802 };
803
804 #include <palacios/vm_guest.h>
805
806 static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
807     struct pit * pit_state = NULL;
808     struct vm_device * dev = NULL;
809     char * dev_id = v3_cfg_val(cfg, "ID");
810     int ret = 0;
811
812     // PIT is only usable in non-multicore environments
813     // just hardcode the core context
814     struct guest_info * info = &(vm->cores[0]);
815
816     uint_t cpu_khz = info->time_state.guest_cpu_freq;
817     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
818
819     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
820
821     if (!pit_state) {
822         PrintError(info->vm_info, info, "Cannot allocate in init\n");
823         return -1;
824     }
825
826     pit_state->speaker = 0;
827     pit_state->vm = vm;
828
829     dev = v3_add_device(vm, dev_id, &dev_ops, pit_state);
830
831     if (dev == NULL) {
832         PrintError(info->vm_info, info, "Could not attach device %s\n", dev_id);
833         V3_Free(pit_state);
834         return -1;
835     }
836
837     ret |= v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
838     ret |= v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
839     ret |= v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
840     ret |= v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
841     ret |= v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
842
843     if (ret != 0) {
844         PrintError(info->vm_info, info, "8254 PIT: Failed to hook IO ports\n");
845         v3_remove_device(dev);
846         return -1;
847     }
848
849 #ifdef V3_CONFIG_DEBUG_PIT
850     PrintDebug(info->vm_info, info, "8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
851     //PrintTrace(reload_val);
852     PrintDebug(info->vm_info, info, "\n");
853 #endif
854
855     
856
857     pit_state->timer = v3_add_timer(info, &timer_ops, pit_state);
858
859     if (pit_state->timer == NULL) {
860         v3_remove_device(dev);
861         return -1;
862     }
863
864     // Get cpu frequency and calculate the global pit oscilattor counter/cycle
865
866     do_divll(reload_val, OSC_HZ);
867     pit_state->pit_counter = reload_val;
868     pit_state->pit_reload = reload_val;
869
870
871     init_channel(&(pit_state->ch_0));
872     init_channel(&(pit_state->ch_1));
873     init_channel(&(pit_state->ch_2));
874
875 #ifdef V3_CONFIG_DEBUG_PIT
876     PrintDebug(info->vm_info, info, "8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
877     //PrintTraceLL(pit_state->pit_counter);
878     PrintDebug(info->vm_info, info, "\n");
879 #endif
880
881     return 0;
882 }
883
884
885 device_register("8254_PIT", pit_init);