2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 //#define CHIP_MASK (I8259_MAX_CHIPS - 1)
14 void I8259::initialize()
17 __I8259_MAX_CHIPS = osd->get_feature_uint32_value(_T("I8259_MAX_CHIPS"));
18 if(__I8259_MAX_CHIPS >= 2) __I8259_MAX_CHIPS = 2;
19 __CHIP_MASK = __I8259_MAX_CHIPS - 1;
20 for(uint32_t c = 0; c < __I8259_MAX_CHIPS; c++) {
22 pic[c].irr = pic[c].isr = pic[c].prio = 0;
23 pic[c].icw1 = pic[c].icw2 = pic[c].icw3 = pic[c].icw4 = 0;
25 pic[c].icw2_r = pic[c].icw3_r = pic[c].icw4_r = 0;
31 for(uint32_t c = 0; c < __I8259_MAX_CHIPS; c++) {
33 pic[c].irr_tmp_id = -1;
37 void I8259::write_io8(uint32_t addr, uint32_t data)
39 int c = (addr >> 1) & __CHIP_MASK;
46 } else if(pic[c].icw3_r) {
50 } else if(pic[c].icw4_r) {
56 uint8_t irr = pic[c].irr;
57 for(int i = 0; i < 8; i++) {
59 if((pic[c].irr & bit) && (pic[c].imr & bit) && !(data & bit)) {
61 pic[c].irr_tmp |= bit;
64 if(irr != pic[c].irr) {
65 if(pic[c].irr_tmp_id != -1) {
66 cancel_event(this, pic[c].irr_tmp_id);
68 register_event(this, c, 10, false, &pic[c].irr_tmp_id);
77 pic[c].icw3_r = (data & 2) ? 0 : 1;
78 pic[c].icw4_r = data & 1;
85 if(!(pic[c].icw1 & 1)) {
89 } else if((data & 0x98) == 0x08) {
92 } else if((data & 0x18) == 0x00) {
95 uint8_t mask = 1 << n;
102 for(n = 0, mask = (1 << pic[c].prio); n < 8; n++, mask = (mask << 1) | (mask >> 7)) {
103 if(pic[c].isr & mask) {
112 if(pic[c].isr & mask) {
117 pic[c].prio = (pic[c].prio + 1) & 7;
120 for(n = 0, mask = (1 << pic[c].prio); n < 8; n++, mask = (mask << 1) | (mask >> 7)) {
121 if(pic[c].isr & mask) {
123 pic[c].prio = (pic[c].prio + 1) & 7;
132 if(pic[c].isr & mask) {
135 pic[c].irr_tmp &= ~mask;
136 pic[c].prio = (pic[c].prio + 1) & 7;
145 uint32_t I8259::read_io8(uint32_t addr)
147 int c = (addr >> 1) & __CHIP_MASK;
152 if(pic[c].ocw3 & 4) {
154 if(pic[c].isr & ~pic[c].imr) {
157 for(int i = 0; i < 8; i++) {
158 if((1 << i) & pic[c].irr & ~pic[c].imr) {
162 } else if((pic[c].ocw3 & 3) == 2) {
164 } else if((pic[c].ocw3 & 3) == 3) {
165 return pic[c].isr & ~pic[c].imr;
171 void I8259::write_signal(int id, uint32_t data, uint32_t mask)
174 pic[id >> 3].irr |= 1 << (id & 7);
177 pic[id >> 3].irr &= ~(1 << (id & 7));
182 void I8259::event_callback(int event_id, int err)
184 int c = event_id & __CHIP_MASK;
185 uint8_t irr = pic[c].irr;
187 pic[c].irr |= pic[c].irr_tmp;
189 pic[c].irr_tmp_id = -1;
191 if(irr != pic[c].irr) {
196 uint32_t I8259::read_signal(int id)
198 return (pic[id >> 3].irr & (1 << (id & 7))) ? 1 : 0;
201 void I8259::update_intr()
205 for(uint32_t c = 0; c < __I8259_MAX_CHIPS; c++) {
206 uint8_t irr = pic[c].irr;
207 if((c + 1) < __I8259_MAX_CHIPS) {
209 if(pic[c + 1].irr & (~pic[c + 1].imr)) {
210 // request from slave
211 irr |= 1 << (pic[c + 1].icw3 & 7);
214 irr &= (~pic[c].imr);
218 if(!(pic[c].ocw3 & 0x20)) {
221 int level = pic[c].prio;
222 uint8_t bit = 1 << level;
223 while(!(irr & bit)) {
224 level = (level + 1) & 7;
227 if(((c + 1) < __I8259_MAX_CHIPS) && (pic[c].icw3 & bit)) {
231 if(pic[c].isr & bit) {
243 d_cpu->set_intr_line(intr, true, 0);
247 uint32_t I8259::get_intr_ack()
252 pic[req_chip].isr |= req_bit;
253 pic[req_chip].irr &= ~req_bit;
255 // update isr and irr of master
256 uint8_t slave = 1 << (pic[req_chip].icw3 & 7);
257 pic[req_chip - 1].isr |= slave;
258 pic[req_chip - 1].irr &= ~slave;
260 if(pic[req_chip].icw4 & 1) {
262 vector = (pic[req_chip].icw2 & 0xf8) | req_level;
265 uint16_t addr = (uint16_t)pic[req_chip].icw2 << 8;
266 if(pic[req_chip].icw1 & 4) {
267 addr |= (pic[req_chip].icw1 & 0xe0) | (req_level << 2);
269 addr |= (pic[req_chip].icw1 & 0xc0) | (req_level << 3);
271 vector = 0xcd | (addr << 8);
273 if(pic[req_chip].icw4 & 2) {
275 pic[req_chip].isr &= ~req_bit;
280 #define STATE_VERSION 2
282 bool I8259::process_state(FILEIO* state_fio, bool loading)
284 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
287 if(!state_fio->StateCheckInt32(this_device_id)) {
290 state_fio->StateBuffer(pic, sizeof(pic), 1); // ToDo:
291 state_fio->StateInt32(req_chip);
292 state_fio->StateInt32(req_level);
293 state_fio->StateUint8(req_bit);