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

📄 sbus.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
			iclr = reg_base + SYSIO_ICLR_SLOT0;			break;		case 1:			iclr = reg_base + SYSIO_ICLR_SLOT1;			break;		case 2:			iclr = reg_base + SYSIO_ICLR_SLOT2;			break;		default:		case 3:			iclr = reg_base + SYSIO_ICLR_SLOT3;			break;		};		iclr += ((unsigned long)sbus_level - 1UL) * 8UL;	}	return build_irq(pil, sbus_level, iclr, imap);}/* Error interrupt handling. */#define SYSIO_UE_AFSR	0x0030UL#define SYSIO_UE_AFAR	0x0038UL#define  SYSIO_UEAFSR_PPIO  0x8000000000000000UL /* Primary PIO cause         */#define  SYSIO_UEAFSR_PDRD  0x4000000000000000UL /* Primary DVMA read cause   */#define  SYSIO_UEAFSR_PDWR  0x2000000000000000UL /* Primary DVMA write cause  */#define  SYSIO_UEAFSR_SPIO  0x1000000000000000UL /* Secondary PIO is cause    */#define  SYSIO_UEAFSR_SDRD  0x0800000000000000UL /* Secondary DVMA read cause */#define  SYSIO_UEAFSR_SDWR  0x0400000000000000UL /* Secondary DVMA write cause*/#define  SYSIO_UEAFSR_RESV1 0x03ff000000000000UL /* Reserved                  */#define  SYSIO_UEAFSR_DOFF  0x0000e00000000000UL /* Doubleword Offset         */#define  SYSIO_UEAFSR_SIZE  0x00001c0000000000UL /* Bad transfer size 2^SIZE  */#define  SYSIO_UEAFSR_MID   0x000003e000000000UL /* UPA MID causing the fault */#define  SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved                  */static irqreturn_t 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");	return IRQ_HANDLED;}#define SYSIO_CE_AFSR	0x0040UL#define SYSIO_CE_AFAR	0x0048UL#define  SYSIO_CEAFSR_PPIO  0x8000000000000000UL /* Primary PIO cause         */#define  SYSIO_CEAFSR_PDRD  0x4000000000000000UL /* Primary DVMA read cause   */#define  SYSIO_CEAFSR_PDWR  0x2000000000000000UL /* Primary DVMA write cause  */#define  SYSIO_CEAFSR_SPIO  0x1000000000000000UL /* Secondary PIO cause       */#define  SYSIO_CEAFSR_SDRD  0x0800000000000000UL /* Secondary DVMA read cause */#define  SYSIO_CEAFSR_SDWR  0x0400000000000000UL /* Secondary DVMA write cause*/#define  SYSIO_CEAFSR_RESV1 0x0300000000000000UL /* Reserved                  */#define  SYSIO_CEAFSR_ESYND 0x00ff000000000000UL /* Syndrome Bits             */#define  SYSIO_CEAFSR_DOFF  0x0000e00000000000UL /* Double Offset             */#define  SYSIO_CEAFSR_SIZE  0x00001c0000000000UL /* Bad transfer size 2^SIZE  */#define  SYSIO_CEAFSR_MID   0x000003e000000000UL /* UPA MID causing the fault */#define  SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved                  */static irqreturn_t 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");	return IRQ_HANDLED;}#define SYSIO_SBUS_AFSR		0x2010UL#define SYSIO_SBUS_AFAR		0x2018UL#define  SYSIO_SBAFSR_PLE   0x8000000000000000UL /* Primary Late PIO Error    */#define  SYSIO_SBAFSR_PTO   0x4000000000000000UL /* Primary SBUS Timeout      */#define  SYSIO_SBAFSR_PBERR 0x2000000000000000UL /* Primary SBUS Error ACK    */#define  SYSIO_SBAFSR_SLE   0x1000000000000000UL /* Secondary Late PIO Error  */#define  SYSIO_SBAFSR_STO   0x0800000000000000UL /* Secondary SBUS Timeout    */#define  SYSIO_SBAFSR_SBERR 0x0400000000000000UL /* Secondary SBUS Error ACK  */#define  SYSIO_SBAFSR_RESV1 0x03ff000000000000UL /* Reserved                  */#define  SYSIO_SBAFSR_RD    0x0000800000000000UL /* Primary was late PIO read */#define  SYSIO_SBAFSR_RESV2 0x0000600000000000UL /* Reserved                  */#define  SYSIO_SBAFSR_SIZE  0x00001c0000000000UL /* Size of transfer          */#define  SYSIO_SBAFSR_MID   0x000003e000000000UL /* MID causing the error     */#define  SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved                  */static irqreturn_t 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 */	return IRQ_HANDLED;}#define ECC_CONTROL	0x0020UL#define  SYSIO_ECNTRL_ECCEN	0x8000000000000000UL /* Enable ECC Checking   */#define  SYSIO_ECNTRL_UEEN	0x4000000000000000UL /* Enable UE Interrupts  */#define  SYSIO_ECNTRL_CEEN	0x2000000000000000UL /* 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 boundary. */	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 + -