pci_schizo.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,074 行 · 第 1/5 页

C
2,074
字号
	err_mask = (SCHIZO_PCICTRL_BUS_UNUS |		    SCHIZO_PCICTRL_TTO_ERR |		    SCHIZO_PCICTRL_RTRY_ERR |		    SCHIZO_PCICTRL_SERR |		    SCHIZO_PCICTRL_EEN);	err_no_mask = SCHIZO_PCICTRL_DTO_ERR;	tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);	tmp |= err_mask;	tmp &= ~err_no_mask;	schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);	tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);	tmp |= err_mask;	tmp &= ~err_no_mask;	schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);	err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |		    SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |		    SCHIZO_PCIAFSR_PTTO |		    SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |		    SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |		    SCHIZO_PCIAFSR_STTO);	schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR, err_mask);	schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR, err_mask);	err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR |		    BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD |		    BUS_ERROR_SNOOP_RDS | BUS_ERROR_SNOOP_RDSA |		    BUS_ERROR_SNOOP_OWN | BUS_ERROR_SNOOP_RDO |		    BUS_ERROR_WDATA_PERR | BUS_ERROR_CTRL_PERR |		    BUS_ERROR_SNOOP_ERR | BUS_ERROR_JBUS_ILL_B |		    BUS_ERROR_JBUS_ILL_C | BUS_ERROR_RD_PERR |		    BUS_ERROR_APERR | BUS_ERROR_UNMAP |		    BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT);	schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,		     (SCHIZO_SAFERRCTRL_EN | err_mask));	schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_ERRCTRL,		     (SCHIZO_SAFERRCTRL_EN | err_mask));	schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,		     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));	schizo_write(p->pbm_B.controller_regs + SCHIZO_SAFARI_IRQCTRL,		     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));}static void __init schizo_register_error_handlers(struct pci_controller_info *p){	struct pci_pbm_info *pbm;	unsigned int irq;	struct ino_bucket *bucket;	u64 tmp, err_mask, err_no_mask;	/* Build IRQs and register handlers. */	pbm = pbm_for_ino(p, SCHIZO_UE_INO);	irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_UE_INO);	if (request_irq(irq, schizo_ue_intr,			SA_SHIRQ, "SCHIZO UE", p) < 0) {		prom_printf("%s: Cannot register UE interrupt.\n",			    pbm->name);		prom_halt();	}	bucket = __bucket(irq);	tmp = readl(bucket->imap);	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));	pbm = pbm_for_ino(p, SCHIZO_CE_INO);	irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_CE_INO);	if (request_irq(irq, schizo_ce_intr,			SA_SHIRQ, "SCHIZO CE", p) < 0) {		prom_printf("%s: Cannot register CE interrupt.\n",			    pbm->name);		prom_halt();	}	bucket = __bucket(irq);	tmp = upa_readl(bucket->imap);	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));	pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);	irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO);	if (request_irq(irq, schizo_pcierr_intr,			SA_SHIRQ, "SCHIZO PCIERR", pbm) < 0) {		prom_printf("%s: Cannot register PBM A PciERR interrupt.\n",			    pbm->name);		prom_halt();	}	bucket = __bucket(irq);	tmp = upa_readl(bucket->imap);	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));	pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);	irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO);	if (request_irq(irq, schizo_pcierr_intr,			SA_SHIRQ, "SCHIZO PCIERR", &p->pbm_B) < 0) {		prom_printf("%s: Cannot register PBM B PciERR interrupt.\n",			    pbm->name);		prom_halt();	}	bucket = __bucket(irq);	tmp = upa_readl(bucket->imap);	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));	pbm = pbm_for_ino(p, SCHIZO_SERR_INO);	irq = schizo_irq_build(pbm, NULL, (pbm->portid << 6) | SCHIZO_SERR_INO);	if (request_irq(irq, schizo_safarierr_intr,			SA_SHIRQ, "SCHIZO SERR", p) < 0) {		prom_printf("%s: Cannot register SafariERR interrupt.\n",			    pbm->name);		prom_halt();	}	bucket = __bucket(irq);	tmp = upa_readl(bucket->imap);	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));	/* Enable UE and CE interrupts for controller. */	schizo_write(p->pbm_A.controller_regs + SCHIZO_ECC_CTRL,		     (SCHIZO_ECCCTRL_EE |		      SCHIZO_ECCCTRL_UE |		      SCHIZO_ECCCTRL_CE));	err_mask = (SCHIZO_PCICTRL_BUS_UNUS |		    SCHIZO_PCICTRL_ESLCK |		    SCHIZO_PCICTRL_TTO_ERR |		    SCHIZO_PCICTRL_RTRY_ERR |		    SCHIZO_PCICTRL_SBH_ERR |		    SCHIZO_PCICTRL_SERR |		    SCHIZO_PCICTRL_SBH_INT |		    SCHIZO_PCICTRL_EEN);	err_no_mask = SCHIZO_PCICTRL_DTO_ERR;	/* Enable PCI Error interrupts and clear error	 * bits for each PBM.	 */	tmp = schizo_read(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL);	tmp |= err_mask;	tmp &= ~err_no_mask;	schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_CTRL, tmp);	schizo_write(p->pbm_A.pbm_regs + SCHIZO_PCI_AFSR,		     (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |		      SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |		      SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |		      SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |		      SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |		      SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));	tmp = schizo_read(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL);	tmp |= err_mask;	tmp &= ~err_no_mask;	schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_CTRL, tmp);	schizo_write(p->pbm_B.pbm_regs + SCHIZO_PCI_AFSR,		     (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA |		      SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR |		      SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS |		      SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA |		      SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR |		      SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS));	/* Make all Safari error conditions fatal except unmapped	 * errors which we make generate interrupts.	 */	err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SSMDIS |		    BUS_ERROR_BADMA | BUS_ERROR_BADMB |		    BUS_ERROR_BADMC |		    BUS_ERROR_CPU1PS | BUS_ERROR_CPU1PB |		    BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB |		    BUS_ERROR_CIQTO |		    BUS_ERROR_LPQTO | BUS_ERROR_SFPQTO |		    BUS_ERROR_UFPQTO | BUS_ERROR_APERR |		    BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT |		    BUS_ERROR_ILL);#if 1	/* XXX Something wrong with some Excalibur systems	 * XXX Sun is shipping.  The behavior on a 2-cpu	 * XXX machine is that both CPU1 parity error bits	 * XXX are set and are immediately set again when	 * XXX their error status bits are cleared.  Just	 * XXX ignore them for now.  -DaveM	 */	err_mask &= ~(BUS_ERROR_CPU1PS | BUS_ERROR_CPU1PB |		      BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB);#endif	schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_ERRCTRL,		     (SCHIZO_SAFERRCTRL_EN | err_mask));	schizo_write(p->pbm_A.controller_regs + SCHIZO_SAFARI_IRQCTRL,		     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));}static void __init pbm_config_busmastering(struct pci_pbm_info *pbm){	u8 *addr;	/* Set cache-line size to 64 bytes, this is actually	 * a nop but I do it for completeness.	 */	addr = schizo_pci_config_mkaddr(pbm, pbm->pci_first_busno,					0, PCI_CACHE_LINE_SIZE);	pci_config_write8(addr, 64 / sizeof(u32));	/* Set PBM latency timer to 64 PCI clocks. */	addr = schizo_pci_config_mkaddr(pbm, pbm->pci_first_busno,					0, PCI_LATENCY_TIMER);	pci_config_write8(addr, 64);}static void __init pbm_scan_bus(struct pci_controller_info *p,				struct pci_pbm_info *pbm){	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);	if (!cookie) {		prom_printf("%s: Critical allocation failure.\n", pbm->name);		prom_halt();	}	/* All we care about is the PBM. */	memset(cookie, 0, sizeof(*cookie));	cookie->pbm = pbm;	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,				    p->pci_ops,				    pbm);	pci_fixup_host_bridge_self(pbm->pci_bus);	pbm->pci_bus->self->sysdata = cookie;	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);	pci_record_assignments(pbm, pbm->pci_bus);	pci_assign_unassigned(pbm, pbm->pci_bus);	pci_fixup_irq(pbm, pbm->pci_bus);	pci_determine_66mhz_disposition(pbm, pbm->pci_bus);	pci_setup_busmastering(pbm, pbm->pci_bus);}static void __init __schizo_scan_bus(struct pci_controller_info *p,				     int chip_type){	if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {		printk("PCI: Only one PCI bus module of controller found.\n");		printk("PCI: Ignoring entire controller.\n");		return;	}	pbm_config_busmastering(&p->pbm_B);	p->pbm_B.is_66mhz_capable =		prom_getbool(p->pbm_B.prom_node, "66mhz-capable");	pbm_config_busmastering(&p->pbm_A);	p->pbm_A.is_66mhz_capable =		prom_getbool(p->pbm_A.prom_node, "66mhz-capable");	pbm_scan_bus(p, &p->pbm_B);	pbm_scan_bus(p, &p->pbm_A);	/* After the PCI bus scan is complete, we can register	 * the error interrupt handlers.	 */	if (chip_type == PBM_CHIP_TYPE_TOMATILLO)		tomatillo_register_error_handlers(p);	else		schizo_register_error_handlers(p);}static void __init schizo_scan_bus(struct pci_controller_info *p){	__schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);}static void __init tomatillo_scan_bus(struct pci_controller_info *p){	__schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);}static void __init schizo_base_address_update(struct pci_dev *pdev, int resource){	struct pcidev_cookie *pcp = pdev->sysdata;	struct pci_pbm_info *pbm = pcp->pbm;	struct resource *res, *root;	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)		root = &pbm->io_space;	else {		root = &pbm->mem_space;		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 - root->start)) & ~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 schizo_resource_adjust(struct pci_dev *pdev,					  struct resource *res,					  struct resource *root){	res->start += root->start;	res->end += root->start;}/* Use ranges property to determine where PCI MEM, I/O, and Config * space are for this PCI bus module. */static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm){	int i, saw_cfg, saw_mem, saw_io;	saw_cfg = saw_mem = saw_io = 0;	for (i = 0; i < pbm->num_pbm_ranges; i++) {		struct linux_prom_pci_ranges *pr = &pbm->pbm_ranges[i];		unsigned long a;		int type;		type = (pr->child_phys_hi >> 24) & 0x3;		a = (((unsigned long)pr->parent_phys_hi << 32UL) |		     ((unsigned long)pr->parent_phys_lo  <<  0UL));		switch (type) {		case 0:			/* PCI config space, 16MB */			pbm->config_space = a;			saw_cfg = 1;			break;		case 1:			/* 16-bit IO space, 16MB */			pbm->io_space.start = a;			pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL);			pbm->io_space.flags = IORESOURCE_IO;			saw_io = 1;			break;		case 2:			/* 32-bit MEM space, 2GB */			pbm->mem_space.start = a;			pbm->mem_space.end = a + (0x80000000UL - 1UL);			pbm->mem_space.flags = IORESOURCE_MEM;			saw_mem = 1;			break;		default:			break;		};	}	if (!saw_cfg || !saw_io || !saw_mem) {		prom_printf("%s: Fatal error, missing %s PBM range.\n",			    pbm->name,			    ((!saw_cfg ?			      "CFG" :			      (!saw_io ?			       "IO" : "MEM"))));		prom_halt();	}	printk("%s: PCI CFG[%lx] IO[%lx] MEM[%lx]\n",	       pbm->name,	       pbm->config_space,	       pbm->io_space.start,	       pbm->mem_space.start);}static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,						   struct pci_pbm_info *pbm){	pbm->io_space.name = pbm->mem_space.name = pbm->name;	request_resource(&ioport_resource, &pbm->io_space);	request_resource(&iomem_resource, &pbm->mem_space);	pci_register_legacy_regions(&pbm->io_space,				    &pbm->mem_space);}#define SCHIZO_STRBUF_CONTROL		(0x02800UL)#define SCHIZO_STRBUF_FLUSH		(0x02808UL)#define SCHIZO_STRBUF_FSYNC		(0x02810UL)#define SCHIZO_STRBUF_CTXFLUSH		(0x02818UL)#define SCHIZO_STRBUF_CTXMATCH		(0x10000UL)static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm){	unsigned long base = pbm->pbm_regs;	u64 control;	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {

⌨️ 快捷键说明

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