--- trunk/src/devices/dev_footbridge.c 2007/10/08 16:19:16 19 +++ trunk/src/devices/dev_footbridge.c 2007/10/08 16:19:23 20 @@ -25,19 +25,13 @@ * SUCH DAMAGE. * * - * $Id: dev_footbridge.c,v 1.26 2005/10/26 14:37:04 debug Exp $ + * $Id: dev_footbridge.c,v 1.36 2005/11/21 09:17:26 debug Exp $ * * Footbridge. Used in Netwinder and Cats. * - * TODO: Most things. For example: - * - * o) Fix the timer TODO (see below). - * + * TODO: * o) Add actual support for the fcom serial port. - * * o) FIQs. - * - * o) .. */ #include @@ -107,8 +101,9 @@ /* * dev_footbridge_isa_access(): * - * NetBSD seems to read 0x79000000 to find out which ISA interrupt occurred, - * a quicker way than dealing with legacy 0x20/0xa0 ISA ports. + * Reading the byte at 0x79000000 is a quicker way to figure out which ISA + * interrupt has occurred (and acknowledging it at the same time), than + * dealing with the legacy 0x20/0xa0 ISA ports. */ int dev_footbridge_isa_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr, unsigned char *data, size_t len, @@ -123,28 +118,14 @@ fatal("[ footbridge_isa: WARNING/TODO: write! ]\n"); } - /* - * NetBSD seems to want a value of 0x20 + x, where x is the highest - * priority ISA interrupt which is currently asserted and not masked. - */ - - for (x=0; x<16; x++) { - if (x == 2) - continue; - if (x < 8 && (cpu->machine->isa_pic_data.pic1->irr & - ~cpu->machine->isa_pic_data.pic1->ier & - (1 << x))) - break; - if (x >= 8 && (cpu->machine->isa_pic_data.pic2->irr & - ~cpu->machine->isa_pic_data.pic2->ier & - (1 << (x&7)))) - break; - } - - if (x == 16) - fatal("_\n_ SPORADIC but INVALID ISA interrupt\n_\n"); - - odata = 0x20 + (x & 15); + x = cpu->machine->isa_pic_data.last_int; + if (x == 0) + cpu_interrupt_ack(cpu, 32 + x); + + if (x < 8) + odata = cpu->machine->isa_pic_data.pic1->irq_base + x; + else + odata = cpu->machine->isa_pic_data.pic2->irq_base + x - 8; if (writeflag == MEM_READ) memory_writemax64(cpu, data, len, odata); @@ -196,15 +177,15 @@ pci_word = relative_addr & 0x00ffffff; res = bus_pci_access(cpu, mem, BUS_PCI_ADDR, - &pci_word, MEM_WRITE, d->pcibus); + &pci_word, sizeof(uint32_t), MEM_WRITE, d->pcibus); if (writeflag == MEM_READ) { res = bus_pci_access(cpu, mem, BUS_PCI_DATA, - &pci_word, MEM_READ, d->pcibus); + &pci_word, len, MEM_READ, d->pcibus); odata = pci_word; } else { pci_word = idata; res = bus_pci_access(cpu, mem, BUS_PCI_DATA, - &pci_word, MEM_WRITE, d->pcibus); + &pci_word, len, MEM_WRITE, d->pcibus); } if (writeflag == MEM_READ) @@ -245,10 +226,25 @@ odata = 0x1065; /* DC21285_DEVICE_ID */ break; + case 0x04: + case 0x0c: + case 0x10: + case 0x14: + case 0x18: + /* TODO. Written to by Linux. */ + break; + case REVISION: odata = 3; /* footbridge revision number */ break; + case PCI_ADDRESS_EXTENSION: + /* TODO: Written to by Linux. */ + if (writeflag == MEM_WRITE && idata != 0) + fatal("[ footbridge: TODO: write to PCI_ADDRESS_" + "EXTENSION: 0x%llx ]\n", (long long)idata); + break; + case UART_DATA: if (writeflag == MEM_WRITE) console_putchar(d->console_handle, idata); @@ -349,16 +345,19 @@ case TIMER_1_VALUE: if (writeflag == MEM_READ) { /* - * TODO: This is INCORRECT! but speeds up NetBSD - * and OpenBSD boot sequences. A better solution - * would be to only call dev_footbridge_tick() if - * the timer is polled "very often" (such as during - * bootup), but not during normal operation. + * NOTE/TODO: This is INCORRECT but speeds up NetBSD + * and OpenBSD boot sequences: if the timer is polled + * "very often" (such as during bootup), then this + * causes the timers to expire quickly. */ d->timer_being_read = 1; d->timer_poll_mode ++; - if (d->timer_poll_mode > TIMER_POLL_THRESHOLD) + if (d->timer_poll_mode >= TIMER_POLL_THRESHOLD) { + d->timer_poll_mode = TIMER_POLL_THRESHOLD; dev_footbridge_tick(cpu, d); + dev_footbridge_tick(cpu, d); + dev_footbridge_tick(cpu, d); + } odata = d->timer_value[timer_nr]; d->timer_being_read = 0; } else @@ -428,38 +427,42 @@ /* DC21285 register access: */ memory_device_register(devinit->machine->memory, devinit->name, devinit->addr, DEV_FOOTBRIDGE_LENGTH, - dev_footbridge_access, d, MEM_DEFAULT, NULL); + dev_footbridge_access, d, DM_DEFAULT, NULL); - /* ISA interrupt status word: */ + /* ISA interrupt status/acknowledgement: */ memory_device_register(devinit->machine->memory, "footbridge_isa", - 0x79000000, 8, dev_footbridge_isa_access, d, MEM_DEFAULT, NULL); + 0x79000000, 8, dev_footbridge_isa_access, d, DM_DEFAULT, NULL); /* The "fcom" console: */ d->console_handle = console_start_slave(devinit->machine, "fcom"); /* A PCI bus: */ - d->pcibus = bus_pci_init(devinit->irq_nr); + d->pcibus = bus_pci_init( + devinit->irq_nr, /* PCI controller irq */ + 0x7c000000, /* PCI device io offset */ + 0x80000000, /* PCI device mem offset */ + 0x00000000, /* PCI port base */ + 0x00000000, /* PCI mem base */ + 0, /* PCI irq base: TODO */ + 0x7c000000, /* ISA port base */ + 0x80000000, /* ISA mem base */ + 32); /* ISA port base */ /* ... with some default devices for known machine types: */ switch (devinit->machine->machine_type) { case MACHINE_CATS: bus_pci_add(devinit->machine, d->pcibus, - devinit->machine->memory, 0xc0, 7, 0, - pci_ali_m1543_init, pci_ali_m1543_rr); - /* bus_pci_add(devinit->machine, d->pcibus, - devinit->machine->memory, 0xc0, 10, 0, - pci_dec21143_init, pci_dec21143_rr); */ + devinit->machine->memory, 0xc0, 7, 0, "ali_m1543"); + bus_pci_add(devinit->machine, d->pcibus, + devinit->machine->memory, 0xc0, 10, 0, "dec21143"); bus_pci_add(devinit->machine, d->pcibus, - devinit->machine->memory, 0xc0, 16, 0, - pci_ali_m5229_init, pci_ali_m5229_rr); + devinit->machine->memory, 0xc0, 16, 0, "ali_m5229"); break; case MACHINE_NETWINDER: bus_pci_add(devinit->machine, d->pcibus, - devinit->machine->memory, 0xc0, 11, 0, - pci_symphony_83c553_init, pci_symphony_83c553_rr); + devinit->machine->memory, 0xc0, 11, 0, "symphony_83c553"); bus_pci_add(devinit->machine, d->pcibus, - devinit->machine->memory, 0xc0, 11, 1, - pci_symphony_82c105_init, pci_symphony_82c105_rr); + devinit->machine->memory, 0xc0, 11, 1, "symphony_82c105"); break; default:fatal("footbridge: unimplemented machine type.\n"); exit(1); @@ -468,7 +471,7 @@ /* PCI configuration space: */ memory_device_register(devinit->machine->memory, "footbridge_pci", pci_addr, 0x1000000, - dev_footbridge_pci_access, d, MEM_DEFAULT, NULL); + dev_footbridge_pci_access, d, DM_DEFAULT, NULL); /* Timer ticks: */ for (i=0; i