--- trunk/src/devices/dev_sgi_ip30.c 2007/10/08 16:19:23 20 +++ trunk/src/devices/dev_sgi_ip30.c 2007/10/08 16:22:32 42 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2005 Anders Gavare. All rights reserved. + * Copyright (C) 2004-2007 Anders Gavare. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -25,11 +25,11 @@ * SUCH DAMAGE. * * - * $Id: dev_sgi_ip30.c,v 1.19 2005/11/13 00:14:10 debug Exp $ + * $Id: dev_sgi_ip30.c,v 1.26 2007/06/15 19:57:34 debug Exp $ * - * SGI IP30 stuff. + * COMMENT: SGI IP30 stuff * - * This is just comprised of hardcoded guesses so far. (Ugly.) + * NOTE/TODO: This is just comprised of hardcoded guesses so far. (Ugly.) */ #include @@ -37,13 +37,37 @@ #include #include "cpu.h" -#include "devices.h" +#include "device.h" #include "machine.h" #include "memory.h" #include "misc.h" -void dev_sgi_ip30_tick(struct cpu *cpu, void *extra) +#define DEV_SGI_IP30_LENGTH 0x80000 + +struct sgi_ip30_data { + /* ip30: */ + uint64_t imask0; /* 0x10000 */ + uint64_t reg_0x10018; + uint64_t isr; /* 0x10030 */ + uint64_t reg_0x20000; + uint64_t reg_0x30000; + + /* ip30_2: */ + uint64_t reg_0x0029c; + + /* ip30_3: */ + uint64_t reg_0x00284; + + /* ip30_4: */ + uint64_t reg_0x000b0; + + /* ip30_5: */ + uint64_t reg_0x00000; +}; + + +DEVICE_TICK(sgi_ip30) { struct sgi_ip30_data *d = extra; @@ -52,29 +76,28 @@ if (d->imask0 & ((int64_t)1<<50)) { /* TODO: Only interrupt if reg 0x20000 (the counter) has passed the compare (0x30000). */ - cpu_interrupt(cpu, 8+1 + 50); +fatal("IP30 legacy interrupt rewrite: TODO\n"); +abort(); +// cpu_interrupt(cpu, 8+1 + 50); } } -/* - * dev_sgi_ip30_access(): - */ -int dev_sgi_ip30_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(sgi_ip30) { - struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; + struct sgi_ip30_data *d = extra; uint64_t idata = 0, odata = 0; if (writeflag == MEM_WRITE) idata = memory_readmax64(cpu, data, len); switch (relative_addr) { + case 0x20: /* Memory bank configuration: */ odata = 0x80010000ULL; break; + case 0x10000: /* Interrupt mask register 0: */ if (writeflag == MEM_WRITE) { d->imask0 = idata; @@ -82,6 +105,7 @@ odata = d->imask0; } break; + case 0x10018: /* * If this is not implemented, the IP30 PROM complains during @@ -97,26 +121,36 @@ odata = d->reg_0x10018; } break; + case 0x10020: /* Set ISR, according to Linux/IP30 */ d->isr = idata; /* Recalculate CPU interrupt assertions: */ - cpu_interrupt(cpu, 8); +fatal("IP30 legacy interrupt rewrite: TODO\n"); +abort(); +// cpu_interrupt(cpu, 8); break; + case 0x10028: /* Clear ISR, according to Linux/IP30 */ d->isr &= ~idata; /* Recalculate CPU interrupt assertions: */ - cpu_interrupt(cpu, 8); +fatal("IP30 legacy interrupt rewrite: TODO\n"); +abort(); +// cpu_interrupt(cpu, 8); break; + case 0x10030: /* Interrupt Status Register */ if (writeflag == MEM_WRITE) { /* Clear-on-write (TODO: is this correct?) */ d->isr &= ~idata; /* Recalculate CPU interrupt assertions: */ - cpu_interrupt(cpu, 8); +fatal("IP30 legacy interrupt rewrite: TODO\n"); +abort(); +// cpu_interrupt(cpu, 8); } else { odata = d->isr; } break; + case 0x20000: /* A counter */ if (writeflag == MEM_WRITE) { @@ -125,6 +159,7 @@ odata = d->reg_0x20000; } break; + case 0x30000: if (writeflag == MEM_WRITE) { d->reg_0x30000 = idata; @@ -132,6 +167,7 @@ odata = d->reg_0x30000; } break; + default: if (writeflag == MEM_WRITE) { debug("[ sgi_ip30: unimplemented write to address " @@ -150,14 +186,9 @@ } -/* - * dev_sgi_ip30_2_access(): - */ -int dev_sgi_ip30_2_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(sgi_ip30_2) { - struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; + struct sgi_ip30_data *d = extra; uint64_t idata = 0, odata = 0; idata = memory_readmax64(cpu, data, len); @@ -205,19 +236,15 @@ } -/* - * dev_sgi_ip30_3_access(): - */ -int dev_sgi_ip30_3_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(sgi_ip30_3) { - struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; + struct sgi_ip30_data *d = extra; uint64_t idata = 0, odata = 0; idata = memory_readmax64(cpu, data, len); switch (relative_addr) { + case 0xb4: if (writeflag == MEM_WRITE) { debug("[ sgi_ip30_3: unimplemented write to " @@ -227,6 +254,7 @@ odata = 2; /* should be 2, or Irix loops */ } break; + case 0x00104: if (writeflag == MEM_WRITE) { debug("[ sgi_ip30_3: unimplemented write to address " @@ -237,6 +265,7 @@ complains */ } break; + case 0x00284: /* * If this is not implemented, the IP30 PROM complains during @@ -252,6 +281,7 @@ odata = d->reg_0x00284; } break; + default: if (writeflag == MEM_WRITE) { debug("[ sgi_ip30_3: unimplemented write to address " @@ -270,19 +300,15 @@ } -/* - * dev_sgi_ip30_4_access(): - */ -int dev_sgi_ip30_4_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(sgi_ip30_4) { - struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; + struct sgi_ip30_data *d = extra; uint64_t idata = 0, odata = 0; idata = memory_readmax64(cpu, data, len); switch (relative_addr) { + case 0x000b0: /* * If this is not implemented, the IP30 PROM complains during @@ -298,6 +324,7 @@ odata = d->reg_0x000b0; } break; + default: if (writeflag == MEM_WRITE) { debug("[ sgi_ip30_4: unimplemented write to address" @@ -316,19 +343,15 @@ } -/* - * dev_sgi_ip30_5_access(): - */ -int dev_sgi_ip30_5_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(sgi_ip30_5) { - struct sgi_ip30_data *d = (struct sgi_ip30_data *) extra; + struct sgi_ip30_data *d = extra; uint64_t idata = 0, odata = 0; idata = memory_readmax64(cpu, data, len); switch (relative_addr) { + case 0x00000: if (writeflag == MEM_WRITE) { d->reg_0x00000 = idata; @@ -336,6 +359,7 @@ odata = d->reg_0x00000; } break; + default: if (writeflag == MEM_WRITE) { debug("[ sgi_ip30_5: unimplemented write to address " @@ -354,33 +378,32 @@ } -/* - * dev_sgi_ip30_init(): - */ -struct sgi_ip30_data *dev_sgi_ip30_init(struct machine *machine, - struct memory *mem, uint64_t baseaddr) +DEVINIT(sgi_ip30) { - struct sgi_ip30_data *d = malloc(sizeof(struct sgi_ip30_data)); - if (d == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } + struct sgi_ip30_data *d; + + CHECK_ALLOCATION(d = malloc(sizeof(struct sgi_ip30_data))); memset(d, 0, sizeof(struct sgi_ip30_data)); - memory_device_register(mem, "sgi_ip30_1", baseaddr, - DEV_SGI_IP30_LENGTH, dev_sgi_ip30_access, (void *)d, + memory_device_register(devinit->machine->memory, "sgi_ip30_1", + devinit->addr, DEV_SGI_IP30_LENGTH, dev_sgi_ip30_access, (void *)d, DM_DEFAULT, NULL); - memory_device_register(mem, "sgi_ip30_2", 0x10000000, - 0x10000, dev_sgi_ip30_2_access, (void *)d, DM_DEFAULT, NULL); - memory_device_register(mem, "sgi_ip30_3", 0x1f000000, - 0x10000, dev_sgi_ip30_3_access, (void *)d, DM_DEFAULT, NULL); - memory_device_register(mem, "sgi_ip30_4", 0x1f600000, - 0x10000, dev_sgi_ip30_4_access, (void *)d, DM_DEFAULT, NULL); - memory_device_register(mem, "sgi_ip30_5", 0x1f6c0000, - 0x10000, dev_sgi_ip30_5_access, (void *)d, DM_DEFAULT, NULL); + memory_device_register(devinit->machine->memory, "sgi_ip30_2", + 0x10000000, 0x10000, dev_sgi_ip30_2_access, (void *)d, DM_DEFAULT, + NULL); + memory_device_register(devinit->machine->memory, "sgi_ip30_3", + 0x1f000000, 0x10000, dev_sgi_ip30_3_access, (void *)d, DM_DEFAULT, + NULL); + memory_device_register(devinit->machine->memory, "sgi_ip30_4", + 0x1f600000, 0x10000, dev_sgi_ip30_4_access, (void *)d, DM_DEFAULT, + NULL); + memory_device_register(devinit->machine->memory, "sgi_ip30_5", + 0x1f6c0000, 0x10000, dev_sgi_ip30_5_access, (void *)d, DM_DEFAULT, + NULL); - machine_add_tickfunction(machine, dev_sgi_ip30_tick, d, 16); + machine_add_tickfunction(devinit->machine, + dev_sgi_ip30_tick, d, 16); - return d; + return 1; }