1 |
/* |
/* |
2 |
* Copyright (C) 2004-2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2004-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: dev_sgi_ip30.c,v 1.17 2005/02/25 06:14:30 debug Exp $ |
* $Id: dev_sgi_ip30.c,v 1.24 2007/02/03 20:14:23 debug Exp $ |
29 |
* |
* |
30 |
* SGI IP30 stuff. |
* SGI IP30 stuff. |
31 |
* |
* |
37 |
#include <string.h> |
#include <string.h> |
38 |
|
|
39 |
#include "cpu.h" |
#include "cpu.h" |
40 |
#include "devices.h" |
#include "device.h" |
41 |
#include "machine.h" |
#include "machine.h" |
42 |
#include "memory.h" |
#include "memory.h" |
43 |
#include "misc.h" |
#include "misc.h" |
44 |
|
|
45 |
|
|
46 |
|
#define DEV_SGI_IP30_LENGTH 0x80000 |
47 |
|
|
48 |
|
struct sgi_ip30_data { |
49 |
|
/* ip30: */ |
50 |
|
uint64_t imask0; /* 0x10000 */ |
51 |
|
uint64_t reg_0x10018; |
52 |
|
uint64_t isr; /* 0x10030 */ |
53 |
|
uint64_t reg_0x20000; |
54 |
|
uint64_t reg_0x30000; |
55 |
|
|
56 |
|
/* ip30_2: */ |
57 |
|
uint64_t reg_0x0029c; |
58 |
|
|
59 |
|
/* ip30_3: */ |
60 |
|
uint64_t reg_0x00284; |
61 |
|
|
62 |
|
/* ip30_4: */ |
63 |
|
uint64_t reg_0x000b0; |
64 |
|
|
65 |
|
/* ip30_5: */ |
66 |
|
uint64_t reg_0x00000; |
67 |
|
}; |
68 |
|
|
69 |
|
|
70 |
void dev_sgi_ip30_tick(struct cpu *cpu, void *extra) |
void dev_sgi_ip30_tick(struct cpu *cpu, void *extra) |
71 |
{ |
{ |
72 |
struct sgi_ip30_data *d = extra; |
struct sgi_ip30_data *d = extra; |
76 |
if (d->imask0 & ((int64_t)1<<50)) { |
if (d->imask0 & ((int64_t)1<<50)) { |
77 |
/* TODO: Only interrupt if reg 0x20000 (the counter) |
/* TODO: Only interrupt if reg 0x20000 (the counter) |
78 |
has passed the compare (0x30000). */ |
has passed the compare (0x30000). */ |
79 |
cpu_interrupt(cpu, 8+1 + 50); |
fatal("IP30 legacy interrupt rewrite: TODO\n"); |
80 |
|
abort(); |
81 |
|
// cpu_interrupt(cpu, 8+1 + 50); |
82 |
} |
} |
83 |
} |
} |
84 |
|
|
86 |
/* |
/* |
87 |
* dev_sgi_ip30_access(): |
* dev_sgi_ip30_access(): |
88 |
*/ |
*/ |
89 |
int dev_sgi_ip30_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_ip30) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
90 |
{ |
{ |
91 |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
92 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
93 |
|
|
94 |
idata = memory_readmax64(cpu, data, len); |
if (writeflag == MEM_WRITE) |
95 |
|
idata = memory_readmax64(cpu, data, len); |
96 |
|
|
97 |
switch (relative_addr) { |
switch (relative_addr) { |
98 |
case 0x20: |
case 0x20: |
124 |
case 0x10020: /* Set ISR, according to Linux/IP30 */ |
case 0x10020: /* Set ISR, according to Linux/IP30 */ |
125 |
d->isr = idata; |
d->isr = idata; |
126 |
/* Recalculate CPU interrupt assertions: */ |
/* Recalculate CPU interrupt assertions: */ |
127 |
cpu_interrupt(cpu, 8); |
fatal("IP30 legacy interrupt rewrite: TODO\n"); |
128 |
|
abort(); |
129 |
|
// cpu_interrupt(cpu, 8); |
130 |
break; |
break; |
131 |
case 0x10028: /* Clear ISR, according to Linux/IP30 */ |
case 0x10028: /* Clear ISR, according to Linux/IP30 */ |
132 |
d->isr &= ~idata; |
d->isr &= ~idata; |
133 |
/* Recalculate CPU interrupt assertions: */ |
/* Recalculate CPU interrupt assertions: */ |
134 |
cpu_interrupt(cpu, 8); |
fatal("IP30 legacy interrupt rewrite: TODO\n"); |
135 |
|
abort(); |
136 |
|
// cpu_interrupt(cpu, 8); |
137 |
break; |
break; |
138 |
case 0x10030: /* Interrupt Status Register */ |
case 0x10030: /* Interrupt Status Register */ |
139 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
140 |
/* Clear-on-write (TODO: is this correct?) */ |
/* Clear-on-write (TODO: is this correct?) */ |
141 |
d->isr &= ~idata; |
d->isr &= ~idata; |
142 |
/* Recalculate CPU interrupt assertions: */ |
/* Recalculate CPU interrupt assertions: */ |
143 |
cpu_interrupt(cpu, 8); |
fatal("IP30 legacy interrupt rewrite: TODO\n"); |
144 |
|
abort(); |
145 |
|
// cpu_interrupt(cpu, 8); |
146 |
} else { |
} else { |
147 |
odata = d->isr; |
odata = d->isr; |
148 |
} |
} |
183 |
/* |
/* |
184 |
* dev_sgi_ip30_2_access(): |
* dev_sgi_ip30_2_access(): |
185 |
*/ |
*/ |
186 |
int dev_sgi_ip30_2_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_ip30_2) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
187 |
{ |
{ |
188 |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
189 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
236 |
/* |
/* |
237 |
* dev_sgi_ip30_3_access(): |
* dev_sgi_ip30_3_access(): |
238 |
*/ |
*/ |
239 |
int dev_sgi_ip30_3_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_ip30_3) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
240 |
{ |
{ |
241 |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
242 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
299 |
/* |
/* |
300 |
* dev_sgi_ip30_4_access(): |
* dev_sgi_ip30_4_access(): |
301 |
*/ |
*/ |
302 |
int dev_sgi_ip30_4_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_ip30_4) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
303 |
{ |
{ |
304 |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
305 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
343 |
/* |
/* |
344 |
* dev_sgi_ip30_5_access(): |
* dev_sgi_ip30_5_access(): |
345 |
*/ |
*/ |
346 |
int dev_sgi_ip30_5_access(struct cpu *cpu, struct memory *mem, |
DEVICE_ACCESS(sgi_ip30_5) |
|
uint64_t relative_addr, unsigned char *data, size_t len, |
|
|
int writeflag, void *extra) |
|
347 |
{ |
{ |
348 |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; |
349 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
376 |
} |
} |
377 |
|
|
378 |
|
|
379 |
/* |
DEVINIT(sgi_ip30) |
|
* dev_sgi_ip30_init(): |
|
|
*/ |
|
|
struct sgi_ip30_data *dev_sgi_ip30_init(struct machine *machine, |
|
|
struct memory *mem, uint64_t baseaddr) |
|
380 |
{ |
{ |
381 |
struct sgi_ip30_data *d = malloc(sizeof(struct sgi_ip30_data)); |
struct sgi_ip30_data *d = malloc(sizeof(struct sgi_ip30_data)); |
382 |
if (d == NULL) { |
if (d == NULL) { |
385 |
} |
} |
386 |
memset(d, 0, sizeof(struct sgi_ip30_data)); |
memset(d, 0, sizeof(struct sgi_ip30_data)); |
387 |
|
|
388 |
memory_device_register(mem, "sgi_ip30_1", baseaddr, |
memory_device_register(devinit->machine->memory, "sgi_ip30_1", |
389 |
DEV_SGI_IP30_LENGTH, dev_sgi_ip30_access, (void *)d, |
devinit->addr, DEV_SGI_IP30_LENGTH, dev_sgi_ip30_access, (void *)d, |
390 |
MEM_DEFAULT, NULL); |
DM_DEFAULT, NULL); |
391 |
memory_device_register(mem, "sgi_ip30_2", 0x10000000, |
memory_device_register(devinit->machine->memory, "sgi_ip30_2", |
392 |
0x10000, dev_sgi_ip30_2_access, (void *)d, MEM_DEFAULT, NULL); |
0x10000000, 0x10000, dev_sgi_ip30_2_access, (void *)d, DM_DEFAULT, |
393 |
memory_device_register(mem, "sgi_ip30_3", 0x1f000000, |
NULL); |
394 |
0x10000, dev_sgi_ip30_3_access, (void *)d, MEM_DEFAULT, NULL); |
memory_device_register(devinit->machine->memory, "sgi_ip30_3", |
395 |
memory_device_register(mem, "sgi_ip30_4", 0x1f600000, |
0x1f000000, 0x10000, dev_sgi_ip30_3_access, (void *)d, DM_DEFAULT, |
396 |
0x10000, dev_sgi_ip30_4_access, (void *)d, MEM_DEFAULT, NULL); |
NULL); |
397 |
memory_device_register(mem, "sgi_ip30_5", 0x1f6c0000, |
memory_device_register(devinit->machine->memory, "sgi_ip30_4", |
398 |
0x10000, dev_sgi_ip30_5_access, (void *)d, MEM_DEFAULT, NULL); |
0x1f600000, 0x10000, dev_sgi_ip30_4_access, (void *)d, DM_DEFAULT, |
399 |
|
NULL); |
400 |
|
memory_device_register(devinit->machine->memory, "sgi_ip30_5", |
401 |
|
0x1f6c0000, 0x10000, dev_sgi_ip30_5_access, (void *)d, DM_DEFAULT, |
402 |
|
NULL); |
403 |
|
|
404 |
machine_add_tickfunction(machine, dev_sgi_ip30_tick, d, 16); |
machine_add_tickfunction(devinit->machine, |
405 |
|
dev_sgi_ip30_tick, d, 16, 0.0); |
406 |
|
|
407 |
return d; |
return 1; |
408 |
} |
} |
409 |
|
|