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 software strobe
[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         if (ch->op_mode == SW_STROBE) {
158             reload_val = 0xffff;
159         }
160
161         // TODO: Check this....
162         // Is this correct???
163         if (reload_val == 0) {
164             reload_val = 1;
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         channel_cycles += oscillations / reload_val;
176         oscillations = oscillations % reload_val;
177
178         ch->counter = reload_val - oscillations;
179     }
180
181     //  PrintDebug("8254 PIT: Channel Cycles: %d\n", channel_cycles);
182   
183
184
185     switch (ch->op_mode) {
186         case IRQ_ON_TERM_CNT:
187             if ((channel_cycles > 0) && (ch->output_pin == 0)) {
188                 ch->output_pin = 1; 
189                 output_changed = 1;
190             }
191             break;
192         case ONE_SHOT:
193             if ((channel_cycles > 0) && (ch->output_pin == 0)) {
194                 ch->output_pin = 1; 
195                 output_changed = 1;
196             }
197             break;
198         case RATE_GEN:
199             // See the data sheet: we ignore the output pin cycle...
200             if (channel_cycles > 0) {
201                 output_changed = 1;
202             }
203             break;
204         case SQR_WAVE:
205             ch->output_pin = (ch->output_pin + 1) % 2;
206
207             if (ch->output_pin == 1) {
208                 output_changed = 1;
209             }
210
211             break;
212         case SW_STROBE:
213
214             if (channel_cycles > 0) {
215                 if (ch->output_pin == 1) {
216                     ch->output_pin = 0;
217                     output_changed = 1;
218                 }
219             }
220             break;
221         case HW_STROBE:
222             PrintError("Hardware strobe not implemented\n");
223             return -1;
224             break;
225         default:
226             break;
227     }
228
229     return output_changed;
230 }
231                                 
232
233
234 static void pit_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
235     struct vm_device * dev = (struct vm_device *)private_data;
236     struct pit * state = (struct pit *)dev->private_data;
237     //  ullong_t tmp_ctr = state->pit_counter;
238     ullong_t tmp_cycles;
239     uint_t oscillations = 0;
240
241
242     /*
243       PrintDebug("updating cpu_cycles=");
244       PrintTraceLL(cpu_cycles);
245       PrintDebug("\n");
246     
247       PrintDebug("pit_counter=");
248       PrintTraceLL(state->pit_counter);
249       PrintDebug("\n");
250     
251       PrintDebug("pit_reload=");
252       PrintTraceLL(state->pit_reload);
253       PrintDebug("\n");
254     */
255
256     if (state->pit_counter > cpu_cycles) {
257         // Easy...
258         state->pit_counter -= cpu_cycles;
259     } else {
260         ushort_t reload_val = state->pit_reload;
261         // Take off the first part
262         cpu_cycles -= state->pit_counter;
263         state->pit_counter = 0;
264         oscillations = 1;
265     
266         if (cpu_cycles > state->pit_reload) {
267             // how many full oscillations
268       
269             //PrintError("cpu_cycles = %p, reload = %p...\n", 
270             //   (void *)(addr_t)cpu_cycles, 
271             //   (void *)(addr_t)state->pit_reload);
272
273             // How do we check for a one shot....
274             if (state->pit_reload == 0) {
275                 reload_val = 1;
276             }
277
278             tmp_cycles = cpu_cycles;
279
280       
281 #ifdef __V3_64BIT__
282             cpu_cycles = tmp_cycles % state->pit_reload;
283             tmp_cycles = tmp_cycles / state->pit_reload;
284 #else
285             cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
286 #endif
287         
288             oscillations += tmp_cycles;
289         }
290
291         // update counter with remainder (mod reload)
292         state->pit_counter = state->pit_reload - cpu_cycles;    
293
294         //PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
295         if (handle_crystal_tics(dev, &(state->ch_0), oscillations) == 1) {
296             // raise interrupt
297             PrintDebug("8254 PIT: Injecting Timer interrupt to guest\n");
298             v3_raise_irq(dev->vm, 0);
299         }
300
301         //handle_crystal_tics(dev, &(state->ch_1), oscillations);
302         //handle_crystal_tics(dev, &(state->ch_2), oscillations);
303     }
304   
305
306
307  
308     return;
309 }
310
311
312
313 /* This should call out to handle_SQR_WAVE_write, etc...
314  */
315 static int handle_channel_write(struct channel * ch, char val) {
316
317     switch (ch->access_state) {      
318         case WAITING_HIBYTE:
319             {
320                 ushort_t tmp_val = ((ushort_t)val) << 8;
321                 ch->reload_value &= 0x00ff;
322                 ch->reload_value |= tmp_val;
323         
324
325                 if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
326                     ch->run_state = PENDING;  
327                 }
328         
329                 if (ch->access_mode == LOBYTE_HIBYTE) {
330                     ch->access_state = WAITING_LOBYTE;
331                 }
332
333                 PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);        
334                 PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
335                 break;
336             }
337         case WAITING_LOBYTE:
338             ch->reload_value &= 0xff00;
339             ch->reload_value |= val;
340       
341             if (ch->access_mode == LOBYTE_HIBYTE) {
342                 ch->access_state = WAITING_HIBYTE;
343             } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
344                 ch->run_state = PENDING;
345             }
346       
347             PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);
348             PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
349             break;
350         default:
351             PrintError("Invalid Access state\n");
352             return -1;
353     }
354     
355
356     switch (ch->op_mode) {
357         case IRQ_ON_TERM_CNT:
358             ch->output_pin = 0;
359             break;
360         case ONE_SHOT:
361             ch->output_pin = 1;
362             break;
363         case RATE_GEN:
364             ch->output_pin = 1;
365             break;
366         case SQR_WAVE:
367             ch->output_pin = 1;
368             break;
369         case SW_STROBE:
370             ch->output_pin = 1;
371             break;
372         default:
373             PrintError("Invalid OP_MODE: %d\n", ch->op_mode);
374             return -1;
375             break;
376     }
377
378
379     return 0;
380 }
381
382
383 static int handle_channel_read(struct channel * ch, char * val) {
384
385     ushort_t * myval;
386
387     if (ch->latch_state == NOTLATCHED) { 
388         myval = &(ch->counter);
389     } else {
390         myval = &(ch->latched_value);
391     }
392
393     if (ch->read_state == LSB) { 
394         *val = ((char*)myval)[0];  // little endian
395         ch->read_state = MSB;
396     } else {
397         *val = ((char*)myval)[1];
398         ch->read_state = LSB;
399         if (ch->latch_state == LATCHED) { 
400             ch->latch_state = NOTLATCHED;
401         }
402     }
403
404     return 0;
405
406 }
407
408
409
410
411
412 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
413     ch->op_mode = cmd.op_mode;
414     ch->access_mode = cmd.access_mode;
415
416
417
418
419     switch (cmd.access_mode) {
420         case LATCH_COUNT:
421             if (ch->latch_state == NOTLATCHED) { 
422                 ch->latched_value = ch->counter;
423                 ch->latch_state = LATCHED;
424             }
425             break;
426         case HIBYTE_ONLY:
427             ch->access_state = WAITING_HIBYTE;
428             break;
429         case LOBYTE_ONLY: 
430         case LOBYTE_HIBYTE:
431             ch->access_state = WAITING_LOBYTE;
432             break;
433     }
434
435
436     switch (cmd.op_mode) {
437         case IRQ_ON_TERM_CNT:
438             ch->output_pin = 0;
439             break;
440         case ONE_SHOT: 
441             ch->output_pin = 1;
442             break;
443         case RATE_GEN: 
444             ch->output_pin = 1;
445             break;
446         case SQR_WAVE:
447             ch->output_pin = 1;
448             break;
449         case SW_STROBE:
450             ch->output_pin = 1;
451             break;
452         default:
453             PrintError("Invalid OP_MODE: %d\n", cmd.op_mode);
454             return -1;
455     }
456
457     return 0;
458     
459 }
460
461
462
463
464 static int pit_read_channel(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
465     struct pit * state = (struct pit *)dev->private_data;
466     char * val = (char *)dst;
467
468     if (length != 1) {
469         PrintError("8254 PIT: Invalid Read Write length \n");
470         return -1;
471     }
472
473     PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
474
475     switch (port) {
476         case CHANNEL0_PORT: 
477             if (handle_channel_read(&(state->ch_0), val) == -1) {
478                 PrintError("CHANNEL0 read error\n");
479                 return -1;
480             }
481             break;
482         case CHANNEL1_PORT:
483             if (handle_channel_read(&(state->ch_1), val) == -1) {
484                 PrintError("CHANNEL1 read error\n");
485                 return -1;
486             }
487             break;
488         case CHANNEL2_PORT:
489             if (handle_channel_read(&(state->ch_2), val) == -1) {
490                 PrintError("CHANNEL2 read error\n");
491                 return -1;
492             }
493             break;
494         default:
495             PrintError("8254 PIT: Read from invalid port (%d)\n", port);
496             return -1;
497     }
498
499     return length;
500 }
501
502
503
504 static int pit_write_channel(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
505     struct pit * state = (struct pit *)dev->private_data;
506     char val = *(char *)src;
507
508     if (length != 1) {
509         PrintError("8254 PIT: Invalid Write Length\n");
510         return -1;
511     }
512
513     PrintDebug("8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src);
514
515
516     switch (port) {
517         case CHANNEL0_PORT:
518             if (handle_channel_write(&(state->ch_0), val) == -1) {
519                 PrintError("CHANNEL0 write error\n");
520                 return -1;
521             } 
522             break;
523         case CHANNEL1_PORT:
524             if (handle_channel_write(&(state->ch_1), val) == -1) {
525                 PrintError("CHANNEL1 write error\n");
526                 return -1;
527             }
528             break;
529         case CHANNEL2_PORT:
530             if (handle_channel_write(&(state->ch_2), val) == -1) {
531                 PrintError("CHANNEL2 write error\n");   
532                 return -1;
533             }
534             break;
535         default:
536             PrintError("8254 PIT: Write to invalid port (%d)\n", port);
537             return -1;
538     }
539
540     return length;
541 }
542
543
544
545
546 static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
547     struct pit * state = (struct pit *)dev->private_data;
548     struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
549
550     PrintDebug("8254 PIT: Write to PIT Command port\n");
551     PrintDebug("8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
552     if (length != 1) {
553         PrintError("8254 PIT: Write of Invalid length to command port\n");
554         return -1;
555     }
556
557     switch (cmd->channel) {
558         case 0:
559             if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
560                 PrintError("CHANNEL0 command error\n");
561                 return -1;
562             }
563             break;
564         case 1:
565             if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
566                 PrintError("CHANNEL1 command error\n");
567                 return -1;
568             }
569             break;
570         case 2:
571             if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
572                 PrintError("CHANNEL2 command error\n");
573                 return -1;
574             }
575             break;
576         case 3:
577             // Read Back command
578             PrintError("Read back command not implemented\n");
579             return -1;
580             break;
581         default:
582             break;
583     }
584
585
586     return length;
587 }
588
589
590
591
592 static struct vm_timer_ops timer_ops = {
593     .update_time = pit_update_time,
594 };
595
596
597 static void init_channel(struct channel * ch) {
598     ch->run_state = NOT_RUNNING;
599     ch->access_state = NOT_WAITING;
600     ch->access_mode = 0;
601     ch->op_mode = 0;
602
603     ch->counter = 0;
604     ch->reload_value = 0;
605     ch->output_pin = 0;
606     ch->gate_input_pin = 0;
607
608     ch->latched_value = 0;
609     ch->latch_state = NOTLATCHED;
610     ch->read_state = LSB;
611
612     return;
613 }
614
615
616 static int pit_init(struct vm_device * dev) {
617     struct pit * state = (struct pit *)dev->private_data;
618     uint_t cpu_khz = V3_CPU_KHZ();
619     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
620
621     v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
622     v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
623     v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
624     v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
625
626 #ifdef DEBUG_PIT
627     PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
628     PrintTraceLL(reload_val);
629     PrintDebug("\n");
630 #endif
631
632     v3_add_timer(dev->vm, &timer_ops, dev);
633
634     // Get cpu frequency and calculate the global pit oscilattor counter/cycle
635
636     do_divll(reload_val, OSC_HZ);
637     state->pit_counter = reload_val;
638     state->pit_reload = reload_val;
639
640
641
642     init_channel(&(state->ch_0));
643     init_channel(&(state->ch_1));
644     init_channel(&(state->ch_2));
645
646 #ifdef DEBUG_PIT
647     PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
648     PrintTraceLL(state->pit_counter);
649     PrintDebug("\n");
650 #endif
651
652     return 0;
653 }
654
655 static int pit_deinit(struct vm_device * dev) {
656
657     return 0;
658 }
659
660
661 static struct vm_device_ops dev_ops = {
662     .init = pit_init,
663     .deinit = pit_deinit,
664     .reset = NULL,
665     .start = NULL,
666     .stop = NULL,
667
668 };
669
670
671 struct vm_device * v3_create_pit() {
672     struct pit * pit_state = NULL;
673     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
674     V3_ASSERT(pit_state != NULL);
675
676     struct vm_device * dev = v3_create_device("PIT", &dev_ops, pit_state);
677   
678     return dev;
679 }