📄 pci_sabre.c
字号:
/* $Id: pci_sabre.c,v 1.41.2.1 2002/03/03 10:31:56 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) */#include <linux/kernel.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/slab.h>#include <asm/apb.h>#include <asm/pbm.h>#include <asm/iommu.h>#include <asm/irq.h>#include <asm/smp.h>#include "pci_impl.h"#include "iommu_common.h"/* All SABRE registers are 64-bits. The following accessor * routines are how they are accessed. The REG parameter * is a physical address. */#define sabre_read(__reg) \({ u64 __ret; \ __asm__ __volatile__("ldxa [%1] %2, %0" \ : "=r" (__ret) \ : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory"); \ __ret; \})#define sabre_write(__reg, __val) \ __asm__ __volatile__("stxa %0, [%1] %2" \ : /* no outputs */ \ : "r" (__val), "r" (__reg), \ "i" (ASI_PHYS_BYPASS_EC_E) \ : "memory")/* SABRE PCI controller register offsets and definitions. */#define SABRE_UE_AFSR 0x0030UL#define SABRE_UEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */#define SABRE_UEAFSR_PDWR 0x2000000000000000UL /* Primary PCI DMA Write */#define SABRE_UEAFSR_SDRD 0x0800000000000000UL /* Secondary PCI DMA Read */#define SABRE_UEAFSR_SDWR 0x0400000000000000UL /* Secondary PCI DMA Write */#define SABRE_UEAFSR_SDTE 0x0200000000000000UL /* Secondary DMA Translation Error */#define SABRE_UEAFSR_PDTE 0x0100000000000000UL /* Primary DMA Translation Error */#define SABRE_UEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask */#define SABRE_UEAFSR_OFF 0x00000000e0000000UL /* Offset (AFAR bits [5:3] */#define SABRE_UEAFSR_BLK 0x0000000000800000UL /* Was block operation */#define SABRE_UECE_AFAR 0x0038UL#define SABRE_CE_AFSR 0x0040UL#define SABRE_CEAFSR_PDRD 0x4000000000000000UL /* Primary PCI DMA Read */#define SABRE_CEAFSR_PDWR 0x2000000000000000UL /* Primary PCI DMA Write */#define SABRE_CEAFSR_SDRD 0x0800000000000000UL /* Secondary PCI DMA Read */#define SABRE_CEAFSR_SDWR 0x0400000000000000UL /* Secondary PCI DMA Write */#define SABRE_CEAFSR_ESYND 0x00ff000000000000UL /* ECC Syndrome */#define SABRE_CEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask */#define SABRE_CEAFSR_OFF 0x00000000e0000000UL /* Offset */#define SABRE_CEAFSR_BLK 0x0000000000800000UL /* Was block operation */#define SABRE_UECE_AFAR_ALIAS 0x0048UL /* Aliases to 0x0038 */#define SABRE_IOMMU_CONTROL 0x0200UL#define SABRE_IOMMUCTRL_ERRSTS 0x0000000006000000UL /* Error status bits */#define SABRE_IOMMUCTRL_ERR 0x0000000001000000UL /* Error present in IOTLB */#define SABRE_IOMMUCTRL_LCKEN 0x0000000000800000UL /* IOTLB lock enable */#define SABRE_IOMMUCTRL_LCKPTR 0x0000000000780000UL /* IOTLB lock pointer */#define SABRE_IOMMUCTRL_TSBSZ 0x0000000000070000UL /* TSB Size */#define SABRE_IOMMU_TSBSZ_1K 0x0000000000000000#define SABRE_IOMMU_TSBSZ_2K 0x0000000000010000#define SABRE_IOMMU_TSBSZ_4K 0x0000000000020000#define SABRE_IOMMU_TSBSZ_8K 0x0000000000030000#define SABRE_IOMMU_TSBSZ_16K 0x0000000000040000#define SABRE_IOMMU_TSBSZ_32K 0x0000000000050000#define SABRE_IOMMU_TSBSZ_64K 0x0000000000060000#define SABRE_IOMMU_TSBSZ_128K 0x0000000000070000#define SABRE_IOMMUCTRL_TBWSZ 0x0000000000000004UL /* TSB assumed page size */#define SABRE_IOMMUCTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */#define SABRE_IOMMUCTRL_ENAB 0x0000000000000001UL /* IOMMU Enable */#define SABRE_IOMMU_TSBBASE 0x0208UL#define SABRE_IOMMU_FLUSH 0x0210UL#define SABRE_IMAP_A_SLOT0 0x0c00UL#define SABRE_IMAP_B_SLOT0 0x0c20UL#define SABRE_IMAP_SCSI 0x1000UL#define SABRE_IMAP_ETH 0x1008UL#define SABRE_IMAP_BPP 0x1010UL#define SABRE_IMAP_AU_REC 0x1018UL#define SABRE_IMAP_AU_PLAY 0x1020UL#define SABRE_IMAP_PFAIL 0x1028UL#define SABRE_IMAP_KMS 0x1030UL#define SABRE_IMAP_FLPY 0x1038UL#define SABRE_IMAP_SHW 0x1040UL#define SABRE_IMAP_KBD 0x1048UL#define SABRE_IMAP_MS 0x1050UL#define SABRE_IMAP_SER 0x1058UL#define SABRE_IMAP_UE 0x1070UL#define SABRE_IMAP_CE 0x1078UL#define SABRE_IMAP_PCIERR 0x1080UL#define SABRE_IMAP_GFX 0x1098UL#define SABRE_IMAP_EUPA 0x10a0UL#define SABRE_ICLR_A_SLOT0 0x1400UL#define SABRE_ICLR_B_SLOT0 0x1480UL#define SABRE_ICLR_SCSI 0x1800UL#define SABRE_ICLR_ETH 0x1808UL#define SABRE_ICLR_BPP 0x1810UL#define SABRE_ICLR_AU_REC 0x1818UL#define SABRE_ICLR_AU_PLAY 0x1820UL#define SABRE_ICLR_PFAIL 0x1828UL#define SABRE_ICLR_KMS 0x1830UL#define SABRE_ICLR_FLPY 0x1838UL#define SABRE_ICLR_SHW 0x1840UL#define SABRE_ICLR_KBD 0x1848UL#define SABRE_ICLR_MS 0x1850UL#define SABRE_ICLR_SER 0x1858UL#define SABRE_ICLR_UE 0x1870UL#define SABRE_ICLR_CE 0x1878UL#define SABRE_ICLR_PCIERR 0x1880UL#define SABRE_WRSYNC 0x1c20UL#define SABRE_PCICTRL 0x2000UL#define SABRE_PCICTRL_MRLEN 0x0000001000000000UL /* Use MemoryReadLine for block loads/stores */#define SABRE_PCICTRL_SERR 0x0000000400000000UL /* Set when SERR asserted on PCI bus */#define SABRE_PCICTRL_ARBPARK 0x0000000000200000UL /* Bus Parking 0=Ultra-IIi 1=prev-bus-owner */#define SABRE_PCICTRL_CPUPRIO 0x0000000000100000UL /* Ultra-IIi granted every other bus cycle */#define SABRE_PCICTRL_ARBPRIO 0x00000000000f0000UL /* Slot which is granted every other bus cycle */#define SABRE_PCICTRL_ERREN 0x0000000000000100UL /* PCI Error Interrupt Enable */#define SABRE_PCICTRL_RTRYWE 0x0000000000000080UL /* DMA Flow Control 0=wait-if-possible 1=retry */#define SABRE_PCICTRL_AEN 0x000000000000000fUL /* Slot PCI arbitration enables */#define SABRE_PIOAFSR 0x2010UL#define SABRE_PIOAFSR_PMA 0x8000000000000000UL /* Primary Master Abort */#define SABRE_PIOAFSR_PTA 0x4000000000000000UL /* Primary Target Abort */#define SABRE_PIOAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */#define SABRE_PIOAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */#define SABRE_PIOAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort */#define SABRE_PIOAFSR_STA 0x0400000000000000UL /* Secondary Target Abort */#define SABRE_PIOAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */#define SABRE_PIOAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */#define SABRE_PIOAFSR_BMSK 0x0000ffff00000000UL /* Byte Mask */#define SABRE_PIOAFSR_BLK 0x0000000080000000UL /* Was Block Operation */#define SABRE_PIOAFAR 0x2018UL#define SABRE_PCIDIAG 0x2020UL#define SABRE_PCIDIAG_DRTRY 0x0000000000000040UL /* Disable PIO Retry Limit */#define SABRE_PCIDIAG_IPAPAR 0x0000000000000008UL /* Invert PIO Address Parity */#define SABRE_PCIDIAG_IPDPAR 0x0000000000000004UL /* Invert PIO Data Parity */#define SABRE_PCIDIAG_IDDPAR 0x0000000000000002UL /* Invert DMA Data Parity */#define SABRE_PCIDIAG_ELPBK 0x0000000000000001UL /* Loopback Enable - not supported */#define SABRE_PCITASR 0x2028UL#define SABRE_PCITASR_EF 0x0000000000000080UL /* Respond to 0xe0000000-0xffffffff */#define SABRE_PCITASR_CD 0x0000000000000040UL /* Respond to 0xc0000000-0xdfffffff */#define SABRE_PCITASR_AB 0x0000000000000020UL /* Respond to 0xa0000000-0xbfffffff */#define SABRE_PCITASR_89 0x0000000000000010UL /* Respond to 0x80000000-0x9fffffff */#define SABRE_PCITASR_67 0x0000000000000008UL /* Respond to 0x60000000-0x7fffffff */#define SABRE_PCITASR_45 0x0000000000000004UL /* Respond to 0x40000000-0x5fffffff */#define SABRE_PCITASR_23 0x0000000000000002UL /* Respond to 0x20000000-0x3fffffff */#define SABRE_PCITASR_01 0x0000000000000001UL /* Respond to 0x00000000-0x1fffffff */#define SABRE_PIOBUF_DIAG 0x5000UL#define SABRE_DMABUF_DIAGLO 0x5100UL#define SABRE_DMABUF_DIAGHI 0x51c0UL#define SABRE_IMAP_GFX_ALIAS 0x6000UL /* Aliases to 0x1098 */#define SABRE_IMAP_EUPA_ALIAS 0x8000UL /* Aliases to 0x10a0 */#define SABRE_IOMMU_VADIAG 0xa400UL#define SABRE_IOMMU_TCDIAG 0xa408UL#define SABRE_IOMMU_TAG 0xa580UL#define SABRE_IOMMUTAG_ERRSTS 0x0000000001800000UL /* Error status bits */#define SABRE_IOMMUTAG_ERR 0x0000000000400000UL /* Error present */#define SABRE_IOMMUTAG_WRITE 0x0000000000200000UL /* Page is writable */#define SABRE_IOMMUTAG_STREAM 0x0000000000100000UL /* Streamable bit - unused */#define SABRE_IOMMUTAG_SIZE 0x0000000000080000UL /* 0=8k 1=16k */#define SABRE_IOMMUTAG_VPN 0x000000000007ffffUL /* Virtual Page Number [31:13] */#define SABRE_IOMMU_DATA 0xa600UL#define SABRE_IOMMUDATA_VALID 0x0000000040000000UL /* Valid */#define SABRE_IOMMUDATA_USED 0x0000000020000000UL /* Used (for LRU algorithm) */#define SABRE_IOMMUDATA_CACHE 0x0000000010000000UL /* Cacheable */#define SABRE_IOMMUDATA_PPN 0x00000000001fffffUL /* Physical Page Number [33:13] */#define SABRE_PCI_IRQSTATE 0xa800UL#define SABRE_OBIO_IRQSTATE 0xa808UL#define SABRE_FFBCFG 0xf000UL#define SABRE_FFBCFG_SPRQS 0x000000000f000000 /* Slave P_RQST queue size */#define SABRE_FFBCFG_ONEREAD 0x0000000000004000 /* Slave supports one outstanding read */#define SABRE_MCCTRL0 0xf010UL#define SABRE_MCCTRL0_RENAB 0x0000000080000000 /* Refresh Enable */#define SABRE_MCCTRL0_EENAB 0x0000000010000000 /* Enable all ECC functions */#define SABRE_MCCTRL0_11BIT 0x0000000000001000 /* Enable 11-bit column addressing */#define SABRE_MCCTRL0_DPP 0x0000000000000f00 /* DIMM Pair Present Bits */#define SABRE_MCCTRL0_RINTVL 0x00000000000000ff /* Refresh Interval */#define SABRE_MCCTRL1 0xf018UL#define SABRE_MCCTRL1_AMDC 0x0000000038000000 /* Advance Memdata Clock */#define SABRE_MCCTRL1_ARDC 0x0000000007000000 /* Advance DRAM Read Data Clock */#define SABRE_MCCTRL1_CSR 0x0000000000e00000 /* CAS to RAS delay for CBR refresh */#define SABRE_MCCTRL1_CASRW 0x00000000001c0000 /* CAS length for read/write */#define SABRE_MCCTRL1_RCD 0x0000000000038000 /* RAS to CAS delay */#define SABRE_MCCTRL1_CP 0x0000000000007000 /* CAS Precharge */#define SABRE_MCCTRL1_RP 0x0000000000000e00 /* RAS Precharge */#define SABRE_MCCTRL1_RAS 0x00000000000001c0 /* Length of RAS for refresh */#define SABRE_MCCTRL1_CASRW2 0x0000000000000038 /* Must be same as CASRW */#define SABRE_MCCTRL1_RSC 0x0000000000000007 /* RAS after CAS hold time */#define SABRE_RESETCTRL 0xf020UL#define SABRE_CONFIGSPACE 0x001000000UL#define SABRE_IOSPACE 0x002000000UL#define SABRE_IOSPACE_SIZE 0x000ffffffUL#define SABRE_MEMSPACE 0x100000000UL#define SABRE_MEMSPACE_SIZE 0x07fffffffUL/* UltraSparc-IIi Programmer's Manual, page 325, PCI * configuration space address format: * * 32 24 23 16 15 11 10 8 7 2 1 0 * --------------------------------------------------------- * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | * --------------------------------------------------------- */#define SABRE_CONFIG_BASE(PBM) \ ((PBM)->config_space | (1UL << 24))#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ (((unsigned long)(BUS) << 16) | \ ((unsigned long)(DEVFN) << 8) | \ ((unsigned long)(REG)))static int hummingbird_p;static struct pci_bus *sabre_root_bus;static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm, unsigned char bus, unsigned int devfn, int where){ if (!pbm) return NULL; return (void *) (SABRE_CONFIG_BASE(pbm) | SABRE_CONFIG_ENCODE(bus, devfn, where));}static int sabre_out_of_range(unsigned char devfn){ if (hummingbird_p) return 0; return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) || ((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) || (PCI_SLOT(devfn) > 1));}static int __sabre_out_of_range(struct pci_pbm_info *pbm, unsigned char bus, unsigned char devfn){ if (hummingbird_p) return 0; return ((pbm->parent == 0) || ((pbm == &pbm->parent->pbm_B) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) || ((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8));}static int __sabre_read_byte(struct pci_dev *dev, int where, u8 *value){ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number]; unsigned char bus = dev->bus->number; unsigned int devfn = dev->devfn; u8 *addr; *value = 0xff; addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; if (__sabre_out_of_range(pbm, bus, devfn)) return PCIBIOS_SUCCESSFUL; pci_config_read8(addr, value); return PCIBIOS_SUCCESSFUL;}static int __sabre_read_word(struct pci_dev *dev, int where, u16 *value){ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number]; unsigned char bus = dev->bus->number; unsigned int devfn = dev->devfn; u16 *addr; *value = 0xffff; addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; if (__sabre_out_of_range(pbm, bus, devfn)) return PCIBIOS_SUCCESSFUL; if (where & 0x01) { printk("pcibios_read_config_word: misaligned reg [%x]\n", where); return PCIBIOS_SUCCESSFUL; } pci_config_read16(addr, value); return PCIBIOS_SUCCESSFUL;}static int __sabre_read_dword(struct pci_dev *dev, int where, u32 *value){ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number]; unsigned char bus = dev->bus->number; unsigned int devfn = dev->devfn; u32 *addr; *value = 0xffffffff; addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; if (__sabre_out_of_range(pbm, bus, devfn)) return PCIBIOS_SUCCESSFUL; if (where & 0x03) { printk("pcibios_read_config_dword: misaligned reg [%x]\n", where); return PCIBIOS_SUCCESSFUL; } pci_config_read32(addr, value); return PCIBIOS_SUCCESSFUL;}/* When accessing PCI config space of the PCI controller itself (bus * 0, device slot 0, function 0) there are restrictions. Each * register must be accessed as it's natural size. Thus, for example * the Vendor ID must be accessed as a 16-bit quantity. */static int sabre_read_byte(struct pci_dev *dev, int where, u8 *value){ if (!dev->bus->number && sabre_out_of_range(dev->devfn)) { *value = 0xff; return PCIBIOS_SUCCESSFUL; } if (dev->bus->number || PCI_SLOT(dev->devfn)) return __sabre_read_byte(dev, where, value); if (where < 8) { u16 tmp; __sabre_read_word(dev, where & ~1, &tmp); if (where & 1) *value = tmp >> 8; else *value = tmp & 0xff; return PCIBIOS_SUCCESSFUL; } else return __sabre_read_byte(dev, where, value);}static int sabre_read_word(struct pci_dev *dev, int where, u16 *value){ if (!dev->bus->number && sabre_out_of_range(dev->devfn)) { *value = 0xffff; return PCIBIOS_SUCCESSFUL; } if (dev->bus->number || PCI_SLOT(dev->devfn)) return __sabre_read_word(dev, where, value); if (where < 8) return __sabre_read_word(dev, where, value); else { u8 tmp; __sabre_read_byte(dev, where, &tmp); *value = tmp; __sabre_read_byte(dev, where + 1, &tmp); *value |= tmp << 8; return PCIBIOS_SUCCESSFUL; }}static int sabre_read_dword(struct pci_dev *dev, int where, u32 *value){ u16 tmp; if (!dev->bus->number && sabre_out_of_range(dev->devfn)) { *value = 0xffffffff; return PCIBIOS_SUCCESSFUL; } if (dev->bus->number || PCI_SLOT(dev->devfn)) return __sabre_read_dword(dev, where, value); sabre_read_word(dev, where, &tmp); *value = tmp; sabre_read_word(dev, where + 2, &tmp); *value |= tmp << 16; return PCIBIOS_SUCCESSFUL;}static int __sabre_write_byte(struct pci_dev *dev, int where, u8 value){ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number]; unsigned char bus = dev->bus->number; unsigned int devfn = dev->devfn; u8 *addr; addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; if (__sabre_out_of_range(pbm, bus, devfn)) return PCIBIOS_SUCCESSFUL; pci_config_write8(addr, value); return PCIBIOS_SUCCESSFUL;}static int __sabre_write_word(struct pci_dev *dev, int where, u16 value){ struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number]; unsigned char bus = dev->bus->number; unsigned int devfn = dev->devfn; u16 *addr; addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where); if (!addr) return PCIBIOS_SUCCESSFUL; if (__sabre_out_of_range(pbm, bus, devfn)) return PCIBIOS_SUCCESSFUL; if (where & 0x01) { printk("pcibios_write_config_word: misaligned reg [%x]\n", where); return PCIBIOS_SUCCESSFUL; } pci_config_write16(addr, value); return PCIBIOS_SUCCESSFUL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -