Commit 826267d3 authored by Martin Dalecki's avatar Martin Dalecki Committed by Dave Kleikamp

[PATCH] 2.5.21 IDE 91

 - Realize that the only place where ata_do_taskfile gets used is ide-disk.c
   move it and its "friends' over there.

 - Unify the do_request method for disk devices. This saves quite a lot of code.

 - Make task_muin_intr and task_in_intr use the same busy status checks on
   entry.

 - Unfold get_command at the single only place where it's used.

 - Add missing __ata_end_request on kill_rq path.

 - Rename udma_tcq_taskfile() to udma_tcq_init to make the code look like to
   normal udma_init. Revert the logics of udma_init and it's
   implementations to mirror that of udma_tcq_init().

 - Fix a tiny bug in pmac_udma_init() where it was reporting the wrong value up
   on failure.

 - Revert the logics of udma_start(). It's called from udma_init context.
   Realize that it is always returning ide_started. Make it self and the
   implementations of it return void.
parent 3fb57bd6
......@@ -259,7 +259,7 @@ static int ali15x3_udma_setup(struct ata_device *drive)
static int ali15x3_udma_init(struct ata_device *drive, struct request *rq)
{
if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK))
return 1; /* try PIO instead of DMA */
return ide_stopped; /* try PIO instead of DMA */
return udma_pci_init(drive, rq);
}
......
......@@ -175,7 +175,7 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq)
u8 cmd;
if (!(count = udma_new_table(drive, rq)))
return 1; /* try PIO instead of DMA */
return ide_stopped; /* try PIO instead of DMA */
if (rq_data_dir(rq) == READ)
cmd = 0x09;
......@@ -192,7 +192,7 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq)
OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
return 0;
return ide_started;
}
#endif
......
......@@ -858,7 +858,7 @@ static void do_udma_start(struct ata_device *drive)
udelay(10);
}
static int hpt370_udma_start(struct ata_device *drive, struct request *__rq)
static void hpt370_udma_start(struct ata_device *drive, struct request *__rq)
{
struct ata_channel *ch = drive->channel;
......@@ -870,8 +870,6 @@ static int hpt370_udma_start(struct ata_device *drive, struct request *__rq)
*/
outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */
return 0;
}
static void do_timeout_irq(struct ata_device *drive)
......
......@@ -447,18 +447,13 @@ static int icside_dma_stop(struct ata_device *drive)
return get_dma_residue(ch->hw.dma) != 0;
}
static int icside_dma_start(struct ata_device *drive, struct request *rq)
static void icside_dma_start(struct ata_device *drive, struct request *rq)
{
struct ata_channel *ch = drive->channel;
/*
* We can not enable DMA on both channels.
*/
/* We can not enable DMA on both channels simultaneously. */
BUG_ON(dma_channel_active(ch->hw.dma));
enable_dma(ch->hw.dma);
return 0;
}
/*
......@@ -524,10 +519,10 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq)
u8 int cmd;
if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
return 1;
return ide_stopped;
if (drive->type != ATA_DISK)
return 0;
return ide_started;
ata_set_handler(drive, icside_dmaintr, WAIT_CMD, NULL);
......@@ -543,7 +538,7 @@ static int icside_dma_init(struct ata_device *drive, struct request *rq)
enable_dma(ch->hw.dma);
return 0;
return ide_started;
}
static int icside_irq_status(struct ata_device *drive)
......
......@@ -741,7 +741,7 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
else {
if (info->dma) {
if (info->cmd == READ || info->cmd == WRITE)
info->dma = !udma_init(drive, rq);
info->dma = udma_init(drive, rq);
else
printk("ide-cd: DMA set, but not allowed\n");
}
......
......@@ -102,40 +102,44 @@ static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq
spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
if (drive->status & (ERR_STAT|DRQ_STAT)) {
if (drive->status & (ERR_STAT | DRQ_STAT)) {
spin_unlock_irqrestore(ch->lock, flags);
return ata_error(drive, rq, __FUNCTION__);
}
if (!(drive->status & BUSY_STAT)) {
// printk("task_in_intr to Soon wait for next interrupt\n");
ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
/* no data yet, so wait for another interrupt */
ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
return ide_started;
ret = ide_started;
} else {
// printk("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors);
{
unsigned long flags;
char *buf;
buf = ide_map_rq(rq, &flags);
ata_read(drive, buf, SECTOR_WORDS);
ide_unmap_rq(rq, buf, &flags);
}
}
// printk("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors);
{
unsigned long flags;
char *buf;
/* First segment of the request is complete. note that this does not
* necessarily mean that the entire request is done!! this is only true
* if ata_end_request() returns 0.
*/
rq->errors = 0;
--rq->current_nr_sectors;
buf = ide_map_rq(rq, &flags);
ata_read(drive, buf, SECTOR_WORDS);
ide_unmap_rq(rq, buf, &flags);
}
if (rq->current_nr_sectors <= 0) {
if (!__ata_end_request(drive, rq, 1, 0)) {
// printk("Request Ended stat: %02x\n", drive->status);
spin_unlock_irqrestore(ch->lock, flags);
/* First segment of the request is complete. note that this does not
* necessarily mean that the entire request is done!! this is only true
* if ata_end_request() returns 0.
*/
return ide_stopped;
}
}
if (--rq->current_nr_sectors <= 0 && !__ata_end_request(drive, rq, 1, 0)) {
// printk("Request Ended stat: %02x\n", drive->status);
ret = ide_stopped;
} else {
/* still data left to transfer */
ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
......@@ -197,7 +201,7 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request
spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
if (drive->status & (ERR_STAT|DRQ_STAT)) {
if (drive->status & (ERR_STAT | DRQ_STAT)) {
spin_unlock_irqrestore(ch->lock, flags);
return ata_error(drive, rq, __FUNCTION__);
......@@ -235,16 +239,16 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request
rq->errors = 0;
rq->current_nr_sectors -= nsect;
msect -= nsect;
/* FIXME: this seems buggy */
if (!rq->current_nr_sectors) {
if (rq->current_nr_sectors <= 0) {
if (!__ata_end_request(drive, rq, 1, 0)) {
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped;
}
}
msect -= nsect;
} while (msect);
/* more data left */
......@@ -343,212 +347,138 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
}
/*
* Decode with physical ATA command to use and setup associated data.
* Channel lock should be held on entry.
*/
static u8 get_command(struct ata_device *drive, struct ata_taskfile *ar, int cmd)
static ide_startstop_t __do_request(struct ata_device *drive,
struct ata_taskfile *ar, struct request *rq)
{
int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0;
#if 1
lba48bit = drive->addressing;
#endif
struct hd_driveid *id = drive->id;
if (lba48bit) {
if (cmd == READ) {
ar->command_type = IDE_DRIVE_TASK_IN;
if (drive->using_tcq) {
return WIN_READDMA_QUEUED_EXT;
} else if (drive->using_dma) {
return WIN_READDMA_EXT;
} else if (drive->mult_count) {
ar->handler = task_mulin_intr;
return WIN_MULTREAD_EXT;
} else {
ar->handler = task_in_intr;
return WIN_READ_EXT;
}
} else if (cmd == WRITE) {
ar->command_type = IDE_DRIVE_TASK_RAW_WRITE;
if (drive->using_tcq) {
return WIN_WRITEDMA_QUEUED_EXT;
} else if (drive->using_dma) {
return WIN_WRITEDMA_EXT;
} else if (drive->mult_count) {
ar->handler = task_mulout_intr;
return WIN_MULTWRITE_EXT;
} else {
ar->handler = task_out_intr;
return WIN_WRITE_EXT;
}
}
} else {
if (cmd == READ) {
ar->command_type = IDE_DRIVE_TASK_IN;
if (drive->using_tcq) {
return WIN_READDMA_QUEUED;
} else if (drive->using_dma) {
return WIN_READDMA;
} else if (drive->mult_count) {
ar->handler = task_in_intr;
return WIN_MULTREAD;
} else {
ar->handler = task_in_intr;
return WIN_READ;
}
} else if (cmd == WRITE) {
ar->command_type = IDE_DRIVE_TASK_RAW_WRITE;
if (drive->using_tcq) {
return WIN_WRITEDMA_QUEUED;
} else if (drive->using_dma) {
return WIN_WRITEDMA;
} else if (drive->mult_count) {
ar->handler = task_mulout_intr;
return WIN_MULTWRITE;
} else {
ar->handler = task_out_intr;
return WIN_WRITE;
}
}
/* (ks/hs): Moved to start, do not use for multiple out commands.
* FIXME: why not?! */
if (!(ar->cmd == CFA_WRITE_MULTI_WO_ERASE ||
ar->cmd == WIN_MULTWRITE ||
ar->cmd == WIN_MULTWRITE_EXT)) {
ata_irq_enable(drive, 1);
ata_mask(drive);
}
/* not reached! */
return WIN_NOP;
}
static ide_startstop_t chs_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{
struct ata_taskfile args;
int sectors;
if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1))
ata_out_regfile(drive, &ar->hobfile);
unsigned int track = (block / drive->sect);
unsigned int sect = (block % drive->sect) + 1;
unsigned int head = (track % drive->head);
unsigned int cyl = (track / drive->head);
ata_out_regfile(drive, &ar->taskfile);
sectors = rq->nr_sectors;
if (sectors == 256)
sectors = 0;
OUT_BYTE((ar->taskfile.device_head & (drive->addressing ? 0xE0 : 0xEF)) | drive->select.all,
IDE_SELECT_REG);
memset(&args, 0, sizeof(args));
if (ar->XXX_handler) {
struct ata_channel *ch = drive->channel;
if (blk_rq_tagged(rq)) {
args.taskfile.feature = sectors;
args.taskfile.sector_count = rq->tag << 3;
} else
args.taskfile.sector_count = sectors;
args.taskfile.sector_number = sect;
args.taskfile.low_cylinder = cyl;
args.taskfile.high_cylinder = (cyl>>8);
args.taskfile.device_head = head;
args.taskfile.device_head |= drive->select.all;
args.cmd = get_command(drive, &args, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
if (lba) printk("LBAsect=%lld, ", block);
else printk("CHS=%d/%d/%d, ", cyl, head, sect);
printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=%p\n", rq->buffer);
#endif
rq->special = &args;
return ata_do_taskfile(drive, &args, rq);
}
static ide_startstop_t lba28_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{
struct ata_taskfile args;
int sectors;
sectors = rq->nr_sectors;
if (sectors == 256)
sectors = 0;
memset(&args, 0, sizeof(args));
if (blk_rq_tagged(rq)) {
args.taskfile.feature = sectors;
args.taskfile.sector_count = rq->tag << 3;
} else
args.taskfile.sector_count = sectors;
args.taskfile.sector_number = block;
args.taskfile.low_cylinder = (block >>= 8);
args.taskfile.high_cylinder = (block >>= 8);
args.taskfile.device_head = ((block >> 8) & 0x0f);
args.taskfile.device_head |= drive->select.all;
args.cmd = get_command(drive, &args, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
if (lba) printk("LBAsect=%lld, ", block);
else printk("CHS=%d/%d/%d, ", cyl, head, sect);
printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=%p\n", rq->buffer);
#endif
ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL);
OUT_BYTE(ar->cmd, IDE_COMMAND_REG);
rq->special = &args;
/* FIXME: Warning check for race between handler and prehandler
* for writing first block of data. however since we are well
* inside the boundaries of the seek, we should be okay.
*
* FIXME: Replace the switch by using a proper command_type.
*/
return ata_do_taskfile(drive, &args, rq);
}
if (ar->cmd == CFA_WRITE_SECT_WO_ERASE ||
ar->cmd == WIN_WRITE ||
ar->cmd == WIN_WRITE_EXT ||
ar->cmd == WIN_WRITE_VERIFY ||
ar->cmd == WIN_WRITE_BUFFER ||
ar->cmd == WIN_DOWNLOAD_MICROCODE ||
ar->cmd == CFA_WRITE_MULTI_WO_ERASE ||
ar->cmd == WIN_MULTWRITE ||
ar->cmd == WIN_MULTWRITE_EXT) {
ide_startstop_t startstop;
if (ata_status_poll(drive, DATA_READY, drive->bad_wstat,
WAIT_DRQ, rq, &startstop)) {
printk(KERN_ERR "%s: no DRQ after issuing %s\n",
drive->name, drive->mult_count ? "MULTWRITE" : "WRITE");
return startstop;
}
/*
* 268435455 == 137439 MB or 28bit limit
* 320173056 == 163929 MB or 48bit addressing
* 1073741822 == 549756 MB or 48bit addressing fake drive
*/
/* FIXME: This doesn't make the slightest sense.
* (ks/hs): Fixed Multi Write
*/
if (!(ar->cmd == CFA_WRITE_MULTI_WO_ERASE ||
ar->cmd == WIN_MULTWRITE ||
ar->cmd == WIN_MULTWRITE_EXT)) {
unsigned long flags;
char *buf = ide_map_rq(rq, &flags);
static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{
struct ata_taskfile args;
int sectors;
/* For Write_sectors we need to stuff the first sector */
ata_write(drive, buf, SECTOR_WORDS);
sectors = rq->nr_sectors;
if (sectors == 65536)
sectors = 0;
rq->current_nr_sectors--;
ide_unmap_rq(rq, buf, &flags);
memset(&args, 0, sizeof(args));
return ide_started;
} else {
int i;
int ret;
/* Polling wait until the drive is ready.
*
* Stuff the first sector(s) by calling the
* handler driectly therafter.
*
* FIXME: Replace hard-coded 100, what about
* error handling?
*/
for (i = 0; i < 100; ++i) {
if (drive_is_ready(drive))
break;
}
if (!drive_is_ready(drive)) {
printk(KERN_ERR "DISASTER WAITING TO HAPPEN!\n");
}
/* FIXME: make this unlocking go away*/
spin_unlock_irq(ch->lock);
ret = ar->XXX_handler(drive, rq);
spin_lock_irq(ch->lock);
if (blk_rq_tagged(rq)) {
args.taskfile.feature = sectors;
args.hobfile.feature = sectors >> 8;
args.taskfile.sector_count = rq->tag << 3;
return ret;
}
}
} else {
args.taskfile.sector_count = sectors;
args.hobfile.sector_count = sectors >> 8;
}
args.taskfile.sector_number = block; /* low lba */
args.taskfile.low_cylinder = (block >>= 8); /* mid lba */
args.taskfile.high_cylinder = (block >>= 8); /* hi lba */
args.taskfile.device_head = drive->select.all;
args.hobfile.sector_number = (block >>= 8); /* low lba */
args.hobfile.low_cylinder = (block >>= 8); /* mid lba */
args.hobfile.high_cylinder = (block >>= 8); /* hi lba */
args.hobfile.device_head = drive->select.all;
/*
* FIXME: This is a gross hack, need to unify tcq dma proc and
* regular dma proc. It should now be easier.
*
* FIXME: Handle the alternateives by a command type.
*/
args.cmd = get_command(drive, &args, rq_data_dir(rq));
if (!drive->using_dma)
return ide_started;
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
if (lba) printk("LBAsect=%lld, ", block);
else printk("CHS=%d/%d/%d, ", cyl, head, sect);
printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=%p\n",rq->buffer);
/* for dma commands we don't set the handler */
if (ar->cmd == WIN_WRITEDMA ||
ar->cmd == WIN_WRITEDMA_EXT ||
ar->cmd == WIN_READDMA ||
ar->cmd == WIN_READDMA_EXT)
return udma_init(drive, rq);
#ifdef CONFIG_BLK_DEV_IDE_TCQ
else if (ar->cmd == WIN_WRITEDMA_QUEUED ||
ar->cmd == WIN_WRITEDMA_QUEUED_EXT ||
ar->cmd == WIN_READDMA_QUEUED ||
ar->cmd == WIN_READDMA_QUEUED_EXT)
return udma_tcq_init(drive, rq);
#endif
else {
printk(KERN_ERR "%s: unknown command %x\n", __FUNCTION__, ar->cmd);
return ide_stopped;
}
}
rq->special = &args;
return ata_do_taskfile(drive, &args, rq);
return ide_started;
}
/*
......@@ -560,10 +490,13 @@ static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request
*/
static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{
struct ata_taskfile args;
unsigned int sectors;
/* This issues a special drive command.
*/
if (rq->flags & REQ_SPECIAL)
return ata_do_taskfile(drive, rq->special, rq);
return __do_request(drive, rq->special, rq);
/* FIXME: this check doesn't make sense */
if (!(rq->flags & REQ_CMD)) {
......@@ -597,15 +530,150 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
}
}
if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))
return lba48_do_request(drive, rq, block);
else if (drive->select.b.lba)
return lba28_do_request(drive, rq, block);
else
return chs_do_request(drive, rq, block);
memset(&args, 0, sizeof(args));
sectors = rq->nr_sectors;
/* Dispatch depending up on the drive access method. */
if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) {
/* LBA 48 bit */
/*
* 268435455 == 137439 MB or 28bit limit
* 320173056 == 163929 MB or 48bit addressing
* 1073741822 == 549756 MB or 48bit addressing fake drive
*/
if (sectors == 65536)
sectors = 0;
if (blk_rq_tagged(rq)) {
args.taskfile.feature = sectors;
args.hobfile.feature = sectors >> 8;
args.taskfile.sector_count = rq->tag << 3;
} else {
args.taskfile.sector_count = sectors;
args.hobfile.sector_count = sectors >> 8;
}
args.taskfile.sector_number = block; /* low lba */
args.taskfile.low_cylinder = (block >>= 8); /* mid lba */
args.taskfile.high_cylinder = (block >>= 8); /* hi lba */
args.taskfile.device_head = drive->select.all;
args.hobfile.sector_number = (block >>= 8); /* low lba */
args.hobfile.low_cylinder = (block >>= 8); /* mid lba */
args.hobfile.high_cylinder = (block >>= 8); /* hi lba */
} else if (drive->select.b.lba) {
/* LBA 28 bit */
if (sectors == 256)
sectors = 0;
if (blk_rq_tagged(rq)) {
args.taskfile.feature = sectors;
args.taskfile.sector_count = rq->tag << 3;
} else
args.taskfile.sector_count = sectors;
args.taskfile.sector_number = block;
args.taskfile.low_cylinder = (block >>= 8);
args.taskfile.high_cylinder = (block >>= 8);
args.taskfile.device_head = ((block >> 8) & 0x0f);
} else {
/* CHS */
unsigned int track = (block / drive->sect);
unsigned int sect = (block % drive->sect) + 1;
unsigned int head = (track % drive->head);
unsigned int cyl = (track / drive->head);
if (sectors == 256)
sectors = 0;
if (blk_rq_tagged(rq)) {
args.taskfile.feature = sectors;
args.taskfile.sector_count = rq->tag << 3;
} else
args.taskfile.sector_count = sectors;
args.taskfile.sector_number = sect;
args.taskfile.low_cylinder = cyl;
args.taskfile.high_cylinder = (cyl>>8);
args.taskfile.device_head = head;
}
args.taskfile.device_head |= drive->select.all;
/*
* Decode with physical ATA command to use and setup associated data.
*/
if (rq_data_dir(rq) == READ) {
args.command_type = IDE_DRIVE_TASK_IN;
if (drive->addressing) {
if (drive->using_tcq) {
args.cmd = WIN_READDMA_QUEUED_EXT;
} else if (drive->using_dma) {
args.cmd = WIN_READDMA_EXT;
} else if (drive->mult_count) {
args.XXX_handler = task_mulin_intr;
args.cmd = WIN_MULTREAD_EXT;
} else {
args.XXX_handler = task_in_intr;
args.cmd = WIN_READ_EXT;
}
} else {
if (drive->using_tcq) {
args.cmd = WIN_READDMA_QUEUED;
} else if (drive->using_dma) {
args.cmd = WIN_READDMA;
} else if (drive->mult_count) {
/* FIXME : Shouldn't this be task_mulin_intr?! */
args.XXX_handler = task_in_intr;
args.cmd = WIN_MULTREAD;
} else {
args.XXX_handler = task_in_intr;
args.cmd = WIN_READ;
}
}
} else {
args.command_type = IDE_DRIVE_TASK_RAW_WRITE;
if (drive->addressing) {
if (drive->using_tcq) {
args.cmd = WIN_WRITEDMA_QUEUED_EXT;
} else if (drive->using_dma) {
args.cmd = WIN_WRITEDMA_EXT;
} else if (drive->mult_count) {
args.XXX_handler = task_mulout_intr;
args.cmd = WIN_MULTWRITE_EXT;
} else {
args.XXX_handler = task_out_intr;
args.cmd = WIN_WRITE_EXT;
}
} else {
if (drive->using_tcq) {
args.cmd = WIN_WRITEDMA_QUEUED;
} else if (drive->using_dma) {
args.cmd = WIN_WRITEDMA;
} else if (drive->mult_count) {
args.XXX_handler = task_mulout_intr;
args.cmd = WIN_MULTWRITE;
} else {
args.XXX_handler = task_out_intr;
args.cmd = WIN_WRITE;
}
}
}
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
(rq_data_dir(rq)==READ) ? "read" : "writ");
if (lba) printk("LBAsect=%lld, ", block);
else printk("CHS=%d/%d/%d, ", cyl, head, sect);
printk("sectors=%ld, ", rq->nr_sectors);
printk("buffer=%p\n", rq->buffer);
#endif
rq->special = &args;
return __do_request(drive, &args, rq);
}
static int idedisk_open(struct inode *inode, struct file *filp, struct ata_device *drive)
static int idedisk_open(struct inode *inode, struct file *__fp, struct ata_device *drive)
{
MOD_INC_USE_COUNT;
if (drive->removable && drive->usage == 1) {
......
......@@ -1102,7 +1102,7 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque
udma_enable(drive, 0, 1);
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok = !udma_init(drive, rq);
dma_ok = udma_init(drive, rq);
#endif
ata_irq_enable(drive, 1);
......
......@@ -1365,7 +1365,8 @@ static int pmac_udma_start(struct ata_device *drive, struct request *rq)
*/
ix = pmac_ide_find(drive);
if (ix < 0)
return 0;
return ide_started;
dma = pmac_ide[ix].dma_regs;
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
......@@ -1373,7 +1374,8 @@ static int pmac_udma_start(struct ata_device *drive, struct request *rq)
out_le32(&dma->control, (RUN << 16) | RUN);
/* Make sure it gets to the controller right now */
(void)in_le32(&dma->control);
return 0;
return ide_started;
}
static int pmac_udma_stop(struct ata_device *drive)
......@@ -1411,7 +1413,7 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq)
*/
ix = pmac_ide_find(drive);
if (ix < 0)
return 0;
return ide_stopped;
if (rq_data_dir(rq) == READ)
reading = 1;
......@@ -1423,7 +1425,7 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq)
pmac_ide[ix].kind == controller_kl_ata4_80);
if (!pmac_ide_build_dmatable(drive, rq, ix, !reading))
return 1;
return ide_stopped;
/* Apple adds 60ns to wrDataSetup on reads */
if (ata4 && (pmac_ide[ix].timings[unit] & TR_66_UDMA_EN)) {
out_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE),
......@@ -1433,7 +1435,7 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq)
}
drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK)
return 0;
return ide_started;
ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL);
if ((rq->flags & REQ_SPECIAL) &&
......@@ -1447,7 +1449,9 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq)
OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
return udma_start(drive, rq);
udma_start(drive, rq);
return ide_started;
}
/*
......
......@@ -2290,7 +2290,7 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive,
udma_enable(drive, 0, 1);
}
if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
dma_ok = !udma_init(drive, rq);
dma_ok = udma_init(drive, rq);
#endif
ata_irq_enable(drive, 1);
......
......@@ -176,145 +176,6 @@ int drive_is_ready(struct ata_device *drive)
return 1; /* drive ready: *might* be interrupting */
}
/*
* Channel lock should be held on entry.
*/
ide_startstop_t ata_do_taskfile(struct ata_device *drive,
struct ata_taskfile *ar, struct request *rq)
{
struct hd_driveid *id = drive->id;
/* (ks/hs): Moved to start, do not use for multiple out commands.
* FIXME: why not?! */
if (!(ar->cmd == CFA_WRITE_MULTI_WO_ERASE ||
ar->cmd == WIN_MULTWRITE ||
ar->cmd == WIN_MULTWRITE_EXT)) {
ata_irq_enable(drive, 1);
ata_mask(drive);
}
if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1))
ata_out_regfile(drive, &ar->hobfile);
ata_out_regfile(drive, &ar->taskfile);
OUT_BYTE((ar->taskfile.device_head & (drive->addressing ? 0xE0 : 0xEF)) | drive->select.all,
IDE_SELECT_REG);
if (ar->handler) {
struct ata_channel *ch = drive->channel;
/* This is apparently supposed to reset the wait timeout for
* the interrupt to accur.
*/
ata_set_handler(drive, ar->handler, WAIT_CMD, NULL);
OUT_BYTE(ar->cmd, IDE_COMMAND_REG);
/* FIXME: Warning check for race between handler and prehandler
* for writing first block of data. however since we are well
* inside the boundaries of the seek, we should be okay.
*
* FIXME: Replace the switch by using a proper command_type.
*/
if (ar->cmd == CFA_WRITE_SECT_WO_ERASE ||
ar->cmd == WIN_WRITE ||
ar->cmd == WIN_WRITE_EXT ||
ar->cmd == WIN_WRITE_VERIFY ||
ar->cmd == WIN_WRITE_BUFFER ||
ar->cmd == WIN_DOWNLOAD_MICROCODE ||
ar->cmd == CFA_WRITE_MULTI_WO_ERASE ||
ar->cmd == WIN_MULTWRITE ||
ar->cmd == WIN_MULTWRITE_EXT) {
ide_startstop_t startstop;
if (ata_status_poll(drive, DATA_READY, drive->bad_wstat,
WAIT_DRQ, rq, &startstop)) {
printk(KERN_ERR "%s: no DRQ after issuing %s\n",
drive->name, drive->mult_count ? "MULTWRITE" : "WRITE");
return startstop;
}
/* FIXME: This doesn't make the slightest sense.
* (ks/hs): Fixed Multi Write
*/
if (!(ar->cmd == CFA_WRITE_MULTI_WO_ERASE ||
ar->cmd == WIN_MULTWRITE ||
ar->cmd == WIN_MULTWRITE_EXT)) {
unsigned long flags;
char *buf = ide_map_rq(rq, &flags);
/* For Write_sectors we need to stuff the first sector */
ata_write(drive, buf, SECTOR_WORDS);
rq->current_nr_sectors--;
ide_unmap_rq(rq, buf, &flags);
return ide_started;
} else {
int i;
int ret;
/* Polling wait until the drive is ready.
*
* Stuff the first sector(s) by calling the
* handler driectly therafter.
*
* FIXME: Replace hard-coded 100, what about
* error handling?
*/
for (i = 0; i < 100; ++i) {
if (drive_is_ready(drive))
break;
}
if (!drive_is_ready(drive)) {
printk(KERN_ERR "DISASTER WAITING TO HAPPEN!\n");
}
/* FIXME: make this unlocking go away*/
spin_unlock_irq(ch->lock);
ret = ar->handler(drive, rq);
spin_lock_irq(ch->lock);
return ret;
}
}
} else {
/*
* FIXME: This is a gross hack, need to unify tcq dma proc and
* regular dma proc. It should now be easier.
*
* FIXME: Handle the alternateives by a command type.
*/
if (!drive->using_dma)
return ide_started;
/* for dma commands we don't set the handler */
if (ar->cmd == WIN_WRITEDMA ||
ar->cmd == WIN_WRITEDMA_EXT ||
ar->cmd == WIN_READDMA ||
ar->cmd == WIN_READDMA_EXT)
return !udma_init(drive, rq);
#ifdef CONFIG_BLK_DEV_IDE_TCQ
else if (ar->cmd == WIN_WRITEDMA_QUEUED ||
ar->cmd == WIN_WRITEDMA_QUEUED_EXT ||
ar->cmd == WIN_READDMA_QUEUED ||
ar->cmd == WIN_READDMA_QUEUED_EXT)
return udma_tcq_taskfile(drive, rq);
#endif
else {
printk(KERN_ERR "%s: unknown command %x\n", __FUNCTION__, ar->cmd);
return ide_stopped;
}
}
return ide_started;
}
/*
* This function issues a special IDE device request onto the request queue.
*
......@@ -436,7 +297,7 @@ int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar)
struct request req;
ar->command_type = IDE_DRIVE_TASK_NO_DATA;
ar->handler = ata_special_intr;
ar->XXX_handler = ata_special_intr;
memset(&req, 0, sizeof(req));
req.flags = REQ_SPECIAL;
......@@ -449,6 +310,5 @@ EXPORT_SYMBOL(drive_is_ready);
EXPORT_SYMBOL(ide_do_drive_cmd);
EXPORT_SYMBOL(ata_read);
EXPORT_SYMBOL(ata_write);
EXPORT_SYMBOL(ata_do_taskfile);
EXPORT_SYMBOL(ata_special_intr);
EXPORT_SYMBOL(ide_raw_taskfile);
......@@ -702,7 +702,8 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
spin_unlock_irq(ch->lock);
ata_ops(drive)->end_request(drive, rq, 0);
spin_lock_irq(ch->lock);
}
} else
__ata_end_request(drive, rq, 0, 0);
} else
__ata_end_request(drive, rq, 0, 0);
......
......@@ -54,9 +54,6 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
if (copy_from_user(vals, (void *)arg, 4))
return -EFAULT;
memset(&req, 0, sizeof(req));
req.flags = REQ_SPECIAL;
memset(&args, 0, sizeof(args));
args.taskfile.feature = vals[2];
......@@ -83,10 +80,14 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
/* Issue ATA command and wait for completion.
*/
args.handler = ata_special_intr;
args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.XXX_handler = ata_special_intr;
req.buffer = argbuf + 4;
memset(&req, 0, sizeof(req));
req.flags = REQ_SPECIAL;
req.special = &args;
req.buffer = argbuf + 4;
err = ide_do_drive_cmd(drive, &req, ide_wait);
argbuf[0] = drive->status;
......
......@@ -105,12 +105,12 @@ static int ns87415_udma_init(struct ata_device *drive, struct request *rq)
{
ns87415_prepare_drive(drive, 1); /* select DMA xfer */
if (!udma_pci_init(drive, rq)) /* use standard DMA stuff */
return 0;
if (udma_pci_init(drive, rq)) /* use standard DMA stuff */
return ide_started;
ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
return 1;
return ide_stopped;
}
static int ns87415_udma_setup(struct ata_device *drive)
......
......@@ -420,13 +420,11 @@ int udma_pci_start(struct ata_device *drive, struct request *rq)
struct ata_channel *ch = drive->channel;
unsigned long dma_base = ch->dma_base;
/* Note that this is done *after* the cmd has
* been issued to the drive, as per the BM-IDE spec.
* The Promise Ultra33 doesn't work correctly when
* we do this part before issuing the drive cmd.
/* Note that this is done *after* the cmd has been issued to the drive,
* as per the BM-IDE spec. The Promise Ultra33 doesn't work correctly
* when we do this part before issuing the drive cmd.
*/
outb(inb(dma_base)|1, dma_base); /* start DMA */
return 0;
outb(inb(dma_base) | 1, dma_base); /* start DMA */
}
/*
......@@ -545,11 +543,11 @@ int udma_pci_init(struct ata_device *drive, struct request *rq)
u8 cmd;
if (ata_start_dma(drive, rq))
return 1;
return ide_stopped;
/* No DMA transfers on ATAPI devices. */
if (drive->type != ATA_DISK)
return 0;
return ide_started;
if (rq_data_dir(rq) == READ)
cmd = 0x08;
......@@ -562,7 +560,9 @@ int udma_pci_init(struct ata_device *drive, struct request *rq)
else
outb(cmd ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
return udma_start(drive, rq);
udma_start(drive, rq);
return ide_started;
}
EXPORT_SYMBOL(ide_dma_intr);
......
......@@ -573,8 +573,6 @@ static int pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
*/
outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */
return 0;
}
int pdc202xx_udma_stop(struct ata_device *drive)
......
......@@ -784,7 +784,7 @@ ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq,
args.taskfile.high_cylinder = (block>>=8);
args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all;
args.cmd = (rq_data_dir(rq) == READ) ? PROMISE_READ : PROMISE_WRITE;
args.handler = NULL;
args.XXX_handler = NULL;
rq->special = &args;
return do_pdc4030_io(drive, &args, rq);
......
......@@ -209,6 +209,7 @@ static void sl82c105_dma_enable(struct ata_device *drive, int on, int verbose)
static int sl82c105_dma_init(struct ata_device *drive, struct request *rq)
{
sl82c105_reset_host(drive->channel->pci_dev);
return udma_pci_init(drive, rq);
}
......
......@@ -84,7 +84,7 @@ static void tcq_invalidate_queue(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
request_queue_t *q = &drive->queue;
struct ata_taskfile *args;
struct ata_taskfile *ar;
struct request *rq;
unsigned long flags;
......@@ -110,8 +110,8 @@ static void tcq_invalidate_queue(struct ata_device *drive)
* executed before any new commands are started. issue a NOP
* to clear internal queue on drive.
*/
args = kmalloc(sizeof(*args), GFP_ATOMIC);
if (!args) {
ar = kmalloc(sizeof(*ar), GFP_ATOMIC);
if (!ar) {
printk(KERN_ERR "ATA: %s: failed to issue NOP\n", drive->name);
goto out;
}
......@@ -126,10 +126,10 @@ static void tcq_invalidate_queue(struct ata_device *drive)
*/
BUG_ON(!rq);
rq->special = args;
args->cmd = WIN_NOP;
args->handler = tcq_nop_handler;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
rq->special = ar;
ar->cmd = WIN_NOP;
ar->XXX_handler = tcq_nop_handler;
ar->command_type = IDE_DRIVE_TASK_NO_DATA;
rq->rq_dev = mk_kdev(drive->channel->major, (drive->select.b.unit)<<PARTN_BITS);
_elv_add_request(q, rq, 0, 0);
......@@ -539,10 +539,9 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *
return ide_stopped;
set_irq(drive, ide_dmaq_intr);
if (!udma_start(drive, rq))
return ide_started;
udma_start(drive, rq);
return ide_stopped;
return ide_started;
}
/*
......@@ -550,7 +549,7 @@ static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *
*
* Channel lock should be held.
*/
ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq)
ide_startstop_t udma_tcq_init(struct ata_device *drive, struct request *rq)
{
u8 stat;
u8 feat;
......
......@@ -179,7 +179,6 @@ static void trm290_selectproc(struct ata_device *drive)
static int trm290_udma_start(struct ata_device *drive, struct request *__rq)
{
/* Nothing to be done here. */
return 0;
}
static int trm290_udma_stop(struct ata_device *drive)
......@@ -210,7 +209,7 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq)
#ifdef TRM290_NO_DMA_WRITES
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1;
return ide_stopped;
#endif
} else {
reading = 2;
......@@ -219,7 +218,7 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq)
if (!(count = udma_new_table(drive, rq))) {
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1; /* try PIO instead of DMA */
return ide_stopped; /* try PIO instead of DMA */
}
trm290_prepare_drive(drive, 1); /* select DMA xfer */
......@@ -233,7 +232,7 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq)
outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
}
return 0;
return ide_started;
}
static int trm290_udma_irq_status(struct ata_device *drive)
......
......@@ -444,7 +444,7 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request
bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */
if (drive->using_dma && rq->bio)
dma_ok = !udma_init(drive, rq);
dma_ok = udma_init(drive, rq);
ata_select(drive, 10);
ata_irq_enable(drive, 1);
......
......@@ -459,9 +459,9 @@ struct ata_channel {
int (*udma_setup)(struct ata_device *);
void (*udma_enable)(struct ata_device *, int, int);
int (*udma_start) (struct ata_device *, struct request *rq);
void (*udma_start) (struct ata_device *, struct request *);
int (*udma_stop) (struct ata_device *);
int (*udma_init) (struct ata_device *, struct request *rq);
int (*udma_init) (struct ata_device *, struct request *);
int (*udma_irq_status) (struct ata_device *);
void (*udma_timeout) (struct ata_device *);
void (*udma_irq_lost) (struct ata_device *);
......@@ -652,15 +652,12 @@ struct ata_taskfile {
struct hd_drive_task_hdr hobfile;
u8 cmd; /* actual ATA command */
int command_type;
ide_startstop_t (*handler)(struct ata_device *, struct request *);
ide_startstop_t (*XXX_handler)(struct ata_device *, struct request *);
};
extern void ata_read(struct ata_device *, void *, unsigned int);
extern void ata_write(struct ata_device *, void *, unsigned int);
extern ide_startstop_t ata_do_taskfile(struct ata_device *,
struct ata_taskfile *, struct request *);
/*
* Special Flagged Register Validation Caller
*/
......@@ -752,9 +749,9 @@ static inline void udma_enable(struct ata_device *drive, int on, int verbose)
drive->channel->udma_enable(drive, on, verbose);
}
static inline int udma_start(struct ata_device *drive, struct request *rq)
static inline void udma_start(struct ata_device *drive, struct request *rq)
{
return drive->channel->udma_start(drive, rq);
drive->channel->udma_start(drive, rq);
}
static inline int udma_stop(struct ata_device *drive)
......@@ -765,7 +762,7 @@ static inline int udma_stop(struct ata_device *drive)
/*
* Initiate actual DMA data transfer. The direction is encoded in the request.
*/
static inline int udma_init(struct ata_device *drive, struct request *rq)
static inline ide_startstop_t udma_init(struct ata_device *drive, struct request *rq)
{
return drive->channel->udma_init(drive, rq);
}
......@@ -803,7 +800,7 @@ extern void udma_print(struct ata_device *);
extern int udma_black_list(struct ata_device *);
extern int udma_white_list(struct ata_device *);
extern ide_startstop_t udma_tcq_taskfile(struct ata_device *, struct request *);
extern ide_startstop_t udma_tcq_init(struct ata_device *, struct request *);
extern int udma_tcq_enable(struct ata_device *, int);
extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *);
......
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