1 /////////////////////////////////////////////////////////////////////////
2 // $Id: ioapic.cc,v 1.37 2008/04/29 22:14:23 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 class bx_ioapic_c bx_ioapic
;
34 #define LOG_THIS bx_ioapic.
36 static bx_bool
ioapic_read(bx_phy_address a20addr
, unsigned len
, void *data
, void *param
)
38 bx_ioapic
.read(a20addr
, data
, len
);
42 static bx_bool
ioapic_write(bx_phy_address a20addr
, unsigned len
, void *data
, void *param
)
45 BX_PANIC (("I/O apic write with len=%ld (should be 4)", len
));
47 bx_ioapic
.write(a20addr
, (Bit32u
*) data
, len
);
51 void bx_io_redirect_entry_t::sprintf_self(char *buf
)
53 sprintf(buf
, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x",
54 (unsigned) destination(),
55 (unsigned) is_masked(),
56 (unsigned) trigger_mode(),
57 (unsigned) remote_irr(),
58 (unsigned) pin_polarity(),
59 (unsigned) delivery_status(),
60 (unsigned) destination_mode(),
61 (unsigned) delivery_mode(),
65 void bx_io_redirect_entry_t::register_state(bx_param_c
*parent
)
67 BXRS_HEX_PARAM_SIMPLE(parent
, lo
);
68 BXRS_HEX_PARAM_SIMPLE(parent
, hi
);
71 #define BX_IOAPIC_BASE_ADDR (0xfec00000)
73 bx_ioapic_c::bx_ioapic_c()
74 : bx_generic_apic_c(BX_IOAPIC_BASE_ADDR
)
80 bx_ioapic_c::~bx_ioapic_c() {}
82 #define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS)
84 void bx_ioapic_c::init(void)
86 bx_generic_apic_c::init();
87 BX_INFO(("initializing I/O APIC"));
88 base_addr
= BX_IOAPIC_BASE_ADDR
;
89 set_id(BX_IOAPIC_DEFAULT_ID
);
91 DEV_register_memory_handlers(&bx_ioapic
,
92 ioapic_read
, ioapic_write
, base_addr
, base_addr
+ 0xfff);
93 // all interrupts masked
94 for (int i
=0; i
<BX_IOAPIC_NUM_PINS
; i
++) {
95 ioredtbl
[i
].set_lo_part(0x00010000);
96 ioredtbl
[i
].set_hi_part(0x00000000);
102 void bx_ioapic_c::read_aligned(bx_phy_address address
, Bit32u
*data
)
104 BX_DEBUG(("IOAPIC: read aligned addr=%08x", address
));
106 if (address
== 0x00) {
112 BX_PANIC(("IOAPIC: read from unsupported address"));
114 // only reached when reading data register
116 case 0x00: // APIC ID, note this is 4bits, the upper 4 are reserved
117 *data
= ((id
& APIC_ID_MASK
) << 24);
119 case 0x01: // version
120 *data
= BX_IOAPIC_VERSION_ID
;
123 BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0"));
127 int index
= (ioregsel
- 0x10) >> 1;
128 if (index
>= 0 && index
< BX_IOAPIC_NUM_PINS
) {
129 bx_io_redirect_entry_t
*entry
= ioredtbl
+ index
;
130 *data
= (ioregsel
&1) ? entry
->get_hi_part() : entry
->get_lo_part();
133 BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel
));
137 void bx_ioapic_c::write_aligned(bx_phy_address address
, Bit32u
*value
)
139 BX_DEBUG(("IOAPIC: write aligned addr=%08x, data=%08x", address
, *value
));
141 if (address
== 0x00) {
146 BX_PANIC(("IOAPIC: write to unsupported address"));
148 // only reached when writing data register
150 case 0x00: // set APIC ID
152 Bit8u newid
= (*value
>> 24) & APIC_ID_MASK
;
153 BX_INFO(("IOAPIC: setting id to 0x%x", newid
));
157 case 0x01: // version
158 case 0x02: // arbitration id
159 BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel
));
162 int index
= (ioregsel
- 0x10) >> 1;
163 if (index
>= 0 && index
< BX_IOAPIC_NUM_PINS
) {
164 bx_io_redirect_entry_t
*entry
= ioredtbl
+ index
;
166 entry
->set_hi_part(*value
);
168 entry
->set_lo_part(*value
);
170 entry
->sprintf_self(buf
);
171 BX_DEBUG(("IOAPIC: now entry[%d] is %s", index
, buf
));
175 BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel
));
179 void bx_ioapic_c::set_irq_level(Bit8u int_in
, bx_bool level
)
181 BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in
, level
));
182 if (int_in
< BX_IOAPIC_NUM_PINS
) {
183 Bit32u bit
= 1<<int_in
;
184 if ((level
<<int_in
) != (intin
& bit
)) {
185 bx_io_redirect_entry_t
*entry
= ioredtbl
+ int_in
;
186 if (entry
->trigger_mode()) {
210 void bx_ioapic_c::receive_eoi(Bit8u vector
)
212 BX_DEBUG(("IOAPIC: received EOI for vector %d", vector
));
215 void bx_ioapic_c::service_ioapic()
217 static unsigned int stuck
= 0;
219 // look in IRR and deliver any interrupts that are not masked.
220 BX_DEBUG(("IOAPIC: servicing"));
221 for (unsigned bit
=0; bit
< BX_IOAPIC_NUM_PINS
; bit
++) {
222 Bit32u mask
= 1<<bit
;
224 bx_io_redirect_entry_t
*entry
= ioredtbl
+ bit
;
225 if (! entry
->is_masked()) {
226 // clear irr bit and deliver
227 if (entry
->delivery_mode() == 7) {
228 vector
= DEV_pic_iac();
230 vector
= entry
->vector();
232 bx_bool done
= apic_bus_deliver_interrupt(vector
, entry
->destination(), entry
->delivery_mode(), entry
->destination_mode(), entry
->pin_polarity(), entry
->trigger_mode());
234 if (! entry
->trigger_mode())
236 entry
->clear_delivery_status();
239 entry
->set_delivery_status();
242 BX_INFO(("vector %#x stuck?", vector
));
246 BX_DEBUG(("service_ioapic(): INTIN%d is masked", bit
));
252 void bx_ioapic_c::register_state(void)
254 bx_list_c
*list
= new bx_list_c(SIM
->get_bochs_root(), "ioapic", "IOAPIC State", 4);
255 BXRS_HEX_PARAM_SIMPLE(list
, ioregsel
);
256 BXRS_HEX_PARAM_SIMPLE(list
, intin
);
257 BXRS_HEX_PARAM_SIMPLE(list
, irr
);
259 bx_list_c
*table
= new bx_list_c(list
, "ioredtbl", BX_IOAPIC_NUM_PINS
);
260 for (unsigned i
=0; i
<BX_IOAPIC_NUM_PINS
; i
++) {
262 sprintf(name
, "0x%02x", i
);
263 bx_list_c
*entry
= new bx_list_c(table
, name
, 2);
264 ioredtbl
[i
].register_state(entry
);
268 #endif /* if BX_SUPPORT_APIC */