2005-02-06 11:26:56

by Tejun Heo

[permalink] [raw]
Subject: [PATCH 2.6.11-rc2] ide: driver updates, series 3

Hello, Bartlomiej.

Here are four patches which implement taskfile handling functions and
merge flagged_taskfile() into do_rw_taskfile().

I didn't implement separate writing function for flagged taskfile,
rationale being...

1. A single function which properly handles both unflagged and
flagged cases has simpler semantics and, accordingly, less
likely to cause bugs.

If there were two separate functions ide_write_taskfile() and
ide_write_flagged_taskfile(), when somebody tries to add custom
in/out flags to a piece of code which uses unflagged taskfile and
ide_write_taskfile(), it would be easy to set in/out flags but
forget to call ide_write_flagged_taskfile() instead.

2. There virtually is no overhead.


In #03, I moved taskfile reading part of ide_end_drive_cmd() into a
separate function named ide_read_taskfile(), so that taskfile handling
codes can live side-by-side in ide-taskfile.c.

Also, I didn't use any of HWIF, IDE_*_REG macros, as they should go
away. Please tell me what you think about the new referencing style.


[ Start of patch descriptions ]

01_ide_write_taskfile.patch
: ide_write_taskfile() implemented.

ide_write_taskfile(), which writes the content of a ide_task_t
into the IDE taskfile registers, is implemented, and
do_rw_taskfile() and flagged_taskfile() are converted to use
ide_write_taskfile(). Behavior changes are
- flagged taskfile now honors HOB feature register.
- No do_rw_taskfile() HIHI check on select register. Except
for the DEV bit, all bits are honored.

02_ide_do_rw_disk_use_write_taskfile.patch
: __ide_do_rw_disk() rewritten ide_write_taskfile().

__ide_do_rw_disk() rewritten using ide_write_taskfile().

03_ide_read_taskfile.patch
: ide_read_taskfile() implemented.

Status reading part of ide_end_drive_cmd() is moved into
a separate function ide_read_taskfile().

04_ide_merge_rw_and_flagged_taskfile.patch
: merge flagged_taskfile() into do_rw_taskfile()

Merged flagged_taskfile() into do_rw_taskfile(). During the
merge, the following change took place.
- Uses taskfile->data_phase to determine if dma trasfer is
requested. (previously, do_rw_taskfile() directly switched
on taskfile->command for all dma commands)

[ End of patch descriptions ]


Thanks a lot. :-)

--
tejun


2005-02-06 11:30:39

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 2.6.11-rc2 04/04] ide: merge flagged_taskfile() into do_rw_taskfile()


04_ide_merge_rw_and_flagged_taskfile.patch

Merged flagged_taskfile() into do_rw_taskfile(). During the
merge, the following change took place.
- Uses taskfile->data_phase to determine if dma trasfer is
requested. (previously, do_rw_taskfile() directly switched
on taskfile->command for all dma commands)


Signed-off-by: Tejun Heo <[email protected]>


Index: linux-ide-series3-export/drivers/ide/ide-io.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-io.c 2005-02-06 19:49:19.496897703 +0900
+++ linux-ide-series3-export/drivers/ide/ide-io.c 2005-02-06 19:49:19.839841988 +0900
@@ -657,8 +657,6 @@ static ide_startstop_t execute_drive_tas
break;
}

- if (args->tf_out_flags.all != 0)
- return flagged_taskfile(drive, args);
return do_rw_taskfile(drive, args);
}

Index: linux-ide-series3-export/drivers/ide/ide-taskfile.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-taskfile.c 2005-02-06 19:49:19.493898191 +0900
+++ linux-ide-series3-export/drivers/ide/ide-taskfile.c 2005-02-06 19:49:19.840841826 +0900
@@ -215,53 +215,57 @@ void ide_read_taskfile(ide_drive_t *driv
tf->command = stat;
}

