35 #define ICW1_IC4 0x01 // 1 = ICW4 needed 36 #define ICW1_SNGL 0x02 // 1 = single mode, 0 = cascade mode 37 #define ICW1_LTIM 0x08 // 1 = level trig imput, 0 = edge trig input 39 #define ICW4_PM 0x01 // 1 = x86, 0 = 8085 40 #define ICW4_AEOI 0x02 // 1 = auto EOI, 0 = normal EOI 41 #define ICW4_MS 0x04 // valid when ICW4_BUF = 1: 0 = buffered mode slave, 1 = buffered mode master 42 #define ICW4_BUF 0x08 // 1 = buffered mode, 0 = non buffered mode 43 #define ICW4_SFNM 0x10 // 1 = special fully nested mode 45 #define OCW2_EOI 0x20 // 1 = EOI command 46 #define OCW2_SL 0x40 // 1 = with EOI means Specific, with R means Set Priority 47 #define OCW2_R 0x80 // 1 = with EOI means Rotate, with SL means Set Priority 49 #define OCW3_RIS 0x01 // 1 = with OCW3_RR means Read IS register, 0 = with OCW3_RR means Read IR register 50 #define OCW3_RR 0x02 // 1 = OCW3_RIS specifies which register to read, 0 = no action 51 #define OCW3_POLL 0x04 // 1 = poll command 52 #define OCW3_SMM 0x08 // valid when OCW3_ESMM = 1: 0 = reset special mask, 1 = set special mask 54 #define PORT0_ICW1 0x10 // 1 = presenting ICW1 on port 0, 0 = presenting OCW2 or OCW3 on port 0 55 #define PORT0_OCW3 0x08 // 1 = presenting OCW3 on port 0, 0 = presenting OCW2 on port 0 59 #define STATE_READY 0x00 // waiting for ICW1/OCW2/OCW3 on port 0, OCW1 on port 1 60 #define STATE_WAITING_ICW2 0X01 // waiting for ICW2 on port 1 61 #define STATE_WAITING_ICW3 0X02 // waiting for ICW3 on port 2 62 #define STATE_WAITING_ICW4 0X04 // waiting for ICW4 on port 3 67 m_state = STATE_READY;
74 m_pendingInterrupt =
false;
79 void PIC8259::write(
int addr, uint8_t value)
84 if (value & PORT0_ICW1) {
88 m_state = STATE_WAITING_ICW2;
89 m_state |= value & ICW1_IC4 ? STATE_WAITING_ICW4 : 0;
90 m_state |= value & ICW1_SNGL ? 0 : STATE_WAITING_ICW3;
91 }
else if (value & PORT0_OCW3) {
96 m_readISR = value & OCW3_RIS;
101 if (value & OCW2_EOI) {
109 if (m_state & STATE_WAITING_ICW2) {
112 m_baseVector = value & 0xf8;
113 m_state &= ~STATE_WAITING_ICW2;
114 }
else if (m_state & STATE_WAITING_ICW3) {
118 m_state &= ~STATE_WAITING_ICW3;
119 }
else if (m_state & STATE_WAITING_ICW4) {
123 m_autoEOI = value & ICW4_AEOI;
124 m_state &= ~STATE_WAITING_ICW4;
135 uint8_t PIC8259::read(
int addr)
141 return m_readISR ? m_ISR : m_IRR;
156 int PIC8259::getHighestPriorityBitNum(uint8_t value)
159 for (
int i = 0; i < 8; ++i)
160 if ((value >> i) & 1)
168 void PIC8259::setPendingInterrupt()
170 int highestInt = getHighestPriorityBitNum(m_IRR & ~m_IMR);
171 int servicingInt = getHighestPriorityBitNum(m_ISR);
173 if (highestInt < servicingInt) {
175 m_pendingInterrupt =
true;
176 m_pendingIR = highestInt;
182 bool PIC8259::signalInterrupt(
int intnum)
185 bool success =
false;
188 if ((m_ISR & (1 << intnum)) == 0) {
190 m_IRR |= 1 << intnum;
191 setPendingInterrupt();
199 void PIC8259::ackPendingInterrupt()
202 int pendmsk = 1 << m_pendingIR;
205 m_pendingInterrupt =
false;
211 void PIC8259::performEOI()
215 int servicingInt = getHighestPriorityBitNum(m_ISR);
216 m_ISR &= ~(1 << servicingInt);
218 setPendingInterrupt();