/[pearpc]/src/io/pic/pic.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/io/pic/pic.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations)
Wed Sep 5 17:46:33 2007 UTC (16 years, 6 months ago) by dpavlin
File size: 4788 byte(s)
fix IO_PIC_TRACE
1 /*
2 * PearPC
3 * pic.cc
4 *
5 * Copyright (C) 2003 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <cstdlib>
22 #include <cstring>
23
24 #include "tools/snprintf.h"
25 #include "system/arch/sysendian.h"
26 #include "cpu/cpu.h"
27 #include "io/cuda/cuda.h"
28 #include "pic.h"
29 #include "debug/tracers.h"
30 #include "system/systhread.h"
31
32 uint32 PIC_enable_low;
33 uint32 PIC_enable_high;
34 uint32 PIC_pending_low;
35 uint32 PIC_pending_high;
36 uint32 PIC_pending_level;
37
38 sys_mutex PIC_mutex;
39
40 void pic_renew_interrupts()
41 {
42 if (((PIC_pending_low | PIC_pending_level) & PIC_enable_low) || (PIC_pending_high & PIC_enable_high)) {
43 ppc_cpu_raise_ext_exception();
44 } else {
45 ppc_cpu_cancel_ext_exception();
46 }
47 }
48
49 void pic_write(uint32 addr, uint32 data, int size)
50 {
51 IO_PIC_TRACE("write word @%08x: %08x (from %08x)\n", addr, data, ppc_cpu_get_pc);
52 addr -= IO_PIC_PA_START;
53 switch (addr) {
54 case 0x24:
55 case 0x14: {
56 // enable /disable
57 int o=0;
58 if (addr == 0x14) {
59 o = 32;
60 PIC_enable_high = data;
61 } else {
62 PIC_enable_low = data;
63 IO_PIC_TRACE("enable / disable\n");
64 }
65 int x = 1;
66 for (int i=0; i<31; i++) {
67 if (data & x) {
68 IO_PIC_TRACE("enable %d\n", o+i);
69 // gIRQ_Enable[o+i] = true;
70 } else {
71 // gIRQ_Enable[o+i] = false;
72 }
73 x<<=1;
74 }
75 break;
76 }
77 case 0x18:
78 // ack irq
79 IO_PIC_TRACE("ack high\n");
80 PIC_pending_high &= ~data;
81 break;
82 case 0x28:
83 // ack irq
84 IO_PIC_TRACE("ack low\n");
85 PIC_pending_low &= ~data;
86 break;
87 case 0x38:
88 IO_PIC_TRACE("sound\n");
89 data = 0;
90 break;
91 default:
92 IO_PIC_ERR("unknown service %08x (write(%d) %08x from %08x)\n", addr, size, data, ppc_cpu_get_pc(0));
93 }
94 pic_renew_interrupts();
95 }
96
97 void pic_read(uint32 addr, uint32 &data, int size)
98 {
99 IO_PIC_TRACE("read word @%08x (from %08x)\n", addr, ppc_cpu_get_pc(0));
100 addr -= IO_PIC_PA_START;
101 switch (addr) {
102 case 0x24:
103 case 0x14: {
104 // enable /disable
105 uint32 r;
106 if (addr == 0x14) {
107 r = PIC_enable_high;
108 } else {
109 r = PIC_enable_low;
110 }
111 IO_PIC_TRACE("enable / disable %08x\n", r);
112 data = r;
113 break;
114 }
115 case 0x10:
116 IO_PIC_TRACE("interrupt high? (pending_high is %08x)\n", PIC_pending_high);
117 data = PIC_pending_high;
118 break;
119 case 0x1c:
120 IO_PIC_TRACE("level2\n");
121 data = 0;
122 break;
123 case 0x20:
124 IO_PIC_TRACE("interrupt low? (pending_low is %08x)\n", PIC_pending_low);
125 data = PIC_pending_low;
126 break;
127 case 0x2c:
128 // level
129 IO_PIC_TRACE("level1 (%08x)\n", PIC_pending_level);
130 data = PIC_pending_level;
131 break;
132 case 0x38:
133 IO_PIC_TRACE("sound\n");
134 data = 0;
135 break;
136 default:
137 IO_PIC_ERR("unknown service %08x (read(%d) from %08x)\n", addr, size, ppc_cpu_get_pc(0));
138 }
139 }
140
141 void pic_raise_interrupt(int intr)
142 {
143 sys_lock_mutex(PIC_mutex);
144 uint32 mask, pending;
145 int intr_;
146 if (intr>31) {
147 mask = PIC_enable_high;
148 pending = PIC_pending_high;
149 intr_ = intr-32;
150 } else {
151 mask = PIC_enable_low;
152 pending = PIC_pending_low;
153 intr_ = intr;
154 }
155 uint32 ibit = 1<<intr_;
156 bool level = false;
157 if (intr>31) {
158 PIC_pending_high |= ibit;
159 } else {
160 PIC_pending_low |= ibit;
161 if (IO_PIC_LEVEL_TYPE & ibit) {
162 PIC_pending_level |= ibit;
163 level = true;
164 }
165 }
166 /*
167 * edge type:
168 * signal int if not masked and state raises from low to high
169 *
170 * level type:
171 * signal int if not masked and state high
172 */
173 if ((mask & ibit) &&
174 (level || !(pending & ibit))) {
175 IO_PIC_TRACE("*signal int: %d\n", intr);
176 ppc_cpu_raise_ext_exception();
177 } else {
178 IO_PIC_TRACE("/signal int: %d\n", intr);
179 }
180 sys_unlock_mutex(PIC_mutex);
181 ppc_cpu_wakeup();
182 }
183
184 void pic_cancel_interrupt(int intr)
185 {
186 sys_lock_mutex(PIC_mutex);
187 if (intr>31) {
188 PIC_pending_high &= ~(1<<(intr-32));
189 } else {
190 PIC_pending_low &= ~(1<<intr);
191 PIC_pending_level &= ~(1<<intr);
192 }
193 if (((PIC_pending_low | PIC_pending_level) & PIC_enable_low) || (PIC_pending_high & PIC_enable_high)) {
194 ppc_cpu_raise_ext_exception();
195 } else {
196 ppc_cpu_cancel_ext_exception();
197 }
198 sys_unlock_mutex(PIC_mutex);
199 }
200
201 void pic_init()
202 {
203 PIC_pending_low = 0;
204 PIC_pending_high = 0;
205 PIC_enable_low = 0;
206 PIC_enable_high = 0;
207 sys_create_mutex(&PIC_mutex);
208 }
209
210 void pic_done()
211 {
212 sys_destroy_mutex(PIC_mutex);
213 }
214
215 void pic_init_config()
216 {
217 }
218

  ViewVC Help
Powered by ViewVC 1.1.26