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

📄 pci_sabre.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 4 页
字号:
	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);	control |= SABRE_IOMMUCTRL_DENAB;	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);	for(i = 0; i < 16; i++) {		sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);		sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);	}	/* Leave diag mode enabled for full-flushing done	 * in pci_iommu.c	 */	tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));	if (!tsbbase) {		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");		prom_halt();	}	iommu->page_table = (iopte_t *)tsbbase;	iommu->page_table_map_base = dvma_offset;	iommu->dma_addr_mask = dma_mask;	memset((char *)tsbbase, 0, PAGE_SIZE << order);	sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);	control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);	control |= SABRE_IOMMUCTRL_ENAB;	switch(tsbsize) {	case 64:		control |= SABRE_IOMMU_TSBSZ_64K;		iommu->page_table_sz_bits = 16;		break;	case 128:		control |= SABRE_IOMMU_TSBSZ_128K;		iommu->page_table_sz_bits = 17;		break;	default:		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);		prom_halt();		break;	}	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);	/* 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;	}}static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,						   struct pci_pbm_info *pbm){	char *name = pbm->name;	unsigned long ibase = p->controller_regs + SABRE_IOSPACE;	unsigned long mbase = p->controller_regs + SABRE_MEMSPACE;	unsigned int devfn;	unsigned long first, last, i;	u8 *addr, map;	sprintf(name, "SABRE%d PBM%c",		p->index,		(pbm == &p->pbm_A ? 'A' : 'B'));	pbm->io_space.name = pbm->mem_space.name = name;	devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1);	addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP);	map = 0;	pci_config_read8(addr, &map);	first = 8;	last = 0;	for (i = 0; i < 8; i++) {		if ((map & (1 << i)) != 0) {			if (first > i)				first = i;			if (last < i)				last = i;		}	}	pbm->io_space.start = ibase + (first << 21UL);	pbm->io_space.end   = ibase + (last << 21UL) + ((1 << 21UL) - 1);	pbm->io_space.flags = IORESOURCE_IO;	addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP);	map = 0;	pci_config_read8(addr, &map);	first = 8;	last = 0;	for (i = 0; i < 8; i++) {		if ((map & (1 << i)) != 0) {			if (first > i)				first = i;			if (last < i)				last = i;		}	}	pbm->mem_space.start = mbase + (first << 29UL);	pbm->mem_space.end   = mbase + (last << 29UL) + ((1 << 29UL) - 1);	pbm->mem_space.flags = IORESOURCE_MEM;	if (request_resource(&ioport_resource, &pbm->io_space) < 0) {		prom_printf("Cannot register PBM-%c's IO space.\n",			    (pbm == &p->pbm_A ? 'A' : 'B'));		prom_halt();	}	if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {		prom_printf("Cannot register PBM-%c's MEM space.\n",			    (pbm == &p->pbm_A ? 'A' : 'B'));		prom_halt();	}	/* Register legacy regions if this PBM covers that area. */	if (pbm->io_space.start == ibase &&	    pbm->mem_space.start == mbase)		pci_register_legacy_regions(&pbm->io_space,					    &pbm->mem_space);}static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin){	struct pci_pbm_info *pbm;	char namebuf[128];	u32 busrange[2];	int node, simbas_found;	simbas_found = 0;	node = prom_getchild(sabre_node);	while ((node = prom_searchsiblings(node, "pci")) != 0) {		int err;		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));		if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))			goto next_pci;		err = prom_getproperty(node, "bus-range",				       (char *)&busrange[0], sizeof(busrange));		if (err == 0 || err == -1) {			prom_printf("APB: Error, cannot get PCI bus-range.\n");			prom_halt();		}		simbas_found++;		if (busrange[0] == 1)			pbm = &p->pbm_B;		else			pbm = &p->pbm_A;		pbm->parent = p;		pbm->prom_node = node;		pbm->pci_first_slot = 1;		pbm->pci_first_busno = busrange[0];		pbm->pci_last_busno = busrange[1];		for (err = pbm->pci_first_busno;		     err <= pbm->pci_last_busno;		     err++)			pci_bus2pbm[err] = pbm;		prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name));		err = prom_getproperty(node, "ranges",				       (char *)pbm->pbm_ranges,				       sizeof(pbm->pbm_ranges));		if (err != -1)			pbm->num_pbm_ranges =				(err / sizeof(struct linux_prom_pci_ranges));		else			pbm->num_pbm_ranges = 0;		err = prom_getproperty(node, "interrupt-map",				       (char *)pbm->pbm_intmap,				       sizeof(pbm->pbm_intmap));		if (err != -1) {			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));			err = prom_getproperty(node, "interrupt-map-mask",					       (char *)&pbm->pbm_intmask,					       sizeof(pbm->pbm_intmask));			if (err == -1) {				prom_printf("APB: Fatal error, no interrupt-map-mask.\n");				prom_halt();			}		} else {			pbm->num_pbm_intmap = 0;			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));		}		pbm_register_toplevel_resources(p, pbm);	next_pci:		node = prom_getsibling(node);		if (!node)			break;	}	if (simbas_found == 0) {		int err;		/* No APBs underneath, probably this is a hummingbird		 * system.		 */		pbm = &p->pbm_A;		pbm->parent = p;		pbm->prom_node = sabre_node;		pbm->pci_first_busno = p->pci_first_busno;		pbm->pci_last_busno = p->pci_last_busno;		for (err = pbm->pci_first_busno;		     err <= pbm->pci_last_busno;		     err++)			pci_bus2pbm[err] = pbm;		prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name));		err = prom_getproperty(sabre_node, "ranges",				       (char *) pbm->pbm_ranges,				       sizeof(pbm->pbm_ranges));		if (err != -1)			pbm->num_pbm_ranges =				(err / sizeof(struct linux_prom_pci_ranges));		else			pbm->num_pbm_ranges = 0;		err = prom_getproperty(sabre_node, "interrupt-map",				       (char *) pbm->pbm_intmap,				       sizeof(pbm->pbm_intmap));		if (err != -1) {			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));			err = prom_getproperty(sabre_node, "interrupt-map-mask",					       (char *)&pbm->pbm_intmask,					       sizeof(pbm->pbm_intmask));			if (err == -1) {				prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");				prom_halt();			}		} else {			pbm->num_pbm_intmap = 0;			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));		}		sprintf(pbm->name, "SABRE%d PBM%c", p->index,			(pbm == &p->pbm_A ? 'A' : 'B'));		pbm->io_space.name = pbm->mem_space.name = pbm->name;		/* Hack up top-level resources. */		pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;		pbm->io_space.end   = pbm->io_space.start + (1UL << 24) - 1UL;		pbm->io_space.flags = IORESOURCE_IO;		pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE;		pbm->mem_space.end   = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;		pbm->mem_space.flags = IORESOURCE_MEM;		if (request_resource(&ioport_resource, &pbm->io_space) < 0) {			prom_printf("Cannot register Hummingbird's IO space.\n");			prom_halt();		}		if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {			prom_printf("Cannot register Hummingbird's MEM space.\n");			prom_halt();		}		pci_register_legacy_regions(&pbm->io_space,					    &pbm->mem_space);	}}void __init sabre_init(int pnode, char *model_name){	struct linux_prom64_registers pr_regs[2];	struct pci_controller_info *p;	struct pci_iommu *iommu;	unsigned long flags;	int tsbsize, err;	u32 busrange[2];	u32 vdma[2];	u32 upa_portid, dma_mask;	int bus;	hummingbird_p = 0;	if (!strcmp(model_name, "pci108e,a001"))		hummingbird_p = 1;	else if (!strcmp(model_name, "SUNW,sabre")) {		char compat[64];		if (prom_getproperty(pnode, "compatible",				     compat, sizeof(compat)) > 0 &&		    !strcmp(compat, "pci108e,a001")) {			hummingbird_p = 1;		} else {			int cpu_node = linux_cpus[0].prom_node;			/* Of course, Sun has to encode things a thousand			 * different ways, inconsistently.			 */			if (prom_getproperty(cpu_node, "name",					     compat, sizeof(compat)) > 0 &&			    !strcmp(compat, "SUNW,UltraSPARC-IIe"))				hummingbird_p = 1;		}	}	p = kmalloc(sizeof(*p), GFP_ATOMIC);	if (!p) {		prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");		prom_halt();	}	memset(p, 0, sizeof(*p));	iommu = kmalloc(sizeof(*iommu), GFP_ATOMIC);	if (!iommu) {		prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");		prom_halt();	}	memset(iommu, 0, sizeof(*iommu));	p->pbm_A.iommu = p->pbm_B.iommu = iommu;	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);	spin_lock_irqsave(&pci_controller_lock, flags);	p->next = pci_controller_root;	pci_controller_root = p;	spin_unlock_irqrestore(&pci_controller_lock, flags);	p->portid = upa_portid;	p->index = pci_num_controllers++;	p->pbms_same_domain = 1;	p->scan_bus = sabre_scan_bus;	p->irq_build = sabre_irq_build;	p->base_address_update = sabre_base_address_update;	p->resource_adjust = sabre_resource_adjust;	p->pci_ops = &sabre_ops;	/*	 * Map in SABRE register set and report the presence of this SABRE.	 */	err = prom_getproperty(pnode, "reg",			       (char *)&pr_regs[0], sizeof(pr_regs));	if(err == 0 || err == -1) {		prom_printf("SABRE: Error, cannot get U2P registers "			    "from PROM.\n");		prom_halt();	}	/*	 * First REG in property is base of entire SABRE register space.	 */	p->controller_regs = pr_regs[0].phys_addr;	pci_dma_wsync = p->controller_regs + SABRE_WRSYNC;	printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n",	       p->controller_regs, pci_dma_wsync);	/* Error interrupts are enabled later after the bus scan. */	sabre_write(p->controller_regs + SABRE_PCICTRL,		    (SABRE_PCICTRL_MRLEN   | SABRE_PCICTRL_SERR |		     SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));	/* Now map in PCI config space for entire SABRE. */	p->pbm_A.config_space = p->pbm_B.config_space =		(p->controller_regs + SABRE_CONFIGSPACE);	printk("SABRE: Shared PCI config space at %016lx\n",	       p->pbm_A.config_space);	err = prom_getproperty(pnode, "virtual-dma",			       (char *)&vdma[0], sizeof(vdma));	if(err == 0 || err == -1) {		prom_printf("SABRE: Error, cannot get virtual-dma property "			    "from PROM.\n");		prom_halt();	}	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("SABRE: strange virtual-dma size.\n");			prom_halt();	}	sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);	err = prom_getproperty(pnode, "bus-range",				       (char *)&busrange[0], sizeof(busrange));	if(err == 0 || err == -1) {		prom_printf("SABRE: Error, cannot get PCI bus-range "			    " from PROM.\n");		prom_halt();	}	p->pci_first_busno = busrange[0];	p->pci_last_busno = busrange[1];	/*	 * Handle config space reads through any Simba on APB.	 */	for (bus = p->pci_first_busno; bus <= p->pci_last_busno; bus++)		pci_bus2pbm[bus] = &p->pbm_A;	/*	 * Look for APB underneath.	 */	sabre_pbm_init(p, pnode, vdma[0]);}

⌨️ 快捷键说明

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