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

📄 pci_psycho.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: pci_psycho.c,v 1.17 2000/09/21 06:25:14 anton Exp $ * pci_psycho.c: PSYCHO/U2P 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/malloc.h>#include <asm/pbm.h>#include <asm/iommu.h>#include <asm/irq.h>#include <asm/starfire.h>#include "pci_impl.h"/* All PSYCHO registers are 64-bits.  The following accessor * routines are how they are accessed.  The REG parameter * is a physical address. */#define psycho_read(__reg) \({	u64 __ret; \	__asm__ __volatile__("ldxa [%1] %2, %0" \			     : "=r" (__ret) \			     : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \			     : "memory"); \	__ret; \})#define psycho_write(__reg, __val) \	__asm__ __volatile__("stxa %0, [%1] %2" \			     : /* no outputs */ \			     : "r" (__val), "r" (__reg), \			       "i" (ASI_PHYS_BYPASS_EC_E))/* Misc. PSYCHO PCI controller register offsets and definitions. */#define PSYCHO_CONTROL		0x0010UL#define  PSYCHO_CONTROL_IMPL	 0xf000000000000000 /* Implementation of this PSYCHO*/#define  PSYCHO_CONTROL_VER	 0x0f00000000000000 /* Version of this PSYCHO       */#define  PSYCHO_CONTROL_MID	 0x00f8000000000000 /* UPA Module ID of PSYCHO      */#define  PSYCHO_CONTROL_IGN	 0x0007c00000000000 /* Interrupt Group Number       */#define  PSYCHO_CONTROL_RESV     0x00003ffffffffff0 /* Reserved                     */#define  PSYCHO_CONTROL_APCKEN	 0x0000000000000008 /* Address Parity Check Enable  */#define  PSYCHO_CONTROL_APERR	 0x0000000000000004 /* Incoming System Addr Parerr  */#define  PSYCHO_CONTROL_IAP	 0x0000000000000002 /* Invert UPA Parity            */#define  PSYCHO_CONTROL_MODE	 0x0000000000000001 /* PSYCHO clock mode            */#define PSYCHO_PCIA_CTRL	0x2000UL#define PSYCHO_PCIB_CTRL	0x4000UL#define  PSYCHO_PCICTRL_RESV1	 0xfffffff000000000 /* Reserved                     */#define  PSYCHO_PCICTRL_SBH_ERR	 0x0000000800000000 /* Streaming byte hole error    */#define  PSYCHO_PCICTRL_SERR	 0x0000000400000000 /* SERR signal asserted         */#define  PSYCHO_PCICTRL_SPEED	 0x0000000200000000 /* PCI speed (1 is U2P clock)   */#define  PSYCHO_PCICTRL_RESV2	 0x00000001ffc00000 /* Reserved                     */#define  PSYCHO_PCICTRL_ARB_PARK 0x0000000000200000 /* PCI arbitration parking      */#define  PSYCHO_PCICTRL_RESV3	 0x00000000001ff800 /* Reserved                     */#define  PSYCHO_PCICTRL_SBH_INT	 0x0000000000000400 /* Streaming byte hole int enab */#define  PSYCHO_PCICTRL_WEN	 0x0000000000000200 /* Power Mgmt Wake Enable       */#define  PSYCHO_PCICTRL_EEN	 0x0000000000000100 /* PCI Error Interrupt Enable   */#define  PSYCHO_PCICTRL_RESV4	 0x00000000000000c0 /* Reserved                     */#define  PSYCHO_PCICTRL_AEN	 0x000000000000003f /* PCI DVMA Arbitration Enable  *//* U2P Programmer's Manual, page 13-55, 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 PSYCHO_CONFIG_BASE(PBM)	\	((PBM)->parent->config_space | (1UL << 24))#define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG)	\	(((unsigned long)(BUS)   << 16) |	\	 ((unsigned long)(DEVFN) << 8)  |	\	 ((unsigned long)(REG)))static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm,				      unsigned char bus,				      unsigned int devfn,				      int where){	if (!pbm)		return NULL;	return (void *)		(PSYCHO_CONFIG_BASE(pbm) |		 PSYCHO_CONFIG_ENCODE(bus, devfn, where));}static int psycho_out_of_range(struct pci_pbm_info *pbm,			       unsigned char bus,			       unsigned char devfn){	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));}/* PSYCHO PCI configuration space accessors. */static int psycho_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 = psycho_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (psycho_out_of_range(pbm, bus, devfn))		return PCIBIOS_SUCCESSFUL;	pci_config_read8(addr, value);	return PCIBIOS_SUCCESSFUL;}static int psycho_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 = psycho_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (psycho_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 psycho_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 = psycho_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (psycho_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;}static int psycho_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 = psycho_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (psycho_out_of_range(pbm, bus, devfn))		return PCIBIOS_SUCCESSFUL;	pci_config_write8(addr, value);	return PCIBIOS_SUCCESSFUL;}static int psycho_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 = psycho_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (psycho_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 psycho_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 = psycho_pci_config_mkaddr(pbm, bus, devfn, where);	if (!addr)		return PCIBIOS_SUCCESSFUL;	if (psycho_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;	}	pci_config_write32(addr, value);	return PCIBIOS_SUCCESSFUL;}static struct pci_ops psycho_ops = {	psycho_read_byte,	psycho_read_word,	psycho_read_dword,	psycho_write_byte,	psycho_write_word,	psycho_write_dword};/* PSYCHO interrupt mapping support. */#define PSYCHO_IMAP_A_SLOT0	0x0c00UL#define PSYCHO_IMAP_B_SLOT0	0x0c20ULstatic unsigned long psycho_pcislot_imap_offset(unsigned long ino){	unsigned int bus =  (ino & 0x10) >> 4;	unsigned int slot = (ino & 0x0c) >> 2;	if (bus == 0)		return PSYCHO_IMAP_A_SLOT0 + (slot * 8);	else		return PSYCHO_IMAP_B_SLOT0 + (slot * 8);}#define PSYCHO_IMAP_SCSI	0x1000UL#define PSYCHO_IMAP_ETH		0x1008UL#define PSYCHO_IMAP_BPP		0x1010UL#define PSYCHO_IMAP_AU_REC	0x1018UL#define PSYCHO_IMAP_AU_PLAY	0x1020UL#define PSYCHO_IMAP_PFAIL	0x1028UL#define PSYCHO_IMAP_KMS		0x1030UL#define PSYCHO_IMAP_FLPY	0x1038UL#define PSYCHO_IMAP_SHW		0x1040UL#define PSYCHO_IMAP_KBD		0x1048UL#define PSYCHO_IMAP_MS		0x1050UL#define PSYCHO_IMAP_SER		0x1058UL#define PSYCHO_IMAP_TIM0	0x1060UL#define PSYCHO_IMAP_TIM1	0x1068UL#define PSYCHO_IMAP_UE		0x1070UL#define PSYCHO_IMAP_CE		0x1078UL#define PSYCHO_IMAP_A_ERR	0x1080UL#define PSYCHO_IMAP_B_ERR	0x1088UL#define PSYCHO_IMAP_PMGMT	0x1090UL#define PSYCHO_IMAP_GFX		0x1098UL#define PSYCHO_IMAP_EUPA	0x10a0ULstatic unsigned long __onboard_imap_off[] = {/*0x20*/	PSYCHO_IMAP_SCSI,/*0x21*/	PSYCHO_IMAP_ETH,/*0x22*/	PSYCHO_IMAP_BPP,/*0x23*/	PSYCHO_IMAP_AU_REC,/*0x24*/	PSYCHO_IMAP_AU_PLAY,/*0x25*/	PSYCHO_IMAP_PFAIL,/*0x26*/	PSYCHO_IMAP_KMS,/*0x27*/	PSYCHO_IMAP_FLPY,/*0x28*/	PSYCHO_IMAP_SHW,/*0x29*/	PSYCHO_IMAP_KBD,/*0x2a*/	PSYCHO_IMAP_MS,/*0x2b*/	PSYCHO_IMAP_SER,/*0x2c*/	PSYCHO_IMAP_TIM0,/*0x2d*/	PSYCHO_IMAP_TIM1,/*0x2e*/	PSYCHO_IMAP_UE,/*0x2f*/	PSYCHO_IMAP_CE,/*0x30*/	PSYCHO_IMAP_A_ERR,/*0x31*/	PSYCHO_IMAP_B_ERR,/*0x32*/	PSYCHO_IMAP_PMGMT};#define PSYCHO_ONBOARD_IRQ_BASE		0x20#define PSYCHO_ONBOARD_IRQ_LAST		0x32#define psycho_onboard_imap_offset(__ino) \	__onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]#define PSYCHO_ICLR_A_SLOT0	0x1400UL#define PSYCHO_ICLR_SCSI	0x1800UL#define psycho_iclr_offset(ino)					      \	((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \			(PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))/* PCI PSYCHO INO number to Sparc PIL level. */static unsigned char psycho_pil_table[] = {/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D *//*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D *//*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D *//*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D *//*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D *//*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D *//*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D *//*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D *//*0x20*/3,		/* SCSI				*//*0x21*/5,		/* Ethernet			*//*0x22*/8,		/* Parallel Port		*//*0x23*/13,		/* Audio Record			*//*0x24*/14,		/* Audio Playback		*//*0x25*/15,		/* PowerFail			*//*0x26*/3,		/* second SCSI			*//*0x27*/11,		/* Floppy			*//*0x28*/2,		/* Spare Hardware		*//*0x29*/9,		/* Keyboard			*//*0x2a*/4,		/* Mouse			*//*0x2b*/12,		/* Serial			*//*0x2c*/10,		/* Timer 0			*//*0x2d*/11,		/* Timer 1			*//*0x2e*/15,		/* Uncorrectable ECC		*//*0x2f*/15,		/* Correctable ECC		*//*0x30*/15,		/* PCI Bus A Error		*//*0x31*/15,		/* PCI Bus B Error		*//*0x32*/1,		/* Power Management		*/};static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino){	int ret;	ret = psycho_pil_table[ino];	if (ret == 0 && pdev == NULL) {		ret = 1;	} else if (ret == 0) {		switch ((pdev->class >> 16) & 0x0f) {		case PCI_BASE_CLASS_STORAGE:			ret = 4;		case PCI_BASE_CLASS_NETWORK:			ret = 6;		case PCI_BASE_CLASS_DISPLAY:			ret = 9;		case PCI_BASE_CLASS_MULTIMEDIA:		case PCI_BASE_CLASS_MEMORY:		case PCI_BASE_CLASS_BRIDGE:			ret = 10;		default:			ret = 1;		};	}	return ret;}static unsigned int __init psycho_irq_build(struct pci_controller_info *p,					    struct pci_dev *pdev,					    unsigned int ino){	struct ino_bucket *bucket;	unsigned long imap, iclr;	unsigned long imap_off, iclr_off;	int pil, inofixup = 0;	ino &= PCI_IRQ_INO;	if (ino < PSYCHO_ONBOARD_IRQ_BASE) {		/* PCI slot */		imap_off = psycho_pcislot_imap_offset(ino);	} else {		/* Onboard device */		if (ino > PSYCHO_ONBOARD_IRQ_LAST) {			prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino);			prom_halt();

⌨️ 快捷键说明

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