--- trunk/src/devices/dev_gt.c 2007/10/08 16:18:27 10 +++ trunk/src/devices/dev_gt.c 2007/10/08 16:18:38 12 @@ -25,14 +25,16 @@ * SUCH DAMAGE. * * - * $Id: dev_gt.c,v 1.22 2005/06/20 08:19:58 debug Exp $ + * $Id: dev_gt.c,v 1.26 2005/08/05 07:50:37 debug Exp $ * * Galileo Technology GT-64xxx PCI controller. * * GT-64011 Used in Cobalt machines. * GT-64120 Used in evbmips machines (Malta). * - * TODO: This more or less just a dummy device, so far. + * TODO: This more or less just a dummy device, so far. It happens to work + * with NetBSD/cobalt and /evbmips, and in some cases it might happen + * to work with Linux as well, but don't rely on it for anything else. */ #include @@ -47,14 +49,15 @@ #include "misc.h" -#define TICK_STEPS_SHIFT 16 +#define TICK_SHIFT 14 + +/* #define debug fatal */ #define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */ #define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 System Controller */ #define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */ struct gt_data { - int reg[8]; int irqnr; int pciirq; int type; @@ -81,29 +84,68 @@ unsigned char *data, size_t len, int writeflag, void *extra) { uint64_t idata = 0, odata = 0; - int i; + int i, asserted; struct gt_data *d = extra; idata = memory_readmax64(cpu, data, len); switch (relative_addr) { + + case 0x48: + switch (d->type) { + case PCI_PRODUCT_GALILEO_GT64120: + /* + * This is needed for Linux on Malta, according + * to Alec Voropay. (TODO: Remove this hack when + * things have stabilized.) + */ + if (writeflag == MEM_READ) { + odata = 0x18000000 >> 21; + debug("[ gt: read from 0x48: 0x%08x ]\n", + (int)odata); + } + break; + default: + fatal("[ gt: access to 0x48? (type %i) ]\n", d->type); + } + break; + case 0xc18: if (writeflag == MEM_WRITE) { - debug("[ gt write to 0xc18: data = 0x%08lx ]\n", - (long)idata); + debug("[ gt: write to 0xc18: 0x%08x ]\n", (int)idata); return 1; } else { odata = 0xffffffffULL; /* ??? interrupt something... */ +/* + * TODO: Remove this hack when things have stabilized. + */ odata = 0x00000100; /* netbsd/cobalt cobalt/machdep.c:cpu_intr() */ cpu_interrupt_ack(cpu, d->irqnr); - debug("[ gt read from 0xc18 (data = 0x%08lx) ]\n", - (long)odata); + debug("[ gt: read from 0xc18 (0x%08x) ]\n", (int)odata); } break; + + case 0xc34: /* GT_PCI0_INTR_ACK */ + /* + * Ugly hack, which works for at least evbmips/Malta: + */ + asserted = + (cpu->machine->md_int.isa_pic_data.pic1->irr & + ~cpu->machine->md_int.isa_pic_data.pic1->ier) | + ((cpu->machine->md_int.isa_pic_data.pic2->irr & + ~cpu->machine->md_int.isa_pic_data.pic2->ier) << 8); + odata = 7; /* "Spurious interrupt" defaults to 7. */ + for (i=0; i<16; i++) + if ((asserted >> i) & 1) { + odata = i; + break; + } + break; + case 0xcf8: /* PCI ADDR */ case 0xcfc: /* PCI DATA */ if (writeflag == MEM_WRITE) { @@ -116,15 +158,13 @@ break; default: if (writeflag==MEM_READ) { - debug("[ gt read from addr 0x%x ]\n", + debug("[ gt: read from addr 0x%x ]\n", (int)relative_addr); - odata = d->reg[relative_addr]; } else { - debug("[ gt write to addr 0x%x:", (int)relative_addr); + debug("[ gt: write to addr 0x%x:", (int)relative_addr); for (i=0; ireg[relative_addr] = idata; } } @@ -219,7 +259,7 @@ memory_device_register(mem, "gt", baseaddr, DEV_GT_LENGTH, dev_gt_access, d, MEM_DEFAULT, NULL); - machine_add_tickfunction(machine, dev_gt_tick, d, TICK_STEPS_SHIFT); + machine_add_tickfunction(machine, dev_gt_tick, d, TICK_SHIFT); return d->pci_data; }