00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "src/common/shared.hpp"
00018
00019
00020 #include "src/common/io.hpp"
00021 #include "src/common/bits.hpp"
00022 #include "src/arch/x86/interr.hpp"
00023 #include "src/arch/x86/except_c.hpp"
00024 #include "src/arch/x86/irq.hpp"
00025
00026 namespace Arch {
00027 namespace x86 {
00028 namespace Interr {
00029
00030
00031
00032 pic_service kernel_pic;
00033
00034
00035 void init_pic() {
00036 kernel_pic.set_idt(&Interr::kernel_idt);
00037 }
00038
00039
00040 void pic_service::init(idt_service *_idt)
00041 {
00042 idt = _idt;
00043 setup_pic (DEF_FIRST_IRQ_M_INT, DEF_FIRST_IRQ_S_INT);
00044
00045
00046 IOPorts::outb (DEF_PIC_M_PORT + 1, 0xFF);
00047
00048 __asm__ __volatile__ ("sti");
00049 }
00050
00051
00052
00053
00054
00055
00056
00057 void pic_service::set_idt(idt_service *_idt)
00058 {
00059 idt = _idt;
00060 setup_pic (DEF_FIRST_IRQ_M_INT, DEF_FIRST_IRQ_S_INT);
00061
00062
00063 IOPorts::outb (DEF_PIC_M_PORT + 1, 0xFF);
00064
00065 __asm__ __volatile__ ("sti");
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 void pic_service::setup_pic (char first_irq1, char first_irq2)
00096 {
00097 IOPorts::outb (DEF_PIC_M_PORT, DEF_ICW1);
00098 IOPorts::outb (DEF_PIC_S_PORT, DEF_ICW1);
00099
00100 IOPorts::outb (DEF_PIC_M_PORT + 1, first_irq1);
00101 IOPorts::outb (DEF_PIC_S_PORT + 1, first_irq2);
00102
00103 IOPorts::outb (DEF_PIC_M_PORT + 1, 4);
00104 IOPorts::outb (DEF_PIC_S_PORT + 1, 2);
00105
00106 IOPorts::outb (DEF_PIC_M_PORT + 1, DEF_ICW4);
00107 IOPorts::outb (DEF_PIC_S_PORT + 1, DEF_ICW4);
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117 uint32 pic_service::install_irq (char irq, int (*proc)(except2_t*), short selector)
00118 {
00119 uint32 ret_val;
00120
00121 ret_val = add2interr_chain(0x20 + irq, proc);
00122
00123
00124 mask (irq, 0);
00125
00126
00127 return ret_val;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 void pic_service::mask(char intno, char enabled)
00137 {
00138
00139 if (intno < 8) mask_irq_m (bit_set(get_irq_mask_m(), intno, enabled));
00140 else
00141 {
00142
00143 mask_irq_s (bit_set(get_irq_mask_s(), intno, enabled));
00144
00145 if (!enabled) mask_irq_m (bit_set(get_irq_mask_m(), 2, enabled));
00146 }
00147 }
00148
00149
00150
00151
00152
00153
00154
00155 void pic_service::mask_irq_m (char mask)
00156 {
00157 IOPorts::outb (DEF_PIC_M_PORT + 1, mask);
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 void pic_service::mask_irq_s (char mask)
00167 {
00168 IOPorts::outb (DEF_PIC_S_PORT + 1, mask);
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 char pic_service::get_irq_mask_m()
00178 {
00179 return IOPorts::inb(DEF_PIC_M_PORT + 1);
00180 }
00181
00182
00183
00184
00185
00186
00187
00188 char pic_service::get_irq_mask_s()
00189 {
00190 return IOPorts::inb(DEF_PIC_S_PORT + 1);
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 void pic_service::EOI()
00200 {
00201 IOPorts::outb(0x20, 0x20);
00202 IOPorts::outb(0xA0, 0x20);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 void pic_service::set_pit_freq(float hz)
00217 {
00218 float base = 1193180.0;
00219 union
00220 {
00221 unsigned short sh;
00222 unsigned char bt[2];
00223 } un;
00224
00225 base /= hz;
00226 un.sh = (unsigned short) base;
00227
00228 if (hz >= 17) if (hz <= 19) un.sh = 0x0;
00229
00230 IOPorts::outb(0x43, 0x36);
00231 IOPorts::outb(0x40, un.bt[0]);
00232 IOPorts::outb(0x40, un.bt[1]);
00233 }
00234
00235
00236 };
00237 };
00238 };
00239
00240
00241
00242
00243
00244
00245