patch-2.0.34 linux/drivers/block/ide.c
Next file: linux/drivers/block/ide.h
Previous file: linux/drivers/block/ide-cd.c
Back to the patch index
Back to the overall index
- Lines: 152
- Date:
Wed Jun 3 15:17:47 1998
- Orig file:
v2.0.33/linux/drivers/block/ide.c
- Orig date:
Mon Aug 4 11:45:55 1997
diff -u --recursive --new-file v2.0.33/linux/drivers/block/ide.c linux/drivers/block/ide.c
@@ -272,6 +272,7 @@
* acknowledge media change on removable drives
* add work-around for BMI drives
* remove "LBA" from boot messages
+ * Version 5.53.1 add UDMA "CRC retry" support
*
* Some additional driver compile-time options are in ide.h
*
@@ -602,6 +603,11 @@
unsigned long chs_sects = id->cyls * id->heads * id->sectors;
unsigned long _10_percent = chs_sects / 10;
+ /* very large drives (8GB+) may lie about the number of cylinders */
+ if (id->cyls == 16383 && id->heads == 16 && id->sectors == 63 && lba_sects > chs_sects) {
+ id->cyls = lba_sects / (16 * 63); /* correct cyls */
+ return 1; /* lba_capacity is our only option */
+ }
/* perform a rough sanity check on lba_sects: within 10% is "okay" */
if ((lba_sects - chs_sects) < _10_percent)
return 1; /* lba_capacity is good */
@@ -636,6 +642,7 @@
/* Determine capacity, and use LBA if the drive properly supports it */
if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {
if (id->lba_capacity >= capacity) {
+ drive->cyl = id->lba_capacity / (drive->head * drive->sect);
capacity = id->lba_capacity;
drive->select.b.lba = 1;
}
@@ -1043,12 +1050,15 @@
} else {
if (drive->media == ide_disk && (stat & ERR_STAT)) {
/* err has different meaning on cdrom and tape */
- if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
+ if (err == ABRT_ERR) {
+ if (drive->select.b.lba && IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY)
+ return; /* some newer drives don't support WIN_SPECIFY */
+ } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR))
+ ; /* UDMA crc error -- just retry the operation */
+ else if (err & (BBD_ERR | ECC_ERR)) /* retries won't help these */
rq->errors = ERROR_MAX;
else if (err & TRK0_ERR) /* help it find track zero */
rq->errors |= ERROR_RECAL;
- else if (err & MC_ERR)
- drive->special.b.mc = 1;
}
if ((stat & DRQ_STAT) && rq->cmd != WRITE)
try_to_flush_leftover_data(drive);
@@ -2270,7 +2280,7 @@
{
byte args[4], *argbuf = args;
int argsize = 4;
- if (!suser()) return -EACCES;
+ if (!suser() || securelevel > 0) return -EACCES;
if (NULL == (void *) arg) {
err = ide_do_drive_cmd(drive, &rq, ide_wait);
} else if (!(err = verify_area(VERIFY_READ,(void *)arg, 4))) {
@@ -2561,14 +2571,16 @@
drive->head = id->heads;
drive->sect = id->sectors;
}
+
+ /* calculate drive capacity, and select LBA if possible */
+ (void) current_capacity (drive);
+
/* Correct the number of cyls if the bios value is too small */
if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) {
if (drive->cyl > drive->bios_cyl)
drive->bios_cyl = drive->cyl;
}
- (void) current_capacity (drive); /* initialize LBA selection */
-
if (!strncmp(id->model, "BMI ", 4) &&
strstr(id->model, " ENHANCED IDE ") &&
drive->select.b.lba)
@@ -2587,8 +2599,12 @@
drive->special.b.set_multmode = 1;
}
if (drive->autotune != 2 && HWIF(drive)->dmaproc != NULL) {
- if (!(HWIF(drive)->dmaproc(ide_dma_check, drive)))
- printk(", DMA");
+ if (!(HWIF(drive)->dmaproc(ide_dma_check, drive))) {
+ if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7))
+ printk(", UDMA");
+ else
+ printk(", DMA");
+ }
}
printk("\n");
}
@@ -2618,11 +2634,12 @@
{
int hd_status, rc;
unsigned long timeout;
- int irqs = 0;
+ unsigned long irqs_on = 0;
+ int irq_off;
if (!HWIF(drive)->irq) { /* already got an IRQ? */
probe_irq_off(probe_irq_on()); /* clear dangling irqs */
- irqs = probe_irq_on(); /* start monitoring irqs */
+ irqs_on = probe_irq_on(); /* start monitoring irqs */
OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* enable device irq */
}
@@ -2636,8 +2653,8 @@
#if CONFIG_BLK_DEV_PROMISE
if (IS_PROMISE_DRIVE) {
if (promise_cmd(drive,PROMISE_IDENTIFY)) {
- if (irqs)
- (void) probe_irq_off(irqs);
+ if (irqs_on)
+ (void) probe_irq_off(irqs_on);
return 1;
}
} else
@@ -2647,8 +2664,8 @@
timeout += jiffies;
do {
if (jiffies > timeout) {
- if (irqs)
- (void) probe_irq_off(irqs);
+ if (irqs_on)
+ (void) probe_irq_off(irqs_on);
return 1; /* drive timed-out */
}
delay_50ms(); /* give drive a breather */
@@ -2666,18 +2683,18 @@
} else
rc = 2; /* drive refused ID */
if (!HWIF(drive)->irq) {
- irqs = probe_irq_off(irqs); /* get our irq number */
- if (irqs > 0) {
- HWIF(drive)->irq = irqs; /* save it for later */
- irqs = probe_irq_on();
+ irq_off = probe_irq_off(irqs_on); /* get our irq number */
+ if (irq_off > 0) {
+ HWIF(drive)->irq = irq_off; /* save it for later */
+ irqs_on = probe_irq_on();
OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
udelay(5);
- (void) probe_irq_off(irqs);
+ (void) probe_irq_off(irqs_on);
(void) probe_irq_off(probe_irq_on()); /* clear self-inflicted irq */
(void) GET_STAT(); /* clear drive IRQ */
} else { /* Mmmm.. multiple IRQs.. don't know which was ours */
- printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
+ printk("%s: IRQ probe failed (%d)\n", drive->name, irq_off);
#ifdef CONFIG_BLK_DEV_CMD640
#ifdef CMD640_DUMP_REGS
if (HWIF(drive)->chipset == ide_cmd640) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov