Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.14 147 lines 3.7 kB view raw
1#include <linux/kernel.h> 2#include <linux/init.h> 3#include <linux/pci.h> 4#include <asm/bootinfo.h> 5 6#include <asm/lasat/lasat.h> 7#include <asm/gt64120.h> 8#include <asm/nile4.h> 9 10#define PCI_ACCESS_READ 0 11#define PCI_ACCESS_WRITE 1 12 13#define LO(reg) (reg / 4) 14#define HI(reg) (reg / 4 + 1) 15 16volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; 17 18static spinlock_t nile4_pci_lock; 19 20static int nile4_pcibios_config_access(unsigned char access_type, 21 struct pci_bus *bus, unsigned int devfn, int where, u32 * val) 22{ 23 unsigned char busnum = bus->number; 24 u32 adr, mask, err; 25 26 if ((busnum == 0) && (PCI_SLOT(devfn) > 8)) 27 /* The addressing scheme chosen leaves room for just 28 * 8 devices on the first busnum (besides the PCI 29 * controller itself) */ 30 return PCIBIOS_DEVICE_NOT_FOUND; 31 32 if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) { 33 /* Access controller registers directly */ 34 if (access_type == PCI_ACCESS_WRITE) { 35 vrc_pciregs[(0x200 + where) >> 2] = *val; 36 } else { 37 *val = vrc_pciregs[(0x200 + where) >> 2]; 38 } 39 return PCIBIOS_SUCCESSFUL; 40 } 41 42 /* Temporarily map PCI Window 1 to config space */ 43 mask = vrc_pciregs[LO(NILE4_PCIINIT1)]; 44 vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0); 45 46 /* Clear PCI Error register. This also clears the Error Type 47 * bits in the Control register */ 48 vrc_pciregs[LO(NILE4_PCIERR)] = 0; 49 vrc_pciregs[HI(NILE4_PCIERR)] = 0; 50 51 /* Setup address */ 52 if (busnum == 0) 53 adr = 54 KSEG1ADDR(PCI_WINDOW1) + 55 ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8) 56 | (where & ~3)); 57 else 58 adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) | 59 (where & ~3); 60 61 if (access_type == PCI_ACCESS_WRITE) 62 *(u32 *) adr = *val; 63 else 64 *val = *(u32 *) adr; 65 66 /* Check for master or target abort */ 67 err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7; 68 69 /* Restore PCI Window 1 */ 70 vrc_pciregs[LO(NILE4_PCIINIT1)] = mask; 71 72 if (err) 73 return PCIBIOS_DEVICE_NOT_FOUND; 74 75 return PCIBIOS_SUCCESSFUL; 76} 77 78static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, 79 int where, int size, u32 * val) 80{ 81 unsigned long flags; 82 u32 data = 0; 83 int err; 84 85 if ((size == 2) && (where & 1)) 86 return PCIBIOS_BAD_REGISTER_NUMBER; 87 else if ((size == 4) && (where & 3)) 88 return PCIBIOS_BAD_REGISTER_NUMBER; 89 90 spin_lock_irqsave(&nile4_pci_lock, flags); 91 err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, 92 &data); 93 spin_unlock_irqrestore(&nile4_pci_lock, flags); 94 95 if (err) 96 return err; 97 98 if (size == 1) 99 *val = (data >> ((where & 3) << 3)) & 0xff; 100 else if (size == 2) 101 *val = (data >> ((where & 3) << 3)) & 0xffff; 102 else 103 *val = data; 104 105 return PCIBIOS_SUCCESSFUL; 106} 107 108static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, 109 int where, int size, u32 val) 110{ 111 unsigned long flags; 112 u32 data = 0; 113 int err; 114 115 if ((size == 2) && (where & 1)) 116 return PCIBIOS_BAD_REGISTER_NUMBER; 117 else if ((size == 4) && (where & 3)) 118 return PCIBIOS_BAD_REGISTER_NUMBER; 119 120 spin_lock_irqsave(&nile4_pci_lock, flags); 121 err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, 122 &data); 123 spin_unlock_irqrestore(&nile4_pci_lock, flags); 124 125 if (err) 126 return err; 127 128 if (size == 1) 129 data = (data & ~(0xff << ((where & 3) << 3))) | 130 (val << ((where & 3) << 3)); 131 else if (size == 2) 132 data = (data & ~(0xffff << ((where & 3) << 3))) | 133 (val << ((where & 3) << 3)); 134 else 135 data = val; 136 137 if (nile4_pcibios_config_access 138 (PCI_ACCESS_WRITE, bus, devfn, where, &data)) 139 return -1; 140 141 return PCIBIOS_SUCCESSFUL; 142} 143 144struct pci_ops nile4_pci_ops = { 145 .read = nile4_pcibios_read, 146 .write = nile4_pcibios_write, 147};