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 some more device unregister functions
[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 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, LOBYTE_ONLY, HIBYTE_ONLY, LOBYTE_HIBYTE} channel_access_mode_t;
58 typedef enum {IRQ_ON_TERM_CNT, ONE_SHOT, RATE_GEN, SQR_WAVE, SW_STROBE, HW_STROBE} 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 channel ch_0;
93     struct channel ch_1;
94     struct channel ch_2;
95     uint8_t speaker;
96 };
97
98
99 struct pit_cmd_word {
100     uint_t bcd_mode    : 1;
101     uint_t op_mode     : 3;
102     uint_t access_mode : 2;
103     uint_t channel     : 2;
104 };
105
106 struct pit_rdb_cmd_word {
107     uint_t rsvd         : 1; // SBZ
108     uint_t ch_0         : 1;
109     uint_t ch_1         : 1;
110     uint_t ch_2         : 1;
111     uint_t latch_status : 1;
112     uint_t latch_count  : 1;
113     uint_t readback_cmd : 2; // Must Be 0x3
114 };
115
116 struct pit_rdb_status_word {
117     uint_t bcd_mode     : 1;
118     uint_t op_mode      : 3;
119     uint_t access_mode  : 2;
120     uint_t null_count   : 1;
121     uint_t pin_state    : 1; 
122 };
123
124
125
126 /* 
127  * This should call out to handle_SQR_WAVE_tics, etc... 
128  */
129 // Returns true if the the output signal changed state
130 static int handle_crystal_tics(struct vm_device * dev, struct channel * ch, uint_t oscillations) {
131     uint_t channel_cycles = 0;
132     uint_t output_changed = 0;
133   
134     // PrintDebug("8254 PIT: %d crystal tics\n", oscillations);
135     if (ch->run_state == PENDING) {
136         oscillations--;
137         ch->counter = ch->reload_value;
138
139         if (ch->op_mode == SQR_WAVE) {
140             ch->counter -= ch->counter % 2;
141         }
142
143         ch->run_state = RUNNING;
144     } else if (ch->run_state != RUNNING) {
145         return output_changed;
146     }
147
148     /*
149       PrintDebug("8254 PIT: Channel Run State = %d, counter=", ch->run_state);
150       PrintTraceLL(ch->counter);
151       PrintDebug("\n");
152     */
153     if (ch->op_mode == SQR_WAVE) {
154         oscillations *= 2;
155     }
156
157     if (ch->counter > oscillations) {
158         ch->counter -= oscillations;
159         return output_changed;
160     } else {
161         ushort_t reload_val = ch->reload_value; 
162
163         if (ch->op_mode == SW_STROBE) {
164             reload_val = 0xffff;
165         }
166
167         oscillations -= ch->counter;
168         ch->counter = 0;
169         channel_cycles = 1;
170
171         if (ch->op_mode == SQR_WAVE) {
172             reload_val -= reload_val % 2;
173         }
174
175         // TODO: Check this....
176         // Is this correct???
177         if (reload_val == 0) {
178             reload_val = 1;
179         }
180
181         channel_cycles += oscillations / reload_val;
182         oscillations = oscillations % reload_val;
183
184         ch->counter = reload_val - oscillations;
185     }
186
187     //  PrintDebug("8254 PIT: Channel Cycles: %d\n", channel_cycles);
188   
189
190
191     switch (ch->op_mode) {
192         case IRQ_ON_TERM_CNT:
193             if ((channel_cycles > 0) && (ch->output_pin == 0)) {
194                 ch->output_pin = 1; 
195                 output_changed = 1;
196             }
197             break;
198         case ONE_SHOT:
199             if ((channel_cycles > 0) && (ch->output_pin == 0)) {
200                 ch->output_pin = 1; 
201                 output_changed = 1;
202             }
203             break;
204         case RATE_GEN:
205             // See the data sheet: we ignore the output pin cycle...
206             if (channel_cycles > 0) {
207                 output_changed = 1;
208             }
209             break;
210         case SQR_WAVE:
211             ch->output_pin = (ch->output_pin + 1) % 2;
212
213             if (ch->output_pin == 1) {
214                 output_changed = 1;
215             }
216
217             break;
218         case SW_STROBE:
219
220             if (channel_cycles > 0) {
221                 if (ch->output_pin == 1) {
222                     ch->output_pin = 0;
223                     output_changed = 1;
224                 }
225             }
226             break;
227         case HW_STROBE:
228             PrintError("Hardware strobe not implemented\n");
229             return -1;
230             break;
231         default:
232             break;
233     }
234
235     return output_changed;
236 }
237                                 
238
239 #include <palacios/vm_guest.h>
240
241 static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
242     struct vm_device * dev = (struct vm_device *)private_data;
243     struct pit * state = (struct pit *)dev->private_data;
244     //  ullong_t tmp_ctr = state->pit_counter;
245     ullong_t tmp_cycles;
246     uint_t oscillations = 0;
247
248
249     /*
250       PrintDebug("updating cpu_cycles=");
251       PrintTraceLL(cpu_cycles);
252       PrintDebug("\n");
253     
254       PrintDebug("pit_counter=");
255       PrintTraceLL(state->pit_counter);
256       PrintDebug("\n");
257     
258       PrintDebug("pit_reload=");
259       PrintTraceLL(state->pit_reload);
260       PrintDebug("\n");
261     */
262
263     if (state->pit_counter > cpu_cycles) {
264         // Easy...
265         state->pit_counter -= cpu_cycles;
266     } else {
267         ushort_t reload_val = state->pit_reload;
268         // Take off the first part
269         cpu_cycles -= state->pit_counter;
270         state->pit_counter = 0;
271         oscillations = 1;
272     
273         if (cpu_cycles > state->pit_reload) {
274             // how many full oscillations
275       
276             //PrintError("cpu_cycles = %p, reload = %p...\n", 
277             //   (void *)(addr_t)cpu_cycles, 
278             //   (void *)(addr_t)state->pit_reload);
279
280             // How do we check for a one shot....
281             if (state->pit_reload == 0) {
282                 reload_val = 1;
283             }
284
285             tmp_cycles = cpu_cycles;
286
287       
288 #ifdef __V3_64BIT__
289             cpu_cycles = tmp_cycles % state->pit_reload;
290             tmp_cycles = tmp_cycles / state->pit_reload;
291 #else
292             cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
293 #endif
294         
295             oscillations += tmp_cycles;
296         }
297
298         // update counter with remainder (mod reload)
299         state->pit_counter = state->pit_reload - cpu_cycles;    
300
301         //PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
302         if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) {
303             // raise interrupt
304             PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n");
305             v3_raise_irq(info->vm_info, 0);
306         }
307
308         //handle_crystal_tics(dev, &(state->ch_1), oscillations);
309         handle_crystal_tics(dev, &(state->ch_2), oscillations);
310     }
311   
312
313
314  
315     return;
316 }
317
318 /* This should call out to handle_SQR_WAVE_write, etc...
319  */
320 static int handle_channel_write(struct channel * ch, char val) {
321
322     switch (ch->access_state) {      
323         case WAITING_HIBYTE:
324             {
325                 ushort_t tmp_val = ((ushort_t)val) << 8;
326                 ch->reload_value &= 0x00ff;
327                 ch->reload_value |= tmp_val;
328         
329
330                 if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
331                     ch->run_state = PENDING;  
332                 }
333         
334                 if (ch->access_mode == LOBYTE_HIBYTE) {
335                     ch->access_state = WAITING_LOBYTE;
336                 }
337
338                 PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);        
339                 PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
340                 break;
341             }
342         case WAITING_LOBYTE:
343             ch->reload_value &= 0xff00;
344             ch->reload_value |= val;
345       
346             if (ch->access_mode == LOBYTE_HIBYTE) {
347                 ch->access_state = WAITING_HIBYTE;
348             } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
349                 ch->run_state = PENDING;
350             }
351       
352             PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);
353             PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
354             break;
355         default:
356             PrintError("Invalid Access state\n");
357             return -1;
358     }
359     
360
361     switch (ch->op_mode) {
362         case IRQ_ON_TERM_CNT:
363             ch->output_pin = 0;
364             break;
365         case ONE_SHOT:
366             ch->output_pin = 1;
367             break;
368         case RATE_GEN:
369             ch->output_pin = 1;
370             break;
371         case SQR_WAVE:
372             ch->output_pin = 1;
373             break;
374         case SW_STROBE:
375             ch->output_pin = 1;
376             break;
377         default:
378             PrintError("Invalid OP_MODE: %d\n", ch->op_mode);
379             return -1;
380             break;
381     }
382
383
384     return 0;
385 }
386
387
388 static int handle_channel_read(struct channel * ch, char * val) {
389
390     ushort_t * myval;
391
392     if (ch->latch_state == NOTLATCHED) { 
393         myval = &(ch->counter);
394     } else {
395         myval = &(ch->latched_value);
396     }
397
398     if (ch->read_state == LSB) { 
399         *val = ((char*)myval)[0];  // little endian
400         ch->read_state = MSB;
401     } else {
402         *val = ((char*)myval)[1];
403         ch->read_state = LSB;
404         if (ch->latch_state == LATCHED) { 
405             ch->latch_state = NOTLATCHED;
406         }
407     }
408
409     return 0;
410
411 }
412
413 static int handle_speaker_read(uint8_t *speaker, struct channel * ch, char * val) {
414     *val = *speaker;
415
416     if ((*speaker & PIT_SPEAKER_GATE)) {
417         *val |= (ch->output_pin << 5);
418     }
419     
420     return 0;
421 }
422
423 static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) {
424     *speaker = (val & ~0x20);
425     return 0;
426 }
427
428 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
429     ch->op_mode = cmd.op_mode;
430     ch->access_mode = cmd.access_mode;
431
432
433
434
435     switch (cmd.access_mode) {
436         case LATCH_COUNT:
437             if (ch->latch_state == NOTLATCHED) { 
438                 ch->latched_value = ch->counter;
439                 ch->latch_state = LATCHED;
440             }
441             break;
442         case HIBYTE_ONLY:
443             ch->access_state = WAITING_HIBYTE;
444             break;
445         case LOBYTE_ONLY: 
446         case LOBYTE_HIBYTE:
447             ch->access_state = WAITING_LOBYTE;
448             break;
449     }
450
451
452     switch (cmd.op_mode) {
453         case IRQ_ON_TERM_CNT:
454             ch->output_pin = 0;
455             break;
456         case ONE_SHOT: 
457             ch->output_pin = 1;
458             break;
459         case RATE_GEN: 
460             ch->output_pin = 1;
461             break;
462         case SQR_WAVE:
463             ch->output_pin = 1;
464             break;
465         case SW_STROBE:
466             ch->output_pin = 1;
467             break;
468         default:
469             PrintError("Invalid OP_MODE: %d\n", cmd.op_mode);
470             return -1;
471     }
472
473     return 0;
474     
475 }
476
477
478
479
480 static int pit_read_channel(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
481     struct vm_device * dev = (struct vm_device *)priv_data;
482     struct pit * state = (struct pit *)dev->private_data;
483     char * val = (char *)dst;
484
485     if (length != 1) {
486         PrintError("8254 PIT: Invalid Read Write length \n");
487         return -1;
488     }
489
490     PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
491
492     switch (port) {
493         case CHANNEL0_PORT: 
494             if (handle_channel_read(&(state->ch_0), val) == -1) {
495                 PrintError("CHANNEL0 read error\n");
496                 return -1;
497             }
498             break;
499         case CHANNEL1_PORT:
500             if (handle_channel_read(&(state->ch_1), val) == -1) {
501                 PrintError("CHANNEL1 read error\n");
502                 return -1;
503             }
504             break;
505         case CHANNEL2_PORT:
506             if (handle_channel_read(&(state->ch_2), val) == -1) {
507                 PrintError("CHANNEL2 read error\n");
508                 return -1;
509             }
510             break;
511         case SPEAKER_PORT:
512             if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) {
513                 PrintError("SPEAKER read error\n");
514                 return -1;
515             }
516             break;
517         default:
518             PrintError("8254 PIT: Read from invalid port (%d)\n", port);
519             return -1;
520     }
521
522     return length;
523 }
524
525
526
527 static int pit_write_channel(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
528     struct vm_device * dev = (struct vm_device *)priv_data;
529     struct pit * state = (struct pit *)dev->private_data;
530     char val = *(char *)src;
531
532     if (length != 1) {
533         PrintError("8254 PIT: Invalid Write Length\n");
534         return -1;
535     }
536
537     PrintDebug("8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src);
538
539
540     switch (port) {
541         case CHANNEL0_PORT:
542             if (handle_channel_write(&(state->ch_0), val) == -1) {
543                 PrintError("CHANNEL0 write error\n");
544                 return -1;
545             } 
546             break;
547         case CHANNEL1_PORT:
548             if (handle_channel_write(&(state->ch_1), val) == -1) {
549                 PrintError("CHANNEL1 write error\n");
550                 return -1;
551             }
552             break;
553         case CHANNEL2_PORT:
554             if (handle_channel_write(&(state->ch_2), val) == -1) {
555                 PrintError("CHANNEL2 write error\n");   
556                 return -1;
557             }
558             break;
559         case SPEAKER_PORT:
560             if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) {
561                 PrintError("SPEAKER write error\n");
562                 return -1;
563             }
564             break;
565         default:
566             PrintError("8254 PIT: Write to invalid port (%d)\n", port);
567             return -1;
568     }
569
570     return length;
571 }
572
573
574
575
576 static int pit_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
577     struct vm_device * dev = (struct vm_device *)priv_data;
578     struct pit * state = (struct pit *)dev->private_data;
579     struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
580
581     PrintDebug("8254 PIT: Write to PIT Command port\n");
582     PrintDebug("8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
583     if (length != 1) {
584         PrintError("8254 PIT: Write of Invalid length to command port\n");
585         return -1;
586     }
587
588     switch (cmd->channel) {
589         case 0:
590             if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
591                 PrintError("CHANNEL0 command error\n");
592                 return -1;
593             }
594             break;
595         case 1:
596             if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
597                 PrintError("CHANNEL1 command error\n");
598                 return -1;
599             }
600             break;
601         case 2:
602             if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
603                 PrintError("CHANNEL2 command error\n");
604                 return -1;
605             }
606             break;
607         case 3:
608             // Read Back command
609             PrintError("Read back command not implemented\n");
610             return -1;
611             break;
612         default:
613             break;
614     }
615
616
617     return length;
618 }
619
620
621
622
623 static struct v3_timer_ops timer_ops = {
624     .update_timer = pit_update_timer,
625 };
626
627
628 static void init_channel(struct channel * ch) {
629     ch->run_state = NOT_RUNNING;
630     ch->access_state = NOT_WAITING;
631     ch->access_mode = 0;
632     ch->op_mode = 0;
633
634     ch->counter = 0;
635     ch->reload_value = 0;
636     ch->output_pin = 0;
637     ch->gate_input_pin = 0;
638
639     ch->latched_value = 0;
640     ch->latch_state = NOTLATCHED;
641     ch->read_state = LSB;
642
643     return;
644 }
645
646
647
648
649 static int pit_free(struct vm_device * dev) {
650     struct pit * state = (struct pit *)dev->private_data;
651     struct guest_info * info = &(dev->vm->cores[0]);
652
653
654     if (state->timer) {
655         v3_remove_timer(info, state->timer);
656     }
657
658     v3_unhook_io_port(dev->vm, CHANNEL0_PORT);
659     v3_unhook_io_port(dev->vm, CHANNEL1_PORT);
660     v3_unhook_io_port(dev->vm, CHANNEL2_PORT);
661     v3_unhook_io_port(dev->vm, COMMAND_PORT);
662     v3_unhook_io_port(dev->vm, SPEAKER_PORT);
663     
664     V3_Free(state);
665     return 0;
666 }
667
668
669 static struct v3_device_ops dev_ops = {
670     .free = pit_free,
671     .reset = NULL,
672     .start = NULL,
673     .stop = NULL,
674
675 };
676
677 #include <palacios/vm_guest.h>
678
679 static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
680     struct pit * pit_state = NULL;
681     struct vm_device * dev = NULL;
682     char * dev_id = v3_cfg_val(cfg, "ID");
683     int ret = 0;
684
685     // PIT is only usable in non-multicore environments
686     // just hardcode the core context
687     struct guest_info * info = &(vm->cores[0]);
688
689     uint_t cpu_khz = V3_CPU_KHZ();
690     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
691
692     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
693     V3_ASSERT(pit_state != NULL);
694     pit_state->speaker = 0;
695
696     dev = v3_allocate_device(dev_id, &dev_ops, pit_state);
697
698     if (v3_attach_device(vm, dev) == -1) {
699         PrintError("Could not attach device %s\n", dev_id);
700         V3_Free(pit_state);
701         return -1;
702     }
703
704     ret |= v3_hook_io_port(vm, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel, dev);
705     ret |= v3_hook_io_port(vm, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel, dev);
706     ret |= v3_hook_io_port(vm, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel, dev);
707     ret |= v3_hook_io_port(vm, COMMAND_PORT, NULL, &pit_write_command, dev);
708     ret |= v3_hook_io_port(vm, SPEAKER_PORT, &pit_read_channel, &pit_write_channel, dev);
709
710     if (ret != 0) {
711         PrintError("8254 PIT: Failed to hook IO ports\n");
712         v3_detach_device(dev);
713         return -1;
714     }
715
716 #ifdef CONFIG_DEBUG_PIT
717     PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
718     //PrintTrace(reload_val);
719     PrintDebug("\n");
720 #endif
721
722     
723
724     pit_state->timer = v3_add_timer(info, &timer_ops, dev);
725
726     if (pit_state->timer == NULL) {
727         v3_detach_device(dev);
728         return -1;
729     }
730
731     // Get cpu frequency and calculate the global pit oscilattor counter/cycle
732
733     do_divll(reload_val, OSC_HZ);
734     pit_state->pit_counter = reload_val;
735     pit_state->pit_reload = reload_val;
736
737
738     init_channel(&(pit_state->ch_0));
739     init_channel(&(pit_state->ch_1));
740     init_channel(&(pit_state->ch_2));
741
742 #ifdef CONFIG_DEBUG_PIT
743     PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
744     //PrintTraceLL(pit_state->pit_counter);
745     PrintDebug("\n");
746 #endif
747
748     return 0;
749 }
750
751
752 device_register("8254_PIT", pit_init);