dev_8259.cc Source File
Back to the index.
src
devices
dev_8259.cc
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2005-2009 Anders Gavare. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
6
*
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
* 3. The name of the author may not be used to endorse or promote products
13
* derived from this software without specific prior written permission.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*
27
*
28
* COMMENT: Intel 8259 Programmable Interrupt Controller
29
*
30
* See the following URL for more details:
31
* http://www.nondot.org/sabre/os/files/MiscHW/8259pic.txt
32
*/
33
34
#include <stdio.h>
35
#include <stdlib.h>
36
#include <string.h>
37
38
#include "
cpu.h
"
39
#include "
device.h
"
40
#include "
devices.h
"
41
#include "
emul.h
"
42
#include "
machine.h
"
43
#include "
memory.h
"
44
#include "
misc.h
"
45
46
47
#define DEV_8259_LENGTH 2
48
49
/* #define DEV_8259_DEBUG */
50
51
52
DEVICE_ACCESS
(8259)
53
{
54
struct
pic8259_data
*d = (
struct
pic8259_data
*) extra;
55
uint64_t idata = 0, odata = 0;
56
int
i;
57
58
if
(writeflag ==
MEM_WRITE
)
59
idata =
memory_readmax64
(
cpu
,
data
, len);
60
61
#ifdef DEV_8259_DEBUG
62
if
(writeflag ==
MEM_READ
)
63
fatal
(
"[ 8259: read from 0x%x ]\n"
, (
int
)relative_addr);
64
else
65
fatal
(
"[ 8259: write to 0x%x: 0x%x ]\n"
,
66
(
int
)relative_addr, (
int
)idata);
67
#endif
68
69
switch
(relative_addr) {
70
case
0x00:
71
if
(writeflag ==
MEM_WRITE
) {
72
if
((idata & 0x10) == 0x10) {
73
/* Bit 3: 0=edge, 1=level */
74
if
(idata & 0x08)
75
fatal
(
"[ 8259: TODO: Level "
76
"triggered (MCA bus) ]\n"
);
77
if
(idata & 0x04)
78
fatal
(
"[ 8259: WARNING: Bit 2 set ]\n"
);
79
/* Bit 1: 0=cascade, 1=single */
80
/* Bit 0: 1=4th init byte */
81
/* This happens on non-x86 systems:
82
if (!(idata & 0x01))
83
fatal("[ 8259: WARNING: Bit 0 NOT set!"
84
"!! ]\n"); */
85
d->
init_state
= 1;
86
break
;
87
}
88
89
/* TODO: Is it ok to abort init state when there
90
is a non-init command? */
91
if
(d->
init_state
)
92
fatal
(
"[ 8259: WARNING: Was in init-state, but"
93
" it was aborted? ]\n"
);
94
d->
init_state
= 0;
95
96
if
(idata == 0x0a) {
97
d->
current_command
= 0x0a;
98
}
else
if
(idata == 0x0b) {
99
d->
current_command
= 0x0b;
100
}
else
if
(idata == 0x0c) {
101
/* Put Master in Buffered Mode */
102
d->
current_command
= 0x0c;
103
}
else
if
(idata == 0x20) {
104
int
old_irr = d->
irr
;
105
/* End Of Interrupt */
106
/* TODO: in buffered mode, is this an EOI 0? */
107
d->
irr
&= ~d->
isr
;
108
d->
isr
= 0;
109
/* Recalculate interrupt assertions,
110
if necessary: */
111
if
((old_irr & ~d->
ier
) != (d->
irr
& ~d->
ier
)) {
112
if
(d->
irr
& ~d->
ier
)
113
INTERRUPT_ASSERT
(d->
irq
);
114
else
115
INTERRUPT_DEASSERT
(d->
irq
);
116
}
117
}
else
if
((idata >= 0x21 && idata <= 0x27) ||
118
(idata >= 0x60 && idata <= 0x67) ||
119
(idata >= 0xe0 && idata <= 0xe7)) {
120
/* Specific EOI */
121
int
old_irr = d->
irr
;
122
d->
irr
&= ~(1 << (idata & 7));
123
d->
isr
&= ~(1 << (idata & 7));
124
/* Recalc. int assertions, if necessary: */
125
if
((old_irr & ~d->
ier
) != (d->
irr
& ~d->
ier
)) {
126
if
(d->
irr
& ~d->
ier
)
127
INTERRUPT_ASSERT
(d->
irq
);
128
else
129
INTERRUPT_DEASSERT
(d->
irq
);
130
}
131
}
else
if
(idata == 0x68) {
132
/* Set Special Mask Mode */
133
/* TODO */
134
}
else
if
(idata >= 0xc0 && idata <= 0xc7) {
135
/* Set IRQ Priority Order */
136
/* TODO */
137
}
else
{
138
fatal
(
"[ 8259: unimplemented command 0x%02x"
139
" ]\n"
, (
int
)idata);
140
cpu
->
running
= 0;
141
}
142
}
else
{
143
switch
(d->
current_command
) {
144
case
0x0a:
145
odata = d->
irr
;
146
break
;
147
case
0x0b:
148
odata = d->
isr
;
149
break
;
150
case
0x0c:
151
/* Buffered mode. */
152
odata = 0x00;
153
for
(i=0; i<8; i++)
154
if
((d->
irr
>> i) & 1) {
155
odata = 0x80 | i;
156
break
;
157
}
158
break
;
159
default
:
160
odata = 0x00;
161
for
(i=0; i<8; i++)
162
if
((d->
irr
>> i) & 1) {
163
odata = 0x80 | i;
164
break
;
165
}
166
break
;
167
/*
168
* TODO: The "default" label should really do
169
* something like this:
170
*
171
* fatal("[ 8259: unimplemented command 0x%02x"
172
* " while reading ]\n", d->current_command);
173
* cpu->running = 0;
174
*
175
* but Linux seems to read from the secondary PIC
176
* in a manner which works better the way things
177
* are coded right now.
178
*/
179
}
180
}
181
break
;
182
case
0x01:
183
if
(d->
init_state
> 0) {
184
if
(d->
init_state
== 1) {
185
d->
irq_base
= idata & 0xf8;
186
/* This happens on non-x86 machines:
187
if (idata & 7)
188
fatal("[ 8259: WARNING! Lowest"
189
" bits in Init Cmd 1 are"
190
" non-zero! ]\n"); */
191
d->
init_state
= 2;
192
}
else
if
(d->
init_state
== 2) {
193
/* Slave attachment. TODO */
194
d->
init_state
= 3;
195
}
else
if
(d->
init_state
== 3) {
196
if
(idata & 0x02) {
197
/* Should not be set in PCs, but
198
on CATS, for example, it is set. */
199
debug
(
"[ 8259: WARNING! Bit 1 i"
200
"n Init Cmd 4 is set! ]\n"
);
201
}
202
if
(!(idata & 0x01))
203
fatal
(
"[ 8259: WARNING! Bit 0 "
204
"in Init Cmd 4 is not"
205
" set! ]\n"
);
206
d->
init_state
= 0;
207
}
208
break
;
209
}
210
211
if
(writeflag ==
MEM_WRITE
) {
212
int
old_ier = d->
ier
;
213
d->
ier
= idata;
214
215
/* Recalculate interrupt assertions,
216
if necessary: */
217
if
((d->
irr
& ~old_ier) != (d->
irr
& ~d->
ier
)) {
218
if
(d->
irr
& ~d->
ier
)
219
INTERRUPT_ASSERT
(d->
irq
);
220
else
221
INTERRUPT_DEASSERT
(d->
irq
);
222
}
223
}
else
{
224
odata = d->
ier
;
225
}
226
break
;
227
default
:
228
if
(writeflag ==
MEM_WRITE
) {
229
fatal
(
"[ 8259: unimplemented write to address 0x%x"
230
" data=0x%02x ]\n"
, (
int
)relative_addr, (
int
)idata);
231
cpu
->
running
= 0;
232
}
else
{
233
fatal
(
"[ 8259: unimplemented read from address 0x%x "
234
"]\n"
, (
int
)relative_addr);
235
cpu
->
running
= 0;
236
}
237
}
238
239
if
(writeflag ==
MEM_READ
)
240
memory_writemax64
(
cpu
,
data
, len, odata);
241
242
return
1;
243
}
244
245
246
/*
247
* devinit_8259():
248
*
249
* Initialize an 8259 PIC. Important notes:
250
*
251
* x) Most systems use _TWO_ 8259 PICs. These should be registered
252
* as separate devices.
253
*
254
* x) The irq number specified is the number used to re-calculate
255
* CPU interrupt assertions. It is _not_ the irq number at
256
* which the PIC is connected. (That is left to machine specific
257
* code in src/machine.c.)
258
*/
259
DEVINIT
(8259)
260
{
261
struct
pic8259_data
*d;
262
char
*name2;
263
size_t
nlen =
strlen
(
devinit
->
name
) + 20;
264
265
CHECK_ALLOCATION
(d = (
struct
pic8259_data
*) malloc(
sizeof
(
struct
pic8259_data
)));
266
memset(d, 0,
sizeof
(
struct
pic8259_data
));
267
268
INTERRUPT_CONNECT
(
devinit
->
interrupt_path
, d->
irq
);
269
270
CHECK_ALLOCATION
(name2 = (
char
*) malloc(nlen));
271
snprintf(name2, nlen,
"%s"
,
devinit
->
name
);
272
if
((
devinit
->
addr
& 0xfff) == 0xa0) {
273
strlcat(name2,
" [secondary]"
, nlen);
274
d->
irq_base
= 8;
275
}
276
277
memory_device_register
(
devinit
->
machine
->
memory
, name2,
278
devinit
->
addr
,
DEV_8259_LENGTH
, dev_8259_access, d,
279
DM_DEFAULT
, NULL);
280
281
devinit
->
return_ptr
= d;
282
return
1;
283
}
284
pic8259_data::irq_base
int irq_base
Definition:
devices.h:66
pic8259_data::irq
struct interrupt irq
Definition:
devices.h:64
data
u_short data
Definition:
siireg.h:79
INTERRUPT_CONNECT
#define INTERRUPT_CONNECT(name, istruct)
Definition:
interrupt.h:77
DEVICE_ACCESS
DEVICE_ACCESS(8259)
Definition:
dev_8259.cc:52
INTERRUPT_ASSERT
#define INTERRUPT_ASSERT(istruct)
Definition:
interrupt.h:74
cpu::running
uint8_t running
Definition:
cpu.h:353
debug
#define debug
Definition:
dev_adb.cc:57
devinit::addr
uint64_t addr
Definition:
device.h:46
memory_device_register
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition:
memory.cc:339
MEM_READ
#define MEM_READ
Definition:
memory.h:116
DEVINIT
DEVINIT(8259)
Definition:
dev_8259.cc:259
DM_DEFAULT
#define DM_DEFAULT
Definition:
memory.h:130
devinit::machine
struct machine * machine
Definition:
device.h:41
device.h
pic8259_data::init_state
int init_state
Definition:
devices.h:69
MEM_WRITE
#define MEM_WRITE
Definition:
memory.h:117
devinit::interrupt_path
char * interrupt_path
Definition:
device.h:50
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition:
cpu_arm_instr.cc:2686
fatal
void fatal(const char *fmt,...)
Definition:
main.cc:152
misc.h
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition:
memory.cc:55
machine.h
DEV_8259_LENGTH
#define DEV_8259_LENGTH
Definition:
dev_8259.cc:47
devinit::name
char * name
Definition:
device.h:43
emul.h
pic8259_data
Definition:
devices.h:63
devinit
Definition:
device.h:40
cpu.h
machine::memory
struct memory * memory
Definition:
machine.h:126
pic8259_data::irr
uint8_t irr
Definition:
devices.h:72
devinit::return_ptr
void * return_ptr
Definition:
device.h:56
pic8259_data::ier
uint8_t ier
Definition:
devices.h:74
INTERRUPT_DEASSERT
#define INTERRUPT_DEASSERT(istruct)
Definition:
interrupt.h:75
pic8259_data::isr
uint8_t isr
Definition:
devices.h:73
pic8259_data::current_command
int current_command
Definition:
devices.h:67
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition:
memory.cc:89
devices.h
cpu
Definition:
cpu.h:326
memory.h
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition:
misc.h:239
Generated on Tue Aug 25 2020 19:25:06 for GXemul by
1.8.18