00001
00002
00003 #ifndef pic_h
00004 #define pic_h
00005
00006 #include "initcalls.h"
00007
00008
00009
00010
00011
00012
00016 class Pic
00017 {
00018 public:
00022 typedef unsigned Status;
00023
00027 static void init();
00028
00032 static void disable( unsigned irqnum );
00033
00037 static void enable(unsigned irqnum, unsigned prio=0);
00038
00042 static void acknowledge( unsigned irq );
00043
00047 static void block(unsigned irq);
00048
00056 static void disable_locked( unsigned irqnum );
00057
00065 static void enable_locked(unsigned irqnum, unsigned prio = 0);
00066
00074 static void block_locked(unsigned irqnum);
00075
00080 static Status disable_all_save();
00081
00087 static void restore_all( Status s );
00088
00097 static void acknowledge_locked( unsigned irq );
00098 private:
00099
00100 public:
00101 enum
00102 {
00103 MASTER_PIC_BASE = 0x20,
00104 SLAVES_PIC_BASE = 0xa0,
00105 OFF_ICW = 0x00,
00106 OFF_OCW = 0x01,
00107
00108 MASTER_ICW = MASTER_PIC_BASE + OFF_ICW,
00109 MASTER_OCW = MASTER_PIC_BASE + OFF_OCW,
00110 SLAVES_ICW = SLAVES_PIC_BASE + OFF_ICW,
00111 SLAVES_OCW = SLAVES_PIC_BASE + OFF_OCW,
00112
00113
00114
00115
00116
00117 ICW_TEMPLATE = 0x10,
00118
00119 LEVL_TRIGGER = 0x08,
00120 EDGE_TRIGGER = 0x00,
00121 ADDR_INTRVL4 = 0x04,
00122 ADDR_INTRVL8 = 0x00,
00123 SINGLE__MODE = 0x02,
00124 CASCADE_MODE = 0x00,
00125 ICW4__NEEDED = 0x01,
00126 NO_ICW4_NEED = 0x00,
00127
00128
00129
00130
00131
00132 SLAVE_ON_IR0 = 0x01,
00133 SLAVE_ON_IR1 = 0x02,
00134 SLAVE_ON_IR2 = 0x04,
00135 SLAVE_ON_IR3 = 0x08,
00136 SLAVE_ON_IR4 = 0x10,
00137 SLAVE_ON_IR5 = 0x20,
00138 SLAVE_ON_IR6 = 0x40,
00139 SLAVE_ON_IR7 = 0x80,
00140
00141 I_AM_SLAVE_0 = 0x00,
00142 I_AM_SLAVE_1 = 0x01,
00143 I_AM_SLAVE_2 = 0x02,
00144 I_AM_SLAVE_3 = 0x03,
00145 I_AM_SLAVE_4 = 0x04,
00146 I_AM_SLAVE_5 = 0x05,
00147 I_AM_SLAVE_6 = 0x06,
00148 I_AM_SLAVE_7 = 0x07,
00149
00150
00151
00152
00153
00154 SNF_MODE_ENA = 0x10,
00155 SNF_MODE_DIS = 0x00,
00156 BUFFERD_MODE = 0x08,
00157 NONBUFD_MODE = 0x00,
00158 AUTO_EOI_MOD = 0x02,
00159 NRML_EOI_MOD = 0x00,
00160 I8086_EMM_MOD = 0x01,
00161 SET_MCS_MODE = 0x00,
00162
00163
00164
00165
00166
00167 PICM_MASK = 0xFF,
00168 PICS_MASK = 0xFF,
00169
00170
00171
00172
00173
00174 NON_SPEC_EOI = 0x20,
00175 SPECIFIC_EOI = 0x60,
00176 ROT_NON_SPEC = 0xa0,
00177 SET_ROT_AEOI = 0x80,
00178 RSET_ROTAEOI = 0x00,
00179 ROT_SPEC_EOI = 0xe0,
00180 SET_PRIORITY = 0xc0,
00181 NO_OPERATION = 0x40,
00182
00183 SND_EOI_IR0 = 0x00,
00184 SND_EOI_IR1 = 0x01,
00185 SND_EOI_IR2 = 0x02,
00186 SND_EOI_IR3 = 0x03,
00187 SND_EOI_IR4 = 0x04,
00188 SND_EOI_IR5 = 0x05,
00189 SND_EOI_IR6 = 0x06,
00190 SND_EOI_IR7 = 0x07,
00191
00192
00193
00194
00195
00196 OCW_TEMPLATE = 0x08,
00197 SPECIAL_MASK = 0x40,
00198 MASK_MDE_SET = 0x20,
00199 MASK_MDE_RST = 0x00,
00200 POLL_COMMAND = 0x04,
00201 NO_POLL_CMND = 0x00,
00202 READ_NEXT_RD = 0x02,
00203 READ_IR_ONRD = 0x00,
00204 READ_IS_ONRD = 0x01,
00205
00206
00207
00208
00209 PICM_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8
00210 | CASCADE_MODE | ICW4__NEEDED),
00211 PICM_ICW3 = SLAVE_ON_IR2,
00212 PICM_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD
00213 | I8086_EMM_MOD),
00214
00215 PICS_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8
00216 | CASCADE_MODE | ICW4__NEEDED),
00217 PICS_ICW3 = I_AM_SLAVE_2,
00218 PICS_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD
00219 | I8086_EMM_MOD),
00220 };
00221
00222 static int special_fully_nested_mode;
00223
00224 private:
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 static FIASCO_INIT void pic_init(unsigned char master_base, unsigned char slave_base);
00237 };
00238
00239
00240
00241
00242
00243
00244 #include "processor.h"
00245
00246 #include "io.h"
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 inline void Pic::disable( unsigned irqnum )
00260 {
00261 Proc::Status s = Proc::cli_save();
00262 disable_locked( irqnum );
00263 Proc::sti_restore(s);
00264 }
00265
00266
00267
00268 inline void Pic::enable(unsigned irqnum, unsigned prio)
00269 {
00270 Proc::Status s = Proc::cli_save();
00271 enable_locked(irqnum, prio);
00272 Proc::sti_restore(s);
00273 }
00274
00275
00276
00277 inline void Pic::acknowledge( unsigned irq )
00278 {
00279 Proc::Status s = Proc::cli_save();
00280 acknowledge_locked(irq);
00281 Proc::sti_restore(s);
00282 }
00283
00284
00285
00286 inline void Pic::block(unsigned irq)
00287 {
00288 Proc::Status s = Proc::cli_save();
00289 block_locked(irq);
00290 Proc::sti_restore(s);
00291 }
00292
00293
00294
00295 inline void
00296 Pic::disable_locked( unsigned irq )
00297 {
00298 if (irq < 8)
00299 Io::out8(Io::in8(MASTER_OCW) | (1 << irq), MASTER_OCW);
00300 else
00301 Io::out8(Io::in8(SLAVES_OCW) | (1 << (irq-8)), SLAVES_OCW);
00302 }
00303
00304
00305
00306 inline void
00307 Pic::enable_locked(unsigned irq, unsigned )
00308 {
00309 if (irq < 8)
00310 Io::out8(Io::in8(MASTER_OCW) & ~(1 << irq), MASTER_OCW);
00311 else
00312 Io::out8(Io::in8(SLAVES_OCW) & ~(1 << (irq-8)), SLAVES_OCW);
00313 }
00314
00315
00316
00317 inline void
00318 Pic::acknowledge_locked( unsigned irq )
00319 {
00320 if (irq >= 8)
00321 {
00322 Io::out8(NON_SPEC_EOI, SLAVES_ICW);
00323 if (special_fully_nested_mode)
00324 {
00325 Io::out8(OCW_TEMPLATE | READ_NEXT_RD | READ_IS_ONRD, SLAVES_ICW);
00326 if (Io::in8(SLAVES_ICW))
00327 return;
00328 }
00329 }
00330 Io::out8(NON_SPEC_EOI, MASTER_ICW);
00331 }
00332
00333
00334
00335 inline Pic::Status
00336 Pic::disable_all_save()
00337 {
00338 Status s;
00339 s = Io::in8(MASTER_OCW);
00340 s |= Io::in8(SLAVES_OCW) << 8;
00341 Io::out8( 0xff, MASTER_OCW );
00342 Io::out8( 0xff, SLAVES_OCW );
00343
00344 return s;
00345 }
00346
00347
00348
00349 inline void
00350 Pic::restore_all( Status s )
00351 {
00352 Io::out8( s & 0x0ff, MASTER_OCW );
00353 Io::out8( (s >> 8) & 0x0ff, SLAVES_OCW );
00354 }
00355
00356 #endif // pic_h