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