Commit e355932d authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bart.bkbits.net/ide-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents eb25b5b2 11b005b5
......@@ -423,7 +423,7 @@ static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
drive->name, dma_stat);
}
return DRIVER(drive)->error(drive, __FUNCTION__, stat);
return ide_error(drive, __FUNCTION__, stat);
}
static int icside_dma_setup(ide_drive_t *drive)
......
......@@ -773,7 +773,7 @@ static ide_startstop_t etrax_dma_intr (ide_drive_t *drive)
}
printk("%s: bad DMA status\n", drive->name);
}
return DRIVER(drive)->error(drive, "dma_intr", stat);
return ide_error(drive, "dma_intr", stat);
}
/*
......
......@@ -559,62 +559,6 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
/*
* ide_error() takes action based on the error returned by the drive.
*/
static ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat)
{
struct request *rq;
byte err;
err = ide_dump_atapi_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
/* add decoding error stuff */
}
if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX) {
DRIVER(drive)->end_request(drive, 0, 0);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
++rq->errors;
}
return ide_stopped;
}
static ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg)
{
struct request *rq;
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
rq->errors |= ERROR_RESET;
DRIVER(drive)->end_request(drive, 0, 0);
return ide_stopped;
}
static void cdrom_end_request (ide_drive_t *drive, int uptodate)
{
struct request *rq = HWGROUP(drive)->rq;
......@@ -690,7 +634,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
rq->flags |= REQ_FAILED;
cdrom_end_request(drive, 0);
DRIVER(drive)->error(drive, "request sense failure", stat);
ide_error(drive, "request sense failure", stat);
return 1;
} else if (rq->flags & (REQ_PC | REQ_BLOCK_PC)) {
......@@ -801,7 +745,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
} else if ((err & ~ABRT_ERR) != 0) {
/* Go to the default handler
for other errors. */
DRIVER(drive)->error(drive, "cdrom_decode_status",stat);
ide_error(drive, "cdrom_decode_status", stat);
return 1;
} else if ((++rq->errors > ERROR_MAX)) {
/* We've racked up too many retries. Abort. */
......@@ -1070,7 +1014,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
ide_end_request(drive, 1, rq->nr_sectors);
return ide_stopped;
} else
return DRIVER(drive)->error(drive, "dma error", stat);
return ide_error(drive, "dma error", stat);
}
/* Read the interrupt reason and the transfer length. */
......@@ -1673,7 +1617,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (dma_error) {
printk("ide-cd: dma error\n");
__ide_dma_off(drive);
return DRIVER(drive)->error(drive, "dma error", stat);
return ide_error(drive, "dma error", stat);
}
end_that_request_chunk(rq, 1, rq->data_len);
......@@ -1811,7 +1755,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
*/
if (dma) {
if (dma_error)
return DRIVER(drive)->error(drive, "dma error", stat);
return ide_error(drive, "dma error", stat);
ide_end_request(drive, 1, rq->nr_sectors);
return ide_stopped;
......@@ -3369,9 +3313,6 @@ static ide_driver_t ide_cdrom_driver = {
.supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom,
.sense = ide_dump_atapi_status,
.error = ide_cdrom_error,
.abort = ide_cdrom_abort,
.capacity = ide_cdrom_capacity,
.attach = ide_cdrom_attach,
.drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
......
......@@ -287,189 +287,6 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
return __ide_do_rw_disk(drive, rq, block);
}
static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
u8 err = 0;
local_irq_set(flags);
printk("%s: %s: status=0x%02x", drive->name, msg, stat);
printk(" { ");
if (stat & BUSY_STAT)
printk("Busy ");
else {
if (stat & READY_STAT) printk("DriveReady ");
if (stat & WRERR_STAT) printk("DeviceFault ");
if (stat & SEEK_STAT) printk("SeekComplete ");
if (stat & DRQ_STAT) printk("DataRequest ");
if (stat & ECC_STAT) printk("CorrectedError ");
if (stat & INDEX_STAT) printk("Index ");
if (stat & ERR_STAT) printk("Error ");
}
printk("}");
printk("\n");
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
err = hwif->INB(IDE_ERROR_REG);
printk("%s: %s: error=0x%02x", drive->name, msg, err);
printk(" { ");
if (err & ABRT_ERR) printk("DriveStatusError ");
if (err & ICRC_ERR)
printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector");
if (err & ECC_ERR) printk("UncorrectableError ");
if (err & ID_ERR) printk("SectorIdNotFound ");
if (err & TRK0_ERR) printk("TrackZeroNotFound ");
if (err & MARK_ERR) printk("AddrMarkNotFound ");
printk("}");
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
(err & (ECC_ERR|ID_ERR|MARK_ERR))) {
if (drive->addressing == 1) {
__u64 sectors = 0;
u32 low = 0, high = 0;
low = ide_read_24(drive);
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
high = ide_read_24(drive);
sectors = ((__u64)high << 24) | low;
printk(", LBAsect=%llu, high=%d, low=%d",
(unsigned long long) sectors,
high, low);
} else {
u8 cur = hwif->INB(IDE_SELECT_REG);
if (cur & 0x40) { /* using LBA? */
printk(", LBAsect=%ld", (unsigned long)
((cur&0xf)<<24)
|(hwif->INB(IDE_HCYL_REG)<<16)
|(hwif->INB(IDE_LCYL_REG)<<8)
| hwif->INB(IDE_SECTOR_REG));
} else {
printk(", CHS=%d/%d/%d",
(hwif->INB(IDE_HCYL_REG)<<8) +
hwif->INB(IDE_LCYL_REG),
cur & 0xf,
hwif->INB(IDE_SECTOR_REG));
}
}
if (HWGROUP(drive) && HWGROUP(drive)->rq)
printk(", sector=%llu",
(unsigned long long)HWGROUP(drive)->rq->sector);
}
}
printk("\n");
{
struct request *rq;
unsigned char opcode = 0;
int found = 0;
spin_lock(&ide_lock);
rq = HWGROUP(drive)->rq;
spin_unlock(&ide_lock);
if (!rq)
goto out;
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
char *args = rq->buffer;
if (args) {
opcode = args[0];
found = 1;
}
} else if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
if (args) {
task_struct_t *tf = (task_struct_t *) args->tfRegister;
opcode = tf->command;
found = 1;
}
}
printk("ide: failed opcode was: ");
if (!found)
printk("unknown\n");
else
printk("0x%02x\n", opcode);
}
out:
local_irq_restore(flags);
return err;
}
static ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif;
struct request *rq;
u8 err;
err = idedisk_dump_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
hwif = HWIF(drive);
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else if (stat & ERR_STAT) {
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */
hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
drive->crc_count++;
} 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;
}
}
if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
try_to_flush_leftover_data(drive);
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
}
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
DRIVER(drive)->end_request(drive, 0, 0);
else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
return ide_stopped;
}
static ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg)
{
ide_hwif_t *hwif;
struct request *rq;
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
hwif = HWIF(drive);
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
DRIVER(drive)->end_request(drive, 0, 0);
return ide_stopped;
}
/*
* Queries for true maximum capacity of the drive.
* Returns maximum LBA address (> 0) of the drive, 0 if failed.
......@@ -1358,9 +1175,6 @@ static ide_driver_t idedisk_driver = {
.supports_dsc_overlap = 0,
.cleanup = idedisk_cleanup,
.do_request = ide_do_rw_disk,
.sense = idedisk_dump_status,
.error = idedisk_error,
.abort = idedisk_abort,
.pre_reset = idedisk_pre_reset,
.capacity = idedisk_capacity,
.special = idedisk_special,
......@@ -1434,7 +1248,7 @@ static int idedisk_media_changed(struct gendisk *disk)
static int idedisk_revalidate_disk(struct gendisk *disk)
{
ide_drive_t *drive = disk->private_data;
set_capacity(disk, current_capacity(drive));
set_capacity(disk, idedisk_capacity(drive));
return 0;
}
......@@ -1478,7 +1292,7 @@ static int idedisk_attach(ide_drive_t *drive)
strcpy(g->devfs_name, drive->devfs_name);
g->driverfs_dev = &drive->gendev;
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
set_capacity(g, current_capacity(drive));
set_capacity(g, idedisk_capacity(drive));
g->fops = &idedisk_ops;
add_disk(g);
return 0;
......
......@@ -116,7 +116,6 @@ static const struct drive_list_entry drive_blacklist [] = {
{ "Compaq CRD-8241B" , "ALL" },
{ "CRD-8400B" , "ALL" },
{ "CRD-8480B", "ALL" },
{ "CRD-8480C", "ALL" },
{ "CRD-8482B", "ALL" },
{ "CRD-84" , "ALL" },
{ "SanDisk SDP3B" , "ALL" },
......@@ -184,7 +183,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
drive->name, dma_stat);
}
return DRIVER(drive)->error(drive, "dma_intr", stat);
return ide_error(drive, "dma_intr", stat);
}
EXPORT_SYMBOL_GPL(ide_dma_intr);
......
......@@ -1640,7 +1640,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
}
/*
* Return the current floppy capacity to ide.c.
* Return the current floppy capacity.
*/
static sector_t idefloppy_capacity (ide_drive_t *drive)
{
......@@ -2034,7 +2034,7 @@ static int idefloppy_media_changed(struct gendisk *disk)
static int idefloppy_revalidate_disk(struct gendisk *disk)
{
ide_drive_t *drive = disk->private_data;
set_capacity(disk, current_capacity(drive));
set_capacity(disk, idefloppy_capacity(drive));
return 0;
}
......
......@@ -454,9 +454,88 @@ void try_to_flush_leftover_data (ide_drive_t *drive)
EXPORT_SYMBOL(try_to_flush_leftover_data);
/*
* FIXME Add an ATAPI error
*/
static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else if (stat & ERR_STAT) {
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
/* some newer drives don't support WIN_SPECIFY */
hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
/* UDMA crc error, just retry the operation */
drive->crc_count++;
} 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;
}
}
if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
try_to_flush_leftover_data(drive);
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
drive->driver->end_request(drive, 0, 0);
else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
return ide_stopped;
}
static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
rq->errors |= ERROR_RESET;
} else {
/* add decoding error stuff */
}
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX) {
drive->driver->end_request(drive, 0, 0);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
++rq->errors;
}
return ide_stopped;
}
ide_startstop_t
__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
if (drive->media == ide_disk)
return ide_ata_error(drive, rq, stat, err);
return ide_atapi_error(drive, rq, stat, err);
}
/**
* ide_error - handle an error on the IDE
......@@ -473,73 +552,32 @@ EXPORT_SYMBOL(try_to_flush_leftover_data);
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif;
struct request *rq;
u8 err;
err = ide_dump_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
hwif = HWIF(drive);
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (rq->flags & REQ_DRIVE_TASKFILE) {
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) {
/* other bits are useless when BUSY */
return drive->driver->error(drive, rq, stat, err);
}
EXPORT_SYMBOL_GPL(ide_error);
ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
{
if (drive->media != ide_disk)
rq->errors |= ERROR_RESET;
} else {
if (drive->media != ide_disk)
goto media_out;
if (stat & ERR_STAT) {
/* err has different meaning on cdrom and tape */
if (err == ABRT_ERR) {
if (drive->select.b.lba &&
(hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY))
/* some newer drives don't
* support WIN_SPECIFY
*/
return ide_stopped;
} else if ((err & BAD_CRC) == BAD_CRC) {
drive->crc_count++;
/* 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;
}
}
media_out:
if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE)
try_to_flush_leftover_data(drive);
}
if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) {
/* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
}
if (rq->errors >= ERROR_MAX) {
DRIVER(drive)->end_request(drive, 0, 0);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
return ide_do_reset(drive);
}
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
drive->special.b.recalibrate = 1;
++rq->errors;
}
DRIVER(drive)->end_request(drive, 0, 0);
return ide_stopped;
}
......@@ -559,28 +597,19 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
{
ide_hwif_t *hwif;
struct request *rq;
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
hwif = HWIF(drive);
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
if (rq->flags & REQ_DRIVE_TASKFILE) {
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
rq->errors |= ERROR_RESET;
DRIVER(drive)->end_request(drive, 0, 0);
return ide_stopped;
return drive->driver->abort(drive, rq);
}
/**
......@@ -634,7 +663,7 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
}
if (!OK_STAT(stat, READY_STAT, BAD_STAT) && DRIVER(drive) != NULL)
return DRIVER(drive)->error(drive, "drive_cmd", stat);
return ide_error(drive, "drive_cmd", stat);
/* calls ide_end_drive_cmd */
ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
return ide_stopped;
......@@ -1181,7 +1210,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
if (error < 0) {
printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
(void)HWIF(drive)->ide_dma_end(drive);
ret = DRIVER(drive)->error(drive, "dma timeout error",
ret = ide_error(drive, "dma timeout error",
hwif->INB(IDE_STATUS_REG));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
......@@ -1212,7 +1241,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
rq->sector = rq->bio->bi_sector;
rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
rq->hard_cur_sectors = rq->current_nr_sectors;
rq->buffer = NULL;
rq->buffer = bio_data(rq->bio);
out:
return ret;
}
......@@ -1304,7 +1333,7 @@ void ide_timer_expiry (unsigned long data)
startstop = ide_dma_timeout_retry(drive, wait);
} else
startstop =
DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
ide_error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
}
drive->service_time = jiffies - drive->service_start;
spin_lock_irq(&ide_lock);
......
......@@ -576,7 +576,7 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b
break;
local_irq_restore(flags);
*startstop = DRIVER(drive)->error(drive, "status timeout", stat);
*startstop = ide_error(drive, "status timeout", stat);
return 1;
}
}
......@@ -594,7 +594,7 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b
if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad))
return 0;
}
*startstop = DRIVER(drive)->error(drive, "status error", stat);
*startstop = ide_error(drive, "status error", stat);
return 1;
}
......
......@@ -445,6 +445,114 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
static void ide_dump_opcode(ide_drive_t *drive)
{
struct request *rq;
u8 opcode = 0;
int found = 0;
spin_lock(&ide_lock);
rq = NULL;
if (HWGROUP(drive))
rq = HWGROUP(drive)->rq;
spin_unlock(&ide_lock);
if (!rq)
return;
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
char *args = rq->buffer;
if (args) {
opcode = args[0];
found = 1;
}
} else if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
if (args) {
task_struct_t *tf = (task_struct_t *) args->tfRegister;
opcode = tf->command;
found = 1;
}
}
printk("ide: failed opcode was: ");
if (!found)
printk("unknown\n");
else
printk("0x%02x\n", opcode);
}
static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
u8 err = 0;
local_irq_set(flags);
printk("%s: %s: status=0x%02x", drive->name, msg, stat);
printk(" { ");
if (stat & BUSY_STAT)
printk("Busy ");
else {
if (stat & READY_STAT) printk("DriveReady ");
if (stat & WRERR_STAT) printk("DeviceFault ");
if (stat & SEEK_STAT) printk("SeekComplete ");
if (stat & DRQ_STAT) printk("DataRequest ");
if (stat & ECC_STAT) printk("CorrectedError ");
if (stat & INDEX_STAT) printk("Index ");
if (stat & ERR_STAT) printk("Error ");
}
printk("}");
printk("\n");
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
err = hwif->INB(IDE_ERROR_REG);
printk("%s: %s: error=0x%02x", drive->name, msg, err);
printk(" { ");
if (err & ABRT_ERR) printk("DriveStatusError ");
if (err & ICRC_ERR)
printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector");
if (err & ECC_ERR) printk("UncorrectableError ");
if (err & ID_ERR) printk("SectorIdNotFound ");
if (err & TRK0_ERR) printk("TrackZeroNotFound ");
if (err & MARK_ERR) printk("AddrMarkNotFound ");
printk("}");
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
(err & (ECC_ERR|ID_ERR|MARK_ERR))) {
if (drive->addressing == 1) {
__u64 sectors = 0;
u32 low = 0, high = 0;
low = ide_read_24(drive);
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
high = ide_read_24(drive);
sectors = ((__u64)high << 24) | low;
printk(", LBAsect=%llu, high=%d, low=%d",
(unsigned long long) sectors,
high, low);
} else {
u8 cur = hwif->INB(IDE_SELECT_REG);
if (cur & 0x40) { /* using LBA? */
printk(", LBAsect=%ld", (unsigned long)
((cur&0xf)<<24)
|(hwif->INB(IDE_HCYL_REG)<<16)
|(hwif->INB(IDE_LCYL_REG)<<8)
| hwif->INB(IDE_SECTOR_REG));
} else {
printk(", CHS=%d/%d/%d",
(hwif->INB(IDE_HCYL_REG)<<8) +
hwif->INB(IDE_LCYL_REG),
cur & 0xf,
hwif->INB(IDE_SECTOR_REG));
}
}
if (HWGROUP(drive) && HWGROUP(drive)->rq)
printk(", sector=%llu",
(unsigned long long)HWGROUP(drive)->rq->sector);
}
}
printk("\n");
ide_dump_opcode(drive);
local_irq_restore(flags);
return err;
}
/**
* ide_dump_atapi_status - print human readable atapi status
* @drive: drive that status applies to
......@@ -453,7 +561,8 @@ EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
*
* Error reporting, in human readable form (luxurious, but a memory hog).
*/
byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
{
unsigned long flags;
......@@ -488,8 +597,27 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
error.b.sense_key);
printk("\n");
}
ide_dump_opcode(drive);
local_irq_restore(flags);
return error.all;
}
EXPORT_SYMBOL(ide_dump_atapi_status);
/**
* ide_dump_status - translate ATA/ATAPI error
* @drive: drive the error occured on
* @msg: information string
* @stat: status byte
*
* Error reporting, in human readable form (luxurious, but a memory hog).
* Combines the drive name, message and status byte to provide a
* user understandable explanation of the device error.
*/
u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
{
if (drive->media == ide_disk)
return ide_dump_ata_status(drive, msg, stat);
return ide_dump_atapi_status(drive, msg, stat);
}
EXPORT_SYMBOL(ide_dump_status);
......@@ -199,7 +199,7 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
return ide_stopped;
if (stat & (ERR_STAT|DRQ_STAT))
return DRIVER(drive)->error(drive, "set_geometry_intr", stat);
return ide_error(drive, "set_geometry_intr", stat);
if (HWGROUP(drive)->handler != NULL)
BUG();
......@@ -218,7 +218,7 @@ ide_startstop_t recal_intr (ide_drive_t *drive)
u8 stat;
if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT))
return DRIVER(drive)->error(drive, "recal_intr", stat);
return ide_error(drive, "recal_intr", stat);
return ide_stopped;
}
......@@ -235,7 +235,7 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive)
local_irq_enable();
if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
return DRIVER(drive)->error(drive, "task_no_data_intr", stat);
return ide_error(drive, "task_no_data_intr", stat);
/* calls ide_end_drive_cmd */
}
if (args)
......@@ -363,7 +363,7 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
if (sectors > 0)
drive->driver->end_request(drive, 1, sectors);
}
return drive->driver->error(drive, s, stat);
return ide_error(drive, s, stat);
}
static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
......
......@@ -358,137 +358,6 @@ int ide_system_bus_speed (void)
return system_bus_speed;
}
/**
* current_capacity - drive capacity
* @drive: drive to query
*
* Return the current capacity (in sectors) of a drive according to
* its current geometry/LBA settings. Empty removables are reported
* as size zero.
*/
sector_t current_capacity (ide_drive_t *drive)
{
if (!drive->present)
return 0;
return DRIVER(drive)->capacity(drive);
}
EXPORT_SYMBOL(current_capacity);
/**
* ide_dump_status - translate ATA error
* @drive: drive the error occured on
* @msg: information string
* @stat: status byte
*
* Error reporting, in human readable form (luxurious, but a memory hog).
* Combines the drive name, message and status byte to provide a
* user understandable explanation of the device error.
*/
u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
u8 err = 0;
local_irq_set(flags);
printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat);
printk(" { ");
if (stat & BUSY_STAT) {
printk("Busy ");
} else {
if (stat & READY_STAT) printk("DriveReady ");
if (stat & WRERR_STAT) printk("DeviceFault ");
if (stat & SEEK_STAT) printk("SeekComplete ");
if (stat & DRQ_STAT) printk("DataRequest ");
if (stat & ECC_STAT) printk("CorrectedError ");
if (stat & INDEX_STAT) printk("Index ");
if (stat & ERR_STAT) printk("Error ");
}
printk("}");
printk("\n");
if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
err = hwif->INB(IDE_ERROR_REG);
printk("%s: %s: error=0x%02x", drive->name, msg, err);
if (drive->media == ide_disk) {
printk(" { ");
if (err & ABRT_ERR) printk("DriveStatusError ");
if (err & ICRC_ERR) printk("Bad%s ", (err & ABRT_ERR) ? "CRC" : "Sector");
if (err & ECC_ERR) printk("UncorrectableError ");
if (err & ID_ERR) printk("SectorIdNotFound ");
if (err & TRK0_ERR) printk("TrackZeroNotFound ");
if (err & MARK_ERR) printk("AddrMarkNotFound ");
printk("}");
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
if ((drive->id->command_set_2 & 0x0400) &&
(drive->id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1)) {
u64 sectors = 0;
u32 high = 0;
u32 low = ide_read_24(drive);
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
high = ide_read_24(drive);
sectors = ((u64)high << 24) | low;
printk(", LBAsect=%llu, high=%d, low=%d",
(long long) sectors,
high, low);
} else {
u8 cur = hwif->INB(IDE_SELECT_REG);
if (cur & 0x40) { /* using LBA? */
printk(", LBAsect=%ld", (unsigned long)
((cur&0xf)<<24)
|(hwif->INB(IDE_HCYL_REG)<<16)
|(hwif->INB(IDE_LCYL_REG)<<8)
| hwif->INB(IDE_SECTOR_REG));
} else {
printk(", CHS=%d/%d/%d",
(hwif->INB(IDE_HCYL_REG)<<8) +
hwif->INB(IDE_LCYL_REG),
cur & 0xf,
hwif->INB(IDE_SECTOR_REG));
}
}
if (HWGROUP(drive) && HWGROUP(drive)->rq)
printk(", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector);
}
}
printk("\n");
}
{
struct request *rq;
int opcode = 0x100;
spin_lock(&ide_lock);
rq = NULL;
if (HWGROUP(drive))
rq = HWGROUP(drive)->rq;
spin_unlock(&ide_lock);
if (!rq)
goto out;
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
char *args = rq->buffer;
if (args)
opcode = args[0];
} else if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
if (args) {
task_struct_t *tf = (task_struct_t *) args->tfRegister;
opcode = tf->command;
}
}
printk("ide: failed opcode was %x\n", opcode);
}
out:
local_irq_restore(flags);
return err;
}
EXPORT_SYMBOL(ide_dump_status);
static int ide_open (struct inode * inode, struct file * filp)
{
return -ENXIO;
......@@ -1673,8 +1542,9 @@ int generic_ide_ioctl(struct file *file, struct block_device *bdev,
*/
spin_lock_irqsave(&ide_lock, flags);
DRIVER(drive)->abort(drive, "drive reset");
ide_abort(drive, "drive reset");
if(HWGROUP(drive)->handler)
BUG();
......@@ -2180,14 +2050,10 @@ static int default_end_request (ide_drive_t *drive, int uptodate, int nr_sects)
return ide_end_request(drive, uptodate, nr_sects);
}
static u8 default_sense (ide_drive_t *drive, const char *msg, u8 stat)
{
return ide_dump_status(drive, msg, stat);
}
static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, u8 stat)
static ide_startstop_t
default_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
return ide_error(drive, msg, stat);
return __ide_error(drive, rq, stat, err);
}
static void default_pre_reset (ide_drive_t *drive)
......@@ -2216,9 +2082,9 @@ static int default_attach (ide_drive_t *drive)
return 0;
}
static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg)
static ide_startstop_t default_abort(ide_drive_t *drive, struct request *rq)
{
return ide_abort(drive, msg);
return __ide_abort(drive, rq);
}
static ide_startstop_t default_start_power_step(ide_drive_t *drive,
......@@ -2233,7 +2099,6 @@ static void setup_driver_defaults (ide_driver_t *d)
if (d->cleanup == NULL) d->cleanup = default_cleanup;
if (d->do_request == NULL) d->do_request = default_do_request;
if (d->end_request == NULL) d->end_request = default_end_request;
if (d->sense == NULL) d->sense = default_sense;
if (d->error == NULL) d->error = default_error;
if (d->abort == NULL) d->abort = default_abort;
if (d->pre_reset == NULL) d->pre_reset = default_pre_reset;
......
......@@ -701,17 +701,11 @@ pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
"firmware is obsolete - please upgrade to revision"
"46 or higher\n", d->name, dev->slot_name);
ret = -EAGAIN;
goto err_disable;
goto out;
}
ret = sgiioc4_ide_setup_pci_device(dev, d);
if (ret < 0)
goto err_disable;
out:
return ret;
err_disable:
pci_disable_device(dev);
goto out;
}
static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
......
......@@ -52,7 +52,7 @@
#include "ide-timing.h"
#define IDE_PMAC_DEBUG
#undef IDE_PMAC_DEBUG
#define DMA_WAIT_TIMEOUT 50
......
......@@ -311,13 +311,11 @@ static int ide_pci_enable(struct pci_dev *dev, ide_pci_device_t *d)
ret = pci_set_dma_mask(dev, DMA_32BIT_MASK);
if (ret < 0) {
printk(KERN_ERR "%s: can't set dma mask\n", d->name);
pci_disable_device(dev);
goto out;
}
/* FIXME: Temporary - until we put in the hotplug interface logic
Check that the bits we want are not in use by someone else.
As someone else uses it, we do not (yuck) disable the device */
Check that the bits we want are not in use by someone else. */
ret = pci_request_region(dev, 4, "ide_tmp");
if (ret < 0)
goto out;
......@@ -542,12 +540,12 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in
ret = pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
if (ret < 0) {
printk(KERN_ERR "%s: error accessing PCI regs\n", d->name);
goto err_disable;
goto out;
}
if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */
ret = ide_pci_configure(dev, d);
if (ret < 0)
goto err_disable;
goto out;
*config = 1;
printk(KERN_INFO "%s: device enabled (Linux)\n", d->name);
}
......@@ -558,17 +556,6 @@ static int ide_setup_pci_controller(struct pci_dev *dev, ide_pci_device_t *d, in
printk(KERN_INFO "%s: chipset revision %d\n", d->name, class_rev);
out:
return ret;
err_disable:
pci_disable_device(dev);
goto out;
}
static void ide_release_pci_controller(struct pci_dev *dev, ide_pci_device_t *d,
int noisy)
{
/* Balance ide_pci_enable() */
pci_disable_device(dev);
}
/**
......@@ -701,7 +688,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d,
*/
ret = d->init_chipset ? d->init_chipset(dev, d->name) : 0;
if (ret < 0)
goto err_release_pci_controller;
goto out;
pciirq = ret;
} else if (tried_config) {
if (noisy)
......@@ -716,7 +703,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d,
if (d->init_chipset) {
ret = d->init_chipset(dev, d->name);
if (ret < 0)
goto err_release_pci_controller;
goto out;
}
if (noisy)
#ifdef __sparc__
......@@ -734,10 +721,6 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d,
ide_pci_setup_ports(dev, d, pciirq, index);
out:
return ret;
err_release_pci_controller:
ide_release_pci_controller(dev, d, noisy);
goto out;
}
int ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d)
......
......@@ -699,6 +699,26 @@ static void __init quirk_svwks_csb5ide(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
/*
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
*/
static void __init quirk_ide_samemode(struct pci_dev *pdev)
{
u8 prog;
pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
if (((prog & 1) && !(prog & 4)) || ((prog & 4) && !(prog & 1))) {
printk(KERN_INFO "PCI: IDE mode mismatch; forcing legacy mode\n");
prog &= ~5;
pdev->class &= ~5;
pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
/* need to re-assign BARs for compat mode */
quirk_ide_bases(pdev);
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode);
/* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
*/
......
......@@ -301,23 +301,9 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
return ide_do_drive_cmd(drive, rq, ide_preempt);
}
ide_startstop_t idescsi_atapi_error (ide_drive_t *drive, const char *msg, byte stat)
static ide_startstop_t
idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
struct request *rq;
byte err;
err = ide_dump_atapi_status(drive, msg, stat);
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
}
if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
/* force an abort */
HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
......@@ -327,20 +313,9 @@ ide_startstop_t idescsi_atapi_error (ide_drive_t *drive, const char *msg, byte s
return ide_stopped;
}
ide_startstop_t idescsi_atapi_abort (ide_drive_t *drive, const char *msg)
static ide_startstop_t
idescsi_atapi_abort(ide_drive_t *drive, struct request *rq)
{
struct request *rq;
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) {
rq->errors = 1;
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
#if IDESCSI_DEBUG_LOG
printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
......
......@@ -1097,9 +1097,8 @@ typedef struct ide_driver_s {
int (*cleanup)(ide_drive_t *);
ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);
int (*end_request)(ide_drive_t *, int, int);
u8 (*sense)(ide_drive_t *, const char *, u8);
ide_startstop_t (*error)(ide_drive_t *, const char *, u8);
ide_startstop_t (*abort)(ide_drive_t *, const char *);
ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
void (*pre_reset)(ide_drive_t *);
sector_t (*capacity)(ide_drive_t *);
......@@ -1147,12 +1146,7 @@ extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigne
*/
extern void ide_execute_command(ide_drive_t *, task_ioreg_t cmd, ide_handler_t *, unsigned int, ide_expiry_t *);
/*
* Error reporting, in human readable form (luxurious, but a memory hog).
*
* (drive, msg, status)
*/
byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
/*
* ide_error() takes action based on the error returned by the controller.
......@@ -1162,6 +1156,8 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
*/
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
ide_startstop_t __ide_abort(ide_drive_t *, struct request *);
/*
* Abort a running command on the controller triggering the abort
* from a host side, non error situation
......@@ -1191,11 +1187,6 @@ extern void ide_fixstring(u8 *, const int, const int);
*/
extern int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
/*
* Return the current idea about the total capacity of this drive.
*/
extern sector_t current_capacity (ide_drive_t *drive);
/*
* Start a reset operation for an IDE interface.
* The caller should return immediately after invoking this.
......@@ -1511,7 +1502,8 @@ extern int ide_dma_enable(ide_drive_t *drive);
extern char *ide_xfer_verbose(u8 xfer_rate);
extern void ide_toggle_bounce(ide_drive_t *drive, int on);
extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
extern byte ide_dump_atapi_status(ide_drive_t *drive, const char *msg, byte stat);
u8 ide_dump_status(ide_drive_t *, const char *, u8);
typedef struct ide_pio_timings_s {
int setup_time; /* Address setup (ns) minimum */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment