2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2000 - 2002 Andre Hedrick < andre @ linux - ide . org >
2008-11-02 23:40:08 +03:00
* Copyright ( C ) 2003 Red Hat
2005-04-17 02:20:36 +04:00
*
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/string.h>
# include <linux/kernel.h>
# include <linux/timer.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/major.h>
# include <linux/errno.h>
# include <linux/genhd.h>
# include <linux/blkpg.h>
# include <linux/slab.h>
# include <linux/pci.h>
# include <linux/delay.h>
# include <linux/ide.h>
# include <linux/bitops.h>
2006-07-30 14:03:29 +04:00
# include <linux/nmi.h>
2005-04-17 02:20:36 +04:00
# include <asm/byteorder.h>
# include <asm/irq.h>
# include <asm/uaccess.h>
# include <asm/io.h>
/*
* 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 SELECT_DRIVE ( ide_drive_t * drive )
{
2008-04-18 02:46:26 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = hwif - > port_ops ;
2008-07-23 21:55:53 +04:00
ide_task_t task ;
2008-04-18 02:46:26 +04:00
2008-04-27 00:25:14 +04:00
if ( port_ops & & port_ops - > selectproc )
port_ops - > selectproc ( drive ) ;
2008-04-18 02:46:26 +04:00
2008-07-23 21:55:53 +04:00
memset ( & task , 0 , sizeof ( task ) ) ;
task . tf_flags = IDE_TFLAG_OUT_DEVICE ;
2008-07-23 21:55:56 +04:00
drive - > hwif - > tp_ops - > tf_load ( drive , & task ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-15 23:21:48 +04:00
void SELECT_MASK ( ide_drive_t * drive , int mask )
2005-04-17 02:20:36 +04:00
{
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = drive - > hwif - > port_ops ;
if ( port_ops & & port_ops - > maskproc )
port_ops - > maskproc ( drive , mask ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-23 21:55:56 +04:00
void ide_exec_command ( ide_hwif_t * hwif , u8 cmd )
2008-07-23 21:55:51 +04:00
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
writeb ( cmd , ( void __iomem * ) hwif - > io_ports . command_addr ) ;
else
outb ( cmd , hwif - > io_ports . command_addr ) ;
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_exec_command ) ;
2008-07-23 21:55:51 +04:00
2008-07-23 21:55:56 +04:00
u8 ide_read_status ( ide_hwif_t * hwif )
2008-07-23 21:55:52 +04:00
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
return readb ( ( void __iomem * ) hwif - > io_ports . status_addr ) ;
else
return inb ( hwif - > io_ports . status_addr ) ;
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_read_status ) ;
2008-07-23 21:55:52 +04:00
2008-07-23 21:55:56 +04:00
u8 ide_read_altstatus ( ide_hwif_t * hwif )
2008-07-23 21:55:52 +04:00
{
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
return readb ( ( void __iomem * ) hwif - > io_ports . ctl_addr ) ;
else
return inb ( hwif - > io_ports . ctl_addr ) ;
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_read_altstatus ) ;
2008-07-23 21:55:52 +04:00
2008-07-23 21:55:56 +04:00
void ide_set_irq ( ide_hwif_t * hwif , int on )
2008-07-23 21:55:52 +04:00
{
u8 ctl = ATA_DEVCTL_OBS ;
if ( on = = 4 ) { /* hack for SRST */
ctl | = 4 ;
on & = ~ 4 ;
}
ctl | = on ? 0 : 2 ;
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
writeb ( ctl , ( void __iomem * ) hwif - > io_ports . ctl_addr ) ;
else
outb ( ctl , hwif - > io_ports . ctl_addr ) ;
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_set_irq ) ;
2008-07-23 21:55:52 +04:00
2008-07-23 21:55:56 +04:00
void ide_tf_load ( ide_drive_t * drive , ide_task_t * task )
2008-04-29 01:44:39 +04:00
{
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
struct ide_taskfile * tf = & task - > tf ;
2008-04-29 01:44:41 +04:00
void ( * tf_outb ) ( u8 addr , unsigned long port ) ;
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
2008-04-29 01:44:39 +04:00
u8 HIHI = ( task - > tf_flags & IDE_TFLAG_LBA48 ) ? 0xE0 : 0xEF ;
2008-04-29 01:44:41 +04:00
if ( mmio )
tf_outb = ide_mm_outb ;
else
tf_outb = ide_outb ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_FLAGGED )
HIHI = 0xFF ;
2008-04-29 01:44:41 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_DATA ) {
u16 data = ( tf - > hob_data < < 8 ) | tf - > data ;
if ( mmio )
writew ( data , ( void __iomem * ) io_ports - > data_addr ) ;
else
outw ( data , io_ports - > data_addr ) ;
}
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_HOB_FEATURE )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > hob_feature , io_ports - > feature_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_HOB_NSECT )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > hob_nsect , io_ports - > nsect_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_HOB_LBAL )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > hob_lbal , io_ports - > lbal_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_HOB_LBAM )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > hob_lbam , io_ports - > lbam_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_HOB_LBAH )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > hob_lbah , io_ports - > lbah_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_FEATURE )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > feature , io_ports - > feature_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_NSECT )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > nsect , io_ports - > nsect_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_LBAL )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > lbal , io_ports - > lbal_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_LBAM )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > lbam , io_ports - > lbam_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_LBAH )
2008-04-29 01:44:41 +04:00
tf_outb ( tf - > lbah , io_ports - > lbah_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_OUT_DEVICE )
2008-10-13 23:39:40 +04:00
tf_outb ( ( tf - > device & HIHI ) | drive - > select ,
2008-04-29 01:44:41 +04:00
io_ports - > device_addr ) ;
2008-04-29 01:44:39 +04:00
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_tf_load ) ;
2008-04-29 01:44:39 +04:00
2008-07-23 21:55:56 +04:00
void ide_tf_read ( ide_drive_t * drive , ide_task_t * task )
2008-04-29 01:44:39 +04:00
{
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
struct ide_taskfile * tf = & task - > tf ;
2008-04-29 01:44:41 +04:00
void ( * tf_outb ) ( u8 addr , unsigned long port ) ;
u8 ( * tf_inb ) ( unsigned long port ) ;
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
if ( mmio ) {
tf_outb = ide_mm_outb ;
tf_inb = ide_mm_inb ;
} else {
tf_outb = ide_outb ;
tf_inb = ide_inb ;
}
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_DATA ) {
2008-04-29 01:44:41 +04:00
u16 data ;
if ( mmio )
data = readw ( ( void __iomem * ) io_ports - > data_addr ) ;
else
data = inw ( io_ports - > data_addr ) ;
2008-04-29 01:44:39 +04:00
tf - > data = data & 0xff ;
tf - > hob_data = ( data > > 8 ) & 0xff ;
}
/* be sure we're looking at the low order bits */
2008-07-15 23:21:50 +04:00
tf_outb ( ATA_DEVCTL_OBS & ~ 0x80 , io_ports - > ctl_addr ) ;
2008-04-29 01:44:39 +04:00
2008-07-23 21:55:53 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_FEATURE )
tf - > feature = tf_inb ( io_ports - > feature_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_NSECT )
2008-04-29 01:44:41 +04:00
tf - > nsect = tf_inb ( io_ports - > nsect_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_LBAL )
2008-04-29 01:44:41 +04:00
tf - > lbal = tf_inb ( io_ports - > lbal_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_LBAM )
2008-04-29 01:44:41 +04:00
tf - > lbam = tf_inb ( io_ports - > lbam_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_LBAH )
2008-04-29 01:44:41 +04:00
tf - > lbah = tf_inb ( io_ports - > lbah_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_DEVICE )
2008-04-29 01:44:41 +04:00
tf - > device = tf_inb ( io_ports - > device_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_LBA48 ) {
2008-07-15 23:21:50 +04:00
tf_outb ( ATA_DEVCTL_OBS | 0x80 , io_ports - > ctl_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_HOB_FEATURE )
2008-04-29 01:44:41 +04:00
tf - > hob_feature = tf_inb ( io_ports - > feature_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_HOB_NSECT )
2008-04-29 01:44:41 +04:00
tf - > hob_nsect = tf_inb ( io_ports - > nsect_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_HOB_LBAL )
2008-04-29 01:44:41 +04:00
tf - > hob_lbal = tf_inb ( io_ports - > lbal_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_HOB_LBAM )
2008-04-29 01:44:41 +04:00
tf - > hob_lbam = tf_inb ( io_ports - > lbam_addr ) ;
2008-04-29 01:44:39 +04:00
if ( task - > tf_flags & IDE_TFLAG_IN_HOB_LBAH )
2008-04-29 01:44:41 +04:00
tf - > hob_lbah = tf_inb ( io_ports - > lbah_addr ) ;
2008-04-29 01:44:39 +04:00
}
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_tf_read ) ;
2008-04-29 01:44:39 +04:00
2005-04-17 02:20:36 +04:00
/*
* 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 .
*/
2008-04-29 01:44:41 +04:00
static void ata_vlb_sync ( unsigned long port )
2005-04-17 02:20:36 +04:00
{
2008-04-29 01:44:41 +04:00
( void ) inb ( port ) ;
( void ) inb ( port ) ;
( void ) inb ( port ) ;
2005-04-17 02:20:36 +04:00
}
/*
* This is used for most PIO data transfers * from * the IDE interface
2008-04-29 01:44:36 +04:00
*
* 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 .
2005-04-17 02:20:36 +04:00
*/
2008-07-23 21:55:56 +04:00
void ide_input_data ( ide_drive_t * drive , struct request * rq , void * buf ,
unsigned int len )
2005-04-17 02:20:36 +04:00
{
2008-04-27 17:38:32 +04:00
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
2008-04-29 01:44:36 +04:00
unsigned long data_addr = io_ports - > data_addr ;
2008-04-27 17:38:32 +04:00
u8 io_32bit = drive - > io_32bit ;
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
2005-04-17 02:20:36 +04:00
2008-04-29 01:44:36 +04:00
len + + ;
2005-04-17 02:20:36 +04:00
if ( io_32bit ) {
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
unsigned long uninitialized_var ( flags ) ;
2008-04-18 02:46:26 +04:00
2008-04-29 01:44:41 +04:00
if ( ( io_32bit & 2 ) & & ! mmio ) {
2005-04-17 02:20:36 +04:00
local_irq_save ( flags ) ;
2008-04-29 01:44:41 +04:00
ata_vlb_sync ( io_ports - > nsect_addr ) ;
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
}
if ( mmio )
__ide_mm_insl ( ( void __iomem * ) data_addr , buf , len / 4 ) ;
else
insl ( data_addr , buf , len / 4 ) ;
2008-04-29 01:44:41 +04:00
if ( ( io_32bit & 2 ) & & ! mmio )
2005-04-17 02:20:36 +04:00
local_irq_restore ( flags ) ;
2008-04-29 01:44:36 +04:00
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
if ( ( len & 3 ) > = 2 ) {
if ( mmio )
__ide_mm_insw ( ( void __iomem * ) data_addr ,
( u8 * ) buf + ( len & ~ 3 ) , 1 ) ;
else
insw ( data_addr , ( u8 * ) buf + ( len & ~ 3 ) , 1 ) ;
}
} else {
if ( mmio )
__ide_mm_insw ( ( void __iomem * ) data_addr , buf , len / 2 ) ;
else
insw ( data_addr , buf , len / 2 ) ;
}
2005-04-17 02:20:36 +04:00
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_input_data ) ;
2005-04-17 02:20:36 +04:00
/*
* This is used for most PIO data transfers * to * the IDE interface
*/
2008-07-23 21:55:56 +04:00
void ide_output_data ( ide_drive_t * drive , struct request * rq , void * buf ,
unsigned int len )
2005-04-17 02:20:36 +04:00
{
2008-04-27 17:38:32 +04:00
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
2008-04-29 01:44:36 +04:00
unsigned long data_addr = io_ports - > data_addr ;
2008-04-27 17:38:32 +04:00
u8 io_32bit = drive - > io_32bit ;
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
u8 mmio = ( hwif - > host_flags & IDE_HFLAG_MMIO ) ? 1 : 0 ;
2005-04-17 02:20:36 +04:00
if ( io_32bit ) {
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
unsigned long uninitialized_var ( flags ) ;
2008-04-18 02:46:26 +04:00
2008-04-29 01:44:41 +04:00
if ( ( io_32bit & 2 ) & & ! mmio ) {
2005-04-17 02:20:36 +04:00
local_irq_save ( flags ) ;
2008-04-29 01:44:41 +04:00
ata_vlb_sync ( io_ports - > nsect_addr ) ;
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
}
if ( mmio )
__ide_mm_outsl ( ( void __iomem * ) data_addr , buf , len / 4 ) ;
else
outsl ( data_addr , buf , len / 4 ) ;
2008-04-29 01:44:41 +04:00
if ( ( io_32bit & 2 ) & & ! mmio )
2005-04-17 02:20:36 +04:00
local_irq_restore ( flags ) ;
ide: remove ->INS{W,L} and ->OUTS{W,L} methods
* Use ins{w,l}()/outs{w,l}() and __ide_mm_ins{w,l}()/__ide_mm_outs{w,l}()
directly in ata_{in,out}put_data() (by using IDE_HFLAG_MMIO host flag to
decide which I/O ops are required).
* Remove no longer needed ->INS{W,L} and ->OUTS{W,L} methods (ide-h8300,
au1xxx-ide and scc_pata implement their own ->{in,out}put_data methods).
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-04-29 01:44:37 +04:00
if ( ( len & 3 ) > = 2 ) {
if ( mmio )
__ide_mm_outsw ( ( void __iomem * ) data_addr ,
( u8 * ) buf + ( len & ~ 3 ) , 1 ) ;
else
outsw ( data_addr , ( u8 * ) buf + ( len & ~ 3 ) , 1 ) ;
}
} else {
if ( mmio )
__ide_mm_outsw ( ( void __iomem * ) data_addr , buf , len / 2 ) ;
else
outsw ( data_addr , buf , len / 2 ) ;
}
2005-04-17 02:20:36 +04:00
}
2008-07-23 21:55:56 +04:00
EXPORT_SYMBOL_GPL ( ide_output_data ) ;
2005-04-17 02:20:36 +04:00
2008-07-23 21:55:53 +04:00
u8 ide_read_error ( ide_drive_t * drive )
{
ide_task_t task ;
memset ( & task , 0 , sizeof ( task ) ) ;
task . tf_flags = IDE_TFLAG_IN_FEATURE ;
2008-07-23 21:55:56 +04:00
drive - > hwif - > tp_ops - > tf_read ( drive , & task ) ;
2008-07-23 21:55:53 +04:00
return task . tf . error ;
}
EXPORT_SYMBOL_GPL ( ide_read_error ) ;
2008-07-23 21:55:54 +04:00
void ide_read_bcount_and_ireason ( ide_drive_t * drive , u16 * bcount , u8 * ireason )
{
ide_task_t task ;
memset ( & task , 0 , sizeof ( task ) ) ;
task . tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
IDE_TFLAG_IN_NSECT ;
2008-07-23 21:55:56 +04:00
drive - > hwif - > tp_ops - > tf_read ( drive , & task ) ;
2008-07-23 21:55:54 +04:00
* bcount = ( task . tf . lbah < < 8 ) | task . tf . lbam ;
* ireason = task . tf . nsect & 3 ;
}
EXPORT_SYMBOL_GPL ( ide_read_bcount_and_ireason ) ;
2008-07-23 21:55:56 +04:00
const struct ide_tp_ops default_tp_ops = {
. exec_command = ide_exec_command ,
. read_status = ide_read_status ,
. read_altstatus = ide_read_altstatus ,
. set_irq = ide_set_irq ,
. tf_load = ide_tf_load ,
. tf_read = ide_tf_read ,
. input_data = ide_input_data ,
. output_data = ide_output_data ,
} ;
2008-10-11 00:39:19 +04:00
void ide_fix_driveid ( u16 * id )
2005-04-17 02:20:36 +04:00
{
# ifndef __LITTLE_ENDIAN
# ifdef __BIG_ENDIAN
int i ;
2008-10-11 00:39:18 +04:00
2008-10-11 00:39:19 +04:00
for ( i = 0 ; i < 256 ; i + + )
2008-10-11 00:39:18 +04:00
id [ i ] = __le16_to_cpu ( id [ i ] ) ;
2005-04-17 02:20:36 +04:00
# else
# error "Please fix <asm / byteorder.h>"
# endif
# endif
}
2007-11-05 23:42:29 +03:00
/*
* ide_fixstring ( ) cleans up and ( optionally ) byte - swaps a text string ,
* removing leading / trailing blanks and compressing internal blanks .
* It is primarily used to tidy up the model name / number fields as
2008-10-11 00:39:21 +04:00
* returned by the ATA_CMD_ID_ATA [ PI ] commands .
2007-11-05 23:42:29 +03:00
*/
2005-04-17 02:20:36 +04:00
void ide_fixstring ( u8 * s , const int bytecount , const int byteswap )
{
ide: re-code ide_fixstring() loop to be less evil
On Friday 25 July 2008, Linus Torvalds wrote:
>
> On Fri, 25 Jul 2008, Ben Dooks wrote:
> >
> > personally, i would much prefer to see the loop being less evil
> > like:
> >
> > for (p = s; p < end; p += 2)
> > be16_to_cpus((u16 *)p);
>
> Well, in this case, the code actually depends on 'p' being back at the
> start of the buffer by the end of it all, so it would need some more
> changes than that.
>
> But yes, I applied David's patch, but I _also_ suspect that we would be
> better off without code that does horrid things like casts and assignments
> inside the function arguments.
>
> So it would be nice to re-code that loop to be more readable. But due to
> the reliance of 'p' being 's' after the loop, the minimal patch would be
> something like the appended.
>
> Bartlomiej - take this or not, I'm not going to commit it - I haven't
> tested it, nor do I even have any machines that would trigger it. So this
> is more a "maybe something like this" than anything else.
From: Linus Torvalds <torvalds@linux-foundation.org>
CC: Ben Dooks <ben-linux@fluff.org>
Cc: David Miller <davem@davemloft.net>
Cc: harvey.harrison@gmail.com
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:22 +04:00
u8 * p , * end = & s [ bytecount & ~ 1 ] ; /* bytecount must be even */
2005-04-17 02:20:36 +04:00
if ( byteswap ) {
/* convert from big-endian to host byte order */
ide: re-code ide_fixstring() loop to be less evil
On Friday 25 July 2008, Linus Torvalds wrote:
>
> On Fri, 25 Jul 2008, Ben Dooks wrote:
> >
> > personally, i would much prefer to see the loop being less evil
> > like:
> >
> > for (p = s; p < end; p += 2)
> > be16_to_cpus((u16 *)p);
>
> Well, in this case, the code actually depends on 'p' being back at the
> start of the buffer by the end of it all, so it would need some more
> changes than that.
>
> But yes, I applied David's patch, but I _also_ suspect that we would be
> better off without code that does horrid things like casts and assignments
> inside the function arguments.
>
> So it would be nice to re-code that loop to be more readable. But due to
> the reliance of 'p' being 's' after the loop, the minimal patch would be
> something like the appended.
>
> Bartlomiej - take this or not, I'm not going to commit it - I haven't
> tested it, nor do I even have any machines that would trigger it. So this
> is more a "maybe something like this" than anything else.
From: Linus Torvalds <torvalds@linux-foundation.org>
CC: Ben Dooks <ben-linux@fluff.org>
Cc: David Miller <davem@davemloft.net>
Cc: harvey.harrison@gmail.com
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:22 +04:00
for ( p = s ; p ! = end ; p + = 2 )
be16_to_cpus ( ( u16 * ) p ) ;
2005-04-17 02:20:36 +04:00
}
ide: re-code ide_fixstring() loop to be less evil
On Friday 25 July 2008, Linus Torvalds wrote:
>
> On Fri, 25 Jul 2008, Ben Dooks wrote:
> >
> > personally, i would much prefer to see the loop being less evil
> > like:
> >
> > for (p = s; p < end; p += 2)
> > be16_to_cpus((u16 *)p);
>
> Well, in this case, the code actually depends on 'p' being back at the
> start of the buffer by the end of it all, so it would need some more
> changes than that.
>
> But yes, I applied David's patch, but I _also_ suspect that we would be
> better off without code that does horrid things like casts and assignments
> inside the function arguments.
>
> So it would be nice to re-code that loop to be more readable. But due to
> the reliance of 'p' being 's' after the loop, the minimal patch would be
> something like the appended.
>
> Bartlomiej - take this or not, I'm not going to commit it - I haven't
> tested it, nor do I even have any machines that would trigger it. So this
> is more a "maybe something like this" than anything else.
From: Linus Torvalds <torvalds@linux-foundation.org>
CC: Ben Dooks <ben-linux@fluff.org>
Cc: David Miller <davem@davemloft.net>
Cc: harvey.harrison@gmail.com
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:22 +04:00
2005-04-17 02:20:36 +04:00
/* strip leading blanks */
ide: re-code ide_fixstring() loop to be less evil
On Friday 25 July 2008, Linus Torvalds wrote:
>
> On Fri, 25 Jul 2008, Ben Dooks wrote:
> >
> > personally, i would much prefer to see the loop being less evil
> > like:
> >
> > for (p = s; p < end; p += 2)
> > be16_to_cpus((u16 *)p);
>
> Well, in this case, the code actually depends on 'p' being back at the
> start of the buffer by the end of it all, so it would need some more
> changes than that.
>
> But yes, I applied David's patch, but I _also_ suspect that we would be
> better off without code that does horrid things like casts and assignments
> inside the function arguments.
>
> So it would be nice to re-code that loop to be more readable. But due to
> the reliance of 'p' being 's' after the loop, the minimal patch would be
> something like the appended.
>
> Bartlomiej - take this or not, I'm not going to commit it - I haven't
> tested it, nor do I even have any machines that would trigger it. So this
> is more a "maybe something like this" than anything else.
From: Linus Torvalds <torvalds@linux-foundation.org>
CC: Ben Dooks <ben-linux@fluff.org>
Cc: David Miller <davem@davemloft.net>
Cc: harvey.harrison@gmail.com
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:22 +04:00
p = s ;
2005-04-17 02:20:36 +04:00
while ( s ! = end & & * s = = ' ' )
+ + s ;
/* compress internal blanks and strip trailing blanks */
while ( s ! = end & & * s ) {
if ( * s + + ! = ' ' | | ( s ! = end & & * s & & * s ! = ' ' ) )
* p + + = * ( s - 1 ) ;
}
/* wipe out trailing garbage */
while ( p ! = end )
* p + + = ' \0 ' ;
}
EXPORT_SYMBOL ( ide_fixstring ) ;
/*
* Needed for PCI irq sharing
*/
int drive_is_ready ( ide_drive_t * drive )
{
2009-01-06 19:20:52 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2005-04-17 02:20:36 +04:00
u8 stat = 0 ;
if ( drive - > waiting_for_dma )
2008-04-27 00:25:24 +04:00
return hwif - > dma_ops - > dma_test_irq ( drive ) ;
2005-04-17 02:20:36 +04:00
/*
* We do a passive status test under shared PCI interrupts on
* cards that truly share the ATA side interrupt , but may also share
* an interrupt with another pci card / device . We make no assumptions
* about possible isa - pnp and pci - pnp issues yet .
*/
2008-12-02 22:40:03 +03:00
if ( hwif - > io_ports . ctl_addr & &
( hwif - > host_flags & IDE_HFLAG_BROKEN_ALTSTATUS ) = = 0 )
2008-07-23 21:55:56 +04:00
stat = hwif - > tp_ops - > read_altstatus ( hwif ) ;
2005-04-17 02:20:36 +04:00
else
/* Note: this may clear a pending IRQ!! */
2008-07-23 21:55:56 +04:00
stat = hwif - > tp_ops - > read_status ( hwif ) ;
2005-04-17 02:20:36 +04:00
2008-10-11 00:39:21 +04:00
if ( stat & ATA_BUSY )
2005-04-17 02:20:36 +04:00
/* drive busy: definitely not interrupting */
return 0 ;
/* drive ready: *might* be interrupting */
return 1 ;
}
EXPORT_SYMBOL ( drive_is_ready ) ;
/*
* This routine busy - waits for the drive status to be not " busy " .
* It then checks the status for all of the " good " bits and none
* of the " bad " bits , and if all is okay it returns 0. All other
2007-10-13 19:47:49 +04:00
* cases return error - - caller may then invoke ide_error ( ) .
2005-04-17 02:20:36 +04:00
*
* This routine should get fixed to not hog the cpu during extra long waits . .
* That could be done by busy - waiting for the first jiffy or two , and then
* setting a timer to wake up at half second intervals thereafter ,
* until timeout is achieved , before timing out .
*/
2007-10-13 19:47:50 +04:00
static int __ide_wait_stat ( ide_drive_t * drive , u8 good , u8 bad , unsigned long timeout , u8 * rstat )
2005-04-17 02:20:36 +04:00
{
2008-07-23 21:55:52 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-07-23 21:55:56 +04:00
const struct ide_tp_ops * tp_ops = hwif - > tp_ops ;
2005-04-17 02:20:36 +04:00
unsigned long flags ;
2007-10-13 19:47:49 +04:00
int i ;
u8 stat ;
2005-04-17 02:20:36 +04:00
udelay ( 1 ) ; /* spec allows drive 400ns to assert "BUSY" */
2008-07-23 21:55:56 +04:00
stat = tp_ops - > read_status ( hwif ) ;
2008-02-06 04:57:51 +03:00
2008-10-11 00:39:21 +04:00
if ( stat & ATA_BUSY ) {
2009-01-06 19:20:52 +03:00
local_irq_save ( flags ) ;
local_irq_enable_in_hardirq ( ) ;
2005-04-17 02:20:36 +04:00
timeout + = jiffies ;
2008-10-11 00:39:21 +04:00
while ( ( stat = tp_ops - > read_status ( hwif ) ) & ATA_BUSY ) {
2005-04-17 02:20:36 +04:00
if ( time_after ( jiffies , timeout ) ) {
/*
* One last read after the timeout in case
* heavy interrupt load made us not make any
* progress during the timeout . .
*/
2008-07-23 21:55:56 +04:00
stat = tp_ops - > read_status ( hwif ) ;
2008-10-11 00:39:21 +04:00
if ( ( stat & ATA_BUSY ) = = 0 )
2005-04-17 02:20:36 +04:00
break ;
local_irq_restore ( flags ) ;
2007-10-13 19:47:49 +04:00
* rstat = stat ;
return - EBUSY ;
2005-04-17 02:20:36 +04:00
}
}
local_irq_restore ( flags ) ;
}
/*
* Allow status to settle , then read it again .
* A few rare drives vastly violate the 400 ns spec here ,
* so we ' ll wait up to 10u sec for a " good " status
* rather than expensively fail things immediately .
* This fix courtesy of Matthew Faupel & Niccolo Rigacci .
*/
for ( i = 0 ; i < 10 ; i + + ) {
udelay ( 1 ) ;
2008-07-23 21:55:56 +04:00
stat = tp_ops - > read_status ( hwif ) ;
2008-02-06 04:57:51 +03:00
if ( OK_STAT ( stat , good , bad ) ) {
2007-10-13 19:47:49 +04:00
* rstat = stat ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-10-13 19:47:49 +04:00
}
2005-04-17 02:20:36 +04:00
}
2007-10-13 19:47:49 +04:00
* rstat = stat ;
return - EFAULT ;
}
/*
* In case of error returns error value after doing " *startstop = ide_error() " .
* The caller should return the updated value of " startstop " in this case ,
* " startstop " is unchanged when the function returns 0.
*/
int ide_wait_stat ( ide_startstop_t * startstop , ide_drive_t * drive , u8 good , u8 bad , unsigned long timeout )
{
int err ;
u8 stat ;
/* bail early if we've exceeded max_failures */
if ( drive - > max_failures & & ( drive - > failures > drive - > max_failures ) ) {
* startstop = ide_stopped ;
return 1 ;
}
err = __ide_wait_stat ( drive , good , bad , timeout , & stat ) ;
if ( err ) {
char * s = ( err = = - EBUSY ) ? " status timeout " : " status error " ;
* startstop = ide_error ( drive , s , stat ) ;
}
return err ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( ide_wait_stat ) ;
2007-08-21 00:42:56 +04:00
/**
* ide_in_drive_list - look for drive in black / white list
* @ id : drive identifier
2008-10-11 00:39:19 +04:00
* @ table : list to inspect
2007-08-21 00:42:56 +04:00
*
* Look for a drive in the blacklist and the whitelist tables
* Returns 1 if the drive is found in the table .
*/
2008-10-11 00:39:19 +04:00
int ide_in_drive_list ( u16 * id , const struct drive_list_entry * table )
2007-08-21 00:42:56 +04:00
{
2008-10-11 00:39:19 +04:00
for ( ; table - > id_model ; table + + )
if ( ( ! strcmp ( table - > id_model , ( char * ) & id [ ATA_ID_PROD ] ) ) & &
( ! table - > id_firmware | |
strstr ( ( char * ) & id [ ATA_ID_FW_REV ] , table - > id_firmware ) ) )
2007-08-21 00:42:56 +04:00
return 1 ;
return 0 ;
}
2007-08-21 00:42:57 +04:00
EXPORT_SYMBOL_GPL ( ide_in_drive_list ) ;
2007-08-21 00:42:56 +04:00
/*
* Early UDMA66 devices don ' t set bit14 to 1 , only bit13 is valid .
* We list them here and depend on the device side cable detection for them .
2007-10-26 22:31:16 +04:00
*
* Some optical devices with the buggy firmwares have the same problem .
2007-08-21 00:42:56 +04:00
*/
static const struct drive_list_entry ivb_list [ ] = {
{ " QUANTUM FIREBALLlct10 05 " , " A03.0900 " } ,
2007-10-26 22:31:16 +04:00
{ " TSSTcorp CDDVDW SH-S202J " , " SB00 " } ,
2007-11-27 23:35:57 +03:00
{ " TSSTcorp CDDVDW SH-S202J " , " SB01 " } ,
{ " TSSTcorp CDDVDW SH-S202N " , " SB00 " } ,
{ " TSSTcorp CDDVDW SH-S202N " , " SB01 " } ,
2008-04-29 01:44:43 +04:00
{ " TSSTcorp CDDVDW SH-S202H " , " SB00 " } ,
{ " TSSTcorp CDDVDW SH-S202H " , " SB01 " } ,
2008-12-02 22:40:03 +03:00
{ " SAMSUNG SP0822N " , " WA100-10 " } ,
2007-08-21 00:42:56 +04:00
{ NULL , NULL }
} ;
2005-04-17 02:20:36 +04:00
/*
* All hosts that use the 80 c ribbon must use !
* The name is derived from upper byte of word 93 and the 80 c ribbon .
*/
u8 eighty_ninty_three ( ide_drive_t * drive )
{
2007-05-10 02:01:10 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-10-11 00:39:19 +04:00
u16 * id = drive - > id ;
2007-08-21 00:42:56 +04:00
int ivb = ide_in_drive_list ( id , ivb_list ) ;
2007-05-10 02:01:10 +04:00
2007-07-10 01:17:58 +04:00
if ( hwif - > cbl = = ATA_CBL_PATA40_SHORT )
return 1 ;
2007-08-21 00:42:56 +04:00
if ( ivb )
printk ( KERN_DEBUG " %s: skipping word 93 validity check \n " ,
drive - > name ) ;
2008-10-11 00:39:30 +04:00
if ( ata_id_is_sata ( id ) & & ! ivb )
2008-01-11 01:03:42 +03:00
return 1 ;
2007-08-21 00:42:56 +04:00
if ( hwif - > cbl ! = ATA_CBL_PATA80 & & ! ivb )
2007-05-10 02:01:10 +04:00
goto no_80w ;
2006-06-28 15:26:58 +04:00
2007-03-27 01:03:18 +04:00
/*
* FIXME :
2008-03-29 21:48:21 +03:00
* - change master / slave IDENTIFY order
2007-08-21 00:42:56 +04:00
* - force bit13 ( 80 c cable present ) check also for ! ivb devices
2007-03-27 01:03:18 +04:00
* ( unless the slave device is pre - ATA3 )
*/
2008-10-11 00:39:19 +04:00
if ( ( id [ ATA_ID_HW_CONFIG ] & 0x4000 ) | |
( ivb & & ( id [ ATA_ID_HW_CONFIG ] & 0x2000 ) ) )
2007-05-10 02:01:10 +04:00
return 1 ;
no_80w :
2008-10-13 23:39:36 +04:00
if ( drive - > dev_flags & IDE_DFLAG_UDMA33_WARNED )
2007-05-10 02:01:10 +04:00
return 0 ;
printk ( KERN_WARNING " %s: %s side 80-wire cable detection failed, "
" limiting max speed to UDMA33 \n " ,
2007-07-10 01:17:58 +04:00
drive - > name ,
hwif - > cbl = = ATA_CBL_PATA80 ? " drive " : " host " ) ;
2007-05-10 02:01:10 +04:00
2008-10-13 23:39:36 +04:00
drive - > dev_flags | = IDE_DFLAG_UDMA33_WARNED ;
2007-05-10 02:01:10 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-10-20 02:32:36 +04:00
int ide_driveid_update ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2007-10-20 02:32:36 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-07-23 21:55:56 +04:00
const struct ide_tp_ops * tp_ops = hwif - > tp_ops ;
2008-10-11 00:39:19 +04:00
u16 * id ;
2008-10-11 00:39:23 +04:00
unsigned long flags ;
2008-02-06 04:57:51 +03:00
u8 stat ;
2005-04-17 02:20:36 +04:00
/*
* Re - read drive - > id for possible DMA mode
* change ( copied from ide - probe . c )
*/
SELECT_MASK ( drive , 1 ) ;
2008-07-23 21:55:56 +04:00
tp_ops - > set_irq ( hwif , 0 ) ;
2005-04-17 02:20:36 +04:00
msleep ( 50 ) ;
2008-10-11 00:39:21 +04:00
tp_ops - > exec_command ( hwif , ATA_CMD_ID_ATA ) ;
2008-02-06 04:57:51 +03:00
2008-10-11 00:39:23 +04:00
if ( ide_busy_sleep ( hwif , WAIT_WORSTCASE , 1 ) ) {
SELECT_MASK ( drive , 0 ) ;
return 0 ;
}
2008-02-06 04:57:51 +03:00
2008-10-11 00:39:21 +04:00
msleep ( 50 ) ; /* wait for IRQ and ATA_DRQ */
2008-07-23 21:55:56 +04:00
stat = tp_ops - > read_status ( hwif ) ;
2008-02-06 04:57:51 +03:00
2008-10-11 00:39:21 +04:00
if ( ! OK_STAT ( stat , ATA_DRQ , BAD_R_STAT ) ) {
2005-04-17 02:20:36 +04:00
SELECT_MASK ( drive , 0 ) ;
printk ( " %s: CHECK for good STATUS \n " , drive - > name ) ;
return 0 ;
}
local_irq_save ( flags ) ;
SELECT_MASK ( drive , 0 ) ;
2008-10-11 00:39:28 +04:00
id = kmalloc ( SECTOR_SIZE , GFP_ATOMIC ) ;
2005-04-17 02:20:36 +04:00
if ( ! id ) {
local_irq_restore ( flags ) ;
return 0 ;
}
2008-07-23 21:55:56 +04:00
tp_ops - > input_data ( drive , NULL , id , SECTOR_SIZE ) ;
( void ) tp_ops - > read_status ( hwif ) ; /* clear drive IRQ */
2005-04-17 02:20:36 +04:00
local_irq_enable ( ) ;
local_irq_restore ( flags ) ;
ide_fix_driveid ( id ) ;
2008-10-11 00:39:19 +04:00
drive - > id [ ATA_ID_UDMA_MODES ] = id [ ATA_ID_UDMA_MODES ] ;
drive - > id [ ATA_ID_MWDMA_MODES ] = id [ ATA_ID_MWDMA_MODES ] ;
drive - > id [ ATA_ID_SWDMA_MODES ] = id [ ATA_ID_SWDMA_MODES ] ;
/* anything more ? */
kfree ( id ) ;
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_USING_DMA ) & & ide_id_dma_bug ( drive ) )
2008-10-11 00:39:19 +04:00
ide_dma_off ( drive ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2007-10-13 19:47:49 +04:00
int ide_config_drive_speed ( ide_drive_t * drive , u8 speed )
2005-04-17 02:20:36 +04:00
{
2007-10-13 19:47:49 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-07-23 21:55:56 +04:00
const struct ide_tp_ops * tp_ops = hwif - > tp_ops ;
2008-10-11 00:39:19 +04:00
u16 * id = drive - > id , i ;
2007-11-27 23:35:52 +03:00
int error = 0 ;
2005-04-17 02:20:36 +04:00
u8 stat ;
2008-07-23 21:55:52 +04:00
ide_task_t task ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_BLK_DEV_IDEDMA
2008-04-27 00:25:24 +04:00
if ( hwif - > dma_ops ) /* check if host supports DMA */
hwif - > dma_ops - > dma_host_set ( drive , 0 ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-11-27 23:35:52 +03:00
/* Skip setting PIO flow-control modes on pre-EIDE drives */
2008-10-11 00:39:19 +04:00
if ( ( speed & 0xf8 ) = = XFER_PIO_0 & & ata_id_has_iordy ( drive - > id ) = = 0 )
2007-11-27 23:35:52 +03:00
goto skip ;
2005-04-17 02:20:36 +04:00
/*
* Don ' t use ide_wait_cmd here - it will
* attempt to set_geometry and recalibrate ,
* but for some reason these don ' t work at
* this point ( lost interrupt ) .
*/
/*
* Select the drive , and issue the SETFEATURES command
*/
disable_irq_nosync ( hwif - > irq ) ;
/*
* FIXME : we race against the running IRQ here if
* this is called from non IRQ context . If we use
* disable_irq ( ) we hang on the error path . Work
* is needed .
*/
udelay ( 1 ) ;
SELECT_DRIVE ( drive ) ;
2008-10-17 20:09:15 +04:00
SELECT_MASK ( drive , 1 ) ;
2005-04-17 02:20:36 +04:00
udelay ( 1 ) ;
2008-07-23 21:55:56 +04:00
tp_ops - > set_irq ( hwif , 0 ) ;
2008-07-23 21:55:52 +04:00
memset ( & task , 0 , sizeof ( task ) ) ;
task . tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT ;
task . tf . feature = SETFEATURES_XFER ;
task . tf . nsect = speed ;
2008-07-23 21:55:56 +04:00
tp_ops - > tf_load ( drive , & task ) ;
2008-07-23 21:55:52 +04:00
2008-10-11 00:39:21 +04:00
tp_ops - > exec_command ( hwif , ATA_CMD_SET_FEATURES ) ;
2008-07-23 21:55:52 +04:00
2008-01-26 22:13:08 +03:00
if ( drive - > quirk_list = = 2 )
2008-07-23 21:55:56 +04:00
tp_ops - > set_irq ( hwif , 1 ) ;
2005-04-17 02:20:36 +04:00
2007-10-13 19:47:49 +04:00
error = __ide_wait_stat ( drive , drive - > ready_stat ,
2008-10-11 00:39:21 +04:00
ATA_BUSY | ATA_DRQ | ATA_ERR ,
2007-10-13 19:47:49 +04:00
WAIT_CMD , & stat ) ;
2005-04-17 02:20:36 +04:00
SELECT_MASK ( drive , 0 ) ;
enable_irq ( hwif - > irq ) ;
if ( error ) {
( void ) ide_dump_status ( drive , " set_drive_speed_status " , stat ) ;
return error ;
}
2008-10-11 00:39:19 +04:00
id [ ATA_ID_UDMA_MODES ] & = ~ 0xFF00 ;
id [ ATA_ID_MWDMA_MODES ] & = ~ 0x0F00 ;
id [ ATA_ID_SWDMA_MODES ] & = ~ 0x0F00 ;
2005-04-17 02:20:36 +04:00
2007-11-27 23:35:52 +03:00
skip :
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_BLK_DEV_IDEDMA
2008-10-13 23:39:36 +04:00
if ( speed > = XFER_SW_DMA_0 & & ( drive - > dev_flags & IDE_DFLAG_USING_DMA ) )
2008-04-27 00:25:24 +04:00
hwif - > dma_ops - > dma_host_set ( drive , 1 ) ;
else if ( hwif - > dma_ops ) /* check if host supports DMA */
2008-01-26 22:13:01 +03:00
ide_dma_off_quietly ( drive ) ;
2005-04-17 02:20:36 +04:00
# endif
2008-10-11 00:39:19 +04:00
if ( speed > = XFER_UDMA_0 ) {
i = 1 < < ( speed - XFER_UDMA_0 ) ;
id [ ATA_ID_UDMA_MODES ] | = ( i < < 8 | i ) ;
} else if ( speed > = XFER_MW_DMA_0 ) {
i = 1 < < ( speed - XFER_MW_DMA_0 ) ;
id [ ATA_ID_MWDMA_MODES ] | = ( i < < 8 | i ) ;
} else if ( speed > = XFER_SW_DMA_0 ) {
i = 1 < < ( speed - XFER_SW_DMA_0 ) ;
id [ ATA_ID_SWDMA_MODES ] | = ( i < < 8 | i ) ;
2005-04-17 02:20:36 +04:00
}
2008-10-11 00:39:19 +04:00
2005-04-17 02:20:36 +04:00
if ( ! drive - > init_speed )
drive - > init_speed = speed ;
drive - > current_speed = speed ;
return error ;
}
/*
* This should get invoked any time we exit the driver to
* wait for an interrupt response from a drive . handler ( ) points
* at the appropriate code to handle the next interrupt , and a
* timer is started to prevent us from waiting forever in case
* something goes wrong ( see the ide_timer_expiry ( ) handler later on ) .
*
* See also ide_execute_command
*/
static void __ide_set_handler ( ide_drive_t * drive , ide_handler_t * handler ,
unsigned int timeout , ide_expiry_t * expiry )
{
2009-01-06 19:20:50 +03:00
ide_hwif_t * hwif = drive - > hwif ;
BUG_ON ( hwif - > handler ) ;
hwif - > handler = handler ;
hwif - > expiry = expiry ;
hwif - > timer . expires = jiffies + timeout ;
hwif - > req_gen_timer = hwif - > req_gen ;
add_timer ( & hwif - > timer ) ;
2005-04-17 02:20:36 +04:00
}
void ide_set_handler ( ide_drive_t * drive , ide_handler_t * handler ,
unsigned int timeout , ide_expiry_t * expiry )
{
2009-01-06 19:20:50 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2005-04-17 02:20:36 +04:00
unsigned long flags ;
2008-12-29 22:27:31 +03:00
2009-01-06 19:20:50 +03:00
spin_lock_irqsave ( & hwif - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
__ide_set_handler ( drive , handler , timeout , expiry ) ;
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( ide_set_handler ) ;
/**
* ide_execute_command - execute an IDE command
* @ drive : IDE drive to issue the command against
* @ command : command byte to write
* @ handler : handler for next phase
* @ timeout : timeout for command
* @ expiry : handler to run on timeout
*
* Helper function to issue an IDE command . This handles the
* atomicity requirements , command timing and ensures that the
* handler and IRQ setup do not race . All IDE command kick off
* should go via this function or do equivalent locking .
*/
2008-01-26 00:17:06 +03:00
void ide_execute_command ( ide_drive_t * drive , u8 cmd , ide_handler_t * handler ,
unsigned timeout , ide_expiry_t * expiry )
2005-04-17 02:20:36 +04:00
{
2008-12-29 22:27:31 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2005-04-17 02:20:36 +04:00
unsigned long flags ;
2008-02-02 21:56:46 +03:00
2009-01-06 19:20:50 +03:00
spin_lock_irqsave ( & hwif - > lock , flags ) ;
2008-02-02 21:56:46 +03:00
__ide_set_handler ( drive , handler , timeout , expiry ) ;
2008-07-23 21:55:56 +04:00
hwif - > tp_ops - > exec_command ( hwif , cmd ) ;
2008-02-02 21:56:46 +03:00
/*
* Drive takes 400 nS to respond , we must avoid the IRQ being
* serviced before that .
*
* FIXME : we could skip this delay with care on non shared devices
*/
2005-04-17 02:20:36 +04:00
ndelay ( 400 ) ;
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( ide_execute_command ) ;
2008-04-29 01:44:39 +04:00
void ide_execute_pkt_cmd ( ide_drive_t * drive )
{
ide_hwif_t * hwif = drive - > hwif ;
unsigned long flags ;
2009-01-06 19:20:50 +03:00
spin_lock_irqsave ( & hwif - > lock , flags ) ;
2008-10-11 00:39:21 +04:00
hwif - > tp_ops - > exec_command ( hwif , ATA_CMD_PACKET ) ;
2008-04-29 01:44:39 +04:00
ndelay ( 400 ) ;
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2008-04-29 01:44:39 +04:00
}
EXPORT_SYMBOL_GPL ( ide_execute_pkt_cmd ) ;
2005-04-17 02:20:36 +04:00
2008-07-16 22:33:48 +04:00
static inline void ide_complete_drive_reset ( ide_drive_t * drive , int err )
2008-07-16 22:33:48 +04:00
{
2009-01-06 19:20:50 +03:00
struct request * rq = drive - > hwif - > rq ;
2008-07-16 22:33:48 +04:00
if ( rq & & blk_special_request ( rq ) & & rq - > cmd [ 0 ] = = REQ_DRIVE_RESET )
2008-07-16 22:33:48 +04:00
ide_end_request ( drive , err ? err : 1 , 0 ) ;
2008-07-16 22:33:48 +04:00
}
2005-04-17 02:20:36 +04:00
/* needed below */
static ide_startstop_t do_reset1 ( ide_drive_t * , int ) ;
/*
* atapi_reset_pollfunc ( ) gets invoked to poll the interface for completion every 50 ms
* during an atapi drive reset operation . If the drive has not yet responded ,
* and we have not yet hit our maximum waiting time , then the timer is restarted
* for another 50 ms .
*/
static ide_startstop_t atapi_reset_pollfunc ( ide_drive_t * drive )
{
2008-07-23 21:55:52 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2005-04-17 02:20:36 +04:00
u8 stat ;
SELECT_DRIVE ( drive ) ;
udelay ( 10 ) ;
2008-07-23 21:55:56 +04:00
stat = hwif - > tp_ops - > read_status ( hwif ) ;
2005-04-17 02:20:36 +04:00
2008-10-11 00:39:21 +04:00
if ( OK_STAT ( stat , 0 , ATA_BUSY ) )
2005-04-17 02:20:36 +04:00
printk ( " %s: ATAPI reset complete \n " , drive - > name ) ;
2008-02-06 04:57:51 +03:00
else {
2009-01-06 19:20:50 +03:00
if ( time_before ( jiffies , hwif - > poll_timeout ) ) {
2005-04-17 02:20:36 +04:00
ide_set_handler ( drive , & atapi_reset_pollfunc , HZ / 20 , NULL ) ;
/* continue polling */
return ide_started ;
}
/* end of polling */
2009-01-06 19:20:50 +03:00
hwif - > polling = 0 ;
2005-04-17 02:20:36 +04:00
printk ( " %s: ATAPI reset timed-out, status=0x%02x \n " ,
drive - > name , stat ) ;
/* do it the old fashioned way */
return do_reset1 ( drive , 1 ) ;
}
/* done polling */
2009-01-06 19:20:50 +03:00
hwif - > polling = 0 ;
2008-07-16 22:33:48 +04:00
ide_complete_drive_reset ( drive , 0 ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
2008-10-13 23:39:41 +04:00
static void ide_reset_report_error ( ide_hwif_t * hwif , u8 err )
{
static const char * err_master_vals [ ] =
{ NULL , " passed " , " formatter device error " ,
" sector buffer error " , " ECC circuitry error " ,
" controlling MPU error " } ;
u8 err_master = err & 0x7f ;
printk ( KERN_ERR " %s: reset: master: " , hwif - > name ) ;
if ( err_master & & err_master < 6 )
printk ( KERN_CONT " %s " , err_master_vals [ err_master ] ) ;
else
printk ( KERN_CONT " error (0x%02x?) " , err ) ;
if ( err & 0x80 )
printk ( KERN_CONT " ; slave: failed " ) ;
printk ( KERN_CONT " \n " ) ;
}
2005-04-17 02:20:36 +04:00
/*
* reset_pollfunc ( ) gets invoked to poll the interface for completion every 50 ms
* during an ide reset operation . If the drives have not yet responded ,
* and we have not yet hit our maximum waiting time , then the timer is restarted
* for another 50 ms .
*/
static ide_startstop_t reset_pollfunc ( ide_drive_t * drive )
{
2009-01-06 19:20:52 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = hwif - > port_ops ;
2005-04-17 02:20:36 +04:00
u8 tmp ;
2008-07-16 22:33:48 +04:00
int err = 0 ;
2005-04-17 02:20:36 +04:00
2008-04-27 00:25:14 +04:00
if ( port_ops & & port_ops - > reset_poll ) {
2008-07-16 22:33:48 +04:00
err = port_ops - > reset_poll ( drive ) ;
if ( err ) {
2005-04-17 02:20:36 +04:00
printk ( KERN_ERR " %s: host reset_poll failure for %s. \n " ,
hwif - > name , drive - > name ) ;
2008-07-16 22:33:48 +04:00
goto out ;
2005-04-17 02:20:36 +04:00
}
}
2008-07-23 21:55:56 +04:00
tmp = hwif - > tp_ops - > read_status ( hwif ) ;
2008-02-06 04:57:51 +03:00
2008-10-11 00:39:21 +04:00
if ( ! OK_STAT ( tmp , 0 , ATA_BUSY ) ) {
2009-01-06 19:20:50 +03:00
if ( time_before ( jiffies , hwif - > poll_timeout ) ) {
2005-04-17 02:20:36 +04:00
ide_set_handler ( drive , & reset_pollfunc , HZ / 20 , NULL ) ;
/* continue polling */
return ide_started ;
}
printk ( " %s: reset timed-out, status=0x%02x \n " , hwif - > name , tmp ) ;
drive - > failures + + ;
2008-07-16 22:33:48 +04:00
err = - EIO ;
2005-04-17 02:20:36 +04:00
} else {
2008-02-06 04:57:51 +03:00
tmp = ide_read_error ( drive ) ;
if ( tmp = = 1 ) {
2008-10-13 23:39:41 +04:00
printk ( KERN_INFO " %s: reset: success \n " , hwif - > name ) ;
2005-04-17 02:20:36 +04:00
drive - > failures = 0 ;
} else {
2008-10-13 23:39:41 +04:00
ide_reset_report_error ( hwif , tmp ) ;
2005-04-17 02:20:36 +04:00
drive - > failures + + ;
2008-07-16 22:33:48 +04:00
err = - EIO ;
2005-04-17 02:20:36 +04:00
}
}
2008-07-16 22:33:48 +04:00
out :
2009-01-06 19:20:50 +03:00
hwif - > polling = 0 ; /* done polling */
2008-07-16 22:33:48 +04:00
ide_complete_drive_reset ( drive , err ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
static void ide_disk_pre_reset ( ide_drive_t * drive )
{
2008-10-11 00:39:19 +04:00
int legacy = ( drive - > id [ ATA_ID_CFS_ENABLE_2 ] & 0x0400 ) ? 0 : 1 ;
2005-04-17 02:20:36 +04:00
drive - > special . all = 0 ;
drive - > special . b . set_geometry = legacy ;
drive - > special . b . recalibrate = legacy ;
2008-10-13 23:39:36 +04:00
2008-01-26 00:17:08 +03:00
drive - > mult_count = 0 ;
2008-10-13 23:39:50 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_PARKED ;
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_KEEP_SETTINGS ) = = 0 & &
( drive - > dev_flags & IDE_DFLAG_USING_DMA ) = = 0 )
2005-04-17 02:20:36 +04:00
drive - > mult_req = 0 ;
2008-10-13 23:39:36 +04:00
2005-04-17 02:20:36 +04:00
if ( drive - > mult_req ! = drive - > mult_count )
drive - > special . b . set_multmode = 1 ;
}
static void pre_reset ( ide_drive_t * drive )
{
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = drive - > hwif - > port_ops ;
2005-04-17 02:20:36 +04:00
if ( drive - > media = = ide_disk )
ide_disk_pre_reset ( drive ) ;
else
2008-10-13 23:39:36 +04:00
drive - > dev_flags | = IDE_DFLAG_POST_RESET ;
2005-04-17 02:20:36 +04:00
2008-10-13 23:39:36 +04:00
if ( drive - > dev_flags & IDE_DFLAG_USING_DMA ) {
2008-02-02 21:56:47 +03:00
if ( drive - > crc_count )
2008-02-02 21:56:47 +03:00
ide_check_dma_crc ( drive ) ;
2008-02-02 21:56:47 +03:00
else
ide_dma_off ( drive ) ;
}
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_KEEP_SETTINGS ) = = 0 ) {
if ( ( drive - > dev_flags & IDE_DFLAG_USING_DMA ) = = 0 ) {
drive - > dev_flags & = ~ IDE_DFLAG_UNMASK ;
2005-04-17 02:20:36 +04:00
drive - > io_32bit = 0 ;
}
return ;
}
2008-04-27 00:25:14 +04:00
if ( port_ops & & port_ops - > pre_reset )
port_ops - > pre_reset ( drive ) ;
2005-04-17 02:20:36 +04:00
2007-03-27 01:03:20 +04:00
if ( drive - > current_speed ! = 0xff )
drive - > desired_speed = drive - > current_speed ;
drive - > current_speed = 0xff ;
2005-04-17 02:20:36 +04:00
}
/*
* do_reset1 ( ) attempts to recover a confused drive by resetting it .
* Unfortunately , resetting a disk drive actually resets all devices on
* the same interface , so it can really be thought of as resetting the
* interface rather than resetting the drive .
*
* ATAPI devices have their own reset mechanism which allows them to be
* individually reset without clobbering other devices on the same interface .
*
* Unfortunately , the IDE interface does not generate an interrupt to let
* us know when the reset operation has finished , so we must poll for this .
* Equally poor , though , is the fact that this may a very long time to complete ,
* ( up to 30 seconds worstcase ) . So , instead of busy - waiting here for it ,
* we set a timer to poll at 50 ms intervals .
*/
static ide_startstop_t do_reset1 ( ide_drive_t * drive , int do_not_try_atapi )
{
2008-12-29 22:27:31 +03:00
ide_hwif_t * hwif = drive - > hwif ;
struct ide_io_ports * io_ports = & hwif - > io_ports ;
const struct ide_tp_ops * tp_ops = hwif - > tp_ops ;
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops ;
2009-01-06 19:20:56 +03:00
ide_drive_t * tdrive ;
2008-12-29 22:27:31 +03:00
unsigned long flags , timeout ;
2009-01-06 19:20:56 +03:00
int i ;
2008-10-13 23:39:50 +04:00
DEFINE_WAIT ( wait ) ;
2008-04-18 02:46:26 +04:00
2009-01-06 19:20:50 +03:00
spin_lock_irqsave ( & hwif - > lock , flags ) ;
2008-07-23 21:55:56 +04:00
2005-04-17 02:20:36 +04:00
/* We must not reset with running handlers */
2009-01-06 19:20:50 +03:00
BUG_ON ( hwif - > handler ! = NULL ) ;
2005-04-17 02:20:36 +04:00
/* For an ATAPI device, first try an ATAPI SRST. */
if ( drive - > media ! = ide_disk & & ! do_not_try_atapi ) {
pre_reset ( drive ) ;
SELECT_DRIVE ( drive ) ;
udelay ( 20 ) ;
2008-10-11 00:39:21 +04:00
tp_ops - > exec_command ( hwif , ATA_CMD_DEV_RESET ) ;
2005-06-28 02:24:25 +04:00
ndelay ( 400 ) ;
2009-01-06 19:20:50 +03:00
hwif - > poll_timeout = jiffies + WAIT_WORSTCASE ;
hwif - > polling = 1 ;
2005-04-17 02:20:36 +04:00
__ide_set_handler ( drive , & atapi_reset_pollfunc , HZ / 20 , NULL ) ;
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
return ide_started ;
}
2008-10-13 23:39:50 +04:00
/* We must not disturb devices in the IDE_DFLAG_PARKED state. */
do {
unsigned long now ;
prepare_to_wait ( & ide_park_wq , & wait , TASK_UNINTERRUPTIBLE ) ;
timeout = jiffies ;
2009-01-06 19:20:56 +03:00
ide_port_for_each_dev ( i , tdrive , hwif ) {
2008-10-13 23:39:50 +04:00
if ( tdrive - > dev_flags & IDE_DFLAG_PRESENT & &
tdrive - > dev_flags & IDE_DFLAG_PARKED & &
time_after ( tdrive - > sleep , timeout ) )
timeout = tdrive - > sleep ;
}
now = jiffies ;
if ( time_before_eq ( timeout , now ) )
break ;
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2008-10-13 23:39:50 +04:00
timeout = schedule_timeout_uninterruptible ( timeout - now ) ;
2009-01-06 19:20:50 +03:00
spin_lock_irqsave ( & hwif - > lock , flags ) ;
2008-10-13 23:39:50 +04:00
} while ( timeout ) ;
finish_wait ( & ide_park_wq , & wait ) ;
2005-04-17 02:20:36 +04:00
/*
* First , reset any device state data we were maintaining
* for any of the drives on this interface .
*/
2009-01-06 19:20:56 +03:00
ide_port_for_each_dev ( i , tdrive , hwif )
pre_reset ( tdrive ) ;
2005-04-17 02:20:36 +04:00
2008-04-27 17:38:32 +04:00
if ( io_ports - > ctl_addr = = 0 ) {
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2008-07-16 22:33:48 +04:00
ide_complete_drive_reset ( drive , - ENXIO ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
/*
* Note that we also set nIEN while resetting the device ,
* to mask unwanted interrupts from the interface during the reset .
* However , due to the design of PC hardware , this will cause an
* immediate interrupt due to the edge transition it produces .
* This single interrupt gives us a " fast poll " for drives that
* recover from reset very quickly , saving us the first 50 ms wait time .
2008-07-23 21:55:52 +04:00
*
* TODO : add - > softreset method and stop abusing - > set_irq
2005-04-17 02:20:36 +04:00
*/
/* set SRST and nIEN */
2008-07-23 21:55:56 +04:00
tp_ops - > set_irq ( hwif , 4 ) ;
2005-04-17 02:20:36 +04:00
/* more than enough time */
udelay ( 10 ) ;
2008-07-23 21:55:52 +04:00
/* clear SRST, leave nIEN (unless device is on the quirk list) */
2008-07-23 21:55:56 +04:00
tp_ops - > set_irq ( hwif , drive - > quirk_list = = 2 ) ;
2005-04-17 02:20:36 +04:00
/* more than enough time */
udelay ( 10 ) ;
2009-01-06 19:20:50 +03:00
hwif - > poll_timeout = jiffies + WAIT_WORSTCASE ;
hwif - > polling = 1 ;
2005-04-17 02:20:36 +04:00
__ide_set_handler ( drive , & reset_pollfunc , HZ / 20 , NULL ) ;
/*
* Some weird controller like resetting themselves to a strange
* state when the disks are reset this way . At least , the Winbond
* 553 documentation says that
*/
2008-04-27 00:25:14 +04:00
port_ops = hwif - > port_ops ;
if ( port_ops & & port_ops - > resetproc )
port_ops - > resetproc ( drive ) ;
2005-04-17 02:20:36 +04:00
2009-01-06 19:20:50 +03:00
spin_unlock_irqrestore ( & hwif - > lock , flags ) ;
2005-04-17 02:20:36 +04:00
return ide_started ;
}
/*
* ide_do_reset ( ) is the entry point to the drive / interface reset code .
*/
ide_startstop_t ide_do_reset ( ide_drive_t * drive )
{
return do_reset1 ( drive , 0 ) ;
}
EXPORT_SYMBOL ( ide_do_reset ) ;
/*
* ide_wait_not_busy ( ) waits for the currently selected device on the hwif
2008-02-02 01:09:36 +03:00
* to report a non - busy status , see comments in ide_probe_port ( ) .
2005-04-17 02:20:36 +04:00
*/
int ide_wait_not_busy ( ide_hwif_t * hwif , unsigned long timeout )
{
u8 stat = 0 ;
while ( timeout - - ) {
/*
* Turn this into a schedule ( ) sleep once I ' m sure
* about locking issues ( 2.5 work ? ) .
*/
mdelay ( 1 ) ;
2008-07-23 21:55:56 +04:00
stat = hwif - > tp_ops - > read_status ( hwif ) ;
2008-10-11 00:39:21 +04:00
if ( ( stat & ATA_BUSY ) = = 0 )
2005-04-17 02:20:36 +04:00
return 0 ;
/*
* Assume a value of 0xff means nothing is connected to
* the interface and it doesn ' t implement the pull - down
* resistor on D7 .
*/
if ( stat = = 0xff )
return - ENODEV ;
2006-02-03 14:04:55 +03:00
touch_softlockup_watchdog ( ) ;
2006-07-30 14:03:29 +04:00
touch_nmi_watchdog ( ) ;
2005-04-17 02:20:36 +04:00
}
return - EBUSY ;
}