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

📄 pci_schizo.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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) {		/* TOMATILLO lacks streaming cache.  */		return;	}	/* SCHIZO has context flushing. */	pbm->stc.strbuf_control		= base + SCHIZO_STRBUF_CONTROL;	pbm->stc.strbuf_pflush		= base + SCHIZO_STRBUF_FLUSH;	pbm->stc.strbuf_fsync		= base + SCHIZO_STRBUF_FSYNC;	pbm->stc.strbuf_ctxflush	= base + SCHIZO_STRBUF_CTXFLUSH;	pbm->stc.strbuf_ctxmatch_base	= base + SCHIZO_STRBUF_CTXMATCH;	pbm->stc.strbuf_flushflag = (volatile unsigned long *)		((((unsigned long)&pbm->stc.__flushflag_buf[0])		  + 63UL)		 & ~63UL);	pbm->stc.strbuf_flushflag_pa = (unsigned long)		__pa(pbm->stc.strbuf_flushflag);	/* Turn off LRU locking and diag mode, enable the	 * streaming buffer and leave the rerun-disable	 * setting however OBP set it.	 */	control = schizo_read(pbm->stc.strbuf_control);	control &= ~(SCHIZO_STRBUF_CTRL_LPTR |		     SCHIZO_STRBUF_CTRL_LENAB |		     SCHIZO_STRBUF_CTRL_DENAB);	control |= SCHIZO_STRBUF_CTRL_ENAB;	schizo_write(pbm->stc.strbuf_control, control);	pbm->stc.strbuf_enabled = 1;}#define SCHIZO_IOMMU_CONTROL		(0x00200UL)#define SCHIZO_IOMMU_TSBBASE		(0x00208UL)#define SCHIZO_IOMMU_FLUSH		(0x00210UL)#define SCHIZO_IOMMU_CTXFLUSH		(0x00218UL)static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm){	struct pci_iommu *iommu = pbm->iommu;	unsigned long tsbbase, i, tagbase, database, order;	u32 vdma[2], dma_mask;	u64 control;	int err, tsbsize;	err = prom_getproperty(pbm->prom_node, "virtual-dma",			       (char *)&vdma[0], sizeof(vdma));	if (err == 0 || err == -1) {		/* No property, use default values. */		vdma[0] = 0xc0000000;		vdma[1] = 0x40000000;	}	dma_mask = vdma[0];	switch (vdma[1]) {		case 0x20000000:			dma_mask |= 0x1fffffff;			tsbsize = 64;			break;		case 0x40000000:			dma_mask |= 0x3fffffff;			tsbsize = 128;			break;		case 0x80000000:			dma_mask |= 0x7fffffff;			tsbsize = 128;			break;		default:			prom_printf("SCHIZO: strange virtual-dma size.\n");			prom_halt();	};	/* Setup initial software IOMMU state. */	spin_lock_init(&iommu->lock);	iommu->iommu_cur_ctx = 0;	/* Register addresses, SCHIZO has iommu ctx flushing. */	iommu->iommu_control  = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;	iommu->iommu_tsbbase  = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;	iommu->iommu_flush    = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH;	iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH;	/* We use the main control/status register of SCHIZO as the write	 * completion register.	 */	iommu->write_complete_reg = pbm->controller_regs + 0x10000UL;	/*	 * Invalidate TLB Entries.	 */	control = schizo_read(iommu->iommu_control);	control |= SCHIZO_IOMMU_CTRL_DENAB;	schizo_write(iommu->iommu_control, control);	tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA;	for(i = 0; i < 16; i++) {		schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0);		schizo_write(pbm->pbm_regs + database + (i * 8UL), 0);	}	/* Leave diag mode enabled for full-flushing done	 * in pci_iommu.c	 */	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);	if (!iommu->dummy_page) {		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");		prom_halt();	}	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);	/* Using assumed page size 8K with 128K entries we need 1MB iommu page	 * table (128K ioptes * 8 bytes per iopte).  This is	 * page order 7 on UltraSparc.	 */	order = get_order(tsbsize * 8 * 1024);	tsbbase = __get_free_pages(GFP_KERNEL, order);	if (!tsbbase) {		prom_printf("%s: Error, gfp(tsb) failed.\n", pbm->name);		prom_halt();	}	iommu->page_table = (iopte_t *)tsbbase;	iommu->page_table_map_base = vdma[0];	iommu->dma_addr_mask = dma_mask;	pci_iommu_table_init(iommu, PAGE_SIZE << order);	switch (tsbsize) {	case 64:		iommu->page_table_sz_bits = 16;		break;	case 128:		iommu->page_table_sz_bits = 17;		break;	default:		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);		prom_halt();		break;	};	/* We start with no consistent mappings. */	iommu->lowest_consistent_map =		1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS);	for (i = 0; i < PBM_NCLUSTERS; i++) {		iommu->alloc_info[i].flush = 0;		iommu->alloc_info[i].next = 0;	}	schizo_write(iommu->iommu_tsbbase, __pa(tsbbase));	control = schizo_read(iommu->iommu_control);	control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ);	switch (tsbsize) {	case 64:		control |= SCHIZO_IOMMU_TSBSZ_64K;		break;	case 128:		control |= SCHIZO_IOMMU_TSBSZ_128K;		break;	};	control |= SCHIZO_IOMMU_CTRL_ENAB;	schizo_write(iommu->iommu_control, control);}#define SCHIZO_PCI_IRQ_RETRY	(0x1a00UL)#define  SCHIZO_IRQ_RETRY_INF	 0xffUL#define SCHIZO_PCI_DIAG			(0x2020UL)#define  SCHIZO_PCIDIAG_D_BADECC	(1UL << 10UL) /* Disable BAD ECC errors (Schizo) */#define  SCHIZO_PCIDIAG_D_BYPASS	(1UL <<  9UL) /* Disable MMU bypass mode (Schizo/Tomatillo) */#define  SCHIZO_PCIDIAG_D_TTO		(1UL <<  8UL) /* Disable TTO errors (Schizo/Tomatillo) */#define  SCHIZO_PCIDIAG_D_RTRYARB	(1UL <<  7UL) /* Disable retry arbitration (Schizo) */#define  SCHIZO_PCIDIAG_D_RETRY		(1UL <<  6UL) /* Disable retry limit (Schizo/Tomatillo) */#define  SCHIZO_PCIDIAG_D_INTSYNC	(1UL <<  5UL) /* Disable interrupt/DMA synch (Schizo/Tomatillo) */#define  SCHIZO_PCIDIAG_I_DMA_PARITY	(1UL <<  3UL) /* Invert DMA parity (Schizo/Tomatillo) */#define  SCHIZO_PCIDIAG_I_PIOD_PARITY	(1UL <<  2UL) /* Invert PIO data parity (Schizo/Tomatillo) */#define  SCHIZO_PCIDIAG_I_PIOA_PARITY	(1UL <<  1UL) /* Invert PIO address parity (Schizo/Tomatillo) */#define TOMATILLO_PCI_IOC_CSR		(0x2248UL)#define TOMATILLO_IOC_PART_WPENAB	0x0000000000080000UL#define TOMATILLO_IOC_RDMULT_PENAB	0x0000000000040000UL#define TOMATILLO_IOC_RDONE_PENAB	0x0000000000020000UL#define TOMATILLO_IOC_RDLINE_PENAB	0x0000000000010000UL#define TOMATILLO_IOC_RDMULT_PLEN	0x000000000000c000UL#define TOMATILLO_IOC_RDMULT_PLEN_SHIFT	14UL#define TOMATILLO_IOC_RDONE_PLEN	0x0000000000003000UL#define TOMATILLO_IOC_RDONE_PLEN_SHIFT	12UL#define TOMATILLO_IOC_RDLINE_PLEN	0x0000000000000c00UL#define TOMATILLO_IOC_RDLINE_PLEN_SHIFT	10UL#define TOMATILLO_IOC_PREF_OFF		0x00000000000003f8UL#define TOMATILLO_IOC_PREF_OFF_SHIFT	3UL#define TOMATILLO_IOC_RDMULT_CPENAB	0x0000000000000004UL#define TOMATILLO_IOC_RDONE_CPENAB	0x0000000000000002UL#define TOMATILLO_IOC_RDLINE_CPENAB	0x0000000000000001UL#define TOMATILLO_PCI_IOC_TDIAG		(0x2250UL)#define TOMATILLO_PCI_IOC_DDIAG		(0x2290UL)static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm){	u64 tmp;	/* Set IRQ retry to infinity. */	schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY,		     SCHIZO_IRQ_RETRY_INF);	/* Enable arbiter for all PCI slots.  Also, disable PCI interval	 * timer so that DTO (Discard TimeOuts) are not reported because	 * some Schizo revisions report them erroneously.	 */	tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);	if (pbm->chip_type == PBM_CHIP_TYPE_SCHIZO_PLUS &&	    pbm->chip_version == 0x5 &&	    pbm->chip_revision == 0x1)		tmp |= 0x0f;	else		tmp |= 0xff;	tmp &= ~SCHIZO_PCICTRL_PTO;	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&	    pbm->chip_version == 0x2)		tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;	else		tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;	if (!prom_getbool(pbm->prom_node, "no-bus-parking"))		tmp |= SCHIZO_PCICTRL_PARK;	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)		tmp |= SCHIZO_PCICTRL_MRM_PREF;	schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);	tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG);	tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB |		 SCHIZO_PCIDIAG_D_RETRY |		 SCHIZO_PCIDIAG_D_INTSYNC);	schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp);	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {		/* Clear prefetch lengths to workaround a bug in		 * Jalapeno...		 */		tmp = (TOMATILLO_IOC_PART_WPENAB |		       (1 << TOMATILLO_IOC_PREF_OFF_SHIFT) |		       TOMATILLO_IOC_RDMULT_CPENAB |		       TOMATILLO_IOC_RDONE_CPENAB |		       TOMATILLO_IOC_RDLINE_CPENAB);		schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR,			     tmp);	}}static void __init schizo_pbm_init(struct pci_controller_info *p,				   int prom_node, u32 portid,				   int chip_type){	struct linux_prom64_registers pr_regs[4];	unsigned int busrange[2];	struct pci_pbm_info *pbm;	const char *chipset_name;	u32 ino_bitmap[2];	int is_pbm_a;	int err;	switch (chip_type) {	case PBM_CHIP_TYPE_TOMATILLO:		chipset_name = "TOMATILLO";		break;	case PBM_CHIP_TYPE_SCHIZO_PLUS:		chipset_name = "SCHIZO+";		break;	case PBM_CHIP_TYPE_SCHIZO:	default:		chipset_name = "SCHIZO";		break;	};	/* For SCHIZO, three OBP regs:	 * 1) PBM controller regs	 * 2) Schizo front-end controller regs (same for both PBMs)	 * 3) PBM PCI config space	 *	 * For TOMATILLO, four OBP regs:	 * 1) PBM controller regs	 * 2) Tomatillo front-end controller regs	 * 3) PBM PCI config space	 * 4) Ichip regs	 */	err = prom_getproperty(prom_node, "reg",			       (char *)&pr_regs[0],			       sizeof(pr_regs));	if (err == 0 || err == -1) {		prom_printf("%s: Fatal error, no reg property.\n",			    chipset_name);		prom_halt();	}	is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000);	if (is_pbm_a)		pbm = &p->pbm_A;	else		pbm = &p->pbm_B;	pbm->portid = portid;	pbm->parent = p;	pbm->prom_node = prom_node;	pbm->pci_first_slot = 1;	pbm->chip_type = chip_type;	pbm->chip_version =		prom_getintdefault(prom_node, "version#", 0);	pbm->chip_revision =

⌨️ 快捷键说明

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