-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t do_rw_taskfile(ide_drive_t *drive, ide_task_t *task)
{
- ide_hwif_t *hwif = HWIF(drive);
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
+ ide_hwif_t *hwif = drive->hwif;
+ unsigned long *ports = drive->hwif->io_ports;
+ task_struct_t *tf = (task_struct_t *)task->tfRegister;

- /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
- if (IDE_CONTROL_REG) {
- /* clear nIEN */
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+ /* We check this in ide_taskfile_ioctl(), but the setting could
+ have been changed inbetween. */
+ if (task->data_phase == TASKFILE_MULTI_IN ||
+ task->data_phase == TASKFILE_MULTI_OUT) {
+ if (!drive->mult_count) {
+ printk(KERN_ERR "%s: multimode not set!\n",
+ drive->name);
+ /* FIXME: this path is an infnite loop. - tj */
+ return ide_stopped;
+ }
}
+
+ /* ALL Command Block Executions SHALL clear nIEN. */
+ if (ports[IDE_CONTROL_OFFSET])
+ hwif->OUTB(drive->ctl, ports[IDE_CONTROL_OFFSET]);
SELECT_MASK(drive, 0);

ide_write_taskfile(drive, task);

if (task->handler != NULL) {
if (task->prehandler != NULL) {
- hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
+ hwif->OUTBSYNC(drive, tf->command,
+ ports[IDE_COMMAND_OFFSET]);
ndelay(400); /* FIXME */
return task->prehandler(drive, task->rq);
}
- ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
+ ide_execute_command(drive, tf->command, task->handler,
+ WAIT_WORSTCASE, NULL);
return ide_started;
}

- if (!drive->using_dma)
+ switch (task->data_phase) {
+ case TASKFILE_OUT_DMAQ:
+ case TASKFILE_OUT_DMA:
+ case TASKFILE_IN_DMAQ:
+ case TASKFILE_IN_DMA:
+ if (!hwif->dma_setup(drive)) {
+ hwif->dma_exec_cmd(drive, tf->command);
+ hwif->dma_start(drive);
+ return ide_started;
+ }
+ return ide_stopped;
+ default:
return ide_stopped;
-
- switch (taskfile->command) {
- case WIN_WRITEDMA_ONCE:
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_EXT:
- case WIN_READDMA_ONCE:
- case WIN_READDMA:
- case WIN_READDMA_EXT:
- case WIN_IDENTIFY_DMA:
- if (!hwif->dma_setup(drive)) {
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
- return ide_started;
- }
- break;
- default:
- if (task->handler == NULL)
- return ide_stopped;
}
-
- return ide_stopped;
}

EXPORT_SYMBOL(do_rw_taskfile);
@@ -892,69 +896,3 @@ int ide_task_ioctl(ide_drive_t *drive, u

return ret;
}
-
-/*
- * NOTICE: This is additions from IBM to provide a discrete interface,
- * for selective taskregister access operations. Nice JOB Klaus!!!
- * Glad to be able to work and co-develop this with you and IBM.
- */
-ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = HWIF(drive);
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
-#if DEBUG_TASKFILE
- u8 status;
-#endif
-
- if (task->data_phase == TASKFILE_MULTI_IN ||
- task->data_phase == TASKFILE_MULTI_OUT) {
- if (!drive->mult_count) {
- printk(KERN_ERR "%s: multimode not set!\n", drive->name);
- return ide_stopped;
- }
- }
-
- /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
- if (IDE_CONTROL_REG)
- /* clear nIEN */
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
- SELECT_MASK(drive, 0);
-
-#if DEBUG_TASKFILE
- status = hwif->INB(IDE_STATUS_REG);
- if (status & 0x80) {
- printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status);
- udelay(100);
- status = hwif->INB(IDE_STATUS_REG);
- printk("flagged_taskfile -> Status = %02x\n", status);
- }
-#endif
-
- ide_write_taskfile(drive, task);
-
- switch(task->data_phase) {
-
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- hwif->dma_setup(drive);
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
- break;
-
- default:
- if (task->handler == NULL)
- return ide_stopped;
-
- /* Issue the command */
- if (task->prehandler) {
- hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
- ndelay(400); /* FIXME */
- return task->prehandler(drive, task->rq);
- }
- ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
- }
-
- return ide_started;
-}
Index: linux-ide-series3-export/include/linux/ide.h
===================================================================
--- linux-ide-series3-export.orig/include/linux/ide.h 2005-02-06 19:49:19.495897866 +0900
+++ linux-ide-series3-export/include/linux/ide.h 2005-02-06 19:49:19.841841663 +0900
@@ -1303,11 +1303,6 @@ void ide_read_taskfile(ide_drive_t *driv
*/
extern ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);

