better port write decoding(wd) and some changes to run_irq loop
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2073
This commit is contained in:
parent
0fb7da0801
commit
688c8f114f
1 changed files with 65 additions and 68 deletions
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: pic.cpp,v 1.25 2004-11-15 14:56:55 qbix79 Exp $ */
|
||||
/* $Id: pic.cpp,v 1.26 2004-12-07 21:29:14 qbix79 Exp $ */
|
||||
|
||||
#include <list>
|
||||
|
||||
|
@ -44,6 +44,7 @@ struct PIC_Controller {
|
|||
|
||||
bool special;
|
||||
bool auto_eoi;
|
||||
bool rotate_on_auto_eoi;
|
||||
bool request_issr;
|
||||
Bit8u vector_base;
|
||||
};
|
||||
|
@ -75,70 +76,61 @@ static void write_command(Bitu port,Bitu val,Bitu iolen) {
|
|||
Bitu i;
|
||||
Bit16u IRQ_priority_table[16] =
|
||||
{ 0,1,2,9,10,11,12,13,14,15,3,4,5,6,7,8 };
|
||||
switch (val) {
|
||||
case 0x0A: /* select read interrupt request register */
|
||||
pic->request_issr=false;
|
||||
break;
|
||||
case 0x0B: /* select read interrupt in-service register */
|
||||
pic->request_issr=true;
|
||||
break;
|
||||
case 0x10: /* ICW1 */
|
||||
pic->icw_index=1;
|
||||
pic->icw_words=2;
|
||||
break;
|
||||
case 0x11: /* ICW1 + need for ICW4 */
|
||||
pic->icw_index=1;
|
||||
pic->icw_words=3;
|
||||
break;
|
||||
case 0x20:case 0x21:case 0x22:case 0x23:case 0x24:case 0x25:case 0x26:case 0x27:
|
||||
if (PIC_IRQActive<(irq_base+8)) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
for (i=0; i<=15; i++){
|
||||
if(irqs[IRQ_priority_table[i]].inservice) {
|
||||
PIC_IRQActive=IRQ_priority_table[i];
|
||||
break;
|
||||
if (val&0x10) { // ICW1 issued
|
||||
if (val&0x02) E_Exit("PIC: single mode not handled"); // (would have to skip ICW3)
|
||||
if (val&0x04) E_Exit("PIC: 4 byte interval not handled");
|
||||
if (val&0x08) E_Exit("PIC: level triggered mode not handled");
|
||||
if (val&0xe0) E_Exit("PIC: 8080/8085 mode not handled");
|
||||
pic->icw_index=1; // next is ICW3
|
||||
pic->icw_words=2+val&0x01; // =3 if ICW4 needed
|
||||
} else if (val&0x08) { // OCW3 issued
|
||||
if (val&0x04) E_Exit("PIC: poll command not handled");
|
||||
if (val&0x02) { // function select
|
||||
if (val&0x01) pic->request_issr=true; /* select read interrupt in-service register */
|
||||
else pic->request_issr=false; /* select read interrupt request register */
|
||||
}
|
||||
if (val&0x40) { // special mask select
|
||||
if (val&0x20) pic->special=true;
|
||||
else pic->special=false;
|
||||
LOG(LOG_PIC,LOG_NORMAL)("port %X : special mask %s",port,(pic->special)?"ON":"OFF");
|
||||
}
|
||||
} else { // OCW2 issued
|
||||
if (val&0x20) { // EOI commands
|
||||
if (val&0x80) E_Exit("rotate mode not supported");
|
||||
if (val&0x40) { // specific EOI
|
||||
if (PIC_IRQActive==(irq_base+val-0x60U)) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
for (i=0; i<=15; i++) {
|
||||
if (irqs[IRQ_priority_table[i]].inservice) {
|
||||
PIC_IRQActive=IRQ_priority_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} //TODO Warnings?
|
||||
break;
|
||||
case 0x4a: /* OCW3 select read interrupt request register */
|
||||
LOG(LOG_PIC,LOG_NORMAL)("port %X : special OFF",port);
|
||||
pic->special = false;
|
||||
pic->request_issr = false;
|
||||
break;
|
||||
case 0x60:case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:case 0x67:
|
||||
/* Spefific EOI 0-7 */
|
||||
if (PIC_IRQActive==(irq_base+val-0x60U)) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
for (i=0; i<=15; i++) {
|
||||
if (irqs[IRQ_priority_table[i]].inservice) {
|
||||
PIC_IRQActive=IRQ_priority_table[i];
|
||||
break;
|
||||
if (val&0x80); // perform rotation
|
||||
} else { // nonspecific EOI
|
||||
if (PIC_IRQActive<(irq_base+8)) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
for (i=0; i<=15; i++){
|
||||
if(irqs[IRQ_priority_table[i]].inservice) {
|
||||
PIC_IRQActive=IRQ_priority_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val&0x80); // perform rotation
|
||||
}
|
||||
}//TODO Warnings?
|
||||
break;
|
||||
case 0x68:/* OCW3 select */
|
||||
pic->special=true;
|
||||
LOG(LOG_PIC,LOG_NORMAL)("port %X : special ON",port);
|
||||
break;
|
||||
case 0x6b: /* OCW3 select read interrupt in-service register */
|
||||
LOG(LOG_PIC,LOG_NORMAL)("port %X : special ON",port);
|
||||
pic->special = true;
|
||||
pic->request_issr = true;
|
||||
break;
|
||||
case 0xC0:case 0xC1:case 0xC2:case 0xC3:case 0xC4:case 0xC5:case 0xC6:case 0xC7:
|
||||
/* Priority order, no need for it */
|
||||
break;
|
||||
case 0x00:case 0x80: /* Rotate stuff in eoi mode */
|
||||
/* We can live without it for now. (7 cities of gold) */
|
||||
LOG(LOG_PIC,LOG_NORMAL)("port %X : ignoring rotate stuff.",port);
|
||||
break;
|
||||
default:
|
||||
E_Exit("PIC:Unhandled command %02X",val);
|
||||
}
|
||||
} else {
|
||||
if ((val&0x40)==0) { // rotate in auto EOI mode
|
||||
if (val&0x80) pic->rotate_on_auto_eoi=true;
|
||||
else pic->rotate_on_auto_eoi=false;
|
||||
} else if (val&0x80) {
|
||||
E_Exit("set priority command not handled");
|
||||
} // else NOP command
|
||||
}
|
||||
} // end OCW2
|
||||
}
|
||||
|
||||
static void write_data(Bitu port,Bitu val,Bitu iolen) {
|
||||
|
@ -174,7 +166,7 @@ static void write_data(Bitu port,Bitu val,Bitu iolen) {
|
|||
case 3: /* icw 4 */
|
||||
/*
|
||||
0 1 8086/8080 0 mcs-8085 mode
|
||||
1 1 Auto EOI 1 Normal EOI
|
||||
1 1 Auto EOI 0 Normal EOI
|
||||
2-3 0x Non buffer Mode
|
||||
10 Buffer Mode Slave
|
||||
11 Buffer mode Master
|
||||
|
@ -183,9 +175,13 @@ static void write_data(Bitu port,Bitu val,Bitu iolen) {
|
|||
pic->auto_eoi=(val & 0x2)>0;
|
||||
|
||||
LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",port==0x21 ? 0 : 1,val);
|
||||
|
||||
if ((val&0x01)==0) E_Exit("PIC:ICW4: %x, 8085 mode not handled",val);
|
||||
if ((val&0x10)==0) E_Exit("PIC:ICW4: %x, special fully-nested mode not handled",val);
|
||||
|
||||
if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0;
|
||||
break;
|
||||
default: /* icw 3, and 4*/
|
||||
default:
|
||||
LOG(LOG_PIC,LOG_NORMAL)("ICW HUH? %X",val);
|
||||
}
|
||||
}
|
||||
|
@ -246,15 +242,16 @@ void PIC_runIRQs(void) {
|
|||
Bit16u activeIRQ = PIC_IRQActive;
|
||||
if (activeIRQ==PIC_NOIRQ) activeIRQ = 16;
|
||||
for (i=0;i<=15;i++) {
|
||||
if ((IRQ_priority_lookup[i]<IRQ_priority_lookup[activeIRQ]) || (pics[ (i<8)?0:1].special) ){
|
||||
if (!irqs[i].masked && irqs[i].active) {
|
||||
if ((IRQ_priority_lookup[i]<IRQ_priority_lookup[activeIRQ]) || (pics[ (i<8)?0:1].special) ){
|
||||
if (!irqs[i].masked && irqs[i].active) if (i != 2) {
|
||||
irqs[i].active=false;
|
||||
PIC_IRQCheck&=~(1 << i);
|
||||
if (i==2) i=9;
|
||||
CPU_HW_Interrupt(irqs[i].vector);
|
||||
if (!pics[0].auto_eoi) {
|
||||
PIC_IRQActive=i;
|
||||
irqs[i].inservice=true;
|
||||
} else if (pics[0].rotate_on_auto_eoi) {
|
||||
E_Exit("rotate on auto EOI not handled");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -442,7 +439,7 @@ void PIC_Init(Section* sec) {
|
|||
pics[i].active=0;
|
||||
pics[i].inservice=0;
|
||||
pics[i].auto_eoi=false;
|
||||
pics[i].auto_eoi=false;
|
||||
pics[i].rotate_on_auto_eoi=false;
|
||||
pics[i].request_issr=false;
|
||||
pics[i].special=false;
|
||||
pics[i].icw_index=0;
|
||||
|
|
Loading…
Add table
Reference in a new issue