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