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

📄 ide-pmac.c

📁 Linux环境下java编程的经典书籍
💻 C
📖 第 1 页 / 共 3 页
字号:
			return -1;	}	/* Adjust for drive */	if (drive_cycle_time && drive_cycle_time > cycleTime)		cycleTime = drive_cycle_time;	/* OHare limits according to some old Apple sources */		if ((intf_type == controller_ohare) && (cycleTime < 150))		cycleTime = 150;	/* Get the proper timing array for this controller */	switch(intf_type) {		case controller_kl_ata4:		case controller_kl_ata4_80:			tm = mdma_timings_66;			break;		case controller_kl_ata3:			tm = mdma_timings_33k;			break;		default:			tm = mdma_timings_33;			break;	}	/* Lookup matching access & recovery times */	i = -1;	for (;;) {		if (tm[i+1].cycleTime < cycleTime)			break;		i++;	}	if (i < 0)		return -1;	cycleTime = tm[i].cycleTime;	accessTime = tm[i].accessTime;	recTime = tm[i].recoveryTime;#ifdef IDE_PMAC_DEBUG	printk(KERN_ERR "ide_pmac: MDMA, cycleTime: %d, accessTime: %d, recTime: %d\n",		cycleTime, accessTime, recTime);#endif		if (intf_type == controller_kl_ata4 || intf_type == controller_kl_ata4_80) {		/* 66Mhz cell */		accessTicks = SYSCLK_TICKS_66(accessTime);		accessTicks = min(accessTicks, 0x1fU);		accessTicks = max(accessTicks, 0x1U);		recTicks = SYSCLK_TICKS_66(recTime);		recTicks = min(recTicks, 0x1fU);		recTicks = max(recTicks, 0x3U);		/* Clear out mdma bits and disable udma */		*timings = ((*timings) & ~(TR_66_MDMA_MASK | TR_66_UDMA_MASK)) |			(accessTicks << TR_66_MDMA_ACCESS_SHIFT) |			(recTicks << TR_66_MDMA_RECOVERY_SHIFT);	} else if (intf_type == controller_kl_ata3) {		/* 33Mhz cell on KeyLargo */		accessTicks = SYSCLK_TICKS(accessTime);		accessTicks = max(accessTicks, 1U);		accessTicks = min(accessTicks, 0x1fU);		accessTime = accessTicks * IDE_SYSCLK_NS;		recTicks = SYSCLK_TICKS(recTime);		recTicks = max(recTicks, 1U);		recTicks = min(recTicks, 0x1fU);		*timings = ((*timings) & ~TR_33_MDMA_MASK) |				(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |				(recTicks << TR_33_MDMA_RECOVERY_SHIFT);	} else {		/* 33Mhz cell on others */		int halfTick = 0;		int origAccessTime = accessTime;		int origRecTime = recTime;				accessTicks = SYSCLK_TICKS(accessTime);		accessTicks = max(accessTicks, 1U);		accessTicks = min(accessTicks, 0x1fU);		accessTime = accessTicks * IDE_SYSCLK_NS;		recTicks = SYSCLK_TICKS(recTime);		recTicks = max(recTicks, 2U) - 1;		recTicks = min(recTicks, 0x1fU);		recTime = (recTicks + 1) * IDE_SYSCLK_NS;		if ((accessTicks > 1) &&		    ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&		    ((recTime - IDE_SYSCLK_NS/2) >= origRecTime)) {            		halfTick = 1;			accessTicks--;		}		*timings = ((*timings) & ~TR_33_MDMA_MASK) |				(accessTicks << TR_33_MDMA_ACCESS_SHIFT) |				(recTicks << TR_33_MDMA_RECOVERY_SHIFT);		if (halfTick)			*timings |= TR_33_MDMA_HALFTICK;	}#ifdef IDE_PMAC_DEBUG	printk(KERN_ERR "ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",		speed & 0xf,  *timings);#endif		return 0;}#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC *//* You may notice we don't use this function on normal operation, * our, normal mdma function is supposed to be more precise */static int __pmacpmac_ide_tune_chipset (ide_drive_t *drive, byte speed){	int intf		= pmac_ide_find(drive);	int unit		= (drive->select.b.unit & 0x01);	int ret			= 0;	u32 *timings;	if (intf < 0)		return 1;			timings = &pmac_ide[intf].timings[unit];		switch(speed) {#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC		case XFER_UDMA_4:		case XFER_UDMA_3:			if (pmac_ide[intf].kind != controller_kl_ata4_80)				return 1;				case XFER_UDMA_2:		case XFER_UDMA_1:		case XFER_UDMA_0:			if (pmac_ide[intf].kind != controller_kl_ata4 &&				pmac_ide[intf].kind != controller_kl_ata4_80)				return 1;					ret = set_timings_udma(timings, speed);			break;		case XFER_MW_DMA_2:		case XFER_MW_DMA_1:		case XFER_MW_DMA_0:			ret = set_timings_mdma(pmac_ide[intf].kind, timings, speed, 0);			break;		case XFER_SW_DMA_2:		case XFER_SW_DMA_1:		case XFER_SW_DMA_0:			return 1;#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */		case XFER_PIO_4:		case XFER_PIO_3:		case XFER_PIO_2:		case XFER_PIO_1:		case XFER_PIO_0:			pmac_ide_tuneproc(drive, speed & 0x07);			break;		default:			ret = 1;	}	if (ret)		return ret;	ret = pmac_ide_do_setfeature(drive, speed);	if (ret)		return ret;			pmac_ide_selectproc(drive);		drive->current_speed = speed;	return 0;}static void __pmacsanitize_timings(int i){	unsigned value;		switch(pmac_ide[i].kind) {		case controller_kl_ata4:		case controller_kl_ata4_80:			value = 0x0008438c;			break;		case controller_kl_ata3:			value = 0x00084526;			break;		case controller_heathrow:		case controller_ohare:		default:			value = 0x00074526;			break;	}	pmac_ide[i].timings[0] = pmac_ide[i].timings[1] = value;}ide_ioreg_t __pmacpmac_ide_get_base(int index){	return pmac_ide[index].regbase;}int __pmacpmac_ide_check_base(ide_ioreg_t base){	int ix;	 	for (ix = 0; ix < MAX_HWIFS; ++ix)		if (base == pmac_ide[ix].regbase)			return ix;	return -1;}int __pmacpmac_ide_get_irq(ide_ioreg_t base){	int ix;	for (ix = 0; ix < MAX_HWIFS; ++ix)		if (base == pmac_ide[ix].regbase)			return pmac_ide[ix].irq;	return 0;}static int ide_majors[]  __pmacdata = { 3, 22, 33, 34, 56, 57 };kdev_t __initpmac_find_ide_boot(char *bootdevice, int n){	int i;		/*	 * Look through the list of IDE interfaces for this one.	 */	for (i = 0; i < pmac_ide_count; ++i) {		char *name;		if (!pmac_ide[i].node || !pmac_ide[i].node->full_name)			continue;		name = pmac_ide[i].node->full_name;		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {			/* XXX should cope with the 2nd drive as well... */			return MKDEV(ide_majors[i], 0);		}	}	return 0;}void __initpmac_ide_probe(void){	struct device_node *np;	int i;	struct device_node *atas;	struct device_node *p, **pp, *removables, **rp;	unsigned long base;	int irq, big_delay;	ide_hwif_t *hwif;	if (_machine != _MACH_Pmac)		return;	pp = &atas;	rp = &removables;	p = find_devices("ATA");	if (p == NULL)		p = find_devices("IDE");	if (p == NULL)		p = find_type_devices("ide");	if (p == NULL)		p = find_type_devices("ata");	/* Move removable devices such as the media-bay CDROM	   on the PB3400 to the end of the list. */	for (; p != NULL; p = p->next) {		if (p->parent && p->parent->type		    && strcasecmp(p->parent->type, "media-bay") == 0) {			*rp = p;			rp = &p->next;		} else {			*pp = p;			pp = &p->next;		}	}	*rp = NULL;	*pp = removables;	big_delay = 0;	for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {		struct device_node *tp;		struct pmac_ide_hwif* pmhw;		int *bidp;		int in_bay = 0;		/*		 * If this node is not under a mac-io or dbdma node,		 * leave it to the generic PCI driver.		 */		for (tp = np->parent; tp != 0; tp = tp->parent)			if (tp->type && (strcmp(tp->type, "mac-io") == 0					 || strcmp(tp->type, "dbdma") == 0))				break;		if (tp == 0)			continue;		if (np->n_addrs == 0) {			printk(KERN_WARNING "ide: no address for device %s\n",			       np->full_name);			continue;		}		/*		 * If this slot is taken (e.g. by ide-pci.c) try the next one.		 */		while (i < MAX_HWIFS		       && ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0)			++i;		if (i >= MAX_HWIFS)			break;		pmhw = &pmac_ide[i];		/*		 * Some older OFs have bogus sizes, causing request_OF_resource		 * to fail. We fix them up here		 */		if (np->addrs[0].size > 0x1000)			np->addrs[0].size = 0x1000;		if (np->n_addrs > 1 && np->addrs[1].size > 0x100)			np->addrs[1].size = 0x100;		pmhw->reg_resource = request_OF_resource(np, 0, "  (mac-io IDE IO)");		if (!pmhw->reg_resource) {			printk(KERN_ERR "ide-pmac(%s): can't request IO resource !\n", np->name);			continue;		}		base = (unsigned long) ioremap(np->addrs[0].address, 0x400) - _IO_BASE;		/* XXX This is bogus. Should be fixed in the registry by checking		   the kind of host interrupt controller, a bit like gatwick		   fixes in irq.c		 */		if (np->n_intrs == 0) {			printk(KERN_WARNING "ide: no intrs for device %s, using 13\n",			       np->full_name);			irq = 13;		} else {			irq = np->intrs[0].line;		}		pmhw->regbase = base;		pmhw->irq = irq;		pmhw->node = np;		if (device_is_compatible(np, "keylargo-ata")) {			if (strcmp(np->name, "ata-4") == 0)				pmhw->kind = controller_kl_ata4;			else				pmhw->kind = controller_kl_ata3;		} else if (device_is_compatible(np, "heathrow-ata"))			pmhw->kind = controller_heathrow;		else			pmhw->kind = controller_ohare;		bidp = (int *)get_property(np, "AAPL,bus-id", NULL);		pmhw->aapl_bus_id =  bidp ? *bidp : 0;		if (pmhw->kind == controller_kl_ata4) {			char* cable = get_property(np, "cable-type", NULL);			if (cable && !strncmp(cable, "80-", 3))				pmhw->kind = controller_kl_ata4_80;		}		/* Make sure we have sane timings */		sanitize_timings(i);		if (np->parent && np->parent->name		    && strcasecmp(np->parent->name, "media-bay") == 0) {#ifdef CONFIG_PMAC_PBOOK			media_bay_set_ide_infos(np->parent,base,irq,i);#endif /* CONFIG_PMAC_PBOOK */			in_bay = 1;			if (!bidp)				pmhw->aapl_bus_id = 1;		} else if (pmhw->kind == controller_ohare) {			/* The code below is having trouble on some ohare machines			 * (timing related ?). Until I can put my hand on one of these			 * units, I keep the old way			 */			ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);		} else { 			/* This is necessary to enable IDE when net-booting */			printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",				pmhw->aapl_bus_id);			ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmhw->aapl_bus_id, 1);			ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmhw->aapl_bus_id, 1);			mdelay(10);			ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmhw->aapl_bus_id, 0);			big_delay = 1;		}		hwif = &ide_hwifs[i];		pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));		hwif->chipset = ide_pmac;		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay;		hwif->udma_four = (pmhw->kind == controller_kl_ata4_80);#ifdef CONFIG_PMAC_PBOOK		if (in_bay && check_media_bay_by_base(base, MB_CD) == 0)			hwif->noprobe = 0;#endif /* CONFIG_PMAC_PBOOK */#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC		if (np->n_addrs >= 2) {			/* has a DBDMA controller channel */			pmac_ide_setup_dma(np, i);		}#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */		++i;	}	pmac_ide_count = i;	if (big_delay)		mdelay(IDE_WAKEUP_DELAY_MS);#ifdef CONFIG_PMAC_PBOOK	pmu_register_sleep_notifier(&idepmac_sleep_notifier);#endif /* CONFIG_PMAC_PBOOK */	register_reboot_notifier(&pmac_ide_reboot_notifier);}#ifdef CONFIG_BLK_DEV_IDEDMA_PMACstatic void __init pmac_ide_setup_dma(struct device_node *np, int ix){	pmac_ide[ix].dma_resource = request_OF_resource(np, 1, " (mac-io IDE DMA)");	if (!pmac_ide[ix].dma_resource) {		printk(KERN_ERR "ide-pmac(%s): can't request DMA resource !\n", np->name);		return;	}	pmac_ide[ix].dma_regs =		(volatile struct dbdma_regs*)ioremap(np->addrs[1].address, 0x200);	/*	 * Allocate space for the DBDMA commands.	 * The +2 is +1 for the stop command and +1 to allow for	 * aligning the start address to a multiple of 16 bytes.	 */	pmac_ide[ix].dma_table = (struct dbdma_cmd*)	       kmalloc((MAX_DCMDS + 2) * sizeof(struct dbdma_cmd), GFP_KERNEL);	if (pmac_ide[ix].dma_table == 0) {		printk(KERN_ERR "%s: unable to allocate DMA command list\n",		       ide_hwifs[ix].name);		return;	}	ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO	if (!noautodma)		ide_hwifs[ix].autodma = 1;#endif}/* * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. */static int __pmacpmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr){	struct dbdma_cmd *table, *tstart;	int count = 0;	struct request *rq = HWGROUP(drive)->rq;	struct buffer_head *bh = rq->bh;	unsigned int size, addr;	volatile struct dbdma_regs *dma = pmac_ide[ix].dma_regs;	table = tstart = (struct dbdma_cmd *) DBDMA_ALIGN(pmac_ide[ix].dma_table);#ifdef IDE_PMAC_DEBUG	if (in_le32(&dma->status) & (RUN|ACTIVE))		printk("ide-pmac: channel status not stopped ! (%x)\n",			in_le32(&dma->status));#endif		/* Make sure channel is stopped and all error conditions are clear */	out_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);	while (in_le32(&dma->status) & RUN)		udelay(1);	do {		/*		 * Determine addr and size of next buffer area.  We assume that		 * individual virtual buffers are always composed linearly in		 * physical memory.  For example, we assume that any 8kB buffer		 * is always composed of two adjacent physical 4kB pages rather		 * than two possibly non-adjacent physical 4kB pages.		 */		if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */			addr = virt_to_bus(rq->buffer);			size = rq->nr_sectors << 9;		} else {			/* group sequential buffers into one large buffer */			addr = virt_to_bus(bh->b_data);			size = bh->b_size;			while ((bh = bh->b_reqnext) != NULL) {				if ((addr + size) != virt_to_bus(bh->b_data))					break;				size += bh->b_size;			}		}		/*		 * Fill in the next DBDMA command block.		 * Note that one DBDMA command can transfer		 * at most 65535 bytes.		 */#ifdef IDE_PMAC_DEBUG		if (size & 0x01)			printk("ide-pmac: odd size transfer ! (%d)\n", size);#endif					while (size) {			unsigned int tc = (size < 0xfe00)? size: 0xfe00;			if (++count >= MAX_DCMDS) {				printk(KERN_WARNING "%s: DMA table too small\n",				       drive->name);				return 0; /* revert to PIO for this request */			}			st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE);			st_le16(&table->req_count, tc);			st_le32(&table->phy_addr, addr);			table->cmd_dep = 0;			table->xfer_status = 0;			table->res_count = 0;			addr += tc;			size -= tc;			++table;		}	} while (bh != NULL);	/* convert the last command to an input/output last command */	if (count)		st_le16(&table[-1].command, wr? OUTPUT_LAST: INPUT_LAST);	else		printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);	/* add the stop command to the end of the list */	memset(table, 0, sizeof(struct dbdma_cmd));	out_le16(&table->command, DBDMA_STOP);	out_le32(&dma->cmdptr, virt_to_bus(tstart));	return 1;}static __inline__ unsigned chardma_bits_to_command(unsigned char bits){	if(bits & 0x04)		return XFER_MW_DMA_2;	if(bits & 0x02)		return XFER_MW_DMA_1;	if(bits & 0x01)		return XFER_MW_DMA_0;	return 0;}

⌨️ 快捷键说明

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