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

📄 ide-iops.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	drive->id->dma_mword &= ~0x0F00;	drive->id->dma_1word &= ~0x0F00; skip:#ifdef CONFIG_BLK_DEV_IDEDMA	if (speed >= XFER_SW_DMA_0)		hwif->dma_host_on(drive);	else if (hwif->ide_dma_on)	/* check if host supports DMA */		hwif->dma_off_quietly(drive);#endif	switch(speed) {		case XFER_UDMA_7:   drive->id->dma_ultra |= 0x8080; break;		case XFER_UDMA_6:   drive->id->dma_ultra |= 0x4040; break;		case XFER_UDMA_5:   drive->id->dma_ultra |= 0x2020; break;		case XFER_UDMA_4:   drive->id->dma_ultra |= 0x1010; break;		case XFER_UDMA_3:   drive->id->dma_ultra |= 0x0808; break;		case XFER_UDMA_2:   drive->id->dma_ultra |= 0x0404; break;		case XFER_UDMA_1:   drive->id->dma_ultra |= 0x0202; break;		case XFER_UDMA_0:   drive->id->dma_ultra |= 0x0101; break;		case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break;		case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break;		case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break;		case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break;		case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break;		case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break;		default: break;	}	if (!drive->init_speed)		drive->init_speed = speed;	drive->current_speed = speed;	return error;}/* * This should get invoked any time we exit the driver to * wait for an interrupt response from a drive.  handler() points * at the appropriate code to handle the next interrupt, and a * timer is started to prevent us from waiting forever in case * something goes wrong (see the ide_timer_expiry() handler later on). * * See also ide_execute_command */static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,		      unsigned int timeout, ide_expiry_t *expiry){	ide_hwgroup_t *hwgroup = HWGROUP(drive);	if (hwgroup->handler != NULL) {		printk(KERN_CRIT "%s: ide_set_handler: handler not null; "			"old=%p, new=%p\n",			drive->name, hwgroup->handler, handler);	}	hwgroup->handler	= handler;	hwgroup->expiry		= expiry;	hwgroup->timer.expires	= jiffies + timeout;	hwgroup->req_gen_timer = hwgroup->req_gen;	add_timer(&hwgroup->timer);}void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,		      unsigned int timeout, ide_expiry_t *expiry){	unsigned long flags;	spin_lock_irqsave(&ide_lock, flags);	__ide_set_handler(drive, handler, timeout, expiry);	spin_unlock_irqrestore(&ide_lock, flags);}EXPORT_SYMBOL(ide_set_handler); /** *	ide_execute_command	-	execute an IDE command *	@drive: IDE drive to issue the command against *	@command: command byte to write *	@handler: handler for next phase *	@timeout: timeout for command *	@expiry:  handler to run on timeout * *	Helper function to issue an IDE command. This handles the *	atomicity requirements, command timing and ensures that the  *	handler and IRQ setup do not race. All IDE command kick off *	should go via this function or do equivalent locking. */ void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry){	unsigned long flags;	ide_hwgroup_t *hwgroup = HWGROUP(drive);	ide_hwif_t *hwif = HWIF(drive);		spin_lock_irqsave(&ide_lock, flags);		BUG_ON(hwgroup->handler);	hwgroup->handler	= handler;	hwgroup->expiry		= expiry;	hwgroup->timer.expires	= jiffies + timeout;	hwgroup->req_gen_timer = hwgroup->req_gen;	add_timer(&hwgroup->timer);	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);	/* Drive takes 400nS to respond, we must avoid the IRQ being	   serviced before that. 	   	   FIXME: we could skip this delay with care on non shared	   devices 	*/	ndelay(400);	spin_unlock_irqrestore(&ide_lock, flags);}EXPORT_SYMBOL(ide_execute_command);/* needed below */static ide_startstop_t do_reset1 (ide_drive_t *, int);/* * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms * during an atapi drive reset operation. If the drive has not yet responded, * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive){	ide_hwgroup_t *hwgroup	= HWGROUP(drive);	ide_hwif_t *hwif	= HWIF(drive);	u8 stat;	SELECT_DRIVE(drive);	udelay (10);	if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {		printk("%s: ATAPI reset complete\n", drive->name);	} else {		if (time_before(jiffies, hwgroup->poll_timeout)) {			BUG_ON(HWGROUP(drive)->handler != NULL);			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);			/* continue polling */			return ide_started;		}		/* end of polling */		hwgroup->polling = 0;		printk("%s: ATAPI reset timed-out, status=0x%02x\n",				drive->name, stat);		/* do it the old fashioned way */		return do_reset1(drive, 1);	}	/* done polling */	hwgroup->polling = 0;	hwgroup->resetting = 0;	return ide_stopped;}/* * reset_pollfunc() gets invoked to poll the interface for completion every 50ms * during an ide reset operation. If the drives have not yet responded, * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */static ide_startstop_t reset_pollfunc (ide_drive_t *drive){	ide_hwgroup_t *hwgroup	= HWGROUP(drive);	ide_hwif_t *hwif	= HWIF(drive);	u8 tmp;	if (hwif->reset_poll != NULL) {		if (hwif->reset_poll(drive)) {			printk(KERN_ERR "%s: host reset_poll failure for %s.\n",				hwif->name, drive->name);			return ide_stopped;		}	}	if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {		if (time_before(jiffies, hwgroup->poll_timeout)) {			BUG_ON(HWGROUP(drive)->handler != NULL);			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);			/* continue polling */			return ide_started;		}		printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);		drive->failures++;	} else  {		printk("%s: reset: ", hwif->name);		if ((tmp = hwif->INB(IDE_ERROR_REG)) == 1) {			printk("success\n");			drive->failures = 0;		} else {			drive->failures++;			printk("master: ");			switch (tmp & 0x7f) {				case 1: printk("passed");					break;				case 2: printk("formatter device error");					break;				case 3: printk("sector buffer error");					break;				case 4: printk("ECC circuitry error");					break;				case 5: printk("controlling MPU error");					break;				default:printk("error (0x%02x?)", tmp);			}			if (tmp & 0x80)				printk("; slave: failed");			printk("\n");		}	}	hwgroup->polling = 0;	/* done polling */	hwgroup->resetting = 0; /* done reset attempt */	return ide_stopped;}static void check_dma_crc(ide_drive_t *drive){#ifdef CONFIG_BLK_DEV_IDEDMA	if (drive->crc_count) {		drive->hwif->dma_off_quietly(drive);		ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));		if (drive->current_speed >= XFER_SW_DMA_0)			(void) HWIF(drive)->ide_dma_on(drive);	} else		ide_dma_off(drive);#endif}static void ide_disk_pre_reset(ide_drive_t *drive){	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;	drive->special.all = 0;	drive->special.b.set_geometry = legacy;	drive->special.b.recalibrate  = legacy;	if (OK_TO_RESET_CONTROLLER)		drive->mult_count = 0;	if (!drive->keep_settings && !drive->using_dma)		drive->mult_req = 0;	if (drive->mult_req != drive->mult_count)		drive->special.b.set_multmode = 1;}static void pre_reset(ide_drive_t *drive){	if (drive->media == ide_disk)		ide_disk_pre_reset(drive);	else		drive->post_reset = 1;	if (!drive->keep_settings) {		if (drive->using_dma) {			check_dma_crc(drive);		} else {			drive->unmask = 0;			drive->io_32bit = 0;		}		return;	}	if (drive->using_dma)		check_dma_crc(drive);	if (HWIF(drive)->pre_reset != NULL)		HWIF(drive)->pre_reset(drive);	if (drive->current_speed != 0xff)		drive->desired_speed = drive->current_speed;	drive->current_speed = 0xff;}/* * do_reset1() attempts to recover a confused drive by resetting it. * Unfortunately, resetting a disk drive actually resets all devices on * the same interface, so it can really be thought of as resetting the * interface rather than resetting the drive. * * ATAPI devices have their own reset mechanism which allows them to be * individually reset without clobbering other devices on the same interface. * * Unfortunately, the IDE interface does not generate an interrupt to let * us know when the reset operation has finished, so we must poll for this. * Equally poor, though, is the fact that this may a very long time to complete, * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi){	unsigned int unit;	unsigned long flags;	ide_hwif_t *hwif;	ide_hwgroup_t *hwgroup;		spin_lock_irqsave(&ide_lock, flags);	hwif = HWIF(drive);	hwgroup = HWGROUP(drive);	/* We must not reset with running handlers */	BUG_ON(hwgroup->handler != NULL);	/* For an ATAPI device, first try an ATAPI SRST. */	if (drive->media != ide_disk && !do_not_try_atapi) {		hwgroup->resetting = 1;		pre_reset(drive);		SELECT_DRIVE(drive);		udelay (20);		hwif->OUTBSYNC(drive, WIN_SRST, IDE_COMMAND_REG);		ndelay(400);		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;		hwgroup->polling = 1;		__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);		spin_unlock_irqrestore(&ide_lock, flags);		return ide_started;	}	/*	 * First, reset any device state data we were maintaining	 * for any of the drives on this interface.	 */	for (unit = 0; unit < MAX_DRIVES; ++unit)		pre_reset(&hwif->drives[unit]);#if OK_TO_RESET_CONTROLLER	if (!IDE_CONTROL_REG) {		spin_unlock_irqrestore(&ide_lock, flags);		return ide_stopped;	}	hwgroup->resetting = 1;	/*	 * Note that we also set nIEN while resetting the device,	 * to mask unwanted interrupts from the interface during the reset.	 * However, due to the design of PC hardware, this will cause an	 * immediate interrupt due to the edge transition it produces.	 * This single interrupt gives us a "fast poll" for drives that	 * recover from reset very quickly, saving us the first 50ms wait time.	 */	/* set SRST and nIEN */	hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG);	/* more than enough time */	udelay(10);	if (drive->quirk_list == 2) {		/* clear SRST and nIEN */		hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG);	} else {		/* clear SRST, leave nIEN */		hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG);	}	/* more than enough time */	udelay(10);	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;	hwgroup->polling = 1;	__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);	/*	 * Some weird controller like resetting themselves to a strange	 * state when the disks are reset this way. At least, the Winbond	 * 553 documentation says that	 */	if (hwif->resetproc != NULL) {		hwif->resetproc(drive);	}	#endif	/* OK_TO_RESET_CONTROLLER */	spin_unlock_irqrestore(&ide_lock, flags);	return ide_started;}/* * ide_do_reset() is the entry point to the drive/interface reset code. */ide_startstop_t ide_do_reset (ide_drive_t *drive){	return do_reset1(drive, 0);}EXPORT_SYMBOL(ide_do_reset);/* * ide_wait_not_busy() waits for the currently selected device on the hwif * to report a non-busy status, see comments in probe_hwif(). */int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout){	u8 stat = 0;	while(timeout--) {		/*		 * Turn this into a schedule() sleep once I'm sure		 * about locking issues (2.5 work ?).		 */		mdelay(1);		stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);		if ((stat & BUSY_STAT) == 0)			return 0;		/*		 * Assume a value of 0xff means nothing is connected to		 * the interface and it doesn't implement the pull-down		 * resistor on D7.		 */		if (stat == 0xff)			return -ENODEV;		touch_softlockup_watchdog();		touch_nmi_watchdog();	}	return -EBUSY;}EXPORT_SYMBOL_GPL(ide_wait_not_busy);

⌨️ 快捷键说明

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