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.


9a9ee99a6ff7274d6d2ec36e4f7ce63934be8181
[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         // TODO: Check this....
181         // Is this correct???
182         if (reload_val == 0) {
183             reload_val = 1;
184         }
185
186         channel_cycles += oscillations / reload_val;
187         oscillations = oscillations % reload_val;
188
189         ch->counter = reload_val - oscillations;
190         //      PrintDebug("8254 PIT: Counter reset to %u.\n", 
191         //   (unsigned int)ch->counter);
192
193     }
194
195     //PrintDebug("8254 PIT: Channel %ld (mode = %u) Cycles: %d\n", 
196                //(ch - &pit->ch_0), ch->op_mode, channel_cycles);
197   
198     switch (ch->op_mode) {
199         case IRQ_ON_TERM_CNT:
200             if (channel_cycles > 0) {
201                 if (ch->output_pin == 0) {
202                     ch->output_pin = 1; 
203                     output_changed = 1;
204                 } else {
205                    // PrintDebug("8254: Output not changed in TERM_CNT mode.\n");
206                 }
207             }
208             break;
209         case ONE_SHOT:
210             if (channel_cycles > 0) {
211                 if ((ch->output_pin == 0)) {
212                     ch->output_pin = 1; 
213                     output_changed = 1;
214                 } else {
215                     // PrintDebug("8254: Output not changed in ONE_SHOT mode.\n");
216                 }
217             }
218             break;
219         case RATE_GEN:
220             // See the data sheet: we ignore the output pin cycle...
221             if (channel_cycles > 0) {
222                 output_changed = 1;
223             }
224             break;
225         case SQR_WAVE:
226             ch->output_pin = (ch->output_pin + 1) % 2;
227
228             if (ch->output_pin == 1) {
229                 output_changed = 1;
230             }
231
232
233             break;
234         case SW_STROBE:
235
236             if (channel_cycles > 0) {
237                 if (ch->output_pin == 1) {
238                     ch->output_pin = 0;
239                     output_changed = 1;
240                 }
241             }
242             break;
243         case HW_STROBE:
244             PrintError("Hardware strobe not implemented\n");
245             return -1;
246             break;
247         default:
248             break;
249     }
250
251     return output_changed;
252 }
253                                 
254
255 #include <palacios/vm_guest.h>
256
257 static void pit_update_timer(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
258     struct pit * state = (struct pit *)private_data;
259     //  ullong_t tmp_ctr = state->pit_counter;
260     ullong_t tmp_cycles;
261     uint_t oscillations = 0;
262
263
264     /*
265       PrintDebug("updating cpu_cycles=");
266       PrintTraceLL(cpu_cycles);
267       PrintDebug("\n");
268     
269       PrintDebug("pit_counter=");
270       PrintTraceLL(state->pit_counter);
271       PrintDebug("\n");
272     
273       PrintDebug("pit_reload=");
274       PrintTraceLL(state->pit_reload);
275       PrintDebug("\n");
276     */
277
278     if (state->pit_counter > cpu_cycles) {
279         // Easy...
280         state->pit_counter -= cpu_cycles;
281     } else {
282         ushort_t reload_val = state->pit_reload;
283         // Take off the first part
284         cpu_cycles -= state->pit_counter;
285         state->pit_counter = 0;
286         oscillations = 1;
287     
288         if (cpu_cycles > state->pit_reload) {
289             // how many full oscillations
290       
291             //PrintError("cpu_cycles = %p, reload = %p...\n", 
292             //   (void *)(addr_t)cpu_cycles, 
293             //   (void *)(addr_t)state->pit_reload);
294
295             // How do we check for a one shot....
296             if (state->pit_reload == 0) {
297                 reload_val = 1;
298             }
299
300             tmp_cycles = cpu_cycles;
301
302       
303 #ifdef __V3_64BIT__
304             cpu_cycles = tmp_cycles % state->pit_reload;
305             tmp_cycles = tmp_cycles / state->pit_reload;
306 #else
307             cpu_cycles = do_divll(tmp_cycles, state->pit_reload);
308 #endif
309         
310             oscillations += tmp_cycles;
311         }
312
313         // update counter with remainder (mod reload)
314         state->pit_counter = state->pit_reload - cpu_cycles;    
315
316         if (oscillations) {
317             //    PrintDebug("8254 PIT: Handling %d crystal tics\n", oscillations);
318
319             if (handle_crystal_tics(state, &(state->ch_0), oscillations) == 1) {
320                 // raise interrupt
321                 PrintDebug("8254 PIT: Injecting Timer interrupt to guest (run_state = %d)\n",
322                            state->ch_0.run_state);
323                 v3_raise_irq(info->vm_info, 0);
324             }
325
326             //handle_crystal_tics(state, &(state->ch_1), oscillations);
327             handle_crystal_tics(state, &(state->ch_2), oscillations);
328         }
329     }
330  
331     return;
332 }
333
334 /* This should call out to handle_SQR_WAVE_write, etc...
335  */
336 static int handle_channel_write(struct channel * ch, char val) {
337
338     switch (ch->access_state) {      
339         case WAITING_HIBYTE:
340             {
341                 ushort_t tmp_val = ((ushort_t)val) << 8;
342                 ch->reload_value &= 0x00ff;
343                 ch->reload_value |= tmp_val;
344         
345
346                 if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)){
347                     ch->run_state = PENDING;  
348                 }
349         
350                 if (ch->access_mode == LOBYTE_HIBYTE) {
351                     ch->access_state = WAITING_LOBYTE;
352                 }
353
354                 PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);        
355                 PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
356                 break;
357             }
358         case WAITING_LOBYTE:
359             ch->reload_value &= 0xff00;
360             ch->reload_value |= val;
361       
362             if (ch->access_mode == LOBYTE_HIBYTE) {
363                 ch->access_state = WAITING_HIBYTE;
364             } else if ((ch->op_mode != RATE_GEN) || (ch->run_state != RUNNING)) {
365                 ch->run_state = PENDING;
366             }
367       
368             PrintDebug("8254 PIT: updated channel counter: %d\n", ch->reload_value);
369             PrintDebug("8254 PIT: Channel Run State=%d\n", ch->run_state);
370             break;
371         default:
372             PrintError("Invalid Access state\n");
373             return -1;
374     }
375     
376
377     switch (ch->op_mode) {
378         case IRQ_ON_TERM_CNT:
379             ch->output_pin = 0;
380             break;
381         case ONE_SHOT:
382             ch->output_pin = 1;
383             break;
384         case RATE_GEN:
385             ch->output_pin = 1;
386             break;
387         case SQR_WAVE:
388             ch->output_pin = 1;
389             break;
390         case SW_STROBE:
391             ch->output_pin = 1;
392             break;
393         default:
394             PrintError("Invalid OP_MODE: %d\n", ch->op_mode);
395             return -1;
396             break;
397     }
398
399
400     return 0;
401 }
402
403
404 static int handle_channel_read(struct channel * ch, char * val) {
405
406     ushort_t * myval;
407
408     if (ch->latch_state == NOTLATCHED) { 
409         myval = &(ch->counter);
410     } else {
411         myval = &(ch->latched_value);
412     }
413
414     if (ch->read_state == LSB) { 
415         *val = ((char*)myval)[0];  // little endian
416         ch->read_state = MSB;
417     } else {
418         *val = ((char*)myval)[1];
419         ch->read_state = LSB;
420         if (ch->latch_state == LATCHED) { 
421             ch->latch_state = NOTLATCHED;
422         }
423     }
424
425     return 0;
426
427 }
428
429 static int handle_speaker_read(uint8_t *speaker, struct channel * ch, char * val) {
430     *val = *speaker;
431
432     if ((*speaker & PIT_SPEAKER_GATE)) {
433         *val |= (ch->output_pin << 5);
434     }
435     
436     return 0;
437 }
438
439 static int handle_speaker_write(uint8_t *speaker, struct channel * ch, char val) {
440     *speaker = (val & ~0x20);
441     return 0;
442 }
443
444 static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
445
446     if (cmd.op_mode != ch->op_mode) {
447         PrintDebug("8254 PIT: Changing channel from op mode %d to op mode %d.\n", 
448                    ch->op_mode, cmd.op_mode);
449     }
450
451     if (cmd.access_mode != 0) {
452       ch->op_mode = cmd.op_mode;
453     }
454
455     if (cmd.access_mode != ch->access_mode) {
456         PrintDebug("8254 PIT: Changing channel from access mode %d to access mode %d.\n", 
457                    ch->access_mode, cmd.access_mode);
458     }
459     ch->access_mode = cmd.access_mode;
460
461     switch (cmd.access_mode) {
462         case LATCH_COUNT:
463             if (ch->latch_state == NOTLATCHED) { 
464                 ch->latched_value = ch->counter;
465                 ch->latch_state = LATCHED;
466             }
467             break;
468         case HIBYTE_ONLY:
469             ch->access_state = WAITING_HIBYTE;
470             break;
471         case LOBYTE_ONLY: 
472         case LOBYTE_HIBYTE:
473             ch->access_state = WAITING_LOBYTE;
474             break;
475     }
476
477
478     switch (cmd.op_mode) {
479         case IRQ_ON_TERM_CNT:
480             ch->output_pin = 0;
481             break;
482         case ONE_SHOT: 
483             ch->output_pin = 1;
484             break;
485         case RATE_GEN: 
486             ch->output_pin = 1;
487             break;
488         case SQR_WAVE:
489             ch->output_pin = 1;
490             break;
491         case SW_STROBE:
492             ch->output_pin = 1;
493             break;
494         default:
495             PrintError("Invalid OP_MODE: %d\n", cmd.op_mode);
496             return -1;
497     }
498
499     return 0;
500     
501 }
502
503
504
505
506 static int pit_read_channel(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) {
507     struct pit * state = (struct pit *)priv_data;
508     char * val = (char *)dst;
509
510     if (length != 1) {
511         PrintError("8254 PIT: Invalid Read Write length \n");
512         return -1;
513     }
514
515     PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
516
517     switch (port) {
518         case CHANNEL0_PORT: 
519             if (handle_channel_read(&(state->ch_0), val) == -1) {
520                 PrintError("CHANNEL0 read error\n");
521                 return -1;
522             }
523             break;
524         case CHANNEL1_PORT:
525             if (handle_channel_read(&(state->ch_1), val) == -1) {
526                 PrintError("CHANNEL1 read error\n");
527                 return -1;
528             }
529             break;
530         case CHANNEL2_PORT:
531             if (handle_channel_read(&(state->ch_2), val) == -1) {
532                 PrintError("CHANNEL2 read error\n");
533                 return -1;
534             }
535             break;
536         case SPEAKER_PORT:
537             if (handle_speaker_read(&state->speaker, &(state->ch_2), val) == -1) {
538                 PrintError("SPEAKER read error\n");
539                 return -1;
540             }
541             break;
542         default:
543             PrintError("8254 PIT: Read from invalid port (%d)\n", port);
544             return -1;
545     }
546
547     return length;
548 }
549
550
551
552 static int pit_write_channel(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
553     struct pit * state = (struct pit *)priv_data;
554     char val = *(char *)src;
555
556     if (length != 1) {
557         PrintError("8254 PIT: Invalid Write Length\n");
558         return -1;
559     }
560
561     PrintDebug("8254 PIT: Write to PIT Channel %d (%x)\n", port - CHANNEL0_PORT, *(char*)src);
562
563
564     switch (port) {
565         case CHANNEL0_PORT:
566             if (handle_channel_write(&(state->ch_0), val) == -1) {
567                 PrintError("CHANNEL0 write error\n");
568                 return -1;
569             } 
570             break;
571         case CHANNEL1_PORT:
572             if (handle_channel_write(&(state->ch_1), val) == -1) {
573                 PrintError("CHANNEL1 write error\n");
574                 return -1;
575             }
576             break;
577         case CHANNEL2_PORT:
578             if (handle_channel_write(&(state->ch_2), val) == -1) {
579                 PrintError("CHANNEL2 write error\n");   
580                 return -1;
581             }
582             break;
583         case SPEAKER_PORT:
584             if (handle_speaker_write(&state->speaker, &(state->ch_2), val) == -1) {
585                 PrintError("SPEAKER write error\n");
586                 return -1;
587             }
588             break;
589         default:
590             PrintError("8254 PIT: Write to invalid port (%d)\n", port);
591             return -1;
592     }
593
594     return length;
595 }
596
597
598
599
600 static int pit_write_command(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
601     struct pit * state = (struct pit *)priv_data;
602     struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
603
604     PrintDebug("8254 PIT: Write to PIT Command port\n");
605     PrintDebug("8254 PIT: Writing to channel %d (access_mode = %d, op_mode = %d)\n", cmd->channel, cmd->access_mode, cmd->op_mode);
606     if (length != 1) {
607         PrintError("8254 PIT: Write of Invalid length to command port\n");
608         return -1;
609     }
610
611     switch (cmd->channel) {
612         case 0:
613             if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
614                 PrintError("CHANNEL0 command error\n");
615                 return -1;
616             }
617             break;
618         case 1:
619             if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
620                 PrintError("CHANNEL1 command error\n");
621                 return -1;
622             }
623             break;
624         case 2:
625             if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
626                 PrintError("CHANNEL2 command error\n");
627                 return -1;
628             }
629             break;
630         case 3:
631             // Read Back command
632             PrintError("Read back command not implemented\n");
633             return -1;
634             break;
635         default:
636             break;
637     }
638
639
640     return length;
641 }
642
643
644
645
646 static struct v3_timer_ops timer_ops = {
647     .update_timer = pit_update_timer,
648 };
649
650
651 static void init_channel(struct channel * ch) {
652     ch->run_state = NOT_RUNNING;
653     ch->access_state = NOT_WAITING;
654     ch->access_mode = 0;
655     ch->op_mode = 0;
656
657     ch->counter = 0;
658     ch->reload_value = 0;
659     ch->output_pin = 0;
660     ch->gate_input_pin = 0;
661
662     ch->latched_value = 0;
663     ch->latch_state = NOTLATCHED;
664     ch->read_state = LSB;
665
666     return;
667 }
668
669
670
671
672 static int pit_free(void * private_data) {
673     struct pit * state = (struct pit *)private_data;
674     struct guest_info * info = &(state->vm->cores[0]);
675
676
677     if (state->timer) {
678         v3_remove_timer(info, state->timer);
679     }
680  
681     V3_Free(state);
682     return 0;
683 }
684
685 #ifdef V3_CONFIG_KEYED_STREAMS
686 static int pit_checkpoint(struct vm_device *dev, v3_keyed_stream_t stream)
687 {
688     struct pit *p = (struct pit *) (dev->private_data);
689
690     v3_keyed_stream_key_t ks;
691
692     ks = v3_keyed_stream_open_key(stream,dev->name);
693
694     if (!ks) { 
695         return -1;
696     }
697
698     STD_SAVE(stream,ks,p->pit_counter);
699     STD_SAVE(stream,ks,p->pit_reload);
700     STD_SAVE(stream,ks,p->ch_0);
701     STD_SAVE(stream,ks,p->ch_1);
702     STD_SAVE(stream,ks,p->ch_2);
703     STD_SAVE(stream,ks,p->speaker);
704
705     v3_keyed_stream_close_key(stream,ks);
706     
707     return 0;
708
709
710 }
711
712 static int pit_restore(struct vm_device *dev, v3_keyed_stream_t stream)
713 {
714     struct pit *p = (struct pit *) (dev->private_data);
715
716     v3_keyed_stream_key_t ks;
717
718     ks = v3_keyed_stream_open_key(stream,dev->name);
719
720     if (!ks) { 
721         return -1;
722     }
723
724     STD_LOAD(stream,ks,p->pit_counter);
725     STD_LOAD(stream,ks,p->pit_reload);
726     STD_LOAD(stream,ks,p->ch_0);
727     STD_LOAD(stream,ks,p->ch_1);
728     STD_LOAD(stream,ks,p->ch_2);
729     STD_LOAD(stream,ks,p->speaker);
730
731     v3_keyed_stream_close_key(stream,ks);
732     
733     return 0;
734
735
736 }
737 #endif
738
739 static struct v3_device_ops dev_ops = {
740     .free = (int (*)(void *))pit_free,
741 #ifdef V3_CONFIG_KEYED_STREAMS
742     .checkpoint = pit_checkpoint,
743     .restore = pit_restore,
744 #endif
745 };
746
747 #include <palacios/vm_guest.h>
748
749 static int pit_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
750     struct pit * pit_state = NULL;
751     struct vm_device * dev = NULL;
752     char * dev_id = v3_cfg_val(cfg, "ID");
753     int ret = 0;
754
755     // PIT is only usable in non-multicore environments
756     // just hardcode the core context
757     struct guest_info * info = &(vm->cores[0]);
758
759     uint_t cpu_khz = info->time_state.guest_cpu_freq;
760     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
761
762     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
763
764     V3_ASSERT(pit_state != NULL);
765     pit_state->speaker = 0;
766     pit_state->vm = vm;
767
768     dev = v3_add_device(vm, dev_id, &dev_ops, pit_state);
769
770     if (dev == NULL) {
771         PrintError("Could not attach device %s\n", dev_id);
772         V3_Free(pit_state);
773         return -1;
774     }
775
776     ret |= v3_dev_hook_io(dev, CHANNEL0_PORT, &pit_read_channel, &pit_write_channel);
777     ret |= v3_dev_hook_io(dev, CHANNEL1_PORT, &pit_read_channel, &pit_write_channel);
778     ret |= v3_dev_hook_io(dev, CHANNEL2_PORT, &pit_read_channel, &pit_write_channel);
779     ret |= v3_dev_hook_io(dev, COMMAND_PORT, NULL, &pit_write_command);
780     ret |= v3_dev_hook_io(dev, SPEAKER_PORT, &pit_read_channel, &pit_write_channel);
781
782     if (ret != 0) {
783         PrintError("8254 PIT: Failed to hook IO ports\n");
784         v3_remove_device(dev);
785         return -1;
786     }
787
788 #ifdef V3_CONFIG_DEBUG_PIT
789     PrintDebug("8254 PIT: OSC_HZ=%d, reload_val=", OSC_HZ);
790     //PrintTrace(reload_val);
791     PrintDebug("\n");
792 #endif
793
794     
795
796     pit_state->timer = v3_add_timer(info, &timer_ops, pit_state);
797
798     if (pit_state->timer == NULL) {
799         v3_remove_device(dev);
800         return -1;
801     }
802
803     // Get cpu frequency and calculate the global pit oscilattor counter/cycle
804
805     do_divll(reload_val, OSC_HZ);
806     pit_state->pit_counter = reload_val;
807     pit_state->pit_reload = reload_val;
808
809
810     init_channel(&(pit_state->ch_0));
811     init_channel(&(pit_state->ch_1));
812     init_channel(&(pit_state->ch_2));
813
814 #ifdef V3_CONFIG_DEBUG_PIT
815     PrintDebug("8254 PIT: CPU MHZ=%d -- pit count=", cpu_khz / 1000);
816     //PrintTraceLL(pit_state->pit_counter);
817     PrintDebug("\n");
818 #endif
819
820     return 0;
821 }
822
823
824 device_register("8254_PIT", pit_init);