1 /*
2 * Copyright (C) 2003-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: DEC KN230 (MIPSMATE 5100) stuff
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "device.h"
36 #include "interrupt.h"
37 #include "machine.h"
38 #include "memory.h"
39 #include "misc.h"
40
41 #include "thirdparty/dec_5100.h"
42
43
44 #define DEV_KN230_LENGTH 0x1c00000
45
46 struct kn230_data {
47 struct interrupt mips_irq_2;
48 struct interrupt mips_irq_3;
49
50 uint32_t csr;
51 };
52
53
54 /*
55 * kn230_interrupt_assert():
56 * kn230_interrupt_deassert():
57 *
58 * Called whenever a KN230 interrupt is asserted/deasserted.
59 */
kn230_interrupt_assert(struct interrupt * interrupt)60 void kn230_interrupt_assert(struct interrupt *interrupt)
61 {
62 struct kn230_data *d = (struct kn230_data *) interrupt->extra;
63 int assert2 = 0, assert3 = 0;
64
65 d->csr |= interrupt->line;
66 if (d->csr & (KN230_CSR_INTR_SII | KN230_CSR_INTR_LANCE))
67 assert3 = 1;
68 if (d->csr & (KN230_CSR_INTR_DZ0 |
69 KN230_CSR_INTR_OPT0 | KN230_CSR_INTR_OPT1))
70 assert2 = 1;
71
72 if (assert2)
73 INTERRUPT_ASSERT(d->mips_irq_2);
74 if (assert3)
75 INTERRUPT_ASSERT(d->mips_irq_2);
76 }
kn230_interrupt_deassert(struct interrupt * interrupt)77 void kn230_interrupt_deassert(struct interrupt *interrupt)
78 {
79 struct kn230_data *d = (struct kn230_data *) interrupt->extra;
80 int assert2 = 0, assert3 = 0;
81
82 d->csr &= ~interrupt->line;
83 if (d->csr & (KN230_CSR_INTR_SII | KN230_CSR_INTR_LANCE))
84 assert3 = 1;
85 if (d->csr & (KN230_CSR_INTR_DZ0 |
86 KN230_CSR_INTR_OPT0 | KN230_CSR_INTR_OPT1))
87 assert2 = 1;
88
89 if (!assert2)
90 INTERRUPT_DEASSERT(d->mips_irq_2);
91 if (!assert3)
92 INTERRUPT_DEASSERT(d->mips_irq_2);
93 }
94
95
DEVICE_ACCESS(kn230)96 DEVICE_ACCESS(kn230)
97 {
98 struct kn230_data *d = (struct kn230_data *) extra;
99 uint64_t idata = 0, odata = 0;
100
101 if (writeflag == MEM_WRITE)
102 idata = memory_readmax64(cpu, data, len);
103
104 switch (relative_addr) {
105 case 0:
106 if (writeflag==MEM_READ) {
107 odata = d->csr;
108 /* debug("[ kn230: read from CSR: 0x%08x ]\n",
109 (int)odata); */
110 } else {
111 /* debug("[ kn230: write to CSR: 0x%08x ]\n",
112 (int)idata); */
113 }
114 break;
115 default:
116 if (writeflag==MEM_READ) {
117 debug("[ kn230: read from 0x%08lx ]\n",
118 (long)relative_addr);
119 } else {
120 debug("[ kn230: write to 0x%08lx: 0x%08x ]\n",
121 (long)relative_addr, (int)idata);
122 }
123 }
124
125 if (writeflag == MEM_READ)
126 memory_writemax64(cpu, data, len, odata);
127
128 return 1;
129 }
130
131
DEVINIT(kn230)132 DEVINIT(kn230)
133 {
134 struct kn230_data *d;
135 char tmpstr[300];
136 int i;
137
138 CHECK_ALLOCATION(d = (struct kn230_data *) malloc(sizeof(struct kn230_data)));
139 memset(d, 0, sizeof(struct kn230_data));
140
141 /*
142 * devinit->interrupt_path points to the MIPS cpu itself.
143 * The KN230 interrupt controller interrupts at MIPS interrupts
144 * 2 and 3, depending on which KN230 is asserted.
145 */
146 snprintf(tmpstr, sizeof(tmpstr), "%s.2", devinit->interrupt_path);
147 INTERRUPT_CONNECT(tmpstr, d->mips_irq_2);
148 snprintf(tmpstr, sizeof(tmpstr), "%s.3", devinit->interrupt_path);
149 INTERRUPT_CONNECT(tmpstr, d->mips_irq_3);
150
151 /* Register KN230 interrupts 8..15: */
152 for (i=8; i<=15; i++) {
153 struct interrupt templ;
154 char tmpstr2[300];
155 snprintf(tmpstr2, sizeof(tmpstr2), "%s.kn230.0x%x",
156 devinit->interrupt_path, 1 << i);
157 memset(&templ, 0, sizeof(templ));
158 templ.line = 1 << i;
159 templ.name = tmpstr2;
160 templ.extra = d;
161 templ.interrupt_assert = kn230_interrupt_assert;
162 templ.interrupt_deassert = kn230_interrupt_deassert;
163 interrupt_handler_register(&templ);
164 }
165
166 memory_device_register(devinit->machine->memory, devinit->name,
167 devinit->addr, DEV_KN230_LENGTH, dev_kn230_access, d,
168 DM_DEFAULT, NULL);
169
170 devinit->return_ptr = d;
171
172 return 1;
173 }
174
175