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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26