2009-03-25 01:22:46 +03:00
# include <linux/kernel.h>
2011-07-17 23:33:58 +04:00
# include <linux/export.h>
2009-03-25 01:22:46 +03:00
# include <linux/ide.h>
2009-03-27 14:46:26 +03:00
# if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
defined ( CONFIG_PARISC ) | | defined ( CONFIG_PPC ) | | defined ( CONFIG_SPARC )
# include <asm/ide.h>
# else
# include <asm-generic/ide_iops.h>
# endif
2009-03-25 01:22:46 +03:00
/*
* Conventional PIO operations for ATA devices
*/
static u8 ide_inb ( unsigned long port )
{
return ( u8 ) inb ( port ) ;
}
static void ide_outb ( u8 val , unsigned long port )
{
outb ( val , port ) ;
}
/*
* MMIO operations , typically used for SATA controllers
*/
static u8 ide_mm_inb ( unsigned long port )
{
return ( u8 ) readb ( ( void __iomem * ) port ) ;
}
static void ide_mm_outb ( u8 value , unsigned long port )
{
writeb ( value , ( void __iomem * ) port ) ;
}
void ide_exec_command ( ide_hwif_t * hwif , u8 cmd )
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
writeb ( cmd , ( void __iomem * ) hwif - > io_ports . command_addr ) ;
else
outb ( cmd , hwif - > io_ports . command_addr ) ;
}
EXPORT_SYMBOL_GPL ( ide_exec_command ) ;
u8 ide_read_status ( ide_hwif_t * hwif )
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
return readb ( ( void __iomem * ) hwif - > io_ports . status_addr ) ;
else
return inb ( hwif - > io_ports . status_addr ) ;
}
EXPORT_SYMBOL_GPL ( ide_read_status ) ;
u8 ide_read_altstatus ( ide_hwif_t * hwif )
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
return readb ( ( void __iomem * ) hwif - > io_ports . ctl_addr ) ;
else
return inb ( hwif - > io_ports . ctl_addr ) ;
}
EXPORT_SYMBOL_GPL ( ide_read_altstatus ) ;
2009-03-31 22:15:30 +04:00
void ide_write_devctl ( ide_hwif_t * hwif , u8 ctl )
2009-03-25 01:22:46 +03:00
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
writeb ( ctl , ( void __iomem * ) hwif - > io_ports . ctl_addr ) ;
else
outb ( ctl , hwif - > io_ports . ctl_addr ) ;
}
2009-03-31 22:15:30 +04:00
EXPORT_SYMBOL_GPL ( ide_write_devctl ) ;
2009-03-25 01:22:46 +03:00
2009-03-31 22:15:32 +04:00
void ide_dev_select ( ide_drive_t * drive )
{
ide_hwif_t * hwif = drive - > hwif ;
u8 select = drive - > select | ATA_DEVICE_OBS ;
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
writeb ( select , ( void __iomem * ) hwif - > io_ports . device_addr ) ;
else
outb ( select , hwif - > io_ports . device_addr ) ;
}
EXPORT_SYMBOL_GPL ( ide_dev_select ) ;
2009-04-08 16:13:03 +04:00
void ide_tf_load ( ide_drive_t * drive , struct ide_taskfile * tf , u8 valid )
2009-03-25 01:22:46 +03:00
{
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
void ( * tf_outb ) ( u8 addr , unsigned long port ) ;
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
if ( mmio )
tf_outb = ide_mm_outb ;
else
tf_outb = ide_outb ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_FEATURE )
2009-03-25 01:22:46 +03:00
tf_outb ( tf - > feature , io_ports - > feature_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_NSECT )
2009-03-25 01:22:46 +03:00
tf_outb ( tf - > nsect , io_ports - > nsect_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_LBAL )
2009-03-25 01:22:46 +03:00
tf_outb ( tf - > lbal , io_ports - > lbal_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_LBAM )
2009-03-25 01:22:46 +03:00
tf_outb ( tf - > lbam , io_ports - > lbam_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_LBAH )
2009-03-25 01:22:46 +03:00
tf_outb ( tf - > lbah , io_ports - > lbah_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_DEVICE )
2009-04-08 16:13:02 +04:00
tf_outb ( tf - > device , io_ports - > device_addr ) ;
2009-03-25 01:22:46 +03:00
}
EXPORT_SYMBOL_GPL ( ide_tf_load ) ;
2009-04-08 16:13:03 +04:00
void ide_tf_read ( ide_drive_t * drive , struct ide_taskfile * tf , u8 valid )
2009-03-25 01:22:46 +03:00
{
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
u8 ( * tf_inb ) ( unsigned long port ) ;
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
2009-04-08 16:13:02 +04:00
if ( mmio )
2009-03-25 01:22:46 +03:00
tf_inb = ide_mm_inb ;
2009-04-08 16:13:02 +04:00
else
2009-03-25 01:22:46 +03:00
tf_inb = ide_inb ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_ERROR )
2009-03-31 22:15:30 +04:00
tf - > error = tf_inb ( io_ports - > feature_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_NSECT )
2009-03-25 01:22:46 +03:00
tf - > nsect = tf_inb ( io_ports - > nsect_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_LBAL )
2009-03-25 01:22:46 +03:00
tf - > lbal = tf_inb ( io_ports - > lbal_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_LBAM )
2009-03-25 01:22:46 +03:00
tf - > lbam = tf_inb ( io_ports - > lbam_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_LBAH )
2009-03-25 01:22:46 +03:00
tf - > lbah = tf_inb ( io_ports - > lbah_addr ) ;
2009-04-08 16:13:01 +04:00
if ( valid & IDE_VALID_DEVICE )
2009-03-25 01:22:46 +03:00
tf - > device = tf_inb ( io_ports - > device_addr ) ;
}
EXPORT_SYMBOL_GPL ( ide_tf_read ) ;
/*
* Some localbus EIDE interfaces require a special access sequence
* when using 32 - bit I / O instructions to transfer data . We call this
* the " vlb_sync " sequence , which consists of three successive reads
* of the sector count register location , with interrupts disabled
* to ensure that the reads all happen together .
*/
static void ata_vlb_sync ( unsigned long port )
{
( void ) inb ( port ) ;
( void ) inb ( port ) ;
( void ) inb ( port ) ;
}
/*
* This is used for most PIO data transfers * from * the IDE interface
*
* These routines will round up any request for an odd number of bytes ,
* so if an odd len is specified , be sure that there ' s at least one
* extra byte allocated for the buffer .
*/
2009-03-27 14:46:38 +03:00
void ide_input_data ( ide_drive_t * drive , struct ide_cmd * cmd , void * buf ,
2009-03-25 01:22:46 +03:00
unsigned int len )
{
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
unsigned long data_addr = io_ports - > data_addr ;
2009-03-31 22:15:31 +04:00
unsigned int words = ( len + 1 ) > > 1 ;
2009-03-25 01:22:46 +03:00
u8 io_32bit = drive - > io_32bit ;
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
if ( io_32bit ) {
unsigned long uninitialized_var ( flags ) ;
if ( ( io_32bit & 2 ) & & ! mmio ) {
local_irq_save ( flags ) ;
ata_vlb_sync ( io_ports - > nsect_addr ) ;
}
2009-03-31 22:15:31 +04:00
words > > = 1 ;
2009-03-25 01:22:46 +03:00
if ( mmio )
2009-03-31 22:15:31 +04:00
__ide_mm_insl ( ( void __iomem * ) data_addr , buf , words ) ;
2009-03-25 01:22:46 +03:00
else
2009-03-31 22:15:31 +04:00
insl ( data_addr , buf , words ) ;
2009-03-25 01:22:46 +03:00
if ( ( io_32bit & 2 ) & & ! mmio )
local_irq_restore ( flags ) ;
2009-03-31 22:15:31 +04:00
if ( ( ( len + 1 ) & 3 ) < 2 )
return ;
buf + = len & ~ 3 ;
words = 1 ;
2009-03-25 01:22:46 +03:00
}
2009-03-31 22:15:31 +04:00
if ( mmio )
__ide_mm_insw ( ( void __iomem * ) data_addr , buf , words ) ;
else
insw ( data_addr , buf , words ) ;
2009-03-25 01:22:46 +03:00
}
EXPORT_SYMBOL_GPL ( ide_input_data ) ;
/*
* This is used for most PIO data transfers * to * the IDE interface
*/
2009-03-27 14:46:38 +03:00
void ide_output_data ( ide_drive_t * drive , struct ide_cmd * cmd , void * buf ,
2009-03-25 01:22:46 +03:00
unsigned int len )
{
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
unsigned long data_addr = io_ports - > data_addr ;
2009-03-31 22:15:31 +04:00
unsigned int words = ( len + 1 ) > > 1 ;
2009-03-25 01:22:46 +03:00
u8 io_32bit = drive - > io_32bit ;
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
if ( io_32bit ) {
unsigned long uninitialized_var ( flags ) ;
if ( ( io_32bit & 2 ) & & ! mmio ) {
local_irq_save ( flags ) ;
ata_vlb_sync ( io_ports - > nsect_addr ) ;
}
2009-03-31 22:15:31 +04:00
words > > = 1 ;
2009-03-25 01:22:46 +03:00
if ( mmio )
2009-03-31 22:15:31 +04:00
__ide_mm_outsl ( ( void __iomem * ) data_addr , buf , words ) ;
2009-03-25 01:22:46 +03:00
else
2009-03-31 22:15:31 +04:00
outsl ( data_addr , buf , words ) ;
2009-03-25 01:22:46 +03:00
if ( ( io_32bit & 2 ) & & ! mmio )
local_irq_restore ( flags ) ;
2009-03-31 22:15:31 +04:00
if ( ( ( len + 1 ) & 3 ) < 2 )
return ;
buf + = len & ~ 3 ;
words = 1 ;
2009-03-25 01:22:46 +03:00
}
2009-03-31 22:15:31 +04:00
if ( mmio )
__ide_mm_outsw ( ( void __iomem * ) data_addr , buf , words ) ;
else
outsw ( data_addr , buf , words ) ;
2009-03-25 01:22:46 +03:00
}
EXPORT_SYMBOL_GPL ( ide_output_data ) ;
const struct ide_tp_ops default_tp_ops = {
. exec_command = ide_exec_command ,
. read_status = ide_read_status ,
. read_altstatus = ide_read_altstatus ,
2009-03-31 22:15:30 +04:00
. write_devctl = ide_write_devctl ,
2009-03-25 01:22:46 +03:00
2009-03-31 22:15:32 +04:00
. dev_select = ide_dev_select ,
2009-03-25 01:22:46 +03:00
. tf_load = ide_tf_load ,
. tf_read = ide_tf_read ,
. input_data = ide_input_data ,
. output_data = ide_output_data ,
} ;