⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci_schizo.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: pci_schizo.c,v 1.23.2.2 2002/03/11 07:55:24 davem Exp $ * pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. * * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com) */#include <linux/kernel.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/slab.h>#include <asm/pbm.h>#include <asm/iommu.h>#include <asm/irq.h>#include <asm/upa.h>#include "pci_impl.h"#include "iommu_common.h"/* All SCHIZO registers are 64-bits.  The following accessor * routines are how they are accessed.  The REG parameter * is a physical address. */#define schizo_read(__reg) \({	u64 __ret; \	__asm__ __volatile__("ldxa [%1] %2, %0" \			     : "=r" (__ret) \			     : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \			     : "memory"); \	__ret; \})#define schizo_write(__reg, __val) \	__asm__ __volatile__("stxa %0, [%1] %2" \			     : /* no outputs */ \			     : "r" (__val), "r" (__reg), \			       "i" (ASI_PHYS_BYPASS_EC_E) \			     : "memory")/* This is a convention that at least Excalibur and Merlin * follow.  I suppose the SCHIZO used in Starcat and friends * will do similar. * * The only way I could see this changing is if the newlink * block requires more space in Schizo's address space than * they predicted, thus requiring an address space reorg when * the newer Schizo is taped out. *//* Streaming buffer control register. */#define SCHIZO_STRBUF_CTRL_LPTR    0x00000000000000f0UL /* LRU Lock Pointer */#define SCHIZO_STRBUF_CTRL_LENAB   0x0000000000000008UL /* LRU Lock Enable */#define SCHIZO_STRBUF_CTRL_RRDIS   0x0000000000000004UL /* Rerun Disable */#define SCHIZO_STRBUF_CTRL_DENAB   0x0000000000000002UL /* Diagnostic Mode Enable */#define SCHIZO_STRBUF_CTRL_ENAB    0x0000000000000001UL /* Streaming Buffer Enable *//* IOMMU control register. */#define SCHIZO_IOMMU_CTRL_RESV     0xfffffffff9000000 /* Reserved                      */#define SCHIZO_IOMMU_CTRL_XLTESTAT 0x0000000006000000 /* Translation Error Status      */#define SCHIZO_IOMMU_CTRL_XLTEERR  0x0000000001000000 /* Translation Error encountered */#define SCHIZO_IOMMU_CTRL_LCKEN    0x0000000000800000 /* Enable translation locking    */#define SCHIZO_IOMMU_CTRL_LCKPTR   0x0000000000780000 /* Translation lock pointer      */#define SCHIZO_IOMMU_CTRL_TSBSZ    0x0000000000070000 /* TSB Size                      */#define SCHIZO_IOMMU_TSBSZ_1K      0x0000000000000000 /* TSB Table 1024 8-byte entries */#define SCHIZO_IOMMU_TSBSZ_2K      0x0000000000010000 /* TSB Table 2048 8-byte entries */#define SCHIZO_IOMMU_TSBSZ_4K      0x0000000000020000 /* TSB Table 4096 8-byte entries */#define SCHIZO_IOMMU_TSBSZ_8K      0x0000000000030000 /* TSB Table 8192 8-byte entries */#define SCHIZO_IOMMU_TSBSZ_16K     0x0000000000040000 /* TSB Table 16k 8-byte entries  */#define SCHIZO_IOMMU_TSBSZ_32K     0x0000000000050000 /* TSB Table 32k 8-byte entries  */#define SCHIZO_IOMMU_TSBSZ_64K     0x0000000000060000 /* TSB Table 64k 8-byte entries  */#define SCHIZO_IOMMU_TSBSZ_128K    0x0000000000070000 /* TSB Table 128k 8-byte entries */#define SCHIZO_IOMMU_CTRL_RESV2    0x000000000000fff8 /* Reserved                      */#define SCHIZO_IOMMU_CTRL_TBWSZ    0x0000000000000004 /* Assumed page size, 0=8k 1=64k */#define SCHIZO_IOMMU_CTRL_DENAB    0x0000000000000002 /* Diagnostic mode enable        */#define SCHIZO_IOMMU_CTRL_ENAB     0x0000000000000001 /* IOMMU Enable                  *//* Schizo config space address format is nearly identical to * that of PSYCHO: * *  32             24 23 16 15    11 10       8 7   2  1 0 * --------------------------------------------------------- * |0 0 0 0 0 0 0 0 0| bus | device | function | reg | 0 0 | * --------------------------------------------------------- */#define SCHIZO_CONFIG_BASE(PBM)	((PBM)->config_space)#define SCHIZO_CONFIG_ENCODE(BUS, DEVFN, REG)	\	(((unsigned long)(BUS)   << 16) |	\	 ((unsigned long)(DEVFN) << 8)  |	\	 ((unsigned long)(REG)))static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm,				      unsigned char bus,				      unsigned int devfn,				      int where){	if (!pbm)		return NULL;	bus -= pbm->pci_first_busno;	return (void *)		(SCHIZO_CONFIG_BASE(pbm) |		 SCHIZO_CONFIG_ENCODE(bus, devfn, where));}/* Just make sure the bus number is in range.  */static int schizo_out_of_range(struct pci_pbm_info *pbm,			       unsigned char bus,			       unsigned char devfn){	if (bus < pbm->pci_first_busno ||	    bus > pbm->pci_last_busno)		return 1;	return 0;}/* SCHIZO PCI configuration space accessors. */static int schizo_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 = schizo_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (schizo_out_of_range(pbm, bus, devfn))		return PCIBIOS_SUCCESSFUL;	pci_config_read8(addr, value);	return PCIBIOS_SUCCESSFUL;}static int schizo_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 = schizo_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (schizo_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 schizo_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 = schizo_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (schizo_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);	if (where == PCI_PRIMARY_BUS &&	    dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&	    *value != 0xffffffff) {		u8 *busp = ((u8 *) value) + 1;		int i;		for (i = 0; i < 3; i++)			busp[i] += pbm->pci_first_busno;	}	return PCIBIOS_SUCCESSFUL;}static int schizo_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 = schizo_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (schizo_out_of_range(pbm, bus, devfn))		return PCIBIOS_SUCCESSFUL;	pci_config_write8(addr, value);	return PCIBIOS_SUCCESSFUL;}static int schizo_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 = schizo_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (schizo_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;}static int schizo_write_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;	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (schizo_out_of_range(pbm, bus, devfn))		return PCIBIOS_SUCCESSFUL;	if (where & 0x03) {		printk("pcibios_write_config_dword: misaligned reg [%x]\n",		       where);		return PCIBIOS_SUCCESSFUL;	}	if (where == PCI_PRIMARY_BUS &&	    dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {		u8 *busp = ((u8 *) &value) + 1;		int i;		for (i = 0; i < 3; i++) {			if (busp[i] >= pbm->pci_first_busno)				busp[i] += pbm->pci_first_busno;			else				busp[i] = 0;		}	}	pci_config_write32(addr, value);	return PCIBIOS_SUCCESSFUL;}static struct pci_ops schizo_ops = {	schizo_read_byte,	schizo_read_word,	schizo_read_dword,	schizo_write_byte,	schizo_write_word,	schizo_write_dword};/* SCHIZO interrupt mapping support.  Unlike Psycho, for this controller the * imap/iclr registers are per-PBM. */#define SCHIZO_IMAP_BASE	0x1000UL#define SCHIZO_ICLR_BASE	0x1400ULstatic unsigned long schizo_imap_offset(unsigned long ino){	return SCHIZO_IMAP_BASE + (ino * 8UL);}static unsigned long schizo_iclr_offset(unsigned long ino){	return SCHIZO_ICLR_BASE + (ino * 8UL);}/* PCI SCHIZO INO number to Sparc PIL level.  This table only matters for * INOs which will not have an associated PCI device struct, ie. onboard * EBUS devices and PCI controller internal error interrupts. */static unsigned char schizo_pil_table[] = {/*0x00*/0, 0, 0, 0,	/* PCI slot 0  Int A, B, C, D	*//*0x04*/0, 0, 0, 0,	/* PCI slot 1  Int A, B, C, D	*//*0x08*/0, 0, 0, 0,	/* PCI slot 2  Int A, B, C, D	*//*0x0c*/0, 0, 0, 0,	/* PCI slot 3  Int A, B, C, D	*//*0x10*/0, 0, 0, 0,	/* PCI slot 4  Int A, B, C, D	*//*0x14*/0, 0, 0, 0,	/* PCI slot 5  Int A, B, C, D	*//*0x18*/4,		/* SCSI				*//*0x19*/4,		/* second SCSI			*//*0x1a*/0,		/* UNKNOWN			*//*0x1b*/0,		/* UNKNOWN			*//*0x1c*/8,		/* Parallel			*//*0x1d*/5,		/* Ethernet			*//*0x1e*/8,		/* Firewire-1394		*//*0x1f*/9,		/* USB				*//*0x20*/13,		/* Audio Record			*//*0x21*/14,		/* Audio Playback		*//*0x22*/12,		/* Serial			*//*0x23*/4,		/* EBUS I2C 			*//*0x24*/10,		/* RTC Clock			*//*0x25*/11,		/* Floppy			*//*0x26*/0,		/* UNKNOWN			*//*0x27*/0,		/* UNKNOWN			*//*0x28*/0,		/* UNKNOWN			*//*0x29*/0,		/* UNKNOWN			*//*0x2a*/10,		/* UPA 1			*//*0x2b*/10,		/* UPA 2			*//*0x2c*/0,		/* UNKNOWN			*//*0x2d*/0,		/* UNKNOWN			*//*0x2e*/0,		/* UNKNOWN			*//*0x2f*/0,		/* UNKNOWN			*//*0x30*/15,		/* Uncorrectable ECC		*//*0x31*/15,		/* Correctable ECC		*//*0x32*/15,		/* PCI Bus A Error		*//*0x33*/15,		/* PCI Bus B Error		*//*0x34*/15,		/* Safari Bus Error		*//*0x35*/0,		/* Reserved			*//*0x36*/0,		/* Reserved			*//*0x37*/0,		/* Reserved			*//*0x38*/0,		/* Reserved for NewLink		*//*0x39*/0,		/* Reserved for NewLink		*//*0x3a*/0,		/* Reserved for NewLink		*//*0x3b*/0,		/* Reserved for NewLink		*//*0x3c*/0,		/* Reserved for NewLink		*//*0x3d*/0,		/* Reserved for NewLink		*//*0x3e*/0,		/* Reserved for NewLink		*//*0x3f*/0,		/* Reserved for NewLink		*/};static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino){	int ret;	if (pdev &&	    pdev->vendor == PCI_VENDOR_ID_SUN &&	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)		return 9;	ret = schizo_pil_table[ino];	if (ret == 0 && pdev == NULL) {		ret = 4;	} else if (ret == 0) {		switch ((pdev->class >> 16) & 0xff) {		case PCI_BASE_CLASS_STORAGE:			ret = 4;			break;		case PCI_BASE_CLASS_NETWORK:			ret = 6;			break;		case PCI_BASE_CLASS_DISPLAY:			ret = 9;			break;		case PCI_BASE_CLASS_MULTIMEDIA:		case PCI_BASE_CLASS_MEMORY:		case PCI_BASE_CLASS_BRIDGE:		case PCI_BASE_CLASS_SERIAL:			ret = 10;			break;		default:			ret = 4;			break;		};	}	return ret;}static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,					    struct pci_dev *pdev,					    unsigned int ino){	struct ino_bucket *bucket;	unsigned long imap, iclr;	unsigned long imap_off, iclr_off;	int pil, ign_fixup;	ino &= PCI_IRQ_INO;	imap_off = schizo_imap_offset(ino);	/* Now build the IRQ bucket. */	pil = schizo_ino_to_pil(pdev, ino);	if (PIL_RESERVED(pil))		BUG();	imap = pbm->pbm_regs + imap_off;	imap += 4;	iclr_off = schizo_iclr_offset(ino);	iclr = pbm->pbm_regs + iclr_off;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -