?? ide3.c
字號:
*/void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount){ byte io_32bit; /* first check if this controller has defined a special function * for handling polled ide transfers */ if(HWIF(drive)->ideproc) { HWIF(drive)->ideproc(ideproc_ide_input_data, drive, buffer, wcount); return; } io_32bit = drive->io_32bit; if (io_32bit) {#if SUPPORT_VLB_SYNC if (io_32bit & 2) { unsigned long flags; __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ do_vlb_sync(IDE_NSECTOR_REG); insl(IDE_DATA_REG, buffer, wcount); __restore_flags(flags); /* local CPU only */ } else#endif /* SUPPORT_VLB_SYNC */ insl(IDE_DATA_REG, buffer, wcount); } else {#if SUPPORT_SLOW_DATA_PORTS if (drive->slow) { unsigned short *ptr = (unsigned short *) buffer; while (wcount--) { *ptr++ = inw_p(IDE_DATA_REG); *ptr++ = inw_p(IDE_DATA_REG); } } else#endif /* SUPPORT_SLOW_DATA_PORTS */ insw(IDE_DATA_REG, buffer, wcount<<1); }}/* * This is used for most PIO data transfers *to* the IDE interface */void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount){ byte io_32bit; if(HWIF(drive)->ideproc) { HWIF(drive)->ideproc(ideproc_ide_output_data, drive, buffer, wcount); return; } io_32bit = drive->io_32bit; if (io_32bit) {#if SUPPORT_VLB_SYNC if (io_32bit & 2) { unsigned long flags; __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ do_vlb_sync(IDE_NSECTOR_REG); outsl(IDE_DATA_REG, buffer, wcount); __restore_flags(flags); /* local CPU only */ } else#endif /* SUPPORT_VLB_SYNC */ outsl(IDE_DATA_REG, buffer, wcount); } else {#if SUPPORT_SLOW_DATA_PORTS if (drive->slow) { unsigned short *ptr = (unsigned short *) buffer; while (wcount--) { outw_p(*ptr++, IDE_DATA_REG); outw_p(*ptr++, IDE_DATA_REG); } } else#endif /* SUPPORT_SLOW_DATA_PORTS */ outsw(IDE_DATA_REG, buffer, wcount<<1); }}/* * The following routines are mainly used by the ATAPI drivers. * * These routines will round up any request for an odd number of bytes, * so if an odd bytecount is specified, be sure that there's at least one * extra byte allocated for the buffer. */void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount){ if(HWIF(drive)->ideproc) { HWIF(drive)->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount); return; } ++bytecount;#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) if (MACH_IS_ATARI || MACH_IS_Q40) { /* Atari has a byte-swapped IDE interface */ insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); return; }#endif /* CONFIG_ATARI */ ide_input_data (drive, buffer, bytecount / 4); if ((bytecount & 0x03) >= 2) insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);}void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount){ if(HWIF(drive)->ideproc) { HWIF(drive)->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount); return; } ++bytecount;#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) if (MACH_IS_ATARI || MACH_IS_Q40) { /* Atari has a byte-swapped IDE interface */ outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); return; }#endif /* CONFIG_ATARI */ ide_output_data (drive, buffer, bytecount / 4); if ((bytecount & 0x03) >= 2) outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);}/* * Needed for PCI irq sharing *///static inlineint drive_is_ready (ide_drive_t *drive){ byte stat = 0; if (drive->waiting_for_dma) return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);#if 0 udelay(1); /* need to guarantee 400ns since last command was issued */#endif#ifdef CONFIG_IDEPCI_SHARE_IRQ /* * We do a passive status test under shared PCI interrupts on * cards that truly share the ATA side interrupt, but may also share * an interrupt with another pci card/device. We make no assumptions * about possible isa-pnp and pci-pnp issues yet. */ if (IDE_CONTROL_REG) stat = GET_ALTSTAT(); else#endif /* CONFIG_IDEPCI_SHARE_IRQ */ stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ if (stat & BUSY_STAT) return 0; /* drive busy: definitely not interrupting */ return 1; /* drive ready: *might* be interrupting */}/* * This is our end_request replacement function. */void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup){ struct request *rq; unsigned long flags; ide_drive_t *drive = hwgroup->drive; spin_lock_irqsave(&io_request_lock, flags); rq = hwgroup->rq; /* * decide whether to reenable DMA -- 3 is a random magic for now, * if we DMA timeout more than 3 times, just stay in PIO */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; hwgroup->hwif->dmaproc(ide_dma_on, drive); } if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) { add_blkdev_randomness(MAJOR(rq->rq_dev)); blkdev_dequeue_request(rq); hwgroup->rq = NULL; end_that_request_last(rq); } spin_unlock_irqrestore(&io_request_lock, flags);}/* * 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). */void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry){ unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); spin_lock_irqsave(&io_request_lock, flags); if (hwgroup->handler != NULL) { printk("%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; add_timer(&hwgroup->timer); spin_unlock_irqrestore(&io_request_lock, flags);}/* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. */unsigned long current_capacity (ide_drive_t *drive){ if (!drive->present) return 0; if (drive->driver != NULL) return DRIVER(drive)->capacity(drive); return 0;}extern struct block_device_operations ide_fops[];/* * ide_geninit() is called exactly *once* for each interface. */void ide_geninit (ide_hwif_t *hwif){ unsigned int unit; struct gendisk *gd = hwif->gd; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if (!drive->present) continue; if (drive->media!=ide_disk && drive->media!=ide_floppy) continue; register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS),#ifdef CONFIG_BLK_DEV_ISAPNP (drive->forced_geom && drive->noprobe) ? 1 :#endif /* CONFIG_BLK_DEV_ISAPNP */ 1<<PARTN_BITS, ide_fops, current_capacity(drive)); }}static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below *//* * 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); byte stat; SELECT_DRIVE(HWIF(drive),drive); udelay (10); if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { printk("%s: ATAPI reset complete\n", drive->name); } else { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); return ide_started; /* continue polling */ } hwgroup->poll_timeout = 0; /* end of polling */ printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat); return do_reset1 (drive, 1); /* do it the old fashioned way */ } hwgroup->poll_timeout = 0; /* done polling */ 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); byte tmp; if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); return ide_started; /* continue polling */ } printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); drive->failures++; } else { printk("%s: reset: ", hwif->name); if ((tmp = GET_ERR()) == 1) { printk("success\n"); drive->failures = 0; } else { drive->failures++;#if FANCY_STATUS_DUMPS 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");#else printk("failed\n");#endif /* FANCY_STATUS_DUMPS */ } } hwgroup->poll_timeout = 0; /* done polling */ return ide_stopped;}static void check_dma_crc (ide_drive_t *drive){ if (drive->crc_count) { (void) HWIF(drive)->dmaproc(ide_dma_off_quietly, drive); if ((HWIF(drive)->speedproc) != NULL) HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive)); if (drive->current_speed >= XFER_SW_DMA_0) (void) HWIF(drive)->dmaproc(ide_dma_on, drive); } else { (void) HWIF(drive)->dmaproc(ide_dma_off, drive); }}static void pre_reset (ide_drive_t *drive){ if (drive->driver != NULL) DRIVER(drive)->pre_reset(drive); 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);}/* * 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 = HWIF(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive); __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->media != ide_disk && !do_not_try_atapi) { pre_reset(drive); SELECT_DRIVE(hwif,drive); udelay (20); OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); __restore_flags (flags); /* local CPU only */ return ide_started; } /* * First, reset any device state data we were maintaining * for any of the drives on this interface.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -