falconide/q40ide: add ->atapi_*put_bytes and ->ata_*put_data methods (take 2)

* Add ->atapi_{in,out}put_bytes and ->ata_{in,out}put_data methods to
  falconide and q40ide host drivers (->ata_* methods are implemented on
  top of ->atapi_* methods so they also do byte-swapping now).

* Cleanup atapi_{in,out}put_bytes().

v2:
* Add 'struct request *rq' argument to ->ata_{in,out}put_data methods
  and don't byte-swap disk fs requests (we shouldn't un-swap fs requests
  because fs itself is stored byte-swapped on the disk) - this is how
  things were done before the patch (ideally device mapper should be
  used instead but it would break existing setups and would have some
  performance impact).

Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Michael Schmitz <schmitz@debian.org>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Richard Zidlicky <rz@linux-m68k.org>
Signed-off-by: NBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
上级 284aa76b
...@@ -673,8 +673,10 @@ cris_ide_inb(unsigned long reg) ...@@ -673,8 +673,10 @@ cris_ide_inb(unsigned long reg)
return (unsigned char)cris_ide_inw(reg); return (unsigned char)cris_ide_inw(reg);
} }
static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int); static void cris_ide_input_data(ide_drive_t *, struct request *,
static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int); void *, unsigned int);
static void cris_ide_output_data(ide_drive_t *, struct request *,
void *, unsigned int);
static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int); static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int); static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
...@@ -900,8 +902,8 @@ cris_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun ...@@ -900,8 +902,8 @@ cris_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
/* /*
* This is used for most PIO data transfers *from* the IDE interface * This is used for most PIO data transfers *from* the IDE interface
*/ */
static void static void cris_ide_input_data(ide_drive_t *drive, struct request *rq,
cris_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) void *buffer, unsigned int wcount)
{ {
cris_atapi_input_bytes(drive, buffer, wcount << 2); cris_atapi_input_bytes(drive, buffer, wcount << 2);
} }
...@@ -909,8 +911,8 @@ cris_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) ...@@ -909,8 +911,8 @@ cris_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
/* /*
* This is used for most PIO data transfers *to* the IDE interface * This is used for most PIO data transfers *to* the IDE interface
*/ */
static void static void cris_ide_output_data(ide_drive_t *drive, struct request *,
cris_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) void *buffer, unsigned int wcount)
{ {
cris_atapi_output_bytes(drive, buffer, wcount << 2); cris_atapi_output_bytes(drive, buffer, wcount << 2);
} }
......
...@@ -422,7 +422,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive) ...@@ -422,7 +422,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive)
u32 wcount = (i > 16) ? 16 : i; u32 wcount = (i > 16) ? 16 : i;
i -= wcount; i -= wcount;
HWIF(drive)->ata_input_data(drive, buffer, wcount); drive->hwif->ata_input_data(drive, NULL, buffer, wcount);
} }
} }
......
...@@ -192,7 +192,8 @@ static void ata_vlb_sync(ide_drive_t *drive, unsigned long port) ...@@ -192,7 +192,8 @@ static void ata_vlb_sync(ide_drive_t *drive, unsigned long port)
/* /*
* This is used for most PIO data transfers *from* the IDE interface * This is used for most PIO data transfers *from* the IDE interface
*/ */
static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount) static void ata_input_data(ide_drive_t *drive, struct request *rq,
void *buffer, u32 wcount)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports; struct ide_io_ports *io_ports = &hwif->io_ports;
...@@ -215,7 +216,8 @@ static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount) ...@@ -215,7 +216,8 @@ static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
/* /*
* This is used for most PIO data transfers *to* the IDE interface * This is used for most PIO data transfers *to* the IDE interface
*/ */
static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount) static void ata_output_data(ide_drive_t *drive, struct request *rq,
void *buffer, u32 wcount)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports; struct ide_io_ports *io_ports = &hwif->io_ports;
...@@ -248,14 +250,7 @@ static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount) ...@@ -248,14 +250,7 @@ static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
++bytecount; ++bytecount;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) hwif->ata_input_data(drive, NULL, buffer, bytecount / 4);
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
insw_swapw(hwif->io_ports.data_addr, buffer, bytecount / 2);
return;
}
#endif /* CONFIG_ATARI || CONFIG_Q40 */
hwif->ata_input_data(drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2) if ((bytecount & 0x03) >= 2)
hwif->INSW(hwif->io_ports.data_addr, hwif->INSW(hwif->io_ports.data_addr,
(u8 *)buffer + (bytecount & ~0x03), 1); (u8 *)buffer + (bytecount & ~0x03), 1);
...@@ -266,14 +261,7 @@ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount) ...@@ -266,14 +261,7 @@ static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
++bytecount; ++bytecount;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) hwif->ata_output_data(drive, NULL, buffer, bytecount / 4);
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
outsw_swapw(hwif->io_ports.data_addr, buffer, bytecount / 2);
return;
}
#endif /* CONFIG_ATARI || CONFIG_Q40 */
hwif->ata_output_data(drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2) if ((bytecount & 0x03) >= 2)
hwif->OUTSW(hwif->io_ports.data_addr, hwif->OUTSW(hwif->io_ports.data_addr,
(u8 *)buffer + (bytecount & ~0x03), 1); (u8 *)buffer + (bytecount & ~0x03), 1);
...@@ -668,7 +656,7 @@ int ide_driveid_update(ide_drive_t *drive) ...@@ -668,7 +656,7 @@ int ide_driveid_update(ide_drive_t *drive)
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
hwif->ata_input_data(drive, id, SECTOR_WORDS); hwif->ata_input_data(drive, NULL, id, SECTOR_WORDS);
(void)ide_read_status(drive); /* clear drive IRQ */ (void)ide_read_status(drive); /* clear drive IRQ */
local_irq_enable(); local_irq_enable();
local_irq_restore(flags); local_irq_restore(flags);
......
...@@ -124,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -124,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
id = drive->id; id = drive->id;
/* read 512 bytes of id info */ /* read 512 bytes of id info */
hwif->ata_input_data(drive, id, SECTOR_WORDS); hwif->ata_input_data(drive, NULL, id, SECTOR_WORDS);
drive->id_read = 1; drive->id_read = 1;
local_irq_enable(); local_irq_enable();
......
...@@ -283,7 +283,8 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) ...@@ -283,7 +283,8 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
return stat; return stat;
} }
static void ide_pio_sector(ide_drive_t *drive, unsigned int write) static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
unsigned int write)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table; struct scatterlist *sg = hwif->sg_table;
...@@ -323,9 +324,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) ...@@ -323,9 +324,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
/* do the actual data transfer */ /* do the actual data transfer */
if (write) if (write)
hwif->ata_output_data(drive, buf, SECTOR_WORDS); hwif->ata_output_data(drive, rq, buf, SECTOR_WORDS);
else else
hwif->ata_input_data(drive, buf, SECTOR_WORDS); hwif->ata_input_data(drive, rq, buf, SECTOR_WORDS);
kunmap_atomic(buf, KM_BIO_SRC_IRQ); kunmap_atomic(buf, KM_BIO_SRC_IRQ);
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
...@@ -333,13 +334,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) ...@@ -333,13 +334,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
#endif #endif
} }
static void ide_pio_multi(ide_drive_t *drive, unsigned int write) static void ide_pio_multi(ide_drive_t *drive, struct request *rq,
unsigned int write)
{ {
unsigned int nsect; unsigned int nsect;
nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count); nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count);
while (nsect--) while (nsect--)
ide_pio_sector(drive, write); ide_pio_sector(drive, rq, write);
} }
static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
...@@ -362,10 +364,10 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, ...@@ -362,10 +364,10 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
switch (drive->hwif->data_phase) { switch (drive->hwif->data_phase) {
case TASKFILE_MULTI_IN: case TASKFILE_MULTI_IN:
case TASKFILE_MULTI_OUT: case TASKFILE_MULTI_OUT:
ide_pio_multi(drive, write); ide_pio_multi(drive, rq, write);
break; break;
default: default:
ide_pio_sector(drive, write); ide_pio_sector(drive, rq, write);
break; break;
} }
......
...@@ -44,6 +44,36 @@ ...@@ -44,6 +44,36 @@
int falconide_intr_lock; int falconide_intr_lock;
EXPORT_SYMBOL(falconide_intr_lock); EXPORT_SYMBOL(falconide_intr_lock);
static void falconide_atapi_input_bytes(ide_drive_t *drive, void *buf,
unsigned int len)
{
insw_swapw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
static void falconide_atapi_output_bytes(ide_drive_t *drive, void *buf,
unsigned int len)
{
outsw_swapw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
static void falconide_ata_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int wcount)
{
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return insw(drive->hwif->io_ports.data_addr, buf, wcount * 2);
falconide_atapi_input_bytes(drive, buf, wcount * 4);
}
static void falconide_ata_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int wcount)
{
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return outsw(drive->hwif->io_ports.data_addr, buf, wcount * 2);
falconide_atapi_output_bytes(drive, buf, wcount * 4);
}
static void __init falconide_setup_ports(hw_regs_t *hw) static void __init falconide_setup_ports(hw_regs_t *hw)
{ {
int i; int i;
...@@ -90,6 +120,12 @@ static int __init falconide_init(void) ...@@ -90,6 +120,12 @@ static int __init falconide_init(void)
ide_init_port_data(hwif, index); ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw); ide_init_port_hw(hwif, &hw);
/* Atari has a byte-swapped IDE interface */
hwif->atapi_input_bytes = falconide_atapi_input_bytes;
hwif->atapi_output_bytes = falconide_atapi_output_bytes;
hwif->ata_input_data = falconide_ata_input_data;
hwif->ata_output_data = falconide_ata_output_data;
ide_get_lock(NULL, NULL); ide_get_lock(NULL, NULL);
ide_device_add(idx, NULL); ide_device_add(idx, NULL);
ide_release_lock(); ide_release_lock();
......
...@@ -72,7 +72,35 @@ static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base, ...@@ -72,7 +72,35 @@ static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base,
hw->ack_intr = ack_intr; hw->ack_intr = ack_intr;
} }
static void q40ide_atapi_input_bytes(ide_drive_t *drive, void *buf,
unsigned int len)
{
insw_swapw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
static void q40ide_atapi_output_bytes(ide_drive_t *drive, void *buf,
unsigned int len)
{
outsw_swapw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
static void q40ide_ata_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int wcount)
{
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return insw(drive->hwif->io_ports.data_addr, buf, wcount * 2);
q40ide_atapi_input_bytes(drive, buf, wcount * 4);
}
static void q40ide_ata_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int wcount)
{
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return outsw(drive->hwif->io_ports.data_addr, buf, wcount * 2);
q40ide_atapi_output_bytes(drive, buf, wcount * 4);
}
/* /*
* the static array is needed to have the name reported in /proc/ioports, * the static array is needed to have the name reported in /proc/ioports,
...@@ -123,6 +151,12 @@ static int __init q40ide_init(void) ...@@ -123,6 +151,12 @@ static int __init q40ide_init(void)
ide_init_port_data(hwif, hwif->index); ide_init_port_data(hwif, hwif->index);
ide_init_port_hw(hwif, &hw); ide_init_port_hw(hwif, &hw);
/* Q40 has a byte-swapped IDE interface */
hwif->atapi_input_bytes = q40ide_atapi_input_bytes;
hwif->atapi_output_bytes = q40ide_atapi_output_bytes;
hwif->ata_input_data = q40ide_ata_input_data;
hwif->ata_output_data = q40ide_ata_output_data;
idx[i] = hwif->index; idx[i] = hwif->index;
} }
} }
......
...@@ -467,8 +467,8 @@ typedef struct hwif_s { ...@@ -467,8 +467,8 @@ typedef struct hwif_s {
const struct ide_port_ops *port_ops; const struct ide_port_ops *port_ops;
const struct ide_dma_ops *dma_ops; const struct ide_dma_ops *dma_ops;
void (*ata_input_data)(ide_drive_t *, void *, u32); void (*ata_input_data)(ide_drive_t *, struct request *, void *, u32);
void (*ata_output_data)(ide_drive_t *, void *, u32); void (*ata_output_data)(ide_drive_t *, struct request *, void *, u32);
void (*atapi_input_bytes)(ide_drive_t *, void *, u32); void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
void (*atapi_output_bytes)(ide_drive_t *, void *, u32); void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册