diff -urN linux/arch/ppc/kernel/pci.c bk/arch/ppc/kernel/pci.c --- linux/arch/ppc/kernel/pci.c Wed Aug 2 15:20:18 2000 +++ bk/arch/ppc/kernel/pci.c Tue Aug 29 09:48:33 2000 @@ -188,114 +188,26 @@ return 0; } -/* - * Those syscalls are derived from the Alpha versions, they - * allow userland apps to retreive the per-device iobase and - * mem-base. They also provide wrapper for userland to do - * config space accesses. - * The "host_number" returns the number of the Uni-N sub bridge - */ - -asmlinkage int -sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - unsigned char ubyte; - unsigned short ushort; - unsigned int uint; - long err = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!pcibios_present()) - return -ENOSYS; - - switch (len) { - case 1: - err = pcibios_read_config_byte(bus, dfn, off, &ubyte); - put_user(ubyte, buf); - break; - case 2: - err = pcibios_read_config_word(bus, dfn, off, &ushort); - put_user(ushort, (unsigned short *)buf); - break; - case 4: - err = pcibios_read_config_dword(bus, dfn, off, &uint); - put_user(uint, (unsigned int *)buf); - break; - default: - err = -EINVAL; - break; - } - return err; -} - -asmlinkage int -sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - unsigned char ubyte; - unsigned short ushort; - unsigned int uint; - long err = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (!pcibios_present()) - return -ENOSYS; - - switch (len) { - case 1: - err = get_user(ubyte, buf); - if (err) - break; - err = pcibios_write_config_byte(bus, dfn, off, ubyte); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - case 2: - err = get_user(ushort, (unsigned short *)buf); - if (err) - break; - err = pcibios_write_config_word(bus, dfn, off, ushort); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - case 4: - err = get_user(uint, (unsigned int *)buf); - if (err) - break; - err = pcibios_write_config_dword(bus, dfn, off, uint); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - default: - err = -EINVAL; - break; - } - return err; -} - void * -pci_dev_io_base(unsigned char bus, unsigned char devfn) +pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical) { - /* Defaults to old way */ - if (!ppc_md.pci_dev_io_base) - return pci_io_base(bus); - return ppc_md.pci_dev_io_base(bus, devfn); + if (!ppc_md.pci_dev_io_base) { + /* Please, someone fix this for non-pmac machines, we + * need either the virtual or physical PCI IO base + */ + return 0; + } + return ppc_md.pci_dev_io_base(bus, devfn, physical); } void * pci_dev_mem_base(unsigned char bus, unsigned char devfn) { /* Default memory base is 0 (1:1 mapping) */ - if (!ppc_md.pci_dev_mem_base) + if (!ppc_md.pci_dev_mem_base) { + /* Please, someone fix this for non-pmac machines.*/ return 0; + } return ppc_md.pci_dev_mem_base(bus, devfn); } @@ -318,15 +230,20 @@ asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) { + long result = -EOPNOTSUPP; + switch (which) { case IOBASE_BRIDGE_NUMBER: return (long)pci_dev_root_bridge(bus, devfn); case IOBASE_MEMORY: return (long)pci_dev_mem_base(bus, devfn); case IOBASE_IO: - return (long)pci_dev_io_base(bus, devfn); + result = (long)pci_dev_io_base(bus, devfn, 1); + if (result == 0) + result = -EOPNOTSUPP; + break; } - return -EOPNOTSUPP; + return result; } diff -urN linux/arch/ppc/kernel/pmac_pci.c bk/arch/ppc/kernel/pmac_pci.c --- linux/arch/ppc/kernel/pmac_pci.c Fri Jul 14 14:41:36 2000 +++ bk/arch/ppc/kernel/pmac_pci.c Fri Aug 25 17:10:27 2000 @@ -35,6 +35,7 @@ volatile unsigned int* cfg_addr; volatile unsigned int* cfg_data; void* iobase; + unsigned long iobase_phys; }; static struct uninorth_data uninorth_bridges[3]; @@ -133,15 +134,20 @@ __pmac void * -pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn) +pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical) { - int bridge; - if (uninorth_count == 0) - return pci_io_base(bus); - bridge = pmac_pci_dev_root_bridge(bus, devfn); - if (bridge == -1) - return pci_io_base(bus); - return uninorth_bridges[bridge].iobase; + int bridge = -1; + if (uninorth_count != 0) + bridge = pmac_pci_dev_root_bridge(bus, devfn); + if (bridge == -1) { + struct bridge_data *bp; + + if (bus > max_bus || (bp = bridges[bus]) == 0) + return 0; + return physical ? (void *) bp->io_base_phys : bp->io_base; + } + return physical ? (void *) uninorth_bridges[bridge].iobase_phys + : uninorth_bridges[bridge].iobase; } __pmac @@ -649,7 +655,9 @@ uninorth_bridges[i].cfg_addr = ioremap(addr->address + 0x800000, 0x1000); uninorth_bridges[i].cfg_data = ioremap(addr->address + 0xc00000, 0x1000); uninorth_bridges[i].node = dev; - uninorth_bridges[i].iobase = (void *)addr->address; + uninorth_bridges[i].iobase_phys = addr->address; + /* is 0x10000 enough for io space ? */ + uninorth_bridges[i].iobase = (void *)ioremap(addr->address, 0x10000); /* XXX This is the bridge with the PCI expansion bus. This is also the * address of the bus that will receive type 1 config accesses and io * accesses. Appears to be correct for iMac DV and G4 Sawtooth too. @@ -667,14 +675,15 @@ if (device_is_compatible(dev, "uni-north")) { bp->cfg_addr = 0; bp->cfg_data = 0; - /* is 0x10000 enough for io space ? */ - bp->io_base = (void *)ioremap(addr->address, 0x10000); + bp->io_base = uninorth_bridges[uninorth_count-1].iobase; + bp->io_base_phys = uninorth_bridges[uninorth_count-1].iobase_phys; } else if (strcmp(dev->name, "pci") == 0) { /* XXX assume this is a mpc106 (grackle) */ bp->cfg_addr = (volatile unsigned int *) ioremap(0xfec00000, 0x1000); bp->cfg_data = (volatile unsigned char *) ioremap(0xfee00000, 0x1000); + bp->io_base_phys = 0xfe000000; bp->io_base = (void *) ioremap(0xfe000000, 0x20000); if (machine_is_compatible("AAPL,PowerBook1998")) grackle_set_loop_snoop(bp, 1); @@ -687,6 +696,7 @@ ioremap(addr->address + 0x800000, 0x1000); bp->cfg_data = (volatile unsigned char *) ioremap(addr->address + 0xc00000, 0x1000); + bp->io_base_phys = addr->address; bp->io_base = (void *) ioremap(addr->address, 0x10000); } if (isa_io_base == 0) diff -urN linux/arch/ppc/kernel/pmac_setup.c bk/arch/ppc/kernel/pmac_setup.c --- linux/arch/ppc/kernel/pmac_setup.c Wed Aug 2 15:20:18 2000 +++ bk/arch/ppc/kernel/pmac_setup.c Tue Aug 29 09:48:33 2000 @@ -99,7 +99,7 @@ extern int keyboard_sends_linux_keycodes; extern void pmac_nvram_update(void); -extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn); +extern void *pmac_pci_dev_io_base(unsigned char bus, unsigned char devfn, int physical); extern void *pmac_pci_dev_mem_base(unsigned char bus, unsigned char devfn); extern int pmac_pci_dev_root_bridge(unsigned char bus, unsigned char devfn);