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