linux/arch/mips/pci/ops-bridge.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org)
   7 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
   8 */
   9#include <linux/pci.h>
  10#include <asm/paccess.h>
  11#include <asm/pci/bridge.h>
  12#include <asm/sn/arch.h>
  13#include <asm/sn/intr.h>
  14#include <asm/sn/sn0/hub.h>
  15
  16/*
  17 * Most of the IOC3 PCI config register aren't present
  18 * we emulate what is needed for a normal PCI enumeration
  19 */
  20static u32 emulate_ioc3_cfg(int where, int size)
  21{
  22        if (size == 1 && where == 0x3d)
  23                return 0x01;
  24        else if (size == 2 && where == 0x3c)
  25                return 0x0100;
  26        else if (size == 4 && where == 0x3c)
  27                return 0x00000100;
  28
  29        return 0;
  30}
  31
  32/*
  33 * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
  34 * not really documented, so right now I can't write code which uses it.
  35 * Therefore we use type 0 accesses for now even though they won't work
  36 * correcly for PCI-to-PCI bridges.
  37 *
  38 * The function is complicated by the ultimate brokeness of the IOC3 chip
  39 * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
  40 * accesses and does only decode parts of it's address space.
  41 */
  42
  43static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
  44                                 int where, int size, u32 * value)
  45{
  46        struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
  47        bridge_t *bridge = bc->base;
  48        int slot = PCI_SLOT(devfn);
  49        int fn = PCI_FUNC(devfn);
  50        volatile void *addr;
  51        u32 cf, shift, mask;
  52        int res;
  53
  54        addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
  55        if (get_dbe(cf, (u32 *) addr))
  56                return PCIBIOS_DEVICE_NOT_FOUND;
  57
  58        /*
  59         * IOC3 is fucked fucked beyond believe ...  Don't even give the
  60         * generic PCI code a chance to look at it for real ...
  61         */
  62        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
  63                goto oh_my_gawd;
  64
  65        addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
  66
  67        if (size == 1)
  68                res = get_dbe(*value, (u8 *) addr);
  69        else if (size == 2)
  70                res = get_dbe(*value, (u16 *) addr);
  71        else
  72                res = get_dbe(*value, (u32 *) addr);
  73
  74        return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
  75
  76oh_my_gawd:
  77
  78        /*
  79         * IOC3 is fucked fucked beyond believe ...  Don't even give the
  80         * generic PCI code a chance to look at the wrong register.
  81         */
  82        if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
  83                *value = emulate_ioc3_cfg(where, size);
  84                return PCIBIOS_SUCCESSFUL;
  85        }
  86
  87        /*
  88         * IOC3 is fucked fucked beyond believe ...  Don't try to access
  89         * anything but 32-bit words ...
  90         */
  91        addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
  92
  93        if (get_dbe(cf, (u32 *) addr))
  94                return PCIBIOS_DEVICE_NOT_FOUND;
  95
  96        shift = ((where & 3) << 3);
  97        mask = (0xffffffffU >> ((4 - size) << 3));
  98        *value = (cf >> shift) & mask;
  99
 100        return PCIBIOS_SUCCESSFUL;
 101}
 102
 103static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
 104                                 int where, int size, u32 * value)
 105{
 106        struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
 107        bridge_t *bridge = bc->base;
 108        int busno = bus->number;
 109        int slot = PCI_SLOT(devfn);
 110        int fn = PCI_FUNC(devfn);
 111        volatile void *addr;
 112        u32 cf, shift, mask;
 113        int res;
 114
 115        bridge->b_pci_cfg = (busno << 16) | (slot << 11);
 116        addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
 117        if (get_dbe(cf, (u32 *) addr))
 118                return PCIBIOS_DEVICE_NOT_FOUND;
 119
 120        /*
 121         * IOC3 is fucked fucked beyond believe ...  Don't even give the
 122         * generic PCI code a chance to look at it for real ...
 123         */
 124        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
 125                goto oh_my_gawd;
 126
 127        bridge->b_pci_cfg = (busno << 16) | (slot << 11);
 128        addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
 129
 130        if (size == 1)
 131                res = get_dbe(*value, (u8 *) addr);
 132        else if (size == 2)
 133                res = get_dbe(*value, (u16 *) addr);
 134        else
 135                res = get_dbe(*value, (u32 *) addr);
 136
 137        return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
 138
 139oh_my_gawd:
 140
 141        /*
 142         * IOC3 is fucked fucked beyond believe ...  Don't even give the
 143         * generic PCI code a chance to look at the wrong register.
 144         */
 145        if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
 146                *value = emulate_ioc3_cfg(where, size);
 147                return PCIBIOS_SUCCESSFUL;
 148        }
 149
 150        /*
 151         * IOC3 is fucked fucked beyond believe ...  Don't try to access
 152         * anything but 32-bit words ...
 153         */
 154        bridge->b_pci_cfg = (busno << 16) | (slot << 11);
 155        addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
 156
 157        if (get_dbe(cf, (u32 *) addr))
 158                return PCIBIOS_DEVICE_NOT_FOUND;
 159
 160        shift = ((where & 3) << 3);
 161        mask = (0xffffffffU >> ((4 - size) << 3));
 162        *value = (cf >> shift) & mask;
 163
 164        return PCIBIOS_SUCCESSFUL;
 165}
 166
 167static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
 168                           int where, int size, u32 * value)
 169{
 170        if (bus->number > 0)
 171                return pci_conf1_read_config(bus, devfn, where, size, value);
 172
 173        return pci_conf0_read_config(bus, devfn, where, size, value);
 174}
 175
 176static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
 177                                  int where, int size, u32 value)
 178{
 179        struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
 180        bridge_t *bridge = bc->base;
 181        int slot = PCI_SLOT(devfn);
 182        int fn = PCI_FUNC(devfn);
 183        volatile void *addr;
 184        u32 cf, shift, mask, smask;
 185        int res;
 186
 187        addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
 188        if (get_dbe(cf, (u32 *) addr))
 189                return PCIBIOS_DEVICE_NOT_FOUND;
 190
 191        /*
 192         * IOC3 is fucked fucked beyond believe ...  Don't even give the
 193         * generic PCI code a chance to look at it for real ...
 194         */
 195        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
 196                goto oh_my_gawd;
 197
 198        addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
 199
 200        if (size == 1) {
 201                res = put_dbe(value, (u8 *) addr);
 202        } else if (size == 2) {
 203                res = put_dbe(value, (u16 *) addr);
 204        } else {
 205                res = put_dbe(value, (u32 *) addr);
 206        }
 207
 208        if (res)
 209                return PCIBIOS_DEVICE_NOT_FOUND;
 210
 211        return PCIBIOS_SUCCESSFUL;
 212
 213oh_my_gawd:
 214
 215        /*
 216         * IOC3 is fucked fucked beyond believe ...  Don't even give the
 217         * generic PCI code a chance to touch the wrong register.
 218         */
 219        if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
 220                return PCIBIOS_SUCCESSFUL;
 221
 222        /*
 223         * IOC3 is fucked fucked beyond believe ...  Don't try to access
 224         * anything but 32-bit words ...
 225         */
 226        addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
 227
 228        if (get_dbe(cf, (u32 *) addr))
 229                return PCIBIOS_DEVICE_NOT_FOUND;
 230
 231        shift = ((where & 3) << 3);
 232        mask = (0xffffffffU >> ((4 - size) << 3));
 233        smask = mask << shift;
 234
 235        cf = (cf & ~smask) | ((value & mask) << shift);
 236        if (put_dbe(cf, (u32 *) addr))
 237                return PCIBIOS_DEVICE_NOT_FOUND;
 238
 239        return PCIBIOS_SUCCESSFUL;
 240}
 241
 242static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
 243                                  int where, int size, u32 value)
 244{
 245        struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
 246        bridge_t *bridge = bc->base;
 247        int slot = PCI_SLOT(devfn);
 248        int fn = PCI_FUNC(devfn);
 249        int busno = bus->number;
 250        volatile void *addr;
 251        u32 cf, shift, mask, smask;
 252        int res;
 253
 254        bridge->b_pci_cfg = (busno << 16) | (slot << 11);
 255        addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
 256        if (get_dbe(cf, (u32 *) addr))
 257                return PCIBIOS_DEVICE_NOT_FOUND;
 258
 259        /*
 260         * IOC3 is fucked fucked beyond believe ...  Don't even give the
 261         * generic PCI code a chance to look at it for real ...
 262         */
 263        if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
 264                goto oh_my_gawd;
 265
 266        addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
 267
 268        if (size == 1) {
 269                res = put_dbe(value, (u8 *) addr);
 270        } else if (size == 2) {
 271                res = put_dbe(value, (u16 *) addr);
 272        } else {
 273                res = put_dbe(value, (u32 *) addr);
 274        }
 275
 276        if (res)
 277                return PCIBIOS_DEVICE_NOT_FOUND;
 278
 279        return PCIBIOS_SUCCESSFUL;
 280
 281oh_my_gawd:
 282
 283        /*
 284         * IOC3 is fucked fucked beyond believe ...  Don't even give the
 285         * generic PCI code a chance to touch the wrong register.
 286         */
 287        if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
 288                return PCIBIOS_SUCCESSFUL;
 289
 290        /*
 291         * IOC3 is fucked fucked beyond believe ...  Don't try to access
 292         * anything but 32-bit words ...
 293         */
 294        addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
 295
 296        if (get_dbe(cf, (u32 *) addr))
 297                return PCIBIOS_DEVICE_NOT_FOUND;
 298
 299        shift = ((where & 3) << 3);
 300        mask = (0xffffffffU >> ((4 - size) << 3));
 301        smask = mask << shift;
 302
 303        cf = (cf & ~smask) | ((value & mask) << shift);
 304        if (put_dbe(cf, (u32 *) addr))
 305                return PCIBIOS_DEVICE_NOT_FOUND;
 306
 307        return PCIBIOS_SUCCESSFUL;
 308}
 309
 310static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
 311        int where, int size, u32 value)
 312{
 313        if (bus->number > 0)
 314                return pci_conf1_write_config(bus, devfn, where, size, value);
 315
 316        return pci_conf0_write_config(bus, devfn, where, size, value);
 317}
 318
 319struct pci_ops bridge_pci_ops = {
 320        .read   = pci_read_config,
 321        .write  = pci_write_config,
 322};
 323