dev_sgi_ip22.cc Source File

Back to the index.

dev_sgi_ip22.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-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: SGI IP22 stuff
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "cpu.h"
36 #include "devices.h"
37 #include "machine.h"
38 #include "memory.h"
39 #include "misc.h"
40 
41 #include "thirdparty/imcreg.h"
42 
43 
44 #define SGI_IP22_TICK_SHIFT 14
45 
46 
47 DEVICE_TICK(sgi_ip22)
48 {
49  struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
50 
51  // TODO: Document this!
52  if (d->reg[0x38 / 4] != 0)
53  d->reg[0x38 / 4] --;
54 }
55 
56 
57 /*
58  * dev_sgi_ip22_imc_access():
59  *
60  * The memory controller (?).
61  */
62 DEVICE_ACCESS(sgi_ip22_imc)
63 {
64  struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
65  uint64_t idata = 0, odata = 0;
66  int regnr;
67 
68  if (writeflag == MEM_WRITE)
69  idata = memory_readmax64(cpu, data, len);
70 
71  regnr = relative_addr / sizeof(uint32_t);
72 
73  if (writeflag == MEM_WRITE)
74  d->imc_reg[regnr] = idata;
75  else
76  odata = d->imc_reg[regnr];
77 
78  switch (relative_addr) {
79  case (IMC_CPUCTRL0 - IP22_IMC_BASE):
80  if (writeflag == MEM_WRITE) {
81  /* debug("[ sgi_ip22_imc: write to "
82  "IMC_CPUCTRL0, data=0x%08x ]\n", (int)idata); */
83  } else {
84  /* debug("[ sgi_ip22_imc: read from IMC_CPUCTRL0, "
85  "data=0x%08x ]\n", (int)odata); */
86  }
87  break;
88  case (IMC_SYSID - IP22_IMC_BASE):
89  if (writeflag == MEM_WRITE) {
90  debug("[ sgi_ip22_imc: unimplemented write "
91  "IMC_SYSID, data=0x%08x ]\n", (int)idata);
92  } else {
93  /* Lowest 4 bits are the revision bits. */
94  odata = 3; /* + IMC_SYSID_HAVEISA; */
95  /* debug("[ sgi_ip22_imc: read from IMC_SYSID, "
96  "data=0x%08x ]\n", (int)odata); */
97  }
98  break;
99  case (IMC_WDOG - IP22_IMC_BASE):
100  if (writeflag == MEM_WRITE) {
101  /* debug("[ sgi_ip22_imc: write to IMC_WDOG, "
102  "data=0x%08x ]\n", (int)idata); */
103  } else {
104  /* debug("[ sgi_ip22_imc: read from IMC_WDOG, "
105  "data=0x%08x ]\n", (int)odata); */
106  }
107  break;
108  case (IMC_MEMCFG0 - IP22_IMC_BASE):
109  if (writeflag == MEM_WRITE) {
110  debug("[ sgi_ip22_imc: unimplemented write "
111  "IMC_MEMCFG0, data=0x%08x ]\n", (int)idata);
112  } else {
113  odata = 0x3100 + (0x8000000 >> 22); /* ? TODO */
114  /* debug("[ sgi_ip22_imc: read from IMC_MEMCFG0,"
115  " data=0x%08x ]\n", (int)odata); */
116  }
117  break;
118  case (IMC_MEMCFG1 - IP22_IMC_BASE):
119  if (writeflag == MEM_WRITE) {
120  debug("[ sgi_ip22_imc: unimplemented write "
121  "IMC_MEMCFG1, data=0x%08x ]\n", (int)idata);
122  } else {
123  odata = 0;
124  /* debug("[ sgi_ip22_imc: read from IMC_MEMCFG1, "
125  "data=0x%08x ]\n", (int)odata); */
126  }
127  break;
128  case (IMC_EEPROM - IP22_IMC_BASE):
129  /*
130  * The IP22 prom tries to access this during bootup,
131  * but I have no idea how it works.
132  */
133  if (writeflag == MEM_WRITE) {
134  debug("[ sgi_ip22_imc: write to IMC_EEPROM, data="
135  "0x%08x ]\n", (int)idata);
136  } else {
137  odata = random() & 0x1e;
138  debug("[ sgi_ip22_imc: read from IMC_WDOG, "
139  "data=0x%08x ]\n", (int)odata);
140  }
141  break;
142  default:
143  if (writeflag == MEM_WRITE) {
144  debug("[ sgi_ip22_imc: unimplemented write to "
145  "address 0x%x, data=0x%08x ]\n",
146  (int)relative_addr, (int)idata);
147  } else {
148  debug("[ sgi_ip22_imc: unimplemented read from "
149  "address 0x%x, data=0x%08x ]\n",
150  (int)relative_addr, (int)odata);
151  }
152  }
153 
154  if (writeflag == MEM_READ)
155  memory_writemax64(cpu, data, len, odata);
156 
157  return 1;
158 }
159 
160 
161 /*
162  * dev_sgi_ip22_unknown_access():
163  *
164  * A so far unknown device, used by the IP22 prom during startup.
165  */
166 DEVICE_ACCESS(sgi_ip22_unknown)
167 {
168  struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
169  uint64_t idata = 0, odata = 0;
170 
171  idata = memory_readmax64(cpu, data, len);
172 
173  switch (relative_addr) {
174  case 0x04:
175  if (writeflag == MEM_WRITE) {
176  debug("[ sgi_ip22_unknown: write to address 0x%x,"
177  " data=0x%08x ]\n", (int)relative_addr, (int)idata);
178  } else {
179  odata = d->unknown_timer;
180  d->unknown_timer += 100;
181  debug("[ sgi_ip22_unknown: read from address 0x%x, "
182  "data=0x%08x ]\n", (int)relative_addr, (int)odata);
183  }
184  break;
185  default:
186  if (writeflag == MEM_WRITE) {
187  debug("[ sgi_ip22_unknown: unimplemented write to "
188  "address 0x%x, data=0x%08x ]\n",
189  (int)relative_addr, (int)idata);
190  } else {
191  debug("[ sgi_ip22_unknown: unimplemented read from "
192  "address 0x%x, data=0x%08x ]\n",
193  (int)relative_addr, (int)odata);
194  }
195  }
196 
197  if (writeflag == MEM_READ)
198  memory_writemax64(cpu, data, len, odata);
199 
200  return 1;
201 }
202 
203 
204 /*
205  * dev_sgi_ip22_unknown2_access():
206  *
207  * A so far unknown device, used by the IP22 prom during startup.
208  */
209 DEVICE_ACCESS(sgi_ip22_unknown2)
210 {
211  struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
212  uint64_t idata = 0, odata = 0;
213  int regnr;
214 
215  idata = memory_readmax64(cpu, data, len);
216  regnr = relative_addr / sizeof(uint32_t);
217 
218  if (writeflag == MEM_WRITE)
219  d->unknown2_reg[regnr] = idata;
220  else
221  odata = d->unknown2_reg[regnr];
222 
223  switch (relative_addr) {
224  default:
225  if (writeflag == MEM_WRITE) {
226  debug("[ sgi_ip22_unknown2: unimplemented write "
227  "to address 0x%x, data=0x%08x ]\n",
228  (int)relative_addr, (int)idata);
229  } else {
230  debug("[ sgi_ip22_unknown2: unimplemented read from "
231  "address 0x%x, data=0x%08x ]\n",
232  (int)relative_addr, (int)odata);
233  }
234  }
235 
236  if (writeflag == MEM_READ)
237  memory_writemax64(cpu, data, len, odata);
238 
239  return 1;
240 }
241 
242 
243 DEVICE_ACCESS(sgi_ip22_sysid)
244 {
245  struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
246  uint64_t idata = 0, odata = 0;
247 
248  idata = memory_readmax64(cpu, data, len);
249 
250  if (writeflag == MEM_WRITE) {
251  debug("[ sgi_ip22_sysid: write to address 0x%x, "
252  "data=0x%08x ]\n", (int)relative_addr, (int)idata);
253  } else {
254  /*
255  * According to NetBSD's sgimips/ip22.c:
256  *
257  * printf("IOC rev %d, machine %s, board rev %d\n",
258  * (sysid >> 5) & 0x07,
259  * (sysid & 1) ? "Indigo2 (Fullhouse)" : "Indy (Guiness)",
260  * (sysid >> 1) & 0x0f);
261  */
262 
263  /* IOC rev 1, Guiness, board rev 3: */
264  odata = (1 << 5) + (3 << 1) + (d->guiness_flag? 0 : 1);
265 
266  debug("[ sgi_ip22_sysid: read from address 0x%x, data="
267  "0x%08x ]\n", (int)relative_addr, (int)odata);
268  }
269 
270  if (writeflag == MEM_READ)
271  memory_writemax64(cpu, data, len, odata);
272 
273  return 1;
274 }
275 
276 
277 DEVICE_ACCESS(sgi_ip22)
278 {
279  struct sgi_ip22_data *d = (struct sgi_ip22_data *) extra;
280  uint64_t idata = 0, odata = 0;
281  int regnr;
282 
283  idata = memory_readmax64(cpu, data, len);
284  regnr = relative_addr / sizeof(uint32_t);
285 
286  if (writeflag == MEM_WRITE)
287  d->reg[regnr] = idata;
288  else
289  odata = d->reg[regnr];
290 
291  /* Read from/write to the sgi_ip22: */
292  switch (relative_addr) {
293  case 0x00: /* local0 irq stat */
294  if (writeflag == MEM_WRITE) {
295  debug("[ sgi_ip22: write to local0 IRQ STAT, "
296  "data=0x%llx ]\n", (long long)idata);
297  } else {
298  debug("[ sgi_ip22: read from local0 IRQ STAT, "
299  "data=0x%llx ]\n", (long long)odata);
300  }
301  break;
302  case 0x04: /* local0 irq mask */
303  if (writeflag == MEM_WRITE) {
304  /*
305  * Ugly hack: if an interrupt is asserted, and someone
306  * writes to this mask register, the interrupt should
307  * be masked. That is, sgi_ip22_interrupt() in
308  * src/machine.c has to be called to deal with this.
309  * The ugly solution I choose here is to deassert
310  * some interrupt which should never be used anyway.
311  * (TODO: Fix this.)
312  */
313 
314 fatal("TODO: ip22 legacy interrupt rewrite!\n");
315 abort();
316 
317 // cpu_interrupt_ack(cpu, 8 + 63);
318 // debug("[ sgi_ip22: write to local0 IRQ MASK, "
319 // "data=0x%llx ]\n", (long long)idata);
320  } else {
321  debug("[ sgi_ip22: read from local0 IRQ MASK, "
322  "data=0x%llx ]\n", (long long)odata);
323  }
324  break;
325  case 0x08: /* local1 irq stat */
326  if (writeflag == MEM_WRITE) {
327  debug("[ sgi_ip22: write to local1 IRQ STAT, "
328  "data=0x%llx ]\n", (long long)idata);
329  } else {
330  debug("[ sgi_ip22: read from local1 IRQ STAT, "
331  "data=0x%llx ]\n", (long long)odata);
332  }
333  break;
334  case 0x0c: /* local1 irq mask */
335  if (writeflag == MEM_WRITE) {
336  /* See commen above, about local0 irq mask. */
337 
338 fatal("TODO: ip22 legacy interrupt rewrite!\n");
339 abort();
340 // cpu_interrupt_ack(cpu, 8 + 63);
341 // debug("[ sgi_ip22: write to local1 IRQ MASK, "
342 // "data=0x%llx ]\n", (long long)idata);
343  } else {
344  debug("[ sgi_ip22: read from local1 IRQ MASK, "
345  "data=0x%llx ]\n", (long long)odata);
346  }
347  break;
348  case 0x10:
349  if (writeflag == MEM_WRITE) {
350  debug("[ sgi_ip22: write to mappable IRQ STAT, "
351  "data=0x%llx ]\n", (long long)idata);
352  } else {
353  debug("[ sgi_ip22: read from mappable IRQ STAT, "
354  "data=0x%llx ]\n", (long long)odata);
355  }
356  break;
357  case 0x14:
358  if (writeflag == MEM_WRITE) {
359  debug("[ sgi_ip22: write to mappable local0 IRQ "
360  "MASK, data=0x%llx ]\n", (long long)idata);
361  } else {
362  debug("[ sgi_ip22: read from mappable local0 IRQ "
363  "MASK, data=0x%llx ]\n", (long long)odata);
364  }
365  break;
366  case 0x18:
367  if (writeflag == MEM_WRITE) {
368  debug("[ sgi_ip22: write to mappable local1 IRQ "
369  "MASK, data=0x%llx ]\n", (long long)idata);
370  } else {
371  debug("[ sgi_ip22: read from mappable local1 IRQ "
372  "MASK, data=0x%llx ]\n", (long long)odata);
373  }
374  break;
375  case 0x38: /* timer count */
376  if (writeflag == MEM_WRITE) {
377  /* Two byte values are written to this address,
378  sequentially... TODO */
379  } else {
380  /* The timer is decreased by the tick function. */
381  }
382  break;
383  case 0x3b: /* ? */
384  odata = random();
385  break;
386  case 0x3c: /* timer control */
387  break;
388  case 0x3f: /* ? */
389  odata = random();
390  break;
391  default:
392  if (writeflag == MEM_WRITE) {
393  debug("[ sgi_ip22: unimplemented write to address "
394  "0x%x, data=0x%02x ]\n", (int)relative_addr,
395  (int)idata);
396  } else {
397  debug("[ sgi_ip22: unimplemented read from address "
398  "0x%llx ]\n", (long long)relative_addr);
399  }
400  }
401 
402  if (writeflag == MEM_READ)
403  memory_writemax64(cpu, data, len, odata);
404 
405  return 1;
406 }
407 
408 
410  struct memory *mem, uint64_t baseaddr, int guiness_flag)
411 {
412  struct sgi_ip22_data *d;
413 
414  CHECK_ALLOCATION(d = (struct sgi_ip22_data *) malloc(sizeof(struct sgi_ip22_data)));
415  memset(d, 0, sizeof(struct sgi_ip22_data));
416 
418 
419  memory_device_register(mem, "sgi_ip22", baseaddr, DEV_SGI_IP22_LENGTH,
420  dev_sgi_ip22_access, (void *)d, DM_DEFAULT, NULL);
421  memory_device_register(mem, "sgi_ip22_sysid", 0x1fbd9858, 0x8,
422  dev_sgi_ip22_sysid_access, (void *)d, DM_DEFAULT, NULL);
423  memory_device_register(mem, "sgi_ip22_imc", IP22_IMC_BASE,
424  DEV_SGI_IP22_IMC_LENGTH, dev_sgi_ip22_imc_access, (void *)d,
425  DM_DEFAULT, NULL);
426  memory_device_register(mem, "sgi_ip22_unknown", 0x1fa01000, 0x10,
427  dev_sgi_ip22_unknown_access, (void *)d, DM_DEFAULT, NULL);
428  memory_device_register(mem, "sgi_ip22_unknown2", IP22_UNKNOWN2_BASE,
429  DEV_SGI_IP22_UNKNOWN2_LENGTH, dev_sgi_ip22_unknown2_access,
430  (void *)d, DM_DEFAULT, NULL);
431 
432  machine_add_tickfunction(machine, dev_sgi_ip22_tick, d,
434 
435  return d;
436 }
437 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
void fatal(const char *fmt,...)
Definition: main.cc:152
#define DM_DEFAULT
Definition: memory.h:130
#define IMC_WDOG
Definition: imcreg.h:73
uint32_t imc_reg[DEV_SGI_IP22_IMC_LENGTH/4]
Definition: devices.h:415
#define DEV_SGI_IP22_IMC_LENGTH
Definition: devices.h:408
uint32_t unknown2_reg[DEV_SGI_IP22_UNKNOWN2_LENGTH/4]
Definition: devices.h:416
#define MEM_READ
Definition: memory.h:116
DEVICE_ACCESS(sgi_ip22_imc)
Definition: dev_sgi_ip22.cc:62
#define IMC_MEMCFG0
Definition: imcreg.h:119
#define DEV_SGI_IP22_LENGTH
Definition: devices.h:407
#define IMC_EEPROM
Definition: imcreg.h:84
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
struct sgi_ip22_data * dev_sgi_ip22_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int guiness_flag)
u_short data
Definition: siireg.h:79
int guiness_flag
Definition: devices.h:413
#define MEM_WRITE
Definition: memory.h:117
#define IP22_IMC_BASE
Definition: devices.h:410
DEVICE_TICK(sgi_ip22)
Definition: dev_sgi_ip22.cc:47
#define SGI_IP22_TICK_SHIFT
Definition: dev_sgi_ip22.cc:44
#define debug
Definition: dev_adb.cc:57
Definition: cpu.h:326
#define IMC_SYSID
Definition: imcreg.h:76
#define IMC_CPUCTRL0
Definition: imcreg.h:34
#define IP22_UNKNOWN2_BASE
Definition: devices.h:411
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
#define IMC_MEMCFG1
Definition: imcreg.h:121
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
Definition: memory.h:75
#define DEV_SGI_IP22_UNKNOWN2_LENGTH
Definition: devices.h:409
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
uint32_t reg[DEV_SGI_IP22_LENGTH/4]
Definition: devices.h:414
int dev_sgi_ip22_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, int writeflag, void *)
uint32_t unknown_timer
Definition: devices.h:417

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13