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