-/*
- * Special Flagged Register Validation Caller
- */
-extern ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *);
-
extern ide_startstop_t set_multmode_intr(ide_drive_t *);
extern ide_startstop_t set_geometry_intr(ide_drive_t *);
extern ide_startstop_t recal_intr(ide_drive_t *);

2005-02-06 11:28:23

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 2.6.11-rc2 02/04] ide: __ide_do_rw_disk() rewritten ide_write_taskfile().


02_ide_do_rw_disk_use_write_taskfile.patch

__ide_do_rw_disk() rewritten using ide_write_taskfile().


Signed-off-by: Tejun Heo <[email protected]>


Index: linux-ide-series3-export/drivers/ide/ide-disk.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-disk.c 2005-02-06 19:48:58.744269198 +0900
+++ linux-ide-series3-export/drivers/ide/ide-disk.c 2005-02-06 19:49:19.141955368 +0900
@@ -119,118 +119,80 @@ static int lba_capacity_is_ok (struct hd
/*
* __ide_do_rw_disk() issues READ and WRITE commands to a disk,
* using LBA if supported, or CHS otherwise, to address sectors.
- * It also takes care of issuing special DRIVE_CMDs.
*/
-ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
+ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
{
- ide_hwif_t *hwif = HWIF(drive);
- unsigned int dma = drive->using_dma;
- u8 lba48 = (drive->addressing == 1) ? 1 : 0;
- task_ioreg_t command = WIN_NOP;
- ata_nsector_t nsectors;
-
- nsectors.all = (u16) rq->nr_sectors;
-
- if (hwif->no_lba48_dma && lba48 && dma) {
- if (block + rq->nr_sectors > 1ULL << 28)
- dma = 0;
- }
-
- if (!dma) {
- ide_init_sg_cmd(drive, rq);
- ide_map_sg(drive, rq);
- }
-
- if (IDE_CONTROL_REG)
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
-
+ ide_hwif_t *hwif = drive->hwif;
+ unsigned long *ports = drive->hwif->io_ports;
+ int lba48 = drive->addressing == 1;
+ ide_task_t task;
+ task_ioreg_t *tf = task.tfRegister, *hob = task.hobRegister;
+ task_ioreg_t command;
+
+ /* ALL Command Block Executions SHALL clear nIEN. */
+ if (ports[IDE_CONTROL_OFFSET])
+ hwif->OUTB(drive->ctl, ports[IDE_CONTROL_OFFSET]);
/* FIXME: SELECT_MASK(drive, 0) ? */

- if (drive->select.b.lba) {
- if (drive->addressing == 1) {
- task_ioreg_t tasklets[10];
-
- pr_debug("%s: LBA=0x%012llx\n", drive->name, block);
+ memset(&task, 0, sizeof(task));

- tasklets[0] = 0;
- tasklets[1] = 0;
- tasklets[2] = nsectors.b.low;
- tasklets[3] = nsectors.b.high;
- tasklets[4] = (task_ioreg_t) block;
- tasklets[5] = (task_ioreg_t) (block>>8);
- tasklets[6] = (task_ioreg_t) (block>>16);
- tasklets[7] = (task_ioreg_t) (block>>24);
- if (sizeof(block) == 4) {
- tasklets[8] = (task_ioreg_t) 0;
- tasklets[9] = (task_ioreg_t) 0;
- } else {
- tasklets[8] = (task_ioreg_t)((u64)block >> 32);
- tasklets[9] = (task_ioreg_t)((u64)block >> 40);
- }
-#ifdef DEBUG
- printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
- drive->name, tasklets[3], tasklets[2],
- tasklets[9], tasklets[8], tasklets[7],
- tasklets[6], tasklets[5], tasklets[4]);
-#endif
- hwif->OUTB(tasklets[1], IDE_FEATURE_REG);
- hwif->OUTB(tasklets[3], IDE_NSECTOR_REG);
- hwif->OUTB(tasklets[7], IDE_SECTOR_REG);
- hwif->OUTB(tasklets[8], IDE_LCYL_REG);
- hwif->OUTB(tasklets[9], IDE_HCYL_REG);
-
- hwif->OUTB(tasklets[0], IDE_FEATURE_REG);
- hwif->OUTB(tasklets[2], IDE_NSECTOR_REG);
- hwif->OUTB(tasklets[4], IDE_SECTOR_REG);
- hwif->OUTB(tasklets[5], IDE_LCYL_REG);
- hwif->OUTB(tasklets[6], IDE_HCYL_REG);
- hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG);
- } else {
- hwif->OUTB(0x00, IDE_FEATURE_REG);
- hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
- hwif->OUTB(block, IDE_SECTOR_REG);
- hwif->OUTB(block>>=8, IDE_LCYL_REG);
- hwif->OUTB(block>>=8, IDE_HCYL_REG);
- hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
- }
+ if (drive->select.b.lba) {
+ /* LBA28/LBA48 */
+ tf[IDE_NSECTOR_OFFSET] = rq->nr_sectors;
+ tf[IDE_SECTOR_OFFSET] = block;
+ tf[IDE_LCYL_OFFSET] = block >> 8;
+ tf[IDE_HCYL_OFFSET] = block >> 16;
+
+ if (lba48) {
+ hob[IDE_NSECTOR_OFFSET] = rq->nr_sectors >> 8;
+ hob[IDE_SECTOR_OFFSET] = block >> 24;
+ hob[IDE_LCYL_OFFSET] = block >> 32;
+ hob[IDE_HCYL_OFFSET] = block >> 40;
+ } else
+ tf[IDE_SELECT_OFFSET] = (block >> 24) & 0xf;
} else {
- unsigned int sect,head,cyl,track;
- track = (int)block / drive->sect;
- sect = (int)block % drive->sect + 1;
- hwif->OUTB(sect, IDE_SECTOR_REG);
- head = track % drive->head;
- cyl = track / drive->head;
+ /* CHS */
+ task_ioreg_t track = (int)block / drive->sect;
+ task_ioreg_t cyl = track / drive->head;
+ task_ioreg_t head = track % drive->head;
+ task_ioreg_t sect = (int)block % drive->sect + 1;

pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
-
- hwif->OUTB(0x00, IDE_FEATURE_REG);
- hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
- hwif->OUTB(cyl, IDE_LCYL_REG);
- hwif->OUTB(cyl>>8, IDE_HCYL_REG);
- hwif->OUTB(head|drive->select.all,IDE_SELECT_REG);
- }
-
- if (dma) {
- if (!hwif->dma_setup(drive)) {
- if (rq_data_dir(rq)) {
- command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
- if (drive->vdma)
- command = lba48 ? WIN_WRITE_EXT: WIN_WRITE;
- } else {
- command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
- if (drive->vdma)
- command = lba48 ? WIN_READ_EXT: WIN_READ;
- }
- hwif->dma_exec_cmd(drive, command);
- hwif->dma_start(drive);
- return ide_started;
+ tf[IDE_NSECTOR_OFFSET] = rq->nr_sectors;
+ tf[IDE_SECTOR_OFFSET] = sect;
+ tf[IDE_LCYL_OFFSET] = cyl;
+ tf[IDE_HCYL_OFFSET] = cyl >> 8;
+ tf[IDE_SELECT_OFFSET] = head;
+ }
+
+ ide_write_taskfile(drive, &task);
+
+ if (drive->using_dma &&
+ !(hwif->no_lba48_dma && block + rq->nr_sectors > 1ULL << 28)) {
+ /* DMA */
+ if (hwif->dma_setup(drive))
+ goto fallback_to_pio;
+ if (rq_data_dir(rq) == READ) {
+ command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
+ if (drive->vdma)
+ command = lba48 ? WIN_READ_EXT : WIN_READ;
+ } else {
+ command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+ if (drive->vdma)
+ command = lba48 ? WIN_WRITE_EXT : WIN_WRITE;
}
- /* fallback to PIO */
- ide_init_sg_cmd(drive, rq);
+ hwif->dma_exec_cmd(drive, command);
+ hwif->dma_start(drive);
+ return ide_started;
}

- if (rq_data_dir(rq) == READ) {
+ /* PIO */
+ ide_map_sg(drive, rq);
+ /* dma_setup() has already done ide_map_sg(). */
+ fallback_to_pio:
+ ide_init_sg_cmd(drive, rq);

+ if (rq_data_dir(rq) == READ) {
if (drive->mult_count) {
hwif->data_phase = TASKFILE_MULTI_IN;
command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
@@ -239,7 +201,8 @@ ide_startstop_t __ide_do_rw_disk (ide_dr
command = lba48 ? WIN_READ_EXT : WIN_READ;
}

- ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);
+ ide_execute_command(drive, command, &task_in_intr,
+ WAIT_CMD, NULL);
return ide_started;
} else {
if (drive->mult_count) {
@@ -251,11 +214,11 @@ ide_startstop_t __ide_do_rw_disk (ide_dr
}

/* FIXME: ->OUTBSYNC ? */
- hwif->OUTB(command, IDE_COMMAND_REG);
-
+ hwif->OUTB(command, ports[IDE_COMMAND_OFFSET]);
return pre_task_out_intr(drive, rq);
}
}
+
EXPORT_SYMBOL_GPL(__ide_do_rw_disk);

/*

2005-02-06 11:34:13

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 2.6.11-rc2 03/04] ide: ide_read_taskfile() implemented.


03_ide_read_taskfile.patch

Status reading part of ide_end_drive_cmd() is moved into
a separate function ide_read_taskfile().


Signed-off-by: Tejun Heo <[email protected]>


Index: linux-ide-series3-export/drivers/ide/ide-io.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-io.c 2005-02-06 19:48:58.680279593 +0900
+++ linux-ide-series3-export/drivers/ide/ide-io.c 2005-02-06 19:49:19.496897703 +0900
@@ -339,7 +339,6 @@ static void ide_complete_barrier(ide_dri

void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
{
- ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
struct request *rq;

@@ -351,32 +350,8 @@ void ide_end_drive_cmd (ide_drive_t *dri
ide_task_t *args = (ide_task_t *) rq->special;
if (rq->errors == 0)
rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
-
- if (args) {
- if (args->tf_in_flags.b.data) {
- u16 data = hwif->INW(IDE_DATA_REG);
- args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF;
- args->hobRegister[IDE_DATA_OFFSET] = (data >> 8) & 0xFF;
- }
- args->tfRegister[IDE_ERROR_OFFSET] = err;
- /* be sure we're looking at the low order bits */
- hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
- args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
- args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
- args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
- args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
- args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG);
- args->tfRegister[IDE_STATUS_OFFSET] = stat;
-
- if (drive->addressing == 1) {
- hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
- args->hobRegister[IDE_FEATURE_OFFSET] = hwif->INB(IDE_FEATURE_REG);
- args->hobRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
- args->hobRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG);
- args->hobRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG);
- args->hobRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG);
- }
- }
+ if (args)
+ ide_read_taskfile(drive, args, stat, err);
} else if (blk_pm_request(rq)) {
#ifdef DEBUG_PM
printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
Index: linux-ide-series3-export/drivers/ide/ide-taskfile.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-taskfile.c 2005-02-06 19:49:18.730022291 +0900
+++ linux-ide-series3-export/drivers/ide/ide-taskfile.c 2005-02-06 19:49:19.493898191 +0900
@@ -180,6 +180,41 @@ void ide_write_taskfile(ide_drive_t *dri

EXPORT_SYMBOL(ide_write_taskfile);

+void ide_read_taskfile(ide_drive_t *drive, ide_task_t *task, u8 stat, u8 err)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 (*INB)(unsigned long) = hwif->INB;
+ unsigned long *ports = hwif->io_ports;
+ task_struct_t *tf = (task_struct_t *)task->tfRegister;
+ hob_struct_t *hob = (hob_struct_t *)task->hobRegister;
+
+ if (task->tf_in_flags.b.data) {
+ u16 data = hwif->INW(ports[IDE_DATA_OFFSET]);
+ tf->data = (data) & 0xFF;
+ hob->data = (data >> 8) & 0xFF;
+ }
+
+ if (drive->addressing == 1) {
+ /* read HOB first such that HOB bit stays cleared when
+ we leave this function. */
+ hwif->OUTB(drive->ctl|0x80, ports[IDE_CONTROL_OFFSET]);
+ hob->feature = INB(ports[IDE_FEATURE_OFFSET]);
+ hob->sector_count = INB(ports[IDE_NSECTOR_OFFSET]);
+ hob->sector_number = INB(ports[IDE_SECTOR_OFFSET]);
+ hob->low_cylinder = INB(ports[IDE_LCYL_OFFSET]);
+ hob->high_cylinder = INB(ports[IDE_HCYL_OFFSET]);
+ }
+
+ hwif->OUTB(drive->ctl & ~0x80, ports[IDE_CONTROL_OFFSET]);
+ tf->feature = err;
+ tf->sector_count = INB(ports[IDE_NSECTOR_OFFSET]);
+ tf->sector_number = INB(ports[IDE_SECTOR_OFFSET]);
+ tf->low_cylinder = INB(ports[IDE_LCYL_OFFSET]);
+ tf->high_cylinder = INB(ports[IDE_HCYL_OFFSET]);
+ tf->device_head = INB(ports[IDE_SELECT_OFFSET]);
+ tf->command = stat;
+}
+
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = HWIF(drive);
Index: linux-ide-series3-export/include/linux/ide.h
===================================================================
--- linux-ide-series3-export.orig/include/linux/ide.h 2005-02-06 19:49:18.732021966 +0900
+++ linux-ide-series3-export/include/linux/ide.h 2005-02-06 19:49:19.495897866 +0900
@@ -1296,6 +1296,7 @@ extern int drive_is_ready(ide_drive_t *)
extern int wait_for_ready(ide_drive_t *, int /* timeout */);

void ide_write_taskfile(ide_drive_t *drive, ide_task_t *task);
+void ide_read_taskfile(ide_drive_t *drive, ide_task_t *task, u8 stat, u8 err);

/*
* taskfile io for disks for now...and builds request from ide_ioctl

2005-02-06 11:34:12

by Tejun Heo

[permalink] [raw]
Subject: Re: [PATCH 2.6.11-rc2 01/04] ide: ide_write_taskfile() implemented.


01_ide_write_taskfile.patch

ide_write_taskfile(), which writes the content of a ide_task_t
into the IDE taskfile registers, is implemented, and
do_rw_taskfile() and flagged_taskfile() are converted to use
ide_write_taskfile(). Behavior changes are
- flagged taskfile now honors HOB feature register.
- No do_rw_taskfile() HIHI check on select register. Except
for the DEV bit, all bits are honored.


Signed-off-by: Tejun Heo <[email protected]>


Index: linux-ide-series3-export/drivers/ide/ide-taskfile.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-taskfile.c 2005-02-06 19:48:58.868249056 +0900
+++ linux-ide-series3-export/drivers/ide/ide-taskfile.c 2005-02-06 19:49:18.730022291 +0900
@@ -96,12 +96,94 @@ int taskfile_lib_get_identify (ide_drive
return ide_raw_taskfile(drive, &args, buf);
}

+void ide_write_taskfile(ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ void (*OUTB)(u8, unsigned long) = hwif->OUTB;
+ unsigned long *ports = hwif->io_ports;
+ task_struct_t *tf = (task_struct_t *)task->tfRegister;
+ hob_struct_t *hob = (hob_struct_t *)task->hobRegister;
+
+ /*
+ * (ks) Check taskfile out flags.
+ * If set, then execute as it is defined.
+ * If not set, then,
+ * write all taskfile registers (except data)
+ * write the hob registers (feature,sector,nsector,lcyl,hcyl)
+ */
+ if (task->tf_out_flags.all == 0) {
+ /* Hot path optimization */
+ if (drive->addressing == 1) {
+ /* Send hob registers first */
+ OUTB(hob->feature, ports[IDE_FEATURE_OFFSET]);
+ OUTB(hob->sector_count, ports[IDE_NSECTOR_OFFSET]);
+ OUTB(hob->sector_number, ports[IDE_SECTOR_OFFSET]);
+ OUTB(hob->low_cylinder, ports[IDE_LCYL_OFFSET]);
+ OUTB(hob->high_cylinder, ports[IDE_HCYL_OFFSET]);
+ }
+
+ /* Send now the standard registers */
+ OUTB(tf->feature, ports[IDE_FEATURE_OFFSET]);
+ OUTB(tf->sector_count, ports[IDE_NSECTOR_OFFSET]);
+ OUTB(tf->sector_number, ports[IDE_SECTOR_OFFSET]);
+ OUTB(tf->low_cylinder, ports[IDE_LCYL_OFFSET]);
+ OUTB(tf->high_cylinder, ports[IDE_HCYL_OFFSET]);
+
+ OUTB((tf->device_head & ~0x10) | drive->select.all,
+ ports[IDE_SELECT_OFFSET]);
+
+ return;
+ }
+
+ /* Flagged */
+ if (drive->addressing == 1) {
+ /* (ks) Send hob registers first */
+ if (task->tf_out_flags.b.error_feature)
+ OUTB(hob->feature, ports[IDE_FEATURE_OFFSET]);
+ if (task->tf_out_flags.b.nsector_hob)
+ OUTB(hob->sector_count, ports[IDE_NSECTOR_OFFSET]);
+ if (task->tf_out_flags.b.sector_hob)
+ OUTB(hob->sector_number, ports[IDE_SECTOR_OFFSET]);
+ if (task->tf_out_flags.b.lcyl_hob)
+ OUTB(hob->low_cylinder, ports[IDE_LCYL_OFFSET]);
+ if (task->tf_out_flags.b.hcyl_hob)
+ OUTB(hob->high_cylinder, ports[IDE_HCYL_OFFSET]);
+ }
+
+ /* (ks) Send now the standard registers */
+ if (task->tf_out_flags.b.error_feature)
+ OUTB(tf->feature, ports[IDE_FEATURE_OFFSET]);
+ if (task->tf_out_flags.b.nsector)
+ OUTB(tf->sector_count, ports[IDE_NSECTOR_OFFSET]);
+ if (task->tf_out_flags.b.sector)
+ OUTB(tf->sector_number, ports[IDE_SECTOR_OFFSET]);
+ if (task->tf_out_flags.b.lcyl)
+ OUTB(tf->low_cylinder, ports[IDE_LCYL_OFFSET]);
+ if (task->tf_out_flags.b.hcyl)
+ OUTB(tf->high_cylinder, ports[IDE_HCYL_OFFSET]);
+
+ if (task->tf_out_flags.b.data) {
+ u16 data = tf->data + (hob->data << 8);
+ hwif->OUTW(data, ports[IDE_DATA_OFFSET]);
+ }
+
+ /*
+ * (ks) In the flagged taskfile approch, we will use all
+ * specified registers and the register value will not be
+ * changed, except the select bit (master/slave) in the
+ * drive_head register. We must make sure that the desired
+ * drive is selected.
+ */
+ hwif->OUTB(tf->device_head | drive->select.all,
+ ports[IDE_SELECT_OFFSET]);
+}
+
+EXPORT_SYMBOL(ide_write_taskfile);
+
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = HWIF(drive);
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;

