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: Grand Central Interrupt controller (used by MacPPC)
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "cpu.h"
36 #include "device.h"
37 #include "machine.h"
38 #include "memory.h"
39 #include "misc.h"
40 
41 
42 #define	DEV_GC_LENGTH		0x100
43 
44 struct gc_data {
45 	struct interrupt cpu_irq;
46 
47 	uint32_t	status_hi;
48 	uint32_t	status_lo;
49 	uint32_t	enable_hi;
50 	uint32_t	enable_lo;
51 };
52 
53 
gc_hi_interrupt_assert(struct interrupt * interrupt)54 void gc_hi_interrupt_assert(struct interrupt *interrupt)
55 {
56 	struct gc_data *d = (struct gc_data *) interrupt->extra;
57 	d->status_hi |= interrupt->line;
58 	if (d->status_lo & d->enable_lo || d->status_hi & d->enable_hi)
59 		INTERRUPT_ASSERT(d->cpu_irq);
60 }
gc_hi_interrupt_deassert(struct interrupt * interrupt)61 void gc_hi_interrupt_deassert(struct interrupt *interrupt)
62 {
63 	struct gc_data *d = (struct gc_data *) interrupt->extra;
64 	d->status_hi &= ~interrupt->line;
65 	if (!(d->status_lo & d->enable_lo || d->status_hi & d->enable_hi))
66 		INTERRUPT_DEASSERT(d->cpu_irq);
67 }
gc_lo_interrupt_assert(struct interrupt * interrupt)68 void gc_lo_interrupt_assert(struct interrupt *interrupt)
69 {
70 	struct gc_data *d = (struct gc_data *) interrupt->extra;
71 	d->status_lo |= interrupt->line;
72 	if (d->status_lo & d->enable_lo || d->status_hi & d->enable_hi)
73 		INTERRUPT_ASSERT(d->cpu_irq);
74 }
gc_lo_interrupt_deassert(struct interrupt * interrupt)75 void gc_lo_interrupt_deassert(struct interrupt *interrupt)
76 {
77 	struct gc_data *d = (struct gc_data *) interrupt->extra;
78 	d->status_lo &= ~interrupt->line;
79 	if (!(d->status_lo & d->enable_lo || d->status_hi & d->enable_hi))
80 		INTERRUPT_DEASSERT(d->cpu_irq);
81 }
82 
83 
DEVICE_ACCESS(gc)84 DEVICE_ACCESS(gc)
85 {
86 	struct gc_data *d = (struct gc_data *) extra;
87 	uint64_t idata = 0, odata = 0;
88 
89 	if (writeflag == MEM_WRITE)
90 		idata = memory_readmax64(cpu, data, len);
91 
92 	switch (relative_addr) {
93 
94 #if 0
95 #define INT_STATE_REG_H  (interrupt_reg + 0x00)
96 #define INT_ENABLE_REG_H (interrupt_reg + 0x04)
97 #define INT_CLEAR_REG_H  (interrupt_reg + 0x08)
98 #define INT_LEVEL_REG_H  (interrupt_reg + 0x0c)
99 #define INT_STATE_REG_L  (interrupt_reg + 0x10)
100 #define INT_ENABLE_REG_L (interrupt_reg + 0x14)
101 #define INT_CLEAR_REG_L  (interrupt_reg + 0x18)
102 #define INT_LEVEL_REG_L  (interrupt_reg + 0x1c)
103 #endif
104 
105 	case 0x10:
106 		if (writeflag == MEM_READ)
107 			odata = d->status_hi & d->enable_hi;
108 		break;
109 
110 	case 0x14:
111 		if (writeflag == MEM_READ)
112 			odata = d->enable_hi;
113 		else {
114 			int old_assert = (d->status_lo & d->enable_lo
115 			    || d->status_hi & d->enable_hi);
116 			int new_assert;
117 			d->enable_hi = idata;
118 
119 			new_assert = (d->status_lo & d->enable_lo ||
120 			    d->status_hi & d->enable_hi);
121 
122 			if (old_assert && !new_assert)
123 				INTERRUPT_DEASSERT(d->cpu_irq);
124 			else if (!old_assert && new_assert)
125 				INTERRUPT_ASSERT(d->cpu_irq);
126 		}
127 		break;
128 
129 	case 0x18:
130 		if (writeflag == MEM_WRITE) {
131 			int old_assert = (d->status_lo & d->enable_lo
132 			    || d->status_hi & d->enable_hi);
133 			int new_assert;
134 			d->status_hi &= ~idata;
135 
136 			new_assert = (d->status_lo & d->enable_lo ||
137 			    d->status_hi & d->enable_hi);
138 
139 			if (old_assert && !new_assert)
140 				INTERRUPT_DEASSERT(d->cpu_irq);
141 			else if (!old_assert && new_assert)
142 				INTERRUPT_ASSERT(d->cpu_irq);
143 		}
144 		break;
145 
146 	case 0x20:
147 		if (writeflag == MEM_READ)
148 			odata = d->status_lo & d->enable_lo;
149 		break;
150 
151 	case 0x24:
152 		if (writeflag == MEM_READ)
153 			odata = d->enable_lo;
154 		else {
155 			int old_assert = (d->status_lo & d->enable_lo
156 			    || d->status_hi & d->enable_hi);
157 			int new_assert;
158 			d->enable_lo = idata;
159 
160 			new_assert = (d->status_lo & d->enable_lo ||
161 			    d->status_hi & d->enable_hi);
162 
163 			if (old_assert && !new_assert)
164 				INTERRUPT_DEASSERT(d->cpu_irq);
165 			else if (!old_assert && new_assert)
166 				INTERRUPT_ASSERT(d->cpu_irq);
167 		}
168 		break;
169 
170 	case 0x28:
171 		if (writeflag == MEM_WRITE) {
172 			int old_assert = (d->status_lo & d->enable_lo
173 			    || d->status_hi & d->enable_hi);
174 			int new_assert;
175 			d->status_lo &= ~idata;
176 
177 			new_assert = (d->status_lo & d->enable_lo ||
178 			    d->status_hi & d->enable_hi);
179 
180 			if (old_assert && !new_assert)
181 				INTERRUPT_DEASSERT(d->cpu_irq);
182 			else if (!old_assert && new_assert)
183 				INTERRUPT_ASSERT(d->cpu_irq);
184 		}
185 		break;
186 
187 	case 0x1c:
188 	case 0x2c:
189 		/*  Avoid a debug message.  */
190 		break;
191 
192 	default:if (writeflag == MEM_WRITE) {
193 			fatal("[ gc: unimplemented write to "
194 			    "offset 0x%x: data=0x%x ]\n", (int)
195 			    relative_addr, (int)idata);
196 		} else {
197 			fatal("[ gc: unimplemented read from "
198 			    "offset 0x%x ]\n", (int)relative_addr);
199 		}
200 	}
201 
202 	if (writeflag == MEM_READ)
203 		memory_writemax64(cpu, data, len, odata);
204 
205 	return 1;
206 }
207 
208 
DEVINIT(gc)209 DEVINIT(gc)
210 {
211 	struct gc_data *d;
212 	int i;
213 
214 	CHECK_ALLOCATION(d = (struct gc_data *) malloc(sizeof(struct gc_data)));
215 	memset(d, 0, sizeof(struct gc_data));
216 
217 	/*  Connect to the CPU interrupt pin:  */
218 	INTERRUPT_CONNECT(devinit->interrupt_path, d->cpu_irq);
219 
220 	/*
221 	 *  Register the 64 Grand Central interrupts (32 lo, 32 hi):
222 	 */
223 	for (i=0; i<32; i++) {
224 		struct interrupt templ;
225 		char n[300];
226 		snprintf(n, sizeof(n), "%s.gc.lo.%i",
227 		    devinit->interrupt_path, i);
228 		memset(&templ, 0, sizeof(templ));
229 		templ.line = 1 << i;
230 		templ.name = n;
231 		templ.extra = d;
232 		templ.interrupt_assert = gc_lo_interrupt_assert;
233 		templ.interrupt_deassert = gc_lo_interrupt_deassert;
234 		interrupt_handler_register(&templ);
235 
236 		snprintf(n, sizeof(n), "%s.gc.hi.%i",
237 		    devinit->interrupt_path, i);
238 		memset(&templ, 0, sizeof(templ));
239 		templ.line = 1 << i;
240 		templ.name = n;
241 		templ.extra = d;
242 		templ.interrupt_assert = gc_hi_interrupt_assert;
243 		templ.interrupt_deassert = gc_hi_interrupt_deassert;
244 		interrupt_handler_register(&templ);
245 	}
246 
247 	memory_device_register(devinit->machine->memory, "gc",
248 	    devinit->addr, DEV_GC_LENGTH, dev_gc_access, d, DM_DEFAULT, NULL);
249 
250 	return 1;
251 }
252 
253