patch-2.3.99-pre1 linux/drivers/block/ide-features.c
Next file: linux/drivers/block/ide-floppy.c
Previous file: linux/drivers/block/ide-dma.c
Back to the patch index
Back to the overall index
- Lines: 313
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.3.51/linux/drivers/block/ide-features.c
- Orig date:
Sat Feb 26 22:31:43 2000
diff -u --recursive --new-file v2.3.51/linux/drivers/block/ide-features.c linux/drivers/block/ide-features.c
@@ -1,312 +0,0 @@
-/*
- * linux/drivers/block/ide-features.c Version 0.03 Feb. 10, 2000
- *
- * Copyright (C) 1999-2000 Linus Torvalds & authors (see below)
- *
- * Copyright (C) 1999-2000 Andre Hedrick <andre@suse.com>
- *
- * Extracts if ide.c to address the evolving transfer rate code for
- * the SETFEATURES_XFER callouts. Various parts of any given function
- * are credited to previous ATA-IDE maintainers.
- *
- * May be copied or modified under the terms of the GNU General Public License
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/genhd.h>
-#include <linux/blkpg.h>
-#include <linux/malloc.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-
-#define SETFEATURES_CONTROL_REG (0) /* some arch's may need */
-
-/*
- * A Verbose noise maker for debugging on the attempted transfer rates.
- */
-char *ide_xfer_verbose (byte xfer_rate)
-{
- switch(xfer_rate) {
- case XFER_UDMA_7: return("UDMA 7");
- case XFER_UDMA_6: return("UDMA 6");
- case XFER_UDMA_5: return("UDMA 5");
- case XFER_UDMA_4: return("UDMA 4");
- case XFER_UDMA_3: return("UDMA 3");
- case XFER_UDMA_2: return("UDMA 2");
- case XFER_UDMA_1: return("UDMA 1");
- case XFER_UDMA_0: return("UDMA 0");
- case XFER_MW_DMA_2: return("MW DMA 2");
- case XFER_MW_DMA_1: return("MW DMA 1");
- case XFER_MW_DMA_0: return("MW DMA 0");
- case XFER_SW_DMA_2: return("SW DMA 2");
- case XFER_SW_DMA_1: return("SW DMA 1");
- case XFER_SW_DMA_0: return("SW DMA 0");
- case XFER_PIO_4: return("PIO 4");
- case XFER_PIO_3: return("PIO 3");
- case XFER_PIO_2: return("PIO 2");
- case XFER_PIO_1: return("PIO 1");
- case XFER_PIO_0: return("PIO 0");
- case XFER_PIO_SLOW: return("PIO SLOW");
- default: return("XFER ERROR");
- }
-}
-
-/*
- *
- */
-char *ide_media_verbose (ide_drive_t *drive)
-{
- switch (drive->media) {
- case ide_scsi: return("scsi ");
- case ide_disk: return("disk ");
- case ide_optical: return("optical");
- case ide_cdrom: return("cdrom ");
- case ide_tape: return("tape ");
- case ide_floppy: return("floppy ");
- default: return("???????");
- }
-}
-
-/*
- * A Verbose noise maker for debugging on the attempted dmaing calls.
- */
-char *ide_dmafunc_verbose (ide_dma_action_t dmafunc)
-{
- switch (dmafunc) {
- case ide_dma_read: return("ide_dma_read");
- case ide_dma_write: return("ide_dma_write");
- case ide_dma_begin: return("ide_dma_begin");
- case ide_dma_end: return("ide_dma_end:");
- case ide_dma_check: return("ide_dma_check");
- case ide_dma_on: return("ide_dma_on");
- case ide_dma_off: return("ide_dma_off");
- case ide_dma_off_quietly: return("ide_dma_off_quietly");
- case ide_dma_test_irq: return("ide_dma_test_irq");
- case ide_dma_bad_drive: return("ide_dma_bad_drive");
- case ide_dma_good_drive: return("ide_dma_good_drive");
- case ide_dma_lostirq: return("ide_dma_lostirq");
- case ide_dma_timeout: return("ide_dma_timeout");
- default: return("unknown");
- }
-}
-
-/*
- * Update the
- */
-int ide_driveid_update (ide_drive_t *drive)
-{
- /*
- * Re-read drive->id for possible DMA mode
- * change (copied from ide-probe.c)
- */
- struct hd_driveid *id;
- unsigned long timeout, irqs, flags;
-
- probe_irq_off(probe_irq_on());
- irqs = probe_irq_on();
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
- ide_delay_50ms();
- OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG);
- timeout = jiffies + WAIT_WORSTCASE;
- do {
- if (0 < (signed long)(jiffies - timeout)) {
- if (irqs)
- (void) probe_irq_off(irqs);
- return 0; /* drive timed-out */
- }
- ide_delay_50ms(); /* give drive a breather */
- } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
- ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
- if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
- return 0;
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only; some systems need this */
- id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
- ide_input_data(drive, id, SECTOR_WORDS);
- (void) GET_STAT(); /* clear drive IRQ */
- ide__sti(); /* local CPU only */
- __restore_flags(flags); /* local CPU only */
- ide_fix_driveid(id);
- if (id && id->cyls) {
- drive->id->dma_ultra = id->dma_ultra;
- drive->id->dma_mword = id->dma_mword;
- drive->id->dma_1word = id->dma_1word;
- /* anything more ? */
-#ifdef DEBUG
- printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
- drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
-#endif
- kfree(id);
- }
- return 1;
-}
-
-/*
- * Verify that we are doing an approved SETFEATURES_XFER with respect
- * to the hardware being able to support request. Since some hardware
- * can improperly report capabilties, we check to see if the host adapter
- * in combination with the device (usually a disk) properly detect
- * and acknowledge each end of the ribbon.
- */
-int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
-{
- if ((cmd == WIN_SETFEATURES) &&
- (nsect > XFER_UDMA_2) &&
- (feature == SETFEATURES_XFER)) {
- if (!HWIF(drive)->udma_four) {
- printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name);
- return 1;
- }
- if ((drive->id->hw_config & 0x2000) == 0) {
- printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
- * 1 : Safe to update drive->id DMA registers.
- * 0 : OOPs not allowed.
- */
-int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature)
-{
- struct hd_driveid *id = drive->id;
-
- if ((cmd == WIN_SETFEATURES) &&
- (nsect >= XFER_SW_DMA_0) &&
- (feature == SETFEATURES_XFER) &&
- (id->dma_ultra || id->dma_mword || id->dma_1word))
- return 1;
- return 0;
-}
-
-/*
- * Similar to ide_wait_stat(), except it never calls ide_error internally.
- * This is a kludge to handle the new ide_config_drive_speed() function,
- * and should not otherwise be used anywhere. Eventually, the tuneproc's
- * should be updated to return ide_startstop_t, in which case we can get
- * rid of this abomination again. :) -ml
- *
- * It is gone..........
- *
- * const char *msg == consider adding for verbose errors.
- */
-int ide_config_drive_speed (ide_drive_t *drive, byte speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
- int i, error = 1;
- byte unit = (drive->select.b.unit & 0x01);
- byte stat;
-
- /*
- * Don't use ide_wait_cmd here - it will
- * attempt to set_geometry and recalibrate,
- * but for some reason these don't work at
- * this point (lost interrupt).
- */
- /*
- * Select the drive, and issue the SETFEATURES command
- */
- disable_irq(hwif->irq); /* disable_irq_nosync ?? */
- udelay(1);
- SELECT_DRIVE(HWIF(drive), drive);
- udelay(1);
- if (IDE_CONTROL_REG)
- OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
- OUT_BYTE(speed, IDE_NSECTOR_REG);
- OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
- OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
- if ((IDE_CONTROL_REG) && (SETFEATURES_CONTROL_REG))
- OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
- udelay(1);
- /*
- * Wait for drive to become non-BUSY
- */
- if ((stat = GET_STAT()) & BUSY_STAT) {
- unsigned long flags, timeout;
- __save_flags(flags); /* local CPU only */
- ide__sti(); /* local CPU only -- for jiffies */
- timeout = jiffies + WAIT_CMD;
- while ((stat = GET_STAT()) & BUSY_STAT) {
- if (0 < (signed long)(jiffies - timeout))
- break;
- }
- __restore_flags(flags); /* local CPU only */
- }
-
- /*
- * Allow status to settle, then read it again.
- * A few rare drives vastly violate the 400ns spec here,
- * so we'll wait up to 10usec for a "good" status
- * rather than expensively fail things immediately.
- * This fix courtesy of Matthew Faupel & Niccolo Rigacci.
- */
- for (i = 0; i < 10; i++) {
- udelay(1);
- if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) {
- error = 0;
- break;
- }
- }
-
- enable_irq(hwif->irq);
-
- if (error) {
- (void) ide_dump_status(drive, "set_drive_speed_status", stat);
- return error;
- }
-
- drive->id->dma_ultra &= ~0xFF00;
- drive->id->dma_mword &= ~0x0F00;
- drive->id->dma_1word &= ~0x0F00;
-
- if (speed > XFER_PIO_4) {
- outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2);
- } else {
- outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2);
- }
-
- 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;
- }
- return error;
-}
-
-EXPORT_SYMBOL(ide_driveid_update);
-EXPORT_SYMBOL(ide_ata66_check);
-EXPORT_SYMBOL(set_transfer);
-EXPORT_SYMBOL(ide_config_drive_speed);
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)