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

📄 lba_pci.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \	WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \	if (LBA_DEV(d)->hw_rev < 3) \		lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \}LBA_PORT_OUT( 8, 3)LBA_PORT_OUT(16, 2)LBA_PORT_OUT(32, 0)static struct pci_port_ops lba_astro_port_ops = {	lba_astro_in8, lba_astro_in16, lba_astro_in32,	lba_astro_out8, lba_astro_out16, lba_astro_out32};#ifdef __LP64__#define PIOP_TO_GMMIO(lba, addr) \	((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))/*********************************************************** LBA PAT "I/O Port" Space Accessor Functions**** This set of accessor functions is intended for use with** "PAT PDC" firmware (ie Prelude/Rhapsody/Piranha boxes).**** This uses the PIOP space located in the first 64MB of GMMIO.** Each rope gets a full 64*KB* (ie 4 bytes per page) this way.** bits 1:0 stay the same.  bits 15:2 become 25:12.** Then add the base and we can generate an I/O Port cycle.********************************************************/#undef LBA_PORT_IN#define LBA_PORT_IN(size, mask) \static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \{ \	u##size t; \	ASSERT(bus != NULL); \	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \	t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \	DBG_PORT(" 0x%x\n", t); \	return (t); \}LBA_PORT_IN( 8, 3)LBA_PORT_IN(16, 2)LBA_PORT_IN(32, 0)#undef LBA_PORT_OUT#define LBA_PORT_OUT(size, mask) \static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \{ \	void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \	ASSERT(bus != NULL); \	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \	WRITE_REG##size(val, where); \	/* flush the I/O down to the elroy at least */ \	lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \}LBA_PORT_OUT( 8, 3)LBA_PORT_OUT(16, 2)LBA_PORT_OUT(32, 0)static struct pci_port_ops lba_pat_port_ops = {	lba_pat_in8, lba_pat_in16, lba_pat_in32,	lba_pat_out8, lba_pat_out16, lba_pat_out32};/*** make range information from PDC available to PCI subsystem.** We make the PDC call here in order to get the PCI bus range** numbers. The rest will get forwarded in pcibios_fixup_bus().** We don't have a struct pci_bus assigned to us yet.*/static voidlba_pat_resources( struct hp_device *d, struct lba_device *lba_dev){	pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;	/* PA_VIEW */#ifdef DONT_NEED_THIS_FOR_ASTRO	pdc_pat_cell_mod_maddr_block_t io_pdc_cell;	/* IO_VIEW */	long io_count;#endif	long status;	/* PDC return status */	long pa_count;	int i;	/* return cell module (IO view) */	status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,				PA_VIEW, & pa_pdc_cell);	pa_count = pa_pdc_cell.mod[1];#ifdef DONT_NEED_THIS_FOR_ASTRO	status |= pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,				IO_VIEW, & io_pdc_cell);	io_count = io_pdc_cell.mod[1];#endif	/* We've already done this once for device discovery...*/	if (status != PDC_RET_OK) {		panic("pdc_pat_cell_module() call failed for LBA!\n");	}	if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) {		panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n");	}	/*	** Inspect the resources PAT tells us about	*/	for (i = 0; i < pa_count; i++) {		struct {			unsigned long type;			unsigned long start;			unsigned long end;	/* aka finish */		} *p;		struct resource *r;		p = (void *) &(pa_pdc_cell.mod[2+i*3]);		/* Convert the PAT range data to PCI "struct resource" */		switch(p->type & 0xff) {		case PAT_PBNUM:			lba_dev->hba.bus_num.start = p->start;			lba_dev->hba.bus_num.end   = p->end;			break;		case PAT_LMMIO:			/* used to fix up pre-initialized MEM BARs */			lba_dev->lmmio_base = p->start;			r = &(lba_dev->hba.mem_space);			r->name   = "LBA LMMIO";			r->start  = p->start;			r->end    = p->end;			r->flags  = IORESOURCE_MEM;			r->parent = r->sibling = r->child = NULL;			break;		case PAT_GMMIO:			printk(KERN_WARNING MODULE_NAME				" range[%d] : ignoring GMMIO (0x%lx)\n",				i, p->start);			lba_dev->gmmio_base = p->start;			break;		case PAT_NPIOP:			printk(KERN_WARNING MODULE_NAME				" range[%d] : ignoring NPIOP (0x%lx)\n",				i, p->start);			break;		case PAT_PIOP:			/*			** Postable I/O port space is per PCI host adapter.			*/			/* save base of 64MB PIOP region */			lba_dev->iop_base = p->start;			r = &(lba_dev->hba.io_space);			r->name   = "LBA I/O Port";			r->start = lba_dev->hba.hba_num << 16;			r->end   = r->start + 0xffffUL;			r->flags  = IORESOURCE_IO;			r->parent = r->sibling = r->child = NULL;			break;		default:			printk(KERN_WARNING MODULE_NAME				" range[%d] : unknown pat range type (0x%lx)\n",				i, p->type & 0xff);			break;		}	}}#endif	/* __LP64__ */static voidlba_legacy_resources( struct hp_device *d, struct lba_device *lba_dev){	int lba_num;	struct resource *r;#ifdef __LP64__	/*	** Used to sign extend instead BAR values are only 32-bit.	** 64-bit BARs have the upper 32-bit's zero'd by firmware.	** "Sprockets" PDC initializes for 32-bit OS.	*/	lba_dev->lmmio_base = 0xffffffff00000000UL;#endif	/*	** With "legacy" firmware, the lowest byte of FW_SCRATCH	** represents bus->secondary and the second byte represents	** bus->subsidiary (i.e. highest PPB programmed by firmware).	** PCI bus walk *should* end up with the same result.	** FIXME: But we don't have sanity checks in PCI or LBA.	*/	lba_num = READ_REG32(d->hpa + LBA_FW_SCRATCH);	r = &(lba_dev->hba.bus_num);	r->name = "LBA PCI Busses";	r->start = lba_num & 0xff;	r->end = (lba_num>>8) & 0xff;	/* Set up local PCI Bus resources - we don't really need	** them for Legacy boxes but it's nice to see in /proc.	*/	r = &(lba_dev->hba.mem_space);	r->name  = "LBA PCI LMMIO";	r->flags = IORESOURCE_MEM;	r->start = READ_REG32(d->hpa + LBA_LMMIO_BASE);	r->end   = r->start + ~ (READ_REG32(d->hpa + LBA_LMMIO_MASK));	r = &(lba_dev->hba.io_space);	r->name  = "LBA PCI I/O Ports";	r->flags = IORESOURCE_IO;	r->start = READ_REG32(d->hpa + LBA_IOS_BASE);	r->end   = r->start + (READ_REG32(d->hpa + LBA_IOS_MASK) ^ 0xffff);	lba_num = lba_dev->hba.hba_num << 16;	r->start |= lba_num;	r->end   |= lba_num;}/******************************************************************************   LBA initialization code (HW and SW)****   o identify LBA chip itself**   o initialize LBA chip modes (HardFail)**   o FIXME: initialize DMA hints for reasonable defaults**   o enable configuration functions**   o call pci_register_ops() to discover devs (fixup/fixup_bus get invoked)****************************************************************************/static voidlba_hw_init(struct lba_device *d){	u32 stat;	/* Set HF mode as the default (vs. -1 mode). */        stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);	WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL);	/*	** FIXME: Hint registers are programmed with default hint	** values by firmware. Hints should be sane even if we	** can't reprogram them the way drivers want.	*/}static voidlba_common_init(struct lba_device *lba_dev){	pci_bios = &lba_bios_ops;	pcibios_register_hba((struct pci_hba_data *)lba_dev);	lba_dev->lba_lock = SPIN_LOCK_UNLOCKED;		/*	** Set flags which depend on hw_rev	*/	if (!LBA_TR4PLUS(lba_dev)) {		lba_dev->flags |= LBA_FLAG_NO_DMA_DURING_CFG;	}}/*** Determine if lba should claim this chip (return 0) or not (return 1).** If so, initialize the chip and tell other partners in crime they** have work to do.*/static __init intlba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri){	struct lba_device *lba_dev;	struct pci_bus *lba_bus;	u32 func_class;	void *tmp_obj;	/* from drivers/pci/setup-bus.c */	extern void __init pbus_set_ranges(struct pci_bus *, struct pbus_set_ranges_data *);	/* Read HW Rev First */	func_class = READ_REG32(d->hpa + LBA_FCLASS);	func_class &= 0xf;	switch (func_class) {	case 0:	dri->version = "TR1.0"; break;	case 1:	dri->version = "TR2.0"; break;	case 2:	dri->version = "TR2.1"; break;	case 3:	dri->version = "TR2.2"; break;	case 4:	dri->version = "TR3.0"; break;	case 5:	dri->version = "TR4.0"; break;	default: dri->version = "TR4+";	}	printk("%s version %s (0x%x) found at 0x%p\n", dri->name, dri->version, func_class & 0xf, d->hpa);	/* Just in case we find some prototypes... */	if (func_class < 2) {		printk(KERN_WARNING "Can't support LBA older than TR2.1 "			"- continuing under adversity.\n");	}	/*	** Tell I/O SAPIC driver we have a IRQ handler/region.	*/	tmp_obj = iosapic_register(d->hpa+LBA_IOSAPIC_BASE);	if (NULL == tmp_obj) {		/* iosapic may have failed. But more likely the		** slot isn't occupied and thus has no IRT entries.		** iosapic_register looks for this iosapic in the IRT		** before bothering to allocating data structures		** we don't need.		*/		DBG(KERN_WARNING MODULE_NAME ": iosapic_register says not used\n");		return (1);	}	lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);	if (NULL == lba_dev)	{		printk("lba_init_chip - couldn't alloc lba_device\n");		return(1);	}	memset(lba_dev, 0, sizeof(struct lba_device));	/* ---------- First : initialize data we already have --------- */	/*	** Need hw_rev to adjust configuration space behavior.	** LBA_TR4PLUS macro uses hw_rev field.	*/	lba_dev->hw_rev = func_class;	lba_dev->hba.base_addr = d->hpa;  /* faster access */	lba_dev->iosapic_obj = tmp_obj;  /* save interrupt handle */	/* ------------ Second : initialize common stuff ---------- */	lba_common_init(lba_dev);	lba_hw_init(lba_dev);	/* ---------- Third : setup I/O Port and MMIO resources  --------- */#ifdef __LP64__	if (pdc_pat) {		/* PDC PAT firmware uses PIOP region of GMMIO space. */		pci_port = &lba_pat_port_ops;		/* Go ask PDC PAT what resources this LBA has */		lba_pat_resources(d, lba_dev);	} else {#endif		/* Sprockets PDC uses NPIOP region */		pci_port = &lba_astro_port_ops;		/* Poke the chip a bit for /proc output */		lba_legacy_resources(d, lba_dev);#ifdef __LP64__	}#endif	/* 	** Tell PCI support another PCI bus was found.	** Walks PCI bus for us too.	*/	lba_bus = lba_dev->hba.hba_bus =		pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev);#ifdef __LP64__	if (pdc_pat) {		/* determine window sizes needed by PCI-PCI bridges */		DBG_PAT("LBA pcibios_size_bridge()\n");		pcibios_size_bridge(lba_bus, NULL);		/* assign resources to un-initialized devices */		DBG_PAT("LBA pcibios_assign_unassigned_resources()\n");		pcibios_assign_unassigned_resources(lba_bus);#ifdef DEBUG_LBA_PAT		DBG_PAT("\nLBA PIOP resource tree\n");		lba_dump_res(&lba_dev->hba.io_space, 2);		DBG_PAT("\nLBA LMMIO resource tree\n");		lba_dump_res(&lba_dev->hba.mem_space, 2);#endif		/* program *all* PCI-PCI bridge range registers */		DBG_PAT("LBA pbus_set_ranges()\n");		pbus_set_ranges(lba_bus, NULL);	}#endif /* __LP64__ */	/*	** Once PCI register ops has walked the bus, access to config	** space is restricted. Avoids master aborts on config cycles.	** Early LBA revs go fatal on *any* master abort.	*/	if (!LBA_TR4PLUS(lba_dev)) {		lba_dev->flags |= LBA_FLAG_SKIP_PROBE;	}	/* Whew! Finally done! Tell services we got this one covered. */	return 0;}/*** Initialize the IBASE/IMASK registers for LBA (Elroy).** Only called from sba_iommu.c initialization sequence.*/void lba_init_iregs(void *sba_hpa, u32 ibase, u32 imask){	extern struct pci_hba_data *hba_list;	/* arch/parisc/kernel/pci.c */	struct pci_hba_data *lba;	imask <<= 2;	/* adjust for hints - 2 more bits */	ASSERT((ibase & 0x003fffff) == 0);	ASSERT((imask & 0x003fffff) == 0);		/* FIXME: sba_hpa is intended to search some table to	**      determine which LBA's belong to the caller's SBA.	** IS_ASTRO: just assume only one SBA for now.	*/	ASSERT(NULL != hba_list);	DBG(KERN_DEBUG "%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);	for (lba = hba_list; NULL != lba; lba = lba->next) {		DBG(KERN_DEBUG "%s() base_addr %p\n", __FUNCTION__, lba->base_addr);		WRITE_REG32( imask, lba->base_addr + LBA_IMASK);		WRITE_REG32( ibase, lba->base_addr + LBA_IBASE);	}	DBG(KERN_DEBUG "%s() done\n", __FUNCTION__);}

⌨️ 快捷键说明

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