--- trunk/src/devices/dev_footbridge.c 2007/10/08 16:19:23 20 +++ trunk/src/devices/dev_footbridge.c 2007/10/08 16:19:56 24 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 Anders Gavare. All rights reserved. + * Copyright (C) 2005-2006 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,13 +25,16 @@ * SUCH DAMAGE. * * - * $Id: dev_footbridge.c,v 1.36 2005/11/21 09:17:26 debug Exp $ + * $Id: dev_footbridge.c,v 1.43 2006/03/04 12:38:47 debug Exp $ * * Footbridge. Used in Netwinder and Cats. * * TODO: * o) Add actual support for the fcom serial port. * o) FIQs. + * o) Pretty much everything else as well :) (This entire thing + * is a quick hack to work primarily with NetBSD and OpenBSD + * as a guest OS.) */ #include @@ -42,7 +45,7 @@ #include "console.h" #include "cpu.h" #include "device.h" -#include "devices.h" /* for struct footbridge_data */ +#include "devices.h" #include "machine.h" #include "memory.h" #include "misc.h" @@ -71,7 +74,7 @@ d->timer_poll_mode = 0; for (i=0; itimer_control[i] & TIMER_FCLK_16) amount >>= 4; else if (d->timer_control[i] & TIMER_FCLK_256) @@ -105,9 +108,7 @@ * 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, - int writeflag, void *extra) +DEVICE_ACCESS(footbridge_isa) { /* struct footbridge_data *d = extra; */ uint64_t idata = 0, odata = 0; @@ -137,27 +138,22 @@ /* * dev_footbridge_pci_access(): * - * The Footbridge PCI configuration space is not implemented as "address + - * data port" pair, but instead a 24-bit (16 MB) chunk of physical memory - * decodes as the address. This function translates that into bus_pci_access - * calls. + * The Footbridge PCI configuration space is implemented as a direct memory + * space (i.e. not one port for addr and one port for data). This function + * translates that into bus_pci calls. */ -int dev_footbridge_pci_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(footbridge_pci) { struct footbridge_data *d = extra; uint64_t idata = 0, odata = 0; - int bus, device, function, regnr, res; - uint64_t pci_word; + int bus, dev, func, reg; if (writeflag == MEM_WRITE) - idata = memory_readmax64(cpu, data, len); + idata = memory_readmax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN); - bus = (relative_addr >> 16) & 0xff; - device = (relative_addr >> 11) & 0x1f; - function = (relative_addr >> 8) & 0x7; - regnr = relative_addr & 0xff; + /* Decompose the (direct) address into its components: */ + bus_pci_decompose_1(relative_addr, &bus, &dev, &func, ®); + bus_pci_setaddr(cpu, d->pcibus, bus, dev, func, reg); if (bus == 255) { fatal("[ footbridge DEBUG ERROR: bus 255 unlikely," @@ -165,31 +161,15 @@ exit(1); } - debug("[ footbridge_pci: %s bus %i, device %i, function " - "%i, register %i ]\n", writeflag == MEM_READ? "read from" - : "write to", bus, device, function, regnr); - - if (d->pcibus == NULL) { - fatal("dev_footbridge_pci_access(): no PCI bus?\n"); - return 0; - } + debug("[ footbridge pci: %s bus %i, device %i, function %i, register " + "%i ]\n", writeflag == MEM_READ? "read from" : "write to", bus, + dev, func, reg); - pci_word = relative_addr & 0x00ffffff; - - res = bus_pci_access(cpu, mem, BUS_PCI_ADDR, - &pci_word, sizeof(uint32_t), MEM_WRITE, d->pcibus); - if (writeflag == MEM_READ) { - res = bus_pci_access(cpu, mem, BUS_PCI_DATA, - &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, len, MEM_WRITE, d->pcibus); - } + bus_pci_data_access(cpu, d->pcibus, writeflag == MEM_READ? + &odata : &idata, len, writeflag); if (writeflag == MEM_READ) - memory_writemax64(cpu, data, len, odata); + memory_writemax64(cpu, data, len|MEM_PCI_LITTLE_ENDIAN, odata); return 1; } @@ -200,9 +180,7 @@ * * The DC21285 registers. */ -int dev_footbridge_access(struct cpu *cpu, struct memory *mem, - uint64_t relative_addr, unsigned char *data, size_t len, - int writeflag, void *extra) +DEVICE_ACCESS(footbridge) { struct footbridge_data *d = extra; uint64_t idata = 0, odata = 0; @@ -245,6 +223,11 @@ "EXTENSION: 0x%llx ]\n", (long long)idata); break; + case SA_CONTROL: + /* Read by Linux: */ + odata = PCI_CENTRAL_FUNCTION; + break; + case UART_DATA: if (writeflag == MEM_WRITE) console_putchar(d->console_handle, idata); @@ -408,10 +391,7 @@ } -/* - * devinit_footbridge(): - */ -int devinit_footbridge(struct devinit *devinit) +DEVINIT(footbridge) { struct footbridge_data *d; uint64_t pci_addr = 0x7b000000; @@ -434,10 +414,11 @@ 0x79000000, 8, dev_footbridge_isa_access, d, DM_DEFAULT, NULL); /* The "fcom" console: */ - d->console_handle = console_start_slave(devinit->machine, "fcom"); + d->console_handle = console_start_slave(devinit->machine, "fcom", 0); /* A PCI bus: */ d->pcibus = bus_pci_init( + devinit->machine, devinit->irq_nr, /* PCI controller irq */ 0x7c000000, /* PCI device io offset */ 0x80000000, /* PCI device mem offset */ @@ -479,7 +460,7 @@ d->timer_load[i] = TIMER_MAX_VAL; } machine_add_tickfunction(devinit->machine, - dev_footbridge_tick, d, DEV_FOOTBRIDGE_TICK_SHIFT); + dev_footbridge_tick, d, DEV_FOOTBRIDGE_TICK_SHIFT, 0.0); devinit->return_ptr = d; return 1;