10 MASTER_PIC_BASE = 0x20,
11 SLAVES_PIC_BASE = 0xa0,
15 MASTER_ICW = MASTER_PIC_BASE + OFF_ICW,
16 MASTER_OCW = MASTER_PIC_BASE + OFF_OCW,
17 SLAVES_ICW = SLAVES_PIC_BASE + OFF_ICW,
18 SLAVES_OCW = SLAVES_PIC_BASE + OFF_OCW,
115 ** Standard PIC initialization values for PCs.
117 PICM_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8
118 | CASCADE_MODE | ICW4__NEEDED),
119 PICM_ICW3 = SLAVE_ON_IR2,
120 PICM_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD
123 PICS_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8
124 | CASCADE_MODE | ICW4__NEEDED),
125 PICS_ICW3 = I_AM_SLAVE_2,
126 PICS_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD
130 static int special_fully_nested_mode;
133 IMPLEMENTATION[i8259]:
140 #include "boot_info.h"
143 #include "initcalls.h"
144 #include "mem_layout.h"
146 int Pic::special_fully_nested_mode = 1; // be compatible with Jochen's L4
148 IMPLEMENT FIASCO_INIT
162 // this version of pic_init() overrides the OSKIT's.
164 // differences to standard AT initialization:
165 // . we use the "special fully nested mode" to let irq sources on the
166 // slave irq raise nested
167 // . we give irq 2 (= slave pic) the highest prio on the master pic; this
168 // results in the following sequence of prios: 8-15,3-7,0,1
169 // this way, the timer interrupt on irq 8 always gets thru (even if
170 // some user irq handler doesn't acknowledge its irq!)
174 Pic::pic_init(unsigned char master_base, unsigned char slave_base)
176 // disallow all interrupts before we selectively enable them
177 Pic::disable_all_save();
179 * Set the LINTEN bit in the HyperTransport Transaction
182 * This will cause EXTINT and NMI interrupts routed over the
183 * hypertransport bus to be fed into the LAPIC LINT0/LINT1. If
184 * the bit isn't set, the interrupts will go to the general cpu
185 * INTR/NMI pins. On a dual-core cpu the interrupt winds up
186 * going to BOTH cpus. The first cpu that does the interrupt ack
187 * cycle will get the correct interrupt. The second cpu that does
188 * it will get a spurious interrupt vector (typically IRQ 7).
191 if ((cpu_id & 0xff0) == 0xf30)
197 (1 << 31) | /* enable */
198 (0 << 16) | /* bus */
199 (24 << 11) | /* dev (cpu + 24) */
200 (0 << 8) | /* func */
203 tcr = Io::in32(0xcfc);
204 if ((tcr & 0x00010000) == 0) {
205 Io::out32(0xcfc, tcr|0x00010000);
206 printf("AMD: Rerouting HyperTransport "
207 "EXTINT/NMI to APIC\n");
209 Io::out32(0x0cf8, 0);
212 // VMware isn't able to deal with the special fully nested mode
213 // correctly so we simply don't use it while running under
214 // VMware. Otherwise VMware will barf with
215 // *** VMware Workstation internal monitor error ***
216 // BUG F(152):393 bugNr=4388
218 if (strstr (Cmdline::cmdline(), " -nosfn"))
219 special_fully_nested_mode = 0;
221 if (special_fully_nested_mode)
223 puts ("Enabling special fully nested mode for PIC");
224 /* Initialize the master. */
226 Io::out8_p(PICM_ICW1, MASTER_ICW);
227 Io::out8_p(master_base, MASTER_OCW);
228 Io::out8_p(PICM_ICW3, MASTER_OCW);
229 Io::out8_p(SNF_MODE_ENA | PICM_ICW4, MASTER_OCW);
231 /* Initialize the slave. */
232 Io::out8_p(PICS_ICW1, SLAVES_ICW);
233 Io::out8_p(slave_base, SLAVES_OCW);
234 Io::out8_p(PICS_ICW3, SLAVES_OCW);
235 Io::out8_p(SNF_MODE_ENA | PICS_ICW4, SLAVES_OCW);
237 // the timer interrupt should have the highest priority so that it
238 // always gets through
239 if ( ! Config::profiling
240 && Config::pic_prio_modify
241 && Config::scheduler_mode == Config::SCHED_RTC)
243 // setting specific rotation (specific priority)
244 // -- see Intel 8259A reference manual
245 // irq 1 on master hast lowest prio
246 // => irq 2 (cascade) = irqs 8..15 have highest prio
247 Io::out8_p(SET_PRIORITY | 1, MASTER_ICW);
248 // irq 7 on slave has lowest prio
249 // => irq 0 on slave (= irq 8) has highest prio
250 Io::out8_p(SET_PRIORITY | 7, SLAVES_ICW);
255 printf("%sUsing (normal) fully nested PIC mode\n",
256 Config::found_vmware ? "Found VMware: " : "");
258 /* Initialize the master. */
259 Io::out8_p(PICM_ICW1, MASTER_ICW);
260 Io::out8_p(master_base, MASTER_OCW);
261 Io::out8_p(PICM_ICW3, MASTER_OCW);
262 Io::out8_p(PICM_ICW4, MASTER_OCW);
264 /* Initialize the slave. */
265 Io::out8_p(PICS_ICW1, SLAVES_ICW);
266 Io::out8_p(slave_base, SLAVES_OCW);
267 Io::out8_p(PICS_ICW3, SLAVES_OCW);
268 Io::out8_p(PICS_ICW4, SLAVES_OCW);
272 Io::out8_p(0xfb, MASTER_OCW); // unmask irq2
273 Io::out8_p(0xff, SLAVES_OCW); // mask everything
275 /* Ack any bogus intrs by setting the End Of Interrupt bit. */
276 Io::out8_p(NON_SPEC_EOI, MASTER_ICW);
277 Io::out8_p(NON_SPEC_EOI, SLAVES_ICW);
279 // disallow all interrupts before we selectively enable them
280 Pic::disable_all_save();
284 IMPLEMENT inline NEEDS["io.h"]
286 Pic::disable_locked(unsigned irq)
289 Io::out8(Io::in8(MASTER_OCW) | (1 << irq), MASTER_OCW);
291 Io::out8(Io::in8(SLAVES_OCW) | (1 << (irq-8)), SLAVES_OCW);
294 IMPLEMENT inline NEEDS["io.h"]
296 Pic::enable_locked(unsigned irq, unsigned /*prio*/)
299 Io::out8(Io::in8(MASTER_OCW) & ~(1 << irq), MASTER_OCW);
302 Io::out8(Io::in8(MASTER_OCW) & ~(1 << 2), MASTER_OCW);
303 Io::out8(Io::in8(SLAVES_OCW) & ~(1 << (irq-8)), SLAVES_OCW);
307 IMPLEMENT inline NEEDS["io.h"]
309 Pic::acknowledge_locked(unsigned irq)
313 Io::out8(NON_SPEC_EOI, SLAVES_ICW); // EOI slave
314 if (special_fully_nested_mode)
316 Io::out8(OCW_TEMPLATE | READ_NEXT_RD | READ_IS_ONRD, SLAVES_ICW);
317 if (Io::in8(SLAVES_ICW)) // slave still active?
318 return; // -- don't EOI master
321 Io::out8(NON_SPEC_EOI, MASTER_ICW); // EOI master
326 Pic::block_locked(unsigned)
329 IMPLEMENT inline NEEDS["io.h"]
331 Pic::disable_all_save()
334 s = Io::in8(MASTER_OCW);
335 s |= Io::in8(SLAVES_OCW) << 8;
336 Io::out8( 0xff, MASTER_OCW );
337 Io::out8( 0xff, SLAVES_OCW );
342 IMPLEMENT inline NEEDS["io.h"]
344 Pic::restore_all( Status s )
346 Io::out8( s & 0x0ff, MASTER_OCW );
347 Io::out8( (s >> 8) & 0x0ff, SLAVES_OCW );
351 IMPLEMENT inline NEEDS[<cassert>]
353 Pic::set_cpu(unsigned, unsigned cpu)