/[gxemul]/upstream/0.3.3.1/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

Annotation of /upstream/0.3.3.1/src/devices/dev_dec_ioasic.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Mon Oct 8 16:18:14 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 7847 byte(s)
0.3.3.1
1 dpavlin 4 /*
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