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

📄 pci_sabre.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
{	struct pci_controller_info *p = dev_id;	unsigned long afsr_reg = p->controller_regs + SABRE_CE_AFSR;	unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;	unsigned long afsr, afar, error_bits;	int reported;	/* Latch error status. */	afar = sabre_read(afar_reg);	afsr = sabre_read(afsr_reg);	/* Clear primary/secondary error status bits. */	error_bits = afsr &		(SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |		 SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR);	if (!error_bits)		return;	sabre_write(afsr_reg, error_bits);	/* Log the error. */	printk("SABRE%d: Correctable Error, primary error type[%s]\n",	       p->index,	       ((error_bits & SABRE_CEAFSR_PDRD) ?		"DMA Read" :		((error_bits & SABRE_CEAFSR_PDWR) ?		 "DMA Write" : "???")));	/* XXX Use syndrome and afar to print out module string just like	 * XXX UDB CE trap handler does... -DaveM	 */	printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "	       "was_block(%d)\n",	       p->index,	       (afsr & SABRE_CEAFSR_ESYND) >> 48UL,	       (afsr & SABRE_CEAFSR_BMSK) >> 32UL,	       (afsr & SABRE_CEAFSR_OFF) >> 29UL,	       ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0));	printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar);	printk("SABRE%d: CE Secondary errors [", p->index);	reported = 0;	if (afsr & SABRE_CEAFSR_SDRD) {		reported++;		printk("(DMA Read)");	}	if (afsr & SABRE_CEAFSR_SDWR) {		reported++;		printk("(DMA Write)");	}	if (!reported)		printk("(none)");	printk("]\n");}static void sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs){	struct pci_controller_info *p = dev_id;	unsigned long afsr_reg, afar_reg;	unsigned long afsr, afar, error_bits;	int reported;	afsr_reg = p->controller_regs + SABRE_PIOAFSR;	afar_reg = p->controller_regs + SABRE_PIOAFAR;	/* Latch error status. */	afar = sabre_read(afar_reg);	afsr = sabre_read(afsr_reg);	/* Clear primary/secondary error status bits. */	error_bits = afsr &		(SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA |		 SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR |		 SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA |		 SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR);	if (!error_bits)		return;	sabre_write(afsr_reg, error_bits);	/* Log the error. */	printk("SABRE%d: PCI Error, primary error type[%s]\n",	       p->index,	       (((error_bits & SABRE_PIOAFSR_PMA) ?		 "Master Abort" :		 ((error_bits & SABRE_PIOAFSR_PTA) ?		  "Target Abort" :		  ((error_bits & SABRE_PIOAFSR_PRTRY) ?		   "Excessive Retries" :		   ((error_bits & SABRE_PIOAFSR_PPERR) ?		    "Parity Error" : "???"))))));	printk("SABRE%d: bytemask[%04lx] was_block(%d)\n",	       p->index,	       (afsr & SABRE_PIOAFSR_BMSK) >> 32UL,	       (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0);	printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar);	printk("SABRE%d: PCI Secondary errors [", p->index);	reported = 0;	if (afsr & SABRE_PIOAFSR_SMA) {		reported++;		printk("(Master Abort)");	}	if (afsr & SABRE_PIOAFSR_STA) {		reported++;		printk("(Target Abort)");	}	if (afsr & SABRE_PIOAFSR_SRTRY) {		reported++;		printk("(Excessive Retries)");	}	if (afsr & SABRE_PIOAFSR_SPERR) {		reported++;		printk("(Parity Error)");	}	if (!reported)		printk("(none)");	printk("]\n");	/* For the error types shown, scan both PCI buses for devices	 * which have logged that error type.	 */	/* If we see a Target Abort, this could be the result of an	 * IOMMU translation error of some sort.  It is extremely	 * useful to log this information as usually it indicates	 * a bug in the IOMMU support code or a PCI device driver.	 */	if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) {		sabre_check_iommu_error(p, afsr, afar);		pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus);		pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus);	}	if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) {		pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus);		pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus);	}	/* For excessive retries, SABRE/PBM will abort the device	 * and there is no way to specifically check for excessive	 * retries in the config space status registers.  So what	 * we hope is that we'll catch it via the master/target	 * abort events.	 */	if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) {		pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus);		pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus);	}}/* XXX What about PowerFail/PowerManagement??? -DaveM */#define SABRE_UE_INO		0x2e#define SABRE_CE_INO		0x2f#define SABRE_PCIERR_INO	0x30static void __init sabre_register_error_handlers(struct pci_controller_info *p){	struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */	unsigned long base = p->controller_regs;	unsigned long irq, portid = p->portid;	u64 tmp;	/* We clear the error bits in the appropriate AFSR before	 * registering the handler so that we don't get spurious	 * interrupts.	 */	sabre_write(base + SABRE_UE_AFSR,		    (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR |		     SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |		     SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE));	irq = sabre_irq_build(pbm, NULL, (portid << 6) | SABRE_UE_INO);	if (request_irq(irq, sabre_ue_intr,			SA_SHIRQ, "SABRE UE", p) < 0) {		prom_printf("SABRE%d: Cannot register UE interrupt.\n",			    p->index);		prom_halt();	}	sabre_write(base + SABRE_CE_AFSR,		    (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |		     SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR));	irq = sabre_irq_build(pbm, NULL, (portid << 6) | SABRE_CE_INO);	if (request_irq(irq, sabre_ce_intr,			SA_SHIRQ, "SABRE CE", p) < 0) {		prom_printf("SABRE%d: Cannot register CE interrupt.\n",			    p->index);		prom_halt();	}	irq = sabre_irq_build(pbm, NULL, (portid << 6) | SABRE_PCIERR_INO);	if (request_irq(irq, sabre_pcierr_intr,			SA_SHIRQ, "SABRE PCIERR", p) < 0) {		prom_printf("SABRE%d: Cannot register PciERR interrupt.\n",			    p->index);		prom_halt();	}	tmp = sabre_read(base + SABRE_PCICTRL);	tmp |= SABRE_PCICTRL_ERREN;	sabre_write(base + SABRE_PCICTRL, tmp);}static void __init sabre_resource_adjust(struct pci_dev *pdev,					 struct resource *res,					 struct resource *root){	struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number];	struct pci_controller_info *p = pbm->parent;	unsigned long base;	if (res->flags & IORESOURCE_IO)		base = p->controller_regs + SABRE_IOSPACE;	else		base = p->controller_regs + SABRE_MEMSPACE;	res->start += base;	res->end += base;}static void __init sabre_base_address_update(struct pci_dev *pdev, int resource){	struct pcidev_cookie *pcp = pdev->sysdata;	struct pci_pbm_info *pbm = pcp->pbm;	struct pci_controller_info *p = pbm->parent;	struct resource *res;	unsigned long base;	u32 reg;	int where, size, is_64bit;	res = &pdev->resource[resource];	if (resource < 6) {		where = PCI_BASE_ADDRESS_0 + (resource * 4);	} else if (resource == PCI_ROM_RESOURCE) {		where = pdev->rom_base_reg;	} else {		/* Somebody might have asked allocation of a non-standard resource */		return;	}	is_64bit = 0;	if (res->flags & IORESOURCE_IO)		base = p->controller_regs + SABRE_IOSPACE;	else {		base = p->controller_regs + SABRE_MEMSPACE;		if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)		    == PCI_BASE_ADDRESS_MEM_TYPE_64)			is_64bit = 1;	}	size = res->end - res->start;	pci_read_config_dword(pdev, where, &reg);	reg = ((reg & size) |	       (((u32)(res->start - base)) & ~size));	if (resource == PCI_ROM_RESOURCE) {		reg |= PCI_ROM_ADDRESS_ENABLE;		res->flags |= PCI_ROM_ADDRESS_ENABLE;	}	pci_write_config_dword(pdev, where, reg);	/* This knows that the upper 32-bits of the address	 * must be zero.  Our PCI common layer enforces this.	 */	if (is_64bit)		pci_write_config_dword(pdev, where + 4, 0);}static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus){	struct list_head *walk = &sabre_bus->devices;	for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {		struct pci_dev *pdev = pci_dev_b(walk);		if (pdev->vendor == PCI_VENDOR_ID_SUN &&		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {			u16 word;			sabre_read_word(pdev, PCI_COMMAND, &word);			word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |				PCI_COMMAND_IO;			sabre_write_word(pdev, PCI_COMMAND, word);			/* Status register bits are "write 1 to clear". */			sabre_write_word(pdev, PCI_STATUS, 0xffff);			sabre_write_word(pdev, PCI_SEC_STATUS, 0xffff);			/* Use a primary/seconday latency timer value			 * of 64.			 */			sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64);			sabre_write_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);			/* Enable reporting/forwarding of master aborts,			 * parity, and SERR.			 */			sabre_write_byte(pdev, PCI_BRIDGE_CONTROL,					 (PCI_BRIDGE_CTL_PARITY |					  PCI_BRIDGE_CTL_SERR |					  PCI_BRIDGE_CTL_MASTER_ABORT));		}	}}static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm){	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);	if (!cookie) {		prom_printf("SABRE: Critical allocation failure.\n");		prom_halt();	}	/* All we care about is the PBM. */	memset(cookie, 0, sizeof(*cookie));	cookie->pbm = pbm;	return cookie;}static void __init sabre_scan_bus(struct pci_controller_info *p){	static int once;	struct pci_bus *sabre_bus;	struct pci_pbm_info *pbm;	struct pcidev_cookie *cookie;	struct list_head *walk;	int sabres_scanned;	/* The APB bridge speaks to the Sabre host PCI bridge	 * at 66Mhz, but the front side of APB runs at 33Mhz	 * for both segments.	 */	p->pbm_A.is_66mhz_capable = 0;	p->pbm_B.is_66mhz_capable = 0;	/* Unlike for PSYCHO, we can only have one SABRE	 * in a system.  Having multiple SABREs is thus	 * and error, and as a consequence we do not need	 * to do any bus renumbering but we do have to have	 * the pci_bus2pbm array setup properly.	 *	 * Also note that the SABRE host bridge is hardwired	 * to live at bus 0.	 */	if (once != 0) {		prom_printf("SABRE: Multiple controllers unsupported.\n");		prom_halt();	}	once++;	cookie = alloc_bridge_cookie(&p->pbm_A);	/* The pci_bus2pbm table has already been setup in sabre_init. */	sabre_bus = pci_scan_bus(p->pci_first_busno,				 p->pci_ops,				 &p->pbm_A);	pci_fixup_host_bridge_self(sabre_bus);	sabre_bus->self->sysdata = cookie;	apb_init(p, sabre_bus);	sabres_scanned = 0;	walk = &sabre_bus->children;	for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {		struct pci_bus *pbus = pci_bus_b(walk);		if (pbus->number == p->pbm_A.pci_first_busno) {			pbm = &p->pbm_A;		} else if (pbus->number == p->pbm_B.pci_first_busno) {			pbm = &p->pbm_B;		} else			continue;		cookie = alloc_bridge_cookie(pbm);		pbus->self->sysdata = cookie;		sabres_scanned++;		pbus->sysdata = pbm;		pbm->pci_bus = pbus;		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);		pci_record_assignments(pbm, pbus);		pci_assign_unassigned(pbm, pbus);		pci_fixup_irq(pbm, pbus);		pci_determine_66mhz_disposition(pbm, pbus);		pci_setup_busmastering(pbm, pbus);	}	if (!sabres_scanned) {		/* Hummingbird, no APBs. */		pbm = &p->pbm_A;		sabre_bus->sysdata = pbm;		pbm->pci_bus = sabre_bus;		pci_fill_in_pbm_cookies(sabre_bus, pbm, pbm->prom_node);		pci_record_assignments(pbm, sabre_bus);		pci_assign_unassigned(pbm, sabre_bus);		pci_fixup_irq(pbm, sabre_bus);		pci_determine_66mhz_disposition(pbm, sabre_bus);		pci_setup_busmastering(pbm, sabre_bus);	}	sabre_register_error_handlers(p);}static void __init sabre_iommu_init(struct pci_controller_info *p,				    int tsbsize, unsigned long dvma_offset,				    u32 dma_mask){	struct pci_iommu *iommu = p->pbm_A.iommu;	unsigned long tsbbase, i, order;	u64 control;	/* Setup initial software IOMMU state. */	spin_lock_init(&iommu->lock);	iommu->iommu_cur_ctx = 0;	/* Register addresses. */	iommu->iommu_control  = p->controller_regs + SABRE_IOMMU_CONTROL;	iommu->iommu_tsbbase  = p->controller_regs + SABRE_IOMMU_TSBBASE;	iommu->iommu_flush    = p->controller_regs + SABRE_IOMMU_FLUSH;	iommu->write_complete_reg = p->controller_regs + SABRE_WRSYNC;	/* Sabre's IOMMU lacks ctx flushing. */	iommu->iommu_ctxflush = 0;                                        	/* Invalidate TLB Entries. */

⌨️ 快捷键说明

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