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.


Handle 8254 PIT reload count of 0 correctly (means 65536)
[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("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("8254 PIT: Channel Run State = %d, counter=", ch->run_state);
153       PrintTraceLL(ch->counter);
154       PrintDebug("\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("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("8254 PIT: Counter reset to %u.\n", 
192         //   (unsigned int)ch->counter);
193
194     }
195
196     //PrintDebug("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("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("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("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("updating cpu_cycles=");
267       PrintTraceLL(cpu_cycles);
268       PrintDebug("\n");
269     
270       PrintDebug("pit_counter=");
271       PrintTraceLL(state->pit_counter);
272       PrintDebug("\n");
273     
274       PrintDebug("pit_reload=");
275       PrintTraceLL(state->pit_reload);
276       PrintDebug("\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("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("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("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("8254 PIT: updated channel counter: %d\n", ch->reload_value);        
356                 PrintDebug("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("8254 PIT: updated channel counter: %d\n", ch->reload_value);
370             PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
371             break;
372         default:
373             PrintError("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("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("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("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("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("8254 PIT: Invalid Read Write length \n");
513         return -1;
514     }
515
516     PrintDebug("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("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("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("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("SPEAKER read error\n");
540                 return -1;
541             }
542             break;
543         default:
544             PrintError("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("8254 PIT: Invalid Write Length\n");
559         return -1;
560     }
561
562     PrintDebug("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("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("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("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("SPEAKER write error\n");
587                 return -1;
588             }
589             break;
590         default:
591             PrintError("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("8254 PIT: Write to PIT Command port\n");
606     PrintDebug("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("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("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("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("CHANNEL2 command error\n");
628                 return -1;
629             }
630             break;
631         case 3:
632             // Read Back command
633             PrintError("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 static int pit_save(struct v3_chkpt_ctx * ctx, void * private_data) {
688     struct pit * pit_state = (struct pit *)private_data; 
689
690     V3_CHKPT_STD_SAVE(ctx, pit_state->pit_counter);
691     V3_CHKPT_STD_SAVE(ctx, pit_state->pit_reload);
692     V3_CHKPT_STD_SAVE(ctx, pit_state->ch_0);
693     V3_CHKPT_STD_SAVE(ctx, pit_state->ch_1);
694     V3_CHKPT_STD_SAVE(ctx, pit_state->ch_2);
695     V3_CHKPT_STD_SAVE(ctx, pit_state->speaker);
696     
697     return 0;
698 }
699
700 static int pit_load(struct v3_chkpt_ctx * ctx, void * private_data) {
701     struct pit * pit_state = (struct pit *)private_data;
702
703     V3_CHKPT_STD_LOAD(ctx, pit_state->pit_counter);
704     V3_CHKPT_STD_LOAD(ctx, pit_state->pit_reload);
705     V3_CHKPT_STD_LOAD(ctx, pit_state->ch_0);
706     V3_CHKPT_STD_LOAD(ctx, pit_state->ch_1);
707     V3_CHKPT_STD_LOAD(ctx, pit_state->ch_2);
708     V3_CHKPT_STD_LOAD(ctx, pit_state->speaker);
709
710     return 0;
711 }
712 #endif
713
714 static struct v3_device_ops dev_ops = {
715     .free = (int (*)(void *))pit_free,
716 #ifdef V3_CONFIG_CHECKPOINT
717     .save = pit_save,
718     .load = pit_load,
719 #endif
720 };
721
722 #include <palacios/vm_guest.h>
723
724 static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
725     struct pit * pit_state = NULL;
726     struct vm_device * dev = NULL;
727     char * dev_id = v3_cfg_val(cfg, "ID");
728     int ret = 0;
729
730     // PIT is only usable in non-multicore environments
731     // just hardcode the core context
732     struct guest_info * info = &(vm->cores[0]);
733
734     uint_t cpu_khz = info->time_state.guest_cpu_freq;
735     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
736
737     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
738
739     V3_ASSERT(pit_state != NULL);
740     pit_state->speaker = 0;
741     pit_state->vm = vm;
742
743     dev = v3_add_device(vm, dev_id, &dev_ops, pit_state);
744
745     if (dev == NULL) {
746         PrintError("Could not attach device %s\n", dev_id);
747         V3_Free(pit_state);
748         return -1;
749     }
750
751     ret |= v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
752     ret |= v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
753     ret |= v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
754     ret |= v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
755     ret |= v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
756
757     if (ret != 0) {
758         PrintError("8254 PIT: Failed to hook IO ports\n");
759         v3_remove_device(dev);
760         return -1;
761     }
762
763 #ifdef V3_CONFIG_DEBUG_PIT
764     PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
765     //PrintTrace(reload_val);
766     PrintDebug("\n");
767 #endif
768
769     
770
771     pit_state->timer = v3_add_timer(info, &timer_ops, pit_state);
772
773     if (pit_state->timer == NULL) {
774         v3_remove_device(dev);
775         return -1;
776     }
777
778     // Get cpu frequency and calculate the global pit oscilattor counter/cycle
779
780     do_divll(reload_val, OSC_HZ);
781     pit_state->pit_counter = reload_val;
782     pit_state->pit_reload = reload_val;
783
784
785     init_channel(&(pit_state->ch_0));
786     init_channel(&(pit_state->ch_1));
787     init_channel(&(pit_state->ch_2));
788
789 #ifdef V3_CONFIG_DEBUG_PIT
790     PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
791     //PrintTraceLL(pit_state->pit_counter);
792     PrintDebug("\n");
793 #endif
794
795     return 0;
796 }
797
798
799 device_register("8254_PIT", pit_init);