/[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

Annotation of /src/io/pic/pic.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 8 months ago) by dpavlin
File size: 4771 byte(s)
import upstream CVS
1 dpavlin 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, gCPU.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, gCPU.pc);
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