|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
001 /* Copyright (C) 2004 The KOS Team 001 /* Copyright (C) 2004 The KOS Team 002 Copyright (C) 1999 Free Software Foundatio << 003 002 004 This program is free software; you can redi 003 This program is free software; you can redistribute it and/or 005 modify it under the terms of the GNU Genera 004 modify it under the terms of the GNU General Public License 006 as published by the Free Software Foundatio 005 as published by the Free Software Foundation; either version 2 007 of the License, or (at your option) any lat 006 of the License, or (at your option) any later version. 008 007 009 This program is distributed in the hope tha 008 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the 009 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU General Public License for more details 011 GNU General Public License for more details. 013 012 014 You should have received a copy of the GNU 013 You should have received a copy of the GNU General Public License 015 along with this program; if not, write to t 014 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place - Suite 3 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 017 USA. 016 USA. 018 */ 017 */ 019 #include <hwcore/ioports.h> 018 #include <hwcore/ioports.h> 020 019 021 #include "i8254.h" 020 #include "i8254.h" 022 021 023 /** 82c54 clock frequency */ 022 /** 82c54 clock frequency */ 024 #define I8254_MAX_FREQ 1193180 023 #define I8254_MAX_FREQ 1193180 025 024 026 /* Ports to communicate with the 82c54 */ 025 /* Ports to communicate with the 82c54 */ 027 #define I8254_TIMER0 0x40 026 #define I8254_TIMER0 0x40 028 #define I8254_TIMER1 0x41 027 #define I8254_TIMER1 0x41 029 #define I8254_TIMER2 0x42 028 #define I8254_TIMER2 0x42 030 #define I8254_CONTROL 0x43 029 #define I8254_CONTROL 0x43 031 030 032 /** 031 /** 033 * Configure the first timer of the 82c54 chip 032 * Configure the first timer of the 82c54 chip as a rate generator, 034 * which will raise an IRQ0 on a regular perio 033 * which will raise an IRQ0 on a regular periodic basis, as given by 035 * the freq parameter. Second (RAM refresh) an 034 * the freq parameter. Second (RAM refresh) and third (speaker) timers 036 * are left unchanged. Maximum frequency is th 035 * are left unchanged. Maximum frequency is that of the 8254 clock, ie 037 * 1193180 Hz. 036 * 1193180 Hz. 038 * 037 * 039 * Ahhh PC systems are nice toys: this maximum 038 * Ahhh PC systems are nice toys: this maximum "strange" frequency 040 * equals that of the NTSC clock (14.31818 MHz 039 * equals that of the NTSC clock (14.31818 MHz) divided by 12. In 041 * turn, the famous 4.77 MHz cpu clock frequen 040 * turn, the famous 4.77 MHz cpu clock frequency of the first IBM PC 042 * is this same NTSC frequency divided by 3. W 041 * is this same NTSC frequency divided by 3. Why the NTSC frequency as 043 * a base "standard" ? Because the 14.31818 MH 042 * a base "standard" ? Because the 14.31818 MHz quartz were cheap at 044 * that time, and because it allows to simply 043 * that time, and because it allows to simply drive altogether the 045 * cpu, the "time of day" timer, and the video 044 * cpu, the "time of day" timer, and the video signal generators. 046 */ 045 */ 047 sos_ret_t sos_i8254_set_frequency(unsigned int 046 sos_ret_t sos_i8254_set_frequency(unsigned int freq) 048 { 047 { 049 unsigned int nb_tick; 048 unsigned int nb_tick; 050 049 051 if (freq <= 0) 050 if (freq <= 0) 052 return -SOS_EINVAL; 051 return -SOS_EINVAL; 053 052 054 /* Compute counter value */ 053 /* Compute counter value */ 055 nb_tick = I8254_MAX_FREQ / freq; 054 nb_tick = I8254_MAX_FREQ / freq; 056 055 057 /* Counter must be between 1 and 65536 */ 056 /* Counter must be between 1 and 65536 */ 058 if (nb_tick > 65536) 057 if (nb_tick > 65536) 059 return -SOS_EINVAL; 058 return -SOS_EINVAL; 060 if (nb_tick <= 0) 059 if (nb_tick <= 0) 061 return -SOS_EINVAL; 060 return -SOS_EINVAL; 062 061 063 /* The i8254 interprets 0 to mean counter == 062 /* The i8254 interprets 0 to mean counter == 65536, because 65536 064 cannot be coded on 16bits */ 063 cannot be coded on 16bits */ 065 if (nb_tick == 65536) 064 if (nb_tick == 65536) 066 nb_tick = 0; 065 nb_tick = 0; 067 066 068 /* We want to configure timer0, we want to s 067 /* We want to configure timer0, we want to send both LSB+MSB to set 069 timer0 freq (-> 0x30), and we configure t 068 timer0 freq (-> 0x30), and we configure timer0 in mode 2, ie as a 070 rate generator (-> 0x4) ==> 0x34 */ 069 rate generator (-> 0x4) ==> 0x34 */ 071 outb(0x34, I8254_CONTROL); 070 outb(0x34, I8254_CONTROL); 072 071 073 /* Send LSB of counter first */ 072 /* Send LSB of counter first */ 074 outb((nb_tick & 0xFF), I8254_TIMER0); 073 outb((nb_tick & 0xFF), I8254_TIMER0); 075 074 076 /* Send MSB of counter */ 075 /* Send MSB of counter */ 077 outb((nb_tick >> 8) & 0xFF, I8254_TIMER0); 076 outb((nb_tick >> 8) & 0xFF, I8254_TIMER0); 078 077 079 return SOS_OK; 078 return SOS_OK; 080 } 079 }
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |