ReactOS 0.4.16-dev-297-gc569aee
pic.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: subsystems/mvdm/ntvdm/hardware/pic.c
5 * PURPOSE: Programmable Interrupt Controller emulation
6 * (Interrupt Controller Adapter (ICA) in Windows terminology)
7 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
8 */
9
10/* INCLUDES *******************************************************************/
11
12#include "ntvdm.h"
13
14#define NDEBUG
15#include <debug.h>
16
17#include "emulator.h"
18#include "pic.h"
19
20#include "io.h"
21
22/* PRIVATE VARIABLES **********************************************************/
23
24typedef struct _PIC
25{
38
40
41/* PRIVATE FUNCTIONS **********************************************************/
42
44{
45 PPIC Pic;
46
47 /* Which PIC are we accessing? */
48 if (Port == PIC_MASTER_CMD)
49 Pic = &MasterPic;
50 else // if (Port == PIC_SLAVE_CMD)
51 Pic = &SlavePic;
52
53 if (Pic->ReadIsr)
54 {
55 /* Read the in-service register */
56 Pic->ReadIsr = FALSE;
57 return Pic->InServiceRegister;
58 }
59 else
60 {
61 /* Read the interrupt request register */
62 return Pic->IntRequestRegister;
63 }
64}
65
67{
68 PPIC Pic;
69
70 /* Which PIC are we accessing? */
71 if (Port == PIC_MASTER_CMD)
72 Pic = &MasterPic;
73 else // if (Port == PIC_SLAVE_CMD)
74 Pic = &SlavePic;
75
76 if (Data & PIC_ICW1)
77 {
78 /* Start initialization */
79 Pic->Initialization = TRUE;
80 Pic->IntOffset = 0xFF;
82 Pic->ConfigRegister = Data;
83 return;
84 }
85
86 if (Data & PIC_OCW3)
87 {
88 /* This is an OCR3 */
90 {
91 /* Return the ISR on next read from command port */
92 Pic->ReadIsr = TRUE;
93 }
94
95 return;
96 }
97
98 /* This is an OCW2 */
99 if (Data & PIC_OCW2_EOI)
100 {
101 if (Data & PIC_OCW2_SL)
102 {
103 /* If the SL bit is set, clear a specific IRQ */
104 Pic->InServiceRegister &= ~(1 << (Data & PIC_OCW2_NUM_MASK));
105 }
106 else
107 {
108 /* Otherwise, clear all of them */
109 Pic->InServiceRegister = 0;
110 }
111
113 {
114 /* Signal the next IRQ */
116 }
117 }
118}
119
121{
122 /* Read the mask register */
123 if (Port == PIC_MASTER_DATA)
124 return MasterPic.MaskRegister;
125 else // if (Port == PIC_SLAVE_DATA)
126 return SlavePic.MaskRegister;
127}
128
130{
131 PPIC Pic;
132
133 /* Which PIC are we accessing? */
134 if (Port == PIC_MASTER_DATA)
135 Pic = &MasterPic;
136 else // if (Port == PIC_SLAVE_DATA)
137 Pic = &SlavePic;
138
139 /* Is the PIC ready? */
140 if (!Pic->Initialization)
141 {
142 /* Yes, this is an OCW1 */
143 Pic->MaskRegister = Data;
144 return;
145 }
146
147 /* Has the interrupt offset been set? */
148 if (Pic->IntOffset == 0xFF)
149 {
150 /* This is an ICW2, set the offset (last three bits always zero) */
151 Pic->IntOffset = Data & 0xF8;
152
153 /* Check if we are in single mode and don't need an ICW4 */
155 && !(Pic->ConfigRegister & PIC_ICW1_ICW4))
156 {
157 /* Yes, done initializing */
158 Pic->Initialization = FALSE;
159 }
160 return;
161 }
162
163 /* Check if we are in cascade mode and the cascade register was not set */
165 {
166 /* This is an ICW3 */
167 Pic->CascadeRegister = Data;
169
170 /* Check if we need an ICW4 */
171 if (!(Pic->ConfigRegister & PIC_ICW1_ICW4))
172 {
173 /* No, done initializing */
174 Pic->Initialization = FALSE;
175 }
176 return;
177 }
178
179 /* This must be an ICW4, we will ignore the 8086 bit (assume always set) */
180 if (Data & PIC_ICW4_AEOI)
181 {
182 /* Use automatic end-of-interrupt */
183 Pic->AutoEoi = TRUE;
184 }
185
186 /* Done initializing */
187 Pic->Initialization = FALSE;
188}
189
190/* PUBLIC FUNCTIONS ***********************************************************/
191
193{
194 BYTE i;
195
196 if (/* Number >= 0 && */ Number < 8)
197 {
198 /* Check if any of the higher-priority interrupts are busy */
199 for (i = 0; i <= Number; i++)
200 {
201 if (MasterPic.InServiceRegister & (1 << Number)) return;
202 }
203
204 /* Check if the interrupt is masked */
205 if (MasterPic.MaskRegister & (1 << Number)) return;
206
207 /* Set the appropriate bit in the IRR and interrupt the CPU */
210 }
211 else if (Number >= 8 && Number < 16)
212 {
213 Number -= 8;
214
215 /*
216 * The slave PIC is connected to IRQ 2, always! If the master PIC
217 * was misconfigured, don't do anything.
218 */
219 if (!(MasterPic.CascadeRegister & (1 << 2))
221 {
222 return;
223 }
224
225 /* Check if any of the higher-priority interrupts are busy */
226 if (MasterPic.InServiceRegister != 0) return;
227 for (i = 0; i <= Number; i++)
228 {
229 if (SlavePic.InServiceRegister & (1 << Number)) return;
230 }
231
232 /* Check if the interrupt is masked */
233 if (SlavePic.MaskRegister & (1 << Number)) return;
234
235 /* Set the IRQ 2 bit in the master ISR */
237
238 /* Set the appropriate bit in the IRR and interrupt the CPU */
241 }
242}
243
245{
246 UINT i;
247
248 /* Search the master PIC interrupts by priority */
249 for (i = 0; i < 8; i++)
250 {
251 if (MasterPic.IntRequestRegister & (1 << i))
252 {
253 /* Clear the IRR flag */
254 MasterPic.IntRequestRegister &= ~(1 << i);
255
256 /* Set the ISR flag, unless AEOI is enabled */
258
259 /* Return the interrupt number */
260 return MasterPic.IntOffset + i;
261 }
262 }
263
264 /* Search the slave PIC interrupts by priority */
265 for (i = 0; i < 8; i++)
266 {
267 if (SlavePic.IntRequestRegister & (1 << i))
268 {
269 /* Clear the IRR flag */
270 SlavePic.IntRequestRegister &= ~(1 << i);
271
272 if ((i == 1) && SlavePic.CascadeRegisterSet)
273 {
274 /* This interrupt is routed to the master PIC */
276 }
277 else
278 {
279 /* Set the ISR flag, unless AEOI is enabled */
281
282 /* Return the interrupt number */
283 return SlavePic.IntOffset + i;
284 }
285 }
286 }
287
288 /* Spurious interrupt */
289 if (MasterPic.InServiceRegister & (1 << 2))
290 return SlavePic.IntOffset + 7;
291 else
292 return MasterPic.IntOffset + 7;
293}
294
296{
297 /* Register the I/O Ports */
302}
303
304
305
306VOID
307WINAPI
309 BYTE line,
310 INT count)
311{
312 BYTE InterruptNumber = line;
313
314 /* Check for PIC validity */
315 if (ms != ICA_MASTER && ms != ICA_SLAVE) return;
316
317 /*
318 * Adjust the interrupt request number according to the parameters,
319 * by adding an offset == 8 to the interrupt number.
320 *
321 * Indeed VDDs calling this function usually subtracts 8 so that they give:
322 *
323 * ms | line | corresponding interrupt number
324 * ------------+--------+--------------------------------
325 * ICA_MASTER | 0 -- 7 | 0 -- 7
326 * ICA_SLAVE | 0 -- 7 | 8 -- 15
327 *
328 * and PicInterruptRequest subtracts again 8 to the interrupt number
329 * if it is greater or equal than 8 (so that it determines which PIC
330 * to use via the interrupt number).
331 */
332 if (ms == ICA_SLAVE) InterruptNumber += 8;
333
334 /* Send the specified number of interrupt requests */
335 while (count-- > 0)
336 {
337 PicInterruptRequest(InterruptNumber);
338 /*
339 * FIXME: We should now restart 16-bit emulation and wait for its termination:
340 *
341 * "When the VDD calls VDDSimulateInterrupt, the address pointed to by
342 * the interrupt vector starts running in 16-bit mode. For an asynchronous
343 * interrupt, the VDD should create another thread and call VDDSimulateInterrupt
344 * from that thread."
345 */
346 }
347}
348
349WORD
350WINAPI
352 IN WORD IrqLine)
353{
356 return 0xFFFF;
357}
358
359BOOL
360WINAPI
362 IN WORD IrqLine)
363{
366 return FALSE;
367}
368
369/* EOF */
unsigned char BOOLEAN
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
VOID EmulatorInterruptSignal(VOID)
Definition: emulator.c:120
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
CPPORT Port[4]
Definition: headless.c:35
unsigned int UINT
Definition: ndis.h:50
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:207
unsigned short USHORT
Definition: pedump.c:61
Definition: pic.c:25
BYTE CascadeRegister
Definition: pic.c:32
BOOLEAN CascadeRegisterSet
Definition: pic.c:33
BYTE IntOffset
Definition: pic.c:30
BYTE IntRequestRegister
Definition: pic.c:28
BOOLEAN Slave
Definition: pic.c:35
BOOLEAN AutoEoi
Definition: pic.c:34
BYTE InServiceRegister
Definition: pic.c:29
BOOLEAN Initialization
Definition: pic.c:26
BYTE MaskRegister
Definition: pic.c:27
BYTE ConfigRegister
Definition: pic.c:31
BOOLEAN ReadIsr
Definition: pic.c:36
Definition: parser.c:49
static BYTE WINAPI PicReadCommand(USHORT Port)
Definition: pic.c:43
VOID PicInitialize(VOID)
Definition: pic.c:295
BYTE PicGetInterrupt(VOID)
Definition: pic.c:244
static PIC MasterPic
Definition: pic.c:39
static BYTE WINAPI PicReadData(USHORT Port)
Definition: pic.c:120
struct _PIC PIC
WORD WINAPI VDDReserveIrqLine(IN HANDLE hVdd, IN WORD IrqLine)
Definition: pic.c:351
VOID WINAPI call_ica_hw_interrupt(INT ms, BYTE line, INT count)
Definition: pic.c:308
struct _PIC * PPIC
VOID PicInterruptRequest(BYTE Number)
Definition: pic.c:192
BOOL WINAPI VDDReleaseIrqLine(IN HANDLE hVdd, IN WORD IrqLine)
Definition: pic.c:361
static VOID WINAPI PicWriteCommand(USHORT Port, BYTE Data)
Definition: pic.c:66
static VOID WINAPI PicWriteData(USHORT Port, BYTE Data)
Definition: pic.c:129
static PIC SlavePic
Definition: pic.c:39
#define PIC_ICW1_SINGLE
Definition: pic.h:22
#define PIC_OCW2_NUM_MASK
Definition: pic.h:26
#define PIC_OCW2_SL
Definition: pic.h:28
#define PIC_OCW2_EOI
Definition: pic.h:27
#define PIC_OCW3_READ_ISR
Definition: pic.h:31
#define PIC_SLAVE_DATA
Definition: pic.h:18
#define PIC_ICW1_ICW4
Definition: pic.h:21
#define PIC_MASTER_CMD
Definition: pic.h:15
#define PIC_SLAVE_CMD
Definition: pic.h:17
#define PIC_OCW3
Definition: pic.h:30
#define PIC_MASTER_DATA
Definition: pic.h:16
#define PIC_ICW1
Definition: pic.h:20
#define PIC_ICW4_AEOI
Definition: pic.h:24
VOID RegisterIoPort(USHORT Port, EMULATOR_INB_PROC InHandler, EMULATOR_OUTB_PROC OutHandler)
Definition: io.c:320
HANDLE hVdd
Definition: testvdd.c:87
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
#define ICA_MASTER
Definition: vddsvc.h:32
#define ICA_SLAVE
Definition: vddsvc.h:33
#define WINAPI
Definition: msvc.h:6
unsigned char BYTE
Definition: xxhash.c:193