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

📄 sbus.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* Error interrupt handling. */#define SYSIO_UE_AFSR	0x0030UL#define SYSIO_UE_AFAR	0x0038UL#define  SYSIO_UEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */#define  SYSIO_UEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */#define  SYSIO_UEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */#define  SYSIO_UEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */#define  SYSIO_UEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */#define  SYSIO_UEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/#define  SYSIO_UEAFSR_RESV1	0x03ff000000000000 /* Reserved                     */#define  SYSIO_UEAFSR_DOFF	0x0000e00000000000 /* Doubleword Offset            */#define  SYSIO_UEAFSR_SIZE	0x00001c0000000000 /* Bad transfer size is 2**SIZE */#define  SYSIO_UEAFSR_MID	0x000003e000000000 /* UPA MID causing the fault    */#define  SYSIO_UEAFSR_RESV2	0x0000001fffffffff /* Reserved                     */static void sysio_ue_handler(int irq, void *dev_id, struct pt_regs *regs){	struct sbus_bus *sbus = dev_id;	struct sbus_iommu *iommu = sbus->iommu;	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;	unsigned long afsr_reg, afar_reg;	unsigned long afsr, afar, error_bits;	int reported;	afsr_reg = reg_base + SYSIO_UE_AFSR;	afar_reg = reg_base + SYSIO_UE_AFAR;	/* Latch error status. */	afsr = upa_readq(afsr_reg);	afar = upa_readq(afar_reg);	/* Clear primary/secondary error status bits. */	error_bits = afsr &		(SYSIO_UEAFSR_PPIO | SYSIO_UEAFSR_PDRD | SYSIO_UEAFSR_PDWR |		 SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR);	upa_writeq(error_bits, afsr_reg);	/* Log the error. */	printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n",	       sbus->portid,	       (((error_bits & SYSIO_UEAFSR_PPIO) ?		 "PIO" :		 ((error_bits & SYSIO_UEAFSR_PDRD) ?		  "DVMA Read" :		  ((error_bits & SYSIO_UEAFSR_PDWR) ?		   "DVMA Write" : "???")))));	printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n",	       sbus->portid,	       (afsr & SYSIO_UEAFSR_DOFF) >> 45UL,	       (afsr & SYSIO_UEAFSR_SIZE) >> 42UL,	       (afsr & SYSIO_UEAFSR_MID) >> 37UL);	printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar);	printk("SYSIO[%x]: Secondary UE errors [", sbus->portid);	reported = 0;	if (afsr & SYSIO_UEAFSR_SPIO) {		reported++;		printk("(PIO)");	}	if (afsr & SYSIO_UEAFSR_SDRD) {		reported++;		printk("(DVMA Read)");	}	if (afsr & SYSIO_UEAFSR_SDWR) {		reported++;		printk("(DVMA Write)");	}	if (!reported)		printk("(none)");	printk("]\n");}#define SYSIO_CE_AFSR	0x0040UL#define SYSIO_CE_AFAR	0x0048UL#define  SYSIO_CEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */#define  SYSIO_CEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */#define  SYSIO_CEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */#define  SYSIO_CEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */#define  SYSIO_CEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */#define  SYSIO_CEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/#define  SYSIO_CEAFSR_RESV1	0x0300000000000000 /* Reserved                     */#define  SYSIO_CEAFSR_ESYND	0x00ff000000000000 /* Syndrome Bits                */#define  SYSIO_CEAFSR_DOFF	0x0000e00000000000 /* Double Offset                */#define  SYSIO_CEAFSR_SIZE	0x00001c0000000000 /* Bad transfer size is 2**SIZE */#define  SYSIO_CEAFSR_MID	0x000003e000000000 /* UPA MID causing the fault    */#define  SYSIO_CEAFSR_RESV2	0x0000001fffffffff /* Reserved                     */static void sysio_ce_handler(int irq, void *dev_id, struct pt_regs *regs){	struct sbus_bus *sbus = dev_id;	struct sbus_iommu *iommu = sbus->iommu;	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;	unsigned long afsr_reg, afar_reg;	unsigned long afsr, afar, error_bits;	int reported;	afsr_reg = reg_base + SYSIO_CE_AFSR;	afar_reg = reg_base + SYSIO_CE_AFAR;	/* Latch error status. */	afsr = upa_readq(afsr_reg);	afar = upa_readq(afar_reg);	/* Clear primary/secondary error status bits. */	error_bits = afsr &		(SYSIO_CEAFSR_PPIO | SYSIO_CEAFSR_PDRD | SYSIO_CEAFSR_PDWR |		 SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR);	upa_writeq(error_bits, afsr_reg);	printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n",	       sbus->portid,	       (((error_bits & SYSIO_CEAFSR_PPIO) ?		 "PIO" :		 ((error_bits & SYSIO_CEAFSR_PDRD) ?		  "DVMA Read" :		  ((error_bits & SYSIO_CEAFSR_PDWR) ?		   "DVMA Write" : "???")))));	/* XXX Use syndrome and afar to print out module string just like	 * XXX UDB CE trap handler does... -DaveM	 */	printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n",	       sbus->portid,	       (afsr & SYSIO_CEAFSR_DOFF) >> 45UL,	       (afsr & SYSIO_CEAFSR_ESYND) >> 48UL,	       (afsr & SYSIO_CEAFSR_SIZE) >> 42UL,	       (afsr & SYSIO_CEAFSR_MID) >> 37UL);	printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar);	printk("SYSIO[%x]: Secondary CE errors [", sbus->portid);	reported = 0;	if (afsr & SYSIO_CEAFSR_SPIO) {		reported++;		printk("(PIO)");	}	if (afsr & SYSIO_CEAFSR_SDRD) {		reported++;		printk("(DVMA Read)");	}	if (afsr & SYSIO_CEAFSR_SDWR) {		reported++;		printk("(DVMA Write)");	}	if (!reported)		printk("(none)");	printk("]\n");}#define SYSIO_SBUS_AFSR		0x2010UL#define SYSIO_SBUS_AFAR		0x2018UL#define  SYSIO_SBAFSR_PLE	0x8000000000000000 /* Primary Late PIO Error       */#define  SYSIO_SBAFSR_PTO	0x4000000000000000 /* Primary SBUS Timeout         */#define  SYSIO_SBAFSR_PBERR	0x2000000000000000 /* Primary SBUS Error ACK       */#define  SYSIO_SBAFSR_SLE	0x1000000000000000 /* Secondary Late PIO Error     */#define  SYSIO_SBAFSR_STO	0x0800000000000000 /* Secondary SBUS Timeout       */#define  SYSIO_SBAFSR_SBERR	0x0400000000000000 /* Secondary SBUS Error ACK     */#define  SYSIO_SBAFSR_RESV1	0x03ff000000000000 /* Reserved                     */#define  SYSIO_SBAFSR_RD	0x0000800000000000 /* Primary was late PIO read    */#define  SYSIO_SBAFSR_RESV2	0x0000600000000000 /* Reserved                     */#define  SYSIO_SBAFSR_SIZE	0x00001c0000000000 /* Size of transfer             */#define  SYSIO_SBAFSR_MID	0x000003e000000000 /* MID causing the error        */#define  SYSIO_SBAFSR_RESV3	0x0000001fffffffff /* Reserved                     */static void sysio_sbus_error_handler(int irq, void *dev_id, struct pt_regs *regs){	struct sbus_bus *sbus = dev_id;	struct sbus_iommu *iommu = sbus->iommu;	unsigned long afsr_reg, afar_reg, reg_base;	unsigned long afsr, afar, error_bits;	int reported;	reg_base = iommu->sbus_control_reg - 0x2000UL;	afsr_reg = reg_base + SYSIO_SBUS_AFSR;	afar_reg = reg_base + SYSIO_SBUS_AFAR;	afsr = upa_readq(afsr_reg);	afar = upa_readq(afar_reg);	/* Clear primary/secondary error status bits. */	error_bits = afsr &		(SYSIO_SBAFSR_PLE | SYSIO_SBAFSR_PTO | SYSIO_SBAFSR_PBERR |		 SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR);	upa_writeq(error_bits, afsr_reg);	/* Log the error. */	printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n",	       sbus->portid,	       (((error_bits & SYSIO_SBAFSR_PLE) ?		 "Late PIO Error" :		 ((error_bits & SYSIO_SBAFSR_PTO) ?		  "Time Out" :		  ((error_bits & SYSIO_SBAFSR_PBERR) ?		   "Error Ack" : "???")))),	       (afsr & SYSIO_SBAFSR_RD) ? 1 : 0);	printk("SYSIO[%x]: size[%lx] MID[%lx]\n",	       sbus->portid,	       (afsr & SYSIO_SBAFSR_SIZE) >> 42UL,	       (afsr & SYSIO_SBAFSR_MID) >> 37UL);	printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar);	printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid);	reported = 0;	if (afsr & SYSIO_SBAFSR_SLE) {		reported++;		printk("(Late PIO Error)");	}	if (afsr & SYSIO_SBAFSR_STO) {		reported++;		printk("(Time Out)");	}	if (afsr & SYSIO_SBAFSR_SBERR) {		reported++;		printk("(Error Ack)");	}	if (!reported)		printk("(none)");	printk("]\n");	/* XXX check iommu/strbuf for further error status XXX */}#define ECC_CONTROL	0x0020UL#define  SYSIO_ECNTRL_ECCEN	0x8000000000000000 /* Enable ECC Checking          */#define  SYSIO_ECNTRL_UEEN	0x4000000000000000 /* Enable UE Interrupts         */#define  SYSIO_ECNTRL_CEEN	0x2000000000000000 /* Enable CE Interrupts         */#define SYSIO_UE_INO		0x34#define SYSIO_CE_INO		0x35#define SYSIO_SBUSERR_INO	0x36static void __init sysio_register_error_handlers(struct sbus_bus *sbus){	struct sbus_iommu *iommu = sbus->iommu;	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;	unsigned int irq;	u64 control;	irq = sbus_build_irq(sbus, SYSIO_UE_INO);	if (request_irq(irq, sysio_ue_handler,			SA_SHIRQ, "SYSIO UE", sbus) < 0) {		prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n",			    sbus->portid);		prom_halt();	}	irq = sbus_build_irq(sbus, SYSIO_CE_INO);	if (request_irq(irq, sysio_ce_handler,			SA_SHIRQ, "SYSIO CE", sbus) < 0) {		prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n",			    sbus->portid);		prom_halt();	}	irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO);	if (request_irq(irq, sysio_sbus_error_handler,			SA_SHIRQ, "SYSIO SBUS Error", sbus) < 0) {		prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n",			    sbus->portid);		prom_halt();	}	/* Now turn the error interrupts on and also enable ECC checking. */	upa_writeq((SYSIO_ECNTRL_ECCEN |		    SYSIO_ECNTRL_UEEN  |		    SYSIO_ECNTRL_CEEN),		   reg_base + ECC_CONTROL);	control = upa_readq(iommu->sbus_control_reg);	control |= 0x100UL; /* SBUS Error Interrupt Enable */	upa_writeq(control, iommu->sbus_control_reg);}/* Boot time initialization. */void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus){	struct linux_prom64_registers rprop;	struct sbus_iommu *iommu;	unsigned long regs, tsb_base;	u64 control;	int err, i;	sbus->portid = prom_getintdefault(sbus->prom_node,					  "upa-portid", -1);	err = prom_getproperty(prom_node, "reg",			       (char *)&rprop, sizeof(rprop));	if (err < 0) {		prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n");		prom_halt();	}	regs = rprop.phys_addr;	iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC);	if (iommu == NULL) {		prom_printf("sbus_iommu_init: Fatal error, kmalloc(iommu) failed\n");		prom_halt();	}	/* Align on E$ line boundry. */	iommu = (struct sbus_iommu *)		(((unsigned long)iommu + (SMP_CACHE_BYTES - 1UL)) &		 ~(SMP_CACHE_BYTES - 1UL));	memset(iommu, 0, sizeof(*iommu));	/* We start with no consistent mappings. */	iommu->lowest_consistent_map = CLUSTER_NPAGES;	for (i = 0; i < NCLUSTERS; i++) {		iommu->alloc_info[i].flush = 0;		iommu->alloc_info[i].next = 0;	}	/* Setup spinlock. */	spin_lock_init(&iommu->lock);	/* Init register offsets. */	iommu->iommu_regs = regs + SYSIO_IOMMUREG_BASE;	iommu->strbuf_regs = regs + SYSIO_STRBUFREG_BASE;	/* The SYSIO SBUS control register is used for dummy reads	 * in order to ensure write completion.	 */	iommu->sbus_control_reg = regs + 0x2000UL;	/* Link into SYSIO software state. */	sbus->iommu = iommu;	printk("SYSIO: UPA portID %x, at %016lx\n",	       sbus->portid, regs);	/* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */	control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL);	control = ((7UL << 16UL)	|		   (0UL << 2UL)		|		   (1UL << 1UL)		|		   (1UL << 0UL));	/* Using the above configuration we need 1MB iommu page	 * table (128K ioptes * 8 bytes per iopte).  This is	 * page order 7 on UltraSparc.	 */	tsb_base = __get_free_pages(GFP_ATOMIC, get_order(IO_TSB_SIZE));	if (tsb_base == 0UL) {		prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n");		prom_halt();	}	iommu->page_table = (iopte_t *) tsb_base;	memset(iommu->page_table, 0, IO_TSB_SIZE);	upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL);	/* Clean out any cruft in the IOMMU using	 * diagnostic accesses.	 */	for (i = 0; i < 16; i++) {		unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG;		unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;		dram += (unsigned long)i * 8UL;		tag += (unsigned long)i * 8UL;		upa_writeq(0, dram);		upa_writeq(0, tag);	}	upa_readq(iommu->sbus_control_reg);	/* Give the TSB to SYSIO. */	upa_writeq(__pa(tsb_base), iommu->iommu_regs + IOMMU_TSBBASE);	/* Setup streaming buffer, DE=1 SB_EN=1 */	control = (1UL << 1UL) | (1UL << 0UL);	upa_writeq(control, iommu->strbuf_regs + STRBUF_CONTROL);	/* Clear out the tags using diagnostics. */	for (i = 0; i < 16; i++) {		unsigned long ptag, ltag;		ptag = iommu->strbuf_regs + STRBUF_PTAGDIAG;		ltag = iommu->strbuf_regs + STRBUF_LTAGDIAG;		ptag += (unsigned long)i * 8UL;		ltag += (unsigned long)i * 8UL;		upa_writeq(0UL, ptag);		upa_writeq(0UL, ltag);	}	/* Enable DVMA arbitration for all devices/slots. */	control = upa_readq(iommu->sbus_control_reg);	control |= 0x3fUL;	upa_writeq(control, iommu->sbus_control_reg);	/* Now some Xfire specific grot... */	if (this_is_starfire)		sbus->starfire_cookie = starfire_hookup(sbus->portid);	else		sbus->starfire_cookie = NULL;	sysio_register_error_handlers(sbus);}

⌨️ 快捷键说明

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