/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
if (IDE_CONTROL_REG) {
@@ -110,21 +192,7 @@ ide_startstop_t do_rw_taskfile (ide_driv
}
SELECT_MASK(drive, 0);

- if (drive->addressing == 1) {
- hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
- hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
- hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
- hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
- hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
- }
-
- hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
- hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
- hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
- hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
- hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
-
- hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
+ ide_write_taskfile(drive, task);

if (task->handler != NULL) {
if (task->prehandler != NULL) {
@@ -799,7 +867,6 @@ ide_startstop_t flagged_taskfile (ide_dr
{
ide_hwif_t *hwif = HWIF(drive);
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
#if DEBUG_TASKFILE
u8 status;
#endif
@@ -812,26 +879,6 @@ ide_startstop_t flagged_taskfile (ide_dr
}
}

- /*
- * (ks) Check taskfile in/out flags.
- * If set, then execute as it is defined.
- * If not set, then define default settings.
- * The default values are:
- * write and read all taskfile registers (except data)
- * write and read the hob registers (sector,nsector,lcyl,hcyl)
- */
- if (task->tf_out_flags.all == 0) {
- task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
- if (drive->addressing == 1)
- task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8);
- }
-
- if (task->tf_in_flags.all == 0) {
- task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if (drive->addressing == 1)
- task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
- }
-
/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
if (IDE_CONTROL_REG)
/* clear nIEN */
@@ -848,42 +895,8 @@ ide_startstop_t flagged_taskfile (ide_dr
}
#endif

- if (task->tf_out_flags.b.data) {
- u16 data = taskfile->data + (hobfile->data << 8);
- hwif->OUTW(data, IDE_DATA_REG);
- }
-
- /* (ks) send hob registers first */
- if (task->tf_out_flags.b.nsector_hob)
- hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
- if (task->tf_out_flags.b.sector_hob)
- hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl_hob)
- hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl_hob)
- hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
-
- /* (ks) Send now the standard registers */
- if (task->tf_out_flags.b.error_feature)
- hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
- /* refers to number of sectors to transfer */
- if (task->tf_out_flags.b.nsector)
- hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to sector offset or start sector */
- if (task->tf_out_flags.b.sector)
- hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl)
- hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl)
- hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
+ ide_write_taskfile(drive, task);

- /*
- * (ks) In the flagged taskfile approch, we will use all specified
- * registers and the register value will not be changed, except the
- * select bit (master/slave) in the drive_head register. We must make
- * sure that the desired drive is selected.
- */
- hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
switch(task->data_phase) {

case TASKFILE_OUT_DMAQ:
Index: linux-ide-series3-export/include/linux/ide.h
===================================================================
--- linux-ide-series3-export.orig/include/linux/ide.h 2005-02-06 19:48:58.869248893 +0900
+++ linux-ide-series3-export/include/linux/ide.h 2005-02-06 19:49:18.732021966 +0900
@@ -1295,6 +1295,8 @@ extern void atapi_output_bytes(ide_drive
extern int drive_is_ready(ide_drive_t *);
extern int wait_for_ready(ide_drive_t *, int /* timeout */);

+void ide_write_taskfile(ide_drive_t *drive, ide_task_t *task);
+
/*
* taskfile io for disks for now...and builds request from ide_ioctl
*/