📄 ide-iops.c
字号:
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 + -