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

📄 ide-pmac.c

📁 em85xx的大硬盘修正代码包
💻 C
📖 第 1 页 / 共 3 页
字号:
		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;}ide_ioreg_tpmac_ide_get_base(int index){	return pmac_ide[index].regbase;}intpmac_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[] = { 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;		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;		base = (unsigned long) ioremap(np->addrs[0].address, 0x200) - _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;		}		pmac_ide[i].regbase = base;		pmac_ide[i].irq = irq;		pmac_ide[i].node = np;		if (device_is_compatible(np, "keylargo-ata")) {			if (strcmp(np->name, "ata-4") == 0)				pmac_ide[i].kind = controller_kl_ata4;			else				pmac_ide[i].kind = controller_kl_ata3;		} else if (device_is_compatible(np, "heathrow-ata"))			pmac_ide[i].kind = controller_heathrow;		else			pmac_ide[i].kind = controller_ohare;		bidp = (int *)get_property(np, "AAPL,bus-id", NULL);		pmac_ide[i].aapl_bus_id =  bidp ? *bidp : 0;		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;		} else if (pmac_ide[i].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			 */			 feature_set(np, FEATURE_IDE0_enable);		} else { 			/* This is necessary to enable IDE when net-booting */			printk(KERN_INFO "pmac_ide: enabling IDE bus ID %d\n",				pmac_ide[i].aapl_bus_id);			switch(pmac_ide[i].aapl_bus_id) {			    case 0:				feature_set(np, FEATURE_IDE0_reset);				mdelay(10); 				feature_set(np, FEATURE_IDE0_enable);				mdelay(10);				feature_clear(np, FEATURE_IDE0_reset);				break;			    case 1:				feature_set(np, FEATURE_IDE1_reset);				mdelay(10); 				feature_set(np, FEATURE_IDE1_enable);				mdelay(10);				feature_clear(np, FEATURE_IDE1_reset);				break;			    case 2:			    	/* This one exists only for KL, I don't know				   about any enable bit */				feature_set(np, FEATURE_IDE2_reset);				mdelay(10);				feature_clear(np, FEATURE_IDE2_reset);				break;			}			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;#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 */}#ifdef CONFIG_BLK_DEV_IDEDMA_PMACstatic void __init pmac_ide_setup_dma(struct device_node *np, int ix){	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 intpmac_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);	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.		 */		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;}static __inline__ unsigned charudma_bits_to_command(unsigned char bits){	if(bits & 0x10)		return XFER_UDMA_4;	if(bits & 0x08)		return XFER_UDMA_3;	if(bits & 0x04)		return XFER_UDMA_2;	if(bits & 0x02)		return XFER_UDMA_1;	if(bits & 0x01)		return XFER_UDMA_0;	return 0;}/* Calculate MultiWord DMA timings */static intpmac_ide_mdma_enable(ide_drive_t *drive, int idx){	byte bits = drive->id->dma_mword & 0x07;	byte feature = dma_bits_to_command(bits);	u32 *timings;	int cycleTime, accessTime;	int accessTicks, recTicks;	struct hd_driveid *id = drive->id;	int ret;	/* Set feature on drive */    	printk(KERN_INFO "%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);	ret = pmac_ide_do_setfeature(drive, feature);	if (ret) {	    	printk(KERN_WARNING "%s: Failed !\n", drive->name);	    	return 0;	}	if (!drive->init_speed)		drive->init_speed = feature;		/* which drive is it ? */	if (drive->select.all & 0x10)		timings = &pmac_ide[idx].timings[1];	else		timings = &pmac_ide[idx].timings[0];	/* Calculate accesstime and cycle time */	cycleTime = mdma_timings[feature & 0xf].cycleTime;	accessTime = mdma_timings[feature & 0xf].accessTime;	if ((id->field_valid & 2) && (id->eide_dma_time))		cycleTime = id->eide_dma_time;	if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))		cycleTime = 150;	/* For ata-4 controller */	if (pmac_ide[idx].kind == controller_kl_ata4) {		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;		*timings = ((*timings) & 0xffe003ff) |			(accessTicks | (recTicks << 5)) << 10;	} else {		int halfTick = 0;		int origAccessTime = accessTime;		int origCycleTime = cycleTime;				accessTicks = SYSCLK_TICKS(accessTime);		if (accessTicks < 1)			accessTicks = 1;		accessTime = accessTicks * IDE_SYSCLK_NS;		recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;		if (recTicks < 1)			recTicks = 1;		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;		/* KeyLargo ata-3 don't support the half-tick stuff */		if ((pmac_ide[idx].kind != controller_kl_ata3) &&			(accessTicks > 1) &&			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {            			halfTick    = 1;				accessTicks--;		}		*timings = ((*timings) & 0x7FF) |			(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;

⌨️ 快捷键说明

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