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