/[gxemul]/upstream/0.3.3.2/src/devices/dev_dec_ioasic.c
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 /upstream/0.3.3.2/src/devices/dev_dec_ioasic.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show annotations)
Mon Oct 8 16:18:22 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 7847 byte(s)
0.3.3.2
1 /*
2 * Copyright (C) 2004-2005 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 * $Id: dev_dec_ioasic.c,v 1.12 2005/02/22 20:18:30 debug Exp $
29 *
30 * DECstation "3MIN" and "3MAX" IOASIC device.
31 *
32 * TODO: Lots of stuff, such as DMA and all bits in the control registers.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "cpu.h"
40 #include "devices.h"
41 #include "memory.h"
42 #include "misc.h"
43
44 #include "dec_kn03.h"
45 #include "tc_ioasicreg.h"
46
47 #define IOASIC_DEBUG
48 /* #define debug fatal */
49
50 /*
51 * dev_dec_ioasic_access():
52 */
53 int dev_dec_ioasic_access(struct cpu *cpu, struct memory *mem,
54 uint64_t relative_addr, unsigned char *data, size_t len,
55 int writeflag, void *extra)
56 {
57 struct dec_ioasic_data *d = (struct dec_ioasic_data *) extra;
58 uint64_t idata = 0, odata = 0;
59 uint64_t curptr;
60 int dma_len, dma_res;
61 uint32_t csr;
62 int regnr;
63
64 idata = memory_readmax64(cpu, data, len);
65
66 regnr = (relative_addr - IOASIC_SLOT_1_START) / 0x10;
67 if (relative_addr < 0x80000 && (relative_addr & 0xf) != 0)
68 fatal("[ dec_ioasic: unaligned access? relative_addr = "
69 "0x%x ]\n", (int)relative_addr);
70
71 if (regnr >= 0 && regnr < N_DEC_IOASIC_REGS) {
72 if (writeflag == MEM_WRITE)
73 d->reg[regnr] = idata;
74 else
75 odata = d->reg[regnr];
76 }
77
78 #ifdef IOASIC_DEBUG
79 if (writeflag == MEM_WRITE)
80 debug("[ dec_ioasic: write to address 0x%llx, data=0x"
81 "%016llx ]\n", (long long)relative_addr, (long long)idata);
82 else
83 debug("[ dec_ioasic: read from address 0x%llx ]\n",
84 (long long)relative_addr);
85 #endif
86
87 switch (relative_addr) {
88
89 /* Don't print warnings for these: */
90 case IOASIC_SCSI_DMAPTR:
91 case IOASIC_SCC_T1_DMAPTR:
92 case IOASIC_SCC_T2_DMAPTR:
93 case IOASIC_SCC_R1_DMAPTR:
94 case IOASIC_SCC_R2_DMAPTR:
95 break;
96
97 case IOASIC_CSR:
98 if (writeflag == MEM_WRITE) {
99 csr = d->reg[(IOASIC_CSR - IOASIC_SLOT_1_START) / 0x10];
100
101 d->reg[(IOASIC_INTR - IOASIC_SLOT_1_START) / 0x10] &=
102 ~IOASIC_INTR_T2_PAGE_END;
103
104 if (csr & IOASIC_CSR_DMAEN_T2) {
105 /* Transmit data: */
106 curptr = (d->reg[(IOASIC_SCC_T2_DMAPTR -
107 IOASIC_SLOT_1_START) / 0x10] >> 3)
108 | ((d->reg[(IOASIC_SCC_T2_DMAPTR -
109 IOASIC_SLOT_1_START) / 0x10] & 0x1f) << 29);
110 dma_len = 0x1000 - (curptr & 0xffc);
111
112 if ((curptr & 0xfff) == 0)
113 break;
114
115 if (d->dma_func[3] != NULL) {
116 d->dma_func[3](cpu,
117 d->dma_func_extra[3], curptr,
118 dma_len, 1);
119 } else
120 fatal("[ dec_ioasic: DMA tx: data @ "
121 "%08x, len %i bytes, but no "
122 "handler? ]\n", (int)curptr,
123 dma_len);
124
125 /* and signal the end of page: */
126 d->reg[(IOASIC_INTR - IOASIC_SLOT_1_START) /
127 0x10] |= IOASIC_INTR_T2_PAGE_END;
128
129 d->reg[(IOASIC_CSR - IOASIC_SLOT_1_START) /
130 0x10] &= ~IOASIC_CSR_DMAEN_T2;
131 curptr |= 0xfff;
132 curptr ++;
133
134 d->reg[(IOASIC_SCC_T2_DMAPTR -
135 IOASIC_SLOT_1_START) / 0x10] = ((curptr <<
136 3) & ~0x1f) | ((curptr >> 29) & 0x1f);
137 }
138
139 if (csr & IOASIC_CSR_DMAEN_R2) {
140 /* Receive data: */
141 curptr = (d->reg[(IOASIC_SCC_R2_DMAPTR -
142 IOASIC_SLOT_1_START) / 0x10] >> 3)
143 | ((d->reg[(IOASIC_SCC_R2_DMAPTR -
144 IOASIC_SLOT_1_START) / 0x10] & 0x1f) << 29);
145 dma_len = 0x1000 - (curptr & 0xffc);
146
147 dma_res = 0;
148 if (d->dma_func[3] != NULL) {
149 dma_res = d->dma_func[3](cpu,
150 d->dma_func_extra[3], curptr,
151 dma_len, 0);
152 } else
153 fatal("[ dec_ioasic: DMA tx: data @ "
154 "%08x, len %i bytes, but no "
155 "handler? ]\n", (int)curptr,
156 dma_len);
157
158 /* and signal the end of page: */
159 if (dma_res > 0) {
160 if ((curptr & 0x800) != ((curptr +
161 dma_res) & 0x800))
162 d->reg[(IOASIC_INTR -
163 IOASIC_SLOT_1_START) / 0x10]
164 |= IOASIC_INTR_R2_HALF_PAGE;
165 curptr += dma_res;
166 /* d->reg[(IOASIC_CSR - IOASIC_SLOT_1_START
167 ) / 0x10] &= ~IOASIC_CSR_DMAEN_R2; */
168 d->reg[(IOASIC_SCC_R2_DMAPTR -
169 IOASIC_SLOT_1_START) / 0x10] =
170 ((curptr << 3) & ~0x1f) | ((curptr
171 >> 29) & 0x1f);
172 }
173 }
174 }
175 break;
176
177 case IOASIC_INTR:
178 if (writeflag == MEM_READ) {
179 odata = d->reg[(IOASIC_INTR - IOASIC_SLOT_1_START)
180 / 0x10];
181 /* Note/TODO: How about other models than KN03? */
182 if (!d->rackmount_flag)
183 odata |= KN03_INTR_PROD_JUMPER;
184 } else {
185 /* Clear bits on write. */
186 d->reg[(IOASIC_INTR - IOASIC_SLOT_1_START) / 0x10] &=
187 ~idata;
188
189 /* Make sure that the CPU interrupt is deasserted as
190 well: */
191 if (idata != 0)
192 cpu_interrupt_ack(cpu, 8 + idata);
193 }
194 break;
195
196 case IOASIC_IMSK:
197 if (writeflag == MEM_WRITE) {
198 d->reg[(IOASIC_IMSK - IOASIC_SLOT_1_START) / 0x10] =
199 idata;
200 cpu_interrupt_ack(cpu, 8 + 0);
201 } else
202 odata = d->reg[(IOASIC_IMSK - IOASIC_SLOT_1_START) /
203 0x10];
204 break;
205
206 case IOASIC_CTR:
207 if (writeflag == MEM_READ)
208 odata = 0;
209 break;
210
211 case 0x80000:
212 case 0x80004:
213 case 0x80008:
214 case 0x8000c:
215 case 0x80010:
216 case 0x80014:
217 /* Station's ethernet address: */
218 if (writeflag == MEM_WRITE) {
219 fatal("[ dec_ioasic: attempt to write to the station's"
220 " ethernet address? ]\n");
221 } else {
222 odata = ((relative_addr - 0x80000) / 4 + 1) * 0x10;
223 }
224 break;
225
226 default:
227 if (writeflag == MEM_WRITE)
228 fatal("[ dec_ioasic: unimplemented write to address "
229 "0x%llx, data=0x%016llx ]\n",
230 (long long)relative_addr, (long long)idata);
231 else
232 fatal("[ dec_ioasic: unimplemented read from address "
233 "0x%llx ]\n", (long long)relative_addr);
234 }
235
236 if (writeflag == MEM_READ)
237 memory_writemax64(cpu, data, len, odata);
238
239 return 1;
240 }
241
242
243 /*
244 * dev_dec_ioasic_init():
245 *
246 * For DECstation "type 4", the rackmount_flag selects which model type
247 * the IOASIC should identify itself as (5000 for zero, 5900 if rackmount_flag
248 * is non-zero). It is probably not meaningful on other machines than
249 * type 4.
250 */
251 struct dec_ioasic_data *dev_dec_ioasic_init(struct cpu *cpu,
252 struct memory *mem, uint64_t baseaddr, int rackmount_flag)
253 {
254 struct dec_ioasic_data *d = malloc(sizeof(struct dec_ioasic_data));
255 if (d == NULL) {
256 fprintf(stderr, "out of memory\n");
257 exit(1);
258 }
259 memset(d, 0, sizeof(struct dec_ioasic_data));
260
261 d->rackmount_flag = rackmount_flag;
262
263 memory_device_register(mem, "dec_ioasic", baseaddr,
264 DEV_DEC_IOASIC_LENGTH, dev_dec_ioasic_access, (void *)d,
265 MEM_DEFAULT, NULL);
266 return d;
267 }
268

  ViewVC Help
Powered by ViewVC 1.1.26