From 688c8f114f13536eeb2ef0e616b74e4ebc62bd64 Mon Sep 17 00:00:00 2001 From: Peter Veenstra Date: Tue, 7 Dec 2004 21:29:14 +0000 Subject: [PATCH] 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 --- src/hardware/pic.cpp | 133 +++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 68 deletions(-) diff --git a/src/hardware/pic.cpp b/src/hardware/pic.cpp index 3a412567..279b80ce 100644 --- a/src/hardware/pic.cpp +++ b/src/hardware/pic.cpp @@ -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 @@ -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]