2005-04-17 02:20:36 +04:00
/*
2008-02-02 01:09:33 +03:00
* Copyright ( C ) 1994 - 1998 Linus Torvalds & authors ( see below )
* Copyright ( C ) 2005 , 2007 Bartlomiej Zolnierkiewicz
2005-04-17 02:20:36 +04:00
*/
/*
* Mostly written by Mark Lord < mlord @ pobox . com >
* and Gadi Oxman < gadio @ netvision . net . il >
* and Andre Hedrick < andre @ linux - ide . org >
*
* See linux / MAINTAINERS for address of current maintainer .
*
* This is the IDE probe module , as evolved from hd . c and ide . c .
*
2007-12-13 01:32:00 +03:00
* - - increase WAIT_PIDENTIFY to avoid CD - ROM locking at boot
* by Andrea Arcangeli
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/slab.h>
# include <linux/delay.h>
# include <linux/ide.h>
# include <linux/spinlock.h>
# include <linux/kmod.h>
# include <linux/pci.h>
2007-10-23 11:29:58 +04:00
# include <linux/scatterlist.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>
/**
* generic_id - add a generic drive id
* @ drive : drive to make an ID block for
*
* Add a fake id field to the drive we are passed . This allows
* use to skip a ton of NULL checks ( which people always miss )
* and make drive properties unconditional outside of this file
*/
static void generic_id ( ide_drive_t * drive )
{
2008-10-11 00:39:19 +04:00
u16 * id = drive - > id ;
id [ ATA_ID_CUR_CYLS ] = id [ ATA_ID_CYLS ] = drive - > cyl ;
id [ ATA_ID_CUR_HEADS ] = id [ ATA_ID_HEADS ] = drive - > head ;
id [ ATA_ID_CUR_SECTORS ] = id [ ATA_ID_SECTORS ] = drive - > sect ;
2005-04-17 02:20:36 +04:00
}
static void ide_disk_init_chs ( ide_drive_t * drive )
{
2008-10-11 00:39:19 +04:00
u16 * id = drive - > id ;
2005-04-17 02:20:36 +04:00
/* Extract geometry if we did not already have one for the drive */
if ( ! drive - > cyl | | ! drive - > head | | ! drive - > sect ) {
2008-10-11 00:39:19 +04:00
drive - > cyl = drive - > bios_cyl = id [ ATA_ID_CYLS ] ;
drive - > head = drive - > bios_head = id [ ATA_ID_HEADS ] ;
drive - > sect = drive - > bios_sect = id [ ATA_ID_SECTORS ] ;
2005-04-17 02:20:36 +04:00
}
/* Handle logical geometry translation by the drive */
2008-10-11 00:39:19 +04:00
if ( ata_id_current_chs_valid ( id ) ) {
2008-10-11 00:39:19 +04:00
drive - > cyl = id [ ATA_ID_CUR_CYLS ] ;
drive - > head = id [ ATA_ID_CUR_HEADS ] ;
drive - > sect = id [ ATA_ID_CUR_SECTORS ] ;
2005-04-17 02:20:36 +04:00
}
/* Use physical geometry if what we have still makes no sense */
2008-10-11 00:39:19 +04:00
if ( drive - > head > 16 & & id [ ATA_ID_HEADS ] & & id [ ATA_ID_HEADS ] < = 16 ) {
drive - > cyl = id [ ATA_ID_CYLS ] ;
drive - > head = id [ ATA_ID_HEADS ] ;
drive - > sect = id [ ATA_ID_SECTORS ] ;
2005-04-17 02:20:36 +04:00
}
}
static void ide_disk_init_mult_count ( ide_drive_t * drive )
{
2008-10-11 00:39:19 +04:00
u16 * id = drive - > id ;
u8 max_multsect = id [ ATA_ID_MAX_MULTSECT ] & 0xff ;
2005-04-17 02:20:36 +04:00
2008-10-11 00:39:19 +04:00
if ( max_multsect ) {
if ( ( max_multsect / 2 ) > 1 )
id [ ATA_ID_MULTSECT ] = max_multsect | 0x100 ;
else
id [ ATA_ID_MULTSECT ] & = ~ 0x1ff ;
drive - > mult_req = id [ ATA_ID_MULTSECT ] & 0xff ;
2008-10-11 00:39:26 +04:00
if ( drive - > mult_req )
2009-05-17 21:12:21 +04:00
drive - > special_flags | = IDE_SFLAG_SET_MULTMODE ;
2005-04-17 02:20:36 +04:00
}
}
2009-01-02 18:12:47 +03:00
static void ide_classify_ata_dev ( ide_drive_t * drive )
{
u16 * id = drive - > id ;
char * m = ( char * ) & id [ ATA_ID_PROD ] ;
int is_cfa = ata_id_is_cfa ( id ) ;
/* CF devices are *not* removable in Linux definition of the term */
if ( is_cfa = = 0 & & ( id [ ATA_ID_CONFIG ] & ( 1 < < 7 ) ) )
drive - > dev_flags | = IDE_DFLAG_REMOVABLE ;
drive - > media = ide_disk ;
if ( ! ata_id_has_unload ( drive - > id ) )
drive - > dev_flags | = IDE_DFLAG_NO_UNLOAD ;
printk ( KERN_INFO " %s: %s, %s DISK drive \n " , drive - > name , m ,
is_cfa ? " CFA " : " ATA " ) ;
}
static void ide_classify_atapi_dev ( ide_drive_t * drive )
{
u16 * id = drive - > id ;
char * m = ( char * ) & id [ ATA_ID_PROD ] ;
u8 type = ( id [ ATA_ID_CONFIG ] > > 8 ) & 0x1f ;
printk ( KERN_INFO " %s: %s, ATAPI " , drive - > name , m ) ;
switch ( type ) {
case ide_floppy :
if ( ! strstr ( m , " CD-ROM " ) ) {
if ( ! strstr ( m , " oppy " ) & &
! strstr ( m , " poyp " ) & &
! strstr ( m , " ZIP " ) )
printk ( KERN_CONT " cdrom or floppy?, assuming " ) ;
if ( drive - > media ! = ide_cdrom ) {
printk ( KERN_CONT " FLOPPY " ) ;
drive - > dev_flags | = IDE_DFLAG_REMOVABLE ;
break ;
}
}
/* Early cdrom models used zero */
type = ide_cdrom ;
case ide_cdrom :
drive - > dev_flags | = IDE_DFLAG_REMOVABLE ;
# ifdef CONFIG_PPC
/* kludge for Apple PowerBook internal zip */
if ( ! strstr ( m , " CD-ROM " ) & & strstr ( m , " ZIP " ) ) {
printk ( KERN_CONT " FLOPPY " ) ;
type = ide_floppy ;
break ;
}
# endif
printk ( KERN_CONT " CD/DVD-ROM " ) ;
break ;
case ide_tape :
printk ( KERN_CONT " TAPE " ) ;
break ;
case ide_optical :
printk ( KERN_CONT " OPTICAL " ) ;
drive - > dev_flags | = IDE_DFLAG_REMOVABLE ;
break ;
default :
printk ( KERN_CONT " UNKNOWN (type %d) " , type ) ;
break ;
}
printk ( KERN_CONT " drive \n " ) ;
drive - > media = type ;
/* an ATAPI device ignores DRDY */
drive - > ready_stat = 0 ;
if ( ata_id_cdb_intr ( id ) )
drive - > atapi_flags | = IDE_AFLAG_DRQ_INTERRUPT ;
drive - > dev_flags | = IDE_DFLAG_DOORLOCKING ;
/* we don't do head unloading on ATAPI devices */
drive - > dev_flags | = IDE_DFLAG_NO_UNLOAD ;
}
2005-04-17 02:20:36 +04:00
/**
* do_identify - identify a drive
* @ drive : drive to identify
* @ cmd : command used
2009-03-25 01:22:59 +03:00
* @ id : buffer for IDENTIFY data
2005-04-17 02:20:36 +04:00
*
* Called when we have issued a drive identify command to
* read and parse the results . This function is run with
* interrupts disabled .
*/
2008-12-29 22:27:36 +03:00
2009-03-25 01:22:59 +03:00
static void do_identify ( ide_drive_t * drive , u8 cmd , u16 * id )
2005-04-17 02:20:36 +04:00
{
2009-01-06 19:20:52 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2008-10-11 00:39:19 +04:00
char * m = ( char * ) & id [ ATA_ID_PROD ] ;
2008-12-29 22:27:38 +03:00
unsigned long flags ;
2009-01-02 18:12:47 +03:00
int bswap = 1 ;
2005-04-17 02:20:36 +04:00
2008-12-29 22:27:38 +03:00
/* local CPU only; some systems need this */
local_irq_save ( flags ) ;
2005-04-17 02:20:36 +04:00
/* read 512 bytes of id info */
2008-07-23 21:55:56 +04:00
hwif - > tp_ops - > input_data ( drive , NULL , id , SECTOR_SIZE ) ;
2008-12-29 22:27:38 +03:00
local_irq_restore ( flags ) ;
2005-04-17 02:20:36 +04:00
2008-10-13 23:39:36 +04:00
drive - > dev_flags | = IDE_DFLAG_ID_READ ;
2008-02-02 01:09:28 +03:00
# ifdef DEBUG
printk ( KERN_INFO " %s: dumping identify data \n " , drive - > name ) ;
ide_dump_identify ( ( u8 * ) id ) ;
# endif
2005-04-17 02:20:36 +04:00
ide_fix_driveid ( id ) ;
/*
2008-10-11 00:39:21 +04:00
* ATA_CMD_ID_ATA returns little - endian info ,
* ATA_CMD_ID_ATAPI * usually * returns little - endian info .
2005-04-17 02:20:36 +04:00
*/
2008-10-11 00:39:21 +04:00
if ( cmd = = ATA_CMD_ID_ATAPI ) {
2008-10-11 00:39:19 +04:00
if ( ( m [ 0 ] = = ' N ' & & m [ 1 ] = = ' E ' ) | | /* NEC */
( m [ 0 ] = = ' F ' & & m [ 1 ] = = ' X ' ) | | /* Mitsumi */
( m [ 0 ] = = ' P ' & & m [ 1 ] = = ' i ' ) ) /* Pioneer */
2005-04-17 02:20:36 +04:00
/* Vertos drives may still be weird */
2008-10-11 00:39:19 +04:00
bswap ^ = 1 ;
2005-04-17 02:20:36 +04:00
}
2008-10-11 00:39:19 +04:00
ide_fixstring ( m , ATA_ID_PROD_LEN , bswap ) ;
ide_fixstring ( ( char * ) & id [ ATA_ID_FW_REV ] , ATA_ID_FW_REV_LEN , bswap ) ;
ide_fixstring ( ( char * ) & id [ ATA_ID_SERNO ] , ATA_ID_SERNO_LEN , bswap ) ;
2005-04-17 02:20:36 +04:00
2007-11-05 23:42:25 +03:00
/* we depend on this a lot! */
2008-10-11 00:39:19 +04:00
m [ ATA_ID_PROD_LEN - 1 ] = ' \0 ' ;
2007-11-05 23:42:25 +03:00
2008-10-11 00:39:19 +04:00
if ( strstr ( m , " E X A B Y T E N E S T " ) )
2009-03-27 14:46:26 +03:00
drive - > dev_flags & = ~ IDE_DFLAG_PRESENT ;
else
drive - > dev_flags | = IDE_DFLAG_PRESENT ;
2005-04-17 02:20:36 +04:00
}
/**
2009-03-25 01:22:59 +03:00
* ide_dev_read_id - send ATA / ATAPI IDENTIFY command
2005-04-17 02:20:36 +04:00
* @ drive : drive to identify
* @ cmd : command to use
2009-03-25 01:22:59 +03:00
* @ id : buffer for IDENTIFY data
2009-06-23 15:29:11 +04:00
* @ irq_ctx : flag set when called from the IRQ context
2005-04-17 02:20:36 +04:00
*
2009-03-25 01:22:59 +03:00
* Sends an ATA ( PI ) IDENTIFY request to a drive and waits for a response .
2005-04-17 02:20:36 +04:00
*
* Returns : 0 device was identified
* 1 device timed - out ( no response to identify request )
* 2 device aborted the command ( refused to identify itself )
*/
2009-06-23 15:29:11 +04:00
int ide_dev_read_id ( ide_drive_t * drive , u8 cmd , u16 * id , int irq_ctx )
2005-04-17 02:20:36 +04:00
{
2009-01-06 19:20:52 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2008-04-27 17:38:32 +04:00
struct ide_io_ports * io_ports = & hwif - > io_ports ;
2008-07-23 21:55:56 +04:00
const struct ide_tp_ops * tp_ops = hwif - > tp_ops ;
2008-02-06 04:57:51 +03:00
int use_altstatus = 0 , rc ;
2005-04-17 02:20:36 +04:00
unsigned long timeout ;
u8 s = 0 , a = 0 ;
2009-03-25 01:22:53 +03:00
/*
* Disable device IRQ . Otherwise we ' ll get spurious interrupts
* during the identify phase that the IRQ handler isn ' t expecting .
*/
if ( io_ports - > ctl_addr )
2009-03-31 22:15:30 +04:00
tp_ops - > write_devctl ( hwif , ATA_NIEN | ATA_DEVCTL_OBS ) ;
2009-03-25 01:22:53 +03:00
2005-04-17 02:20:36 +04:00
/* take a deep breath */
2009-06-23 15:29:11 +04:00
if ( irq_ctx )
mdelay ( 50 ) ;
else
msleep ( 50 ) ;
2005-04-17 02:20:36 +04:00
2008-12-02 22:40:03 +03:00
if ( io_ports - > ctl_addr & &
( hwif - > host_flags & IDE_HFLAG_BROKEN_ALTSTATUS ) = = 0 ) {
2008-07-23 21:55:56 +04:00
a = tp_ops - > read_altstatus ( hwif ) ;
s = tp_ops - > read_status ( hwif ) ;
2008-10-11 00:39:21 +04:00
if ( ( a ^ s ) & ~ ATA_IDX )
2005-04-17 02:20:36 +04:00
/* ancient Seagate drives, broken interfaces */
2008-02-06 04:57:51 +03:00
printk ( KERN_INFO " %s: probing with STATUS(0x%02x) "
" instead of ALTSTATUS(0x%02x) \n " ,
drive - > name , s , a ) ;
else
2005-04-17 02:20:36 +04:00
/* use non-intrusive polling */
2008-02-06 04:57:51 +03:00
use_altstatus = 1 ;
}
2005-04-17 02:20:36 +04:00
/* set features register for atapi
* identify command to be sure of reply
*/
2008-10-11 00:39:21 +04:00
if ( cmd = = ATA_CMD_ID_ATAPI ) {
2009-04-08 16:13:03 +04:00
struct ide_taskfile tf ;
2008-07-23 21:55:53 +04:00
2009-04-08 16:13:03 +04:00
memset ( & tf , 0 , sizeof ( tf ) ) ;
2008-07-23 21:55:53 +04:00
/* disable DMA & overlap */
2009-04-08 16:13:03 +04:00
tp_ops - > tf_load ( drive , & tf , IDE_VALID_FEATURE ) ;
2008-07-23 21:55:53 +04:00
}
2005-04-17 02:20:36 +04:00
/* ask drive for ID */
2008-07-23 21:55:56 +04:00
tp_ops - > exec_command ( hwif , cmd ) ;
2005-04-17 02:20:36 +04:00
2008-10-11 00:39:21 +04:00
timeout = ( ( cmd = = ATA_CMD_ID_ATA ) ? WAIT_WORSTCASE : WAIT_PIDENTIFY ) / 2 ;
2008-10-11 00:39:23 +04:00
2008-10-11 00:39:21 +04:00
/* wait for IRQ and ATA_DRQ */
2009-06-23 15:29:11 +04:00
if ( irq_ctx ) {
rc = __ide_wait_stat ( drive , ATA_DRQ , BAD_R_STAT , timeout , & s ) ;
if ( rc )
return 1 ;
} else {
rc = ide_busy_sleep ( drive , timeout , use_altstatus ) ;
if ( rc )
return 1 ;
msleep ( 50 ) ;
s = tp_ops - > read_status ( hwif ) ;
}
2008-02-06 04:57:51 +03:00
2008-10-11 00:39:21 +04:00
if ( OK_STAT ( s , ATA_DRQ , BAD_R_STAT ) ) {
2005-04-17 02:20:36 +04:00
/* drive returned ID */
2009-03-25 01:22:59 +03:00
do_identify ( drive , cmd , id ) ;
2005-04-17 02:20:36 +04:00
/* drive responded with ID */
rc = 0 ;
/* clear drive IRQ */
2008-07-23 21:55:56 +04:00
( void ) tp_ops - > read_status ( hwif ) ;
2005-04-17 02:20:36 +04:00
} else {
/* drive refused ID */
rc = 2 ;
}
return rc ;
}
2009-05-22 18:23:38 +04:00
int ide_busy_sleep ( ide_drive_t * drive , unsigned long timeout , int altstatus )
2008-01-26 22:13:09 +03:00
{
2009-05-22 18:23:38 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-01-26 22:13:09 +03:00
u8 stat ;
2008-10-11 00:39:23 +04:00
timeout + = jiffies ;
2008-01-26 22:13:09 +03:00
do {
2008-10-11 00:39:23 +04:00
msleep ( 50 ) ; /* give drive a breather */
stat = altstatus ? hwif - > tp_ops - > read_altstatus ( hwif )
: hwif - > tp_ops - > read_status ( hwif ) ;
2008-10-11 00:39:21 +04:00
if ( ( stat & ATA_BUSY ) = = 0 )
2008-01-26 22:13:09 +03:00
return 0 ;
} while ( time_before ( jiffies , timeout ) ) ;
2009-05-22 18:23:38 +04:00
printk ( KERN_ERR " %s: timeout in %s \n " , drive - > name , __func__ ) ;
2008-10-11 00:39:23 +04:00
return 1 ; /* drive timed-out */
2008-01-26 22:13:09 +03:00
}
2005-04-17 02:20:36 +04:00
2008-07-23 21:55:54 +04:00
static u8 ide_read_device ( ide_drive_t * drive )
{
2009-04-08 16:13:03 +04:00
struct ide_taskfile tf ;
2008-07-23 21:55:54 +04:00
2009-04-08 16:13:03 +04:00
drive - > hwif - > tp_ops - > tf_read ( drive , & tf , IDE_VALID_DEVICE ) ;
2008-07-23 21:55:54 +04:00
2009-04-08 16:13:03 +04:00
return tf . device ;
2008-07-23 21:55:54 +04:00
}
2005-04-17 02:20:36 +04:00
/**
* do_probe - probe an IDE device
* @ drive : drive to probe
* @ cmd : command to use
*
* do_probe ( ) has the difficult job of finding a drive if it exists ,
* without getting hung up if it doesn ' t exist , without trampling on
* ethernet cards , and without leaving any IRQs dangling to haunt us later .
*
* If a drive is " known " to exist ( from CMOS or kernel parameters ) ,
* but does not respond right away , the probe will " hang in there "
* for the maximum wait time ( about 30 seconds ) , otherwise it will
* exit much more quickly .
*
* Returns : 0 device was identified
* 1 device timed - out ( no response to identify request )
* 2 device aborted the command ( refused to identify itself )
* 3 bad status from device ( possible for ATAPI drives )
* 4 probe was not attempted because failure was obvious
*/
static int do_probe ( ide_drive_t * drive , u8 cmd )
{
2009-01-06 19:20:52 +03: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 ;
2009-03-25 01:22:59 +03:00
u16 * id = drive - > id ;
2008-02-02 21:56:45 +03:00
int rc ;
2008-10-13 23:39:36 +04:00
u8 present = ! ! ( drive - > dev_flags & IDE_DFLAG_PRESENT ) , stat ;
/* avoid waiting for inappropriate probes */
if ( present & & drive - > media ! = ide_disk & & cmd = = ATA_CMD_ID_ATA )
return 4 ;
2005-04-17 02:20:36 +04:00
# ifdef DEBUG
2008-07-25 00:53:36 +04:00
printk ( KERN_INFO " probing for %s: present=%d, media=%d, probetype=%s \n " ,
2008-10-13 23:39:36 +04:00
drive - > name , present , drive - > media ,
2008-10-11 00:39:21 +04:00
( cmd = = ATA_CMD_ID_ATA ) ? " ATA " : " ATAPI " ) ;
2005-04-17 02:20:36 +04:00
# endif
/* needed for some systems
* ( e . g . crw9624 as drive0 with disk as slave )
*/
msleep ( 50 ) ;
2009-03-31 22:15:33 +04:00
tp_ops - > dev_select ( drive ) ;
2005-04-17 02:20:36 +04:00
msleep ( 50 ) ;
2008-07-23 21:55:54 +04:00
2008-10-13 23:39:40 +04:00
if ( ide_read_device ( drive ) ! = drive - > select & & present = = 0 ) {
2008-10-13 23:39:40 +04:00
if ( drive - > dn & 1 ) {
2005-04-17 02:20:36 +04:00
/* exit with drive0 selected */
2009-03-31 22:15:33 +04:00
tp_ops - > dev_select ( hwif - > devices [ 0 ] ) ;
2008-10-11 00:39:21 +04:00
/* allow ATA_BUSY to assert & clear */
2005-04-17 02:20:36 +04:00
msleep ( 50 ) ;
}
/* no i/f present: mmm.. this should be a 4 -ml */
return 3 ;
}
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_DRDY , ATA_BUSY ) | |
2008-10-13 23:39:36 +04:00
present | | cmd = = ATA_CMD_ID_ATAPI ) {
2009-06-23 15:29:11 +04:00
rc = ide_dev_read_id ( drive , cmd , id , 0 ) ;
2009-03-25 01:22:59 +03:00
if ( rc )
2005-04-17 02:20:36 +04:00
/* failed: try again */
2009-06-23 15:29:11 +04:00
rc = ide_dev_read_id ( drive , cmd , id , 0 ) ;
2008-02-02 21:56:45 +03:00
2008-07-23 21:55:56 +04:00
stat = tp_ops - > read_status ( hwif ) ;
2008-02-02 21:56:45 +03:00
2008-10-11 00:39:21 +04:00
if ( stat = = ( ATA_BUSY | ATA_DRDY ) )
2005-04-17 02:20:36 +04:00
return 4 ;
2008-10-11 00:39:21 +04:00
if ( rc = = 1 & & cmd = = ATA_CMD_ID_ATAPI ) {
2008-02-02 21:56:45 +03:00
printk ( KERN_ERR " %s: no response (status = 0x%02x), "
" resetting drive \n " , drive - > name , stat ) ;
2005-04-17 02:20:36 +04:00
msleep ( 50 ) ;
2009-03-31 22:15:33 +04:00
tp_ops - > dev_select ( drive ) ;
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_DEV_RESET ) ;
2009-05-22 18:23:38 +04:00
( void ) ide_busy_sleep ( drive , WAIT_WORSTCASE , 0 ) ;
2009-06-23 15:29:11 +04:00
rc = ide_dev_read_id ( drive , cmd , id , 0 ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 21:56:45 +03:00
/* ensure drive IRQ is clear */
2008-07-23 21:55:56 +04:00
stat = tp_ops - > read_status ( hwif ) ;
2008-02-02 21:56:45 +03:00
2005-04-17 02:20:36 +04:00
if ( rc = = 1 )
2008-02-02 21:56:45 +03:00
printk ( KERN_ERR " %s: no response (status = 0x%02x) \n " ,
drive - > name , stat ) ;
2005-04-17 02:20:36 +04:00
} else {
/* not present or maybe ATAPI */
rc = 3 ;
}
2008-10-13 23:39:40 +04:00
if ( drive - > dn & 1 ) {
2005-04-17 02:20:36 +04:00
/* exit with drive0 selected */
2009-03-31 22:15:33 +04:00
tp_ops - > dev_select ( hwif - > devices [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
msleep ( 50 ) ;
/* ensure drive irq is clear */
2008-07-23 21:55:56 +04:00
( void ) tp_ops - > read_status ( hwif ) ;
2005-04-17 02:20:36 +04:00
}
return rc ;
}
/**
* probe_for_drives - upper level drive probe
* @ drive : drive to probe for
*
* probe_for_drive ( ) tests for existence of a given drive using do_probe ( )
* and presents things to the user as needed .
*
* Returns : 0 no device was found
2008-10-13 23:39:36 +04:00
* 1 device was found
* ( note : IDE_DFLAG_PRESENT might still be not set )
2005-04-17 02:20:36 +04:00
*/
2008-12-29 22:27:36 +03:00
static u8 probe_for_drive ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2008-10-11 00:39:19 +04:00
char * m ;
2009-03-25 01:22:58 +03:00
int rc ;
u8 cmd ;
2008-10-11 00:39:19 +04:00
2008-10-13 23:39:36 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_ID_READ ;
2008-10-11 00:39:19 +04:00
m = ( char * ) & drive - > id [ ATA_ID_PROD ] ;
strcpy ( m , " UNKNOWN " ) ;
2005-04-17 02:20:36 +04:00
/* skip probing? */
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_NOPROBE ) = = 0 ) {
2005-04-17 02:20:36 +04:00
/* if !(success||timed-out) */
2009-03-25 01:22:58 +03:00
cmd = ATA_CMD_ID_ATA ;
rc = do_probe ( drive , cmd ) ;
if ( rc > = 2 ) {
2005-04-17 02:20:36 +04:00
/* look for ATAPI device */
2009-03-25 01:22:58 +03:00
cmd = ATA_CMD_ID_ATAPI ;
rc = do_probe ( drive , cmd ) ;
}
2008-10-11 00:39:23 +04:00
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_PRESENT ) = = 0 )
2009-06-10 16:37:20 +04:00
return 0 ;
2008-10-11 00:39:19 +04:00
2005-04-17 02:20:36 +04:00
/* identification failed? */
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_ID_READ ) = = 0 ) {
2005-04-17 02:20:36 +04:00
if ( drive - > media = = ide_disk ) {
printk ( KERN_INFO " %s: non-IDE drive, CHS=%d/%d/%d \n " ,
drive - > name , drive - > cyl ,
drive - > head , drive - > sect ) ;
} else if ( drive - > media = = ide_cdrom ) {
printk ( KERN_INFO " %s: ATAPI cdrom (?) \n " , drive - > name ) ;
} else {
/* nuke it */
printk ( KERN_WARNING " %s: Unknown device on bus refused identification. Ignoring. \n " , drive - > name ) ;
2008-10-13 23:39:36 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_PRESENT ;
2005-04-17 02:20:36 +04:00
}
2009-03-25 01:22:58 +03:00
} else {
if ( cmd = = ATA_CMD_ID_ATAPI )
ide_classify_atapi_dev ( drive ) ;
else
ide_classify_ata_dev ( drive ) ;
2005-04-17 02:20:36 +04:00
}
}
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_PRESENT ) = = 0 )
2009-06-10 16:37:20 +04:00
return 0 ;
2008-10-13 23:39:36 +04:00
2005-04-17 02:20:36 +04:00
/* The drive wasn't being helpful. Add generic info only */
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_ID_READ ) = = 0 ) {
2005-04-17 02:20:36 +04:00
generic_id ( drive ) ;
return 1 ;
}
if ( drive - > media = = ide_disk ) {
ide_disk_init_chs ( drive ) ;
ide_disk_init_mult_count ( drive ) ;
}
2009-03-27 14:46:26 +03:00
return 1 ;
2005-04-17 02:20:36 +04:00
}
2008-07-23 21:56:02 +04:00
static void hwif_release_dev ( struct device * dev )
2005-04-17 02:20:36 +04:00
{
ide_hwif_t * hwif = container_of ( dev , ide_hwif_t , gendev ) ;
2006-01-10 02:59:27 +03:00
complete ( & hwif - > gendev_rel_comp ) ;
2005-04-17 02:20:36 +04:00
}
2008-04-18 02:46:23 +04:00
static int ide_register_port ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
2006-10-03 12:14:23 +04:00
int ret ;
2005-04-17 02:20:36 +04:00
/* register with global device tree */
2008-12-29 22:27:36 +03:00
dev_set_name ( & hwif - > gendev , hwif - > name ) ;
2009-05-01 01:43:31 +04:00
dev_set_drvdata ( & hwif - > gendev , hwif ) ;
2009-01-19 15:46:56 +03:00
if ( hwif - > gendev . parent = = NULL )
hwif - > gendev . parent = hwif - > dev ;
2005-04-17 02:20:36 +04:00
hwif - > gendev . release = hwif_release_dev ;
2009-01-02 18:12:47 +03:00
2006-10-03 12:14:23 +04:00
ret = device_register ( & hwif - > gendev ) ;
2008-04-18 02:46:23 +04:00
if ( ret < 0 ) {
2006-10-03 12:14:23 +04:00
printk ( KERN_WARNING " IDE: %s: device_register error: %d \n " ,
2008-04-27 00:25:20 +04:00
__func__ , ret ) ;
2008-04-18 02:46:23 +04:00
goto out ;
}
2008-07-22 07:03:34 +04:00
hwif - > portdev = device_create ( ide_port_class , & hwif - > gendev ,
MKDEV ( 0 , 0 ) , hwif , hwif - > name ) ;
2008-04-18 02:46:23 +04:00
if ( IS_ERR ( hwif - > portdev ) ) {
ret = PTR_ERR ( hwif - > portdev ) ;
device_unregister ( & hwif - > gendev ) ;
}
out :
return ret ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 01:09:34 +03:00
/**
* ide_port_wait_ready - wait for port to become ready
* @ hwif : IDE port
*
* This is needed on some PPCs and a bunch of BIOS - less embedded
* platforms . Typical cases are :
*
* - The firmware hard reset the disk before booting the kernel ,
* the drive is still doing it ' s poweron - reset sequence , that
* can take up to 30 seconds .
*
* - The firmware does nothing ( or no firmware ) , the device is
* still in POST state ( same as above actually ) .
*
* - Some CD / DVD / Writer combo drives tend to drive the bus during
* their reset sequence even when they are non - selected slave
* devices , thus preventing discovery of the main HD .
*
* Doing this wait - for - non - busy should not harm any existing
* configuration and fix some issues like the above .
*
* BenH .
*
* Returns 0 on success , error code ( < 0 ) otherwise .
*/
static int ide_port_wait_ready ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
2009-03-31 22:15:33 +04:00
const struct ide_tp_ops * tp_ops = hwif - > tp_ops ;
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
int i , rc ;
2005-04-17 02:20:36 +04:00
printk ( KERN_DEBUG " Probing IDE interface %s... \n " , hwif - > name ) ;
/* Let HW settle down a bit from whatever init state we
* come from */
mdelay ( 2 ) ;
/* Wait for BSY bit to go away, spec timeout is 30 seconds,
* I know of at least one disk who takes 31 seconds , I use 35
* here to be safe
*/
rc = ide_wait_not_busy ( hwif , 35000 ) ;
if ( rc )
return rc ;
/* Now make sure both master & slave are ready */
2009-01-06 19:20:56 +03:00
ide_port_for_each_dev ( i , drive , hwif ) {
2007-11-27 23:35:53 +03:00
/* Ignore disks that we will not probe for later. */
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_NOPROBE ) = = 0 | |
( drive - > dev_flags & IDE_DFLAG_PRESENT ) ) {
2009-03-31 22:15:33 +04:00
tp_ops - > dev_select ( drive ) ;
tp_ops - > write_devctl ( hwif , ATA_DEVCTL_OBS ) ;
2007-11-27 23:35:53 +03:00
mdelay ( 2 ) ;
rc = ide_wait_not_busy ( hwif , 35000 ) ;
if ( rc )
goto out ;
} else
printk ( KERN_DEBUG " %s: ide_wait_not_busy() skipped \n " ,
drive - > name ) ;
}
out :
2005-04-17 02:20:36 +04:00
/* Exit function with master reselected (let's be sane) */
2009-01-06 19:20:56 +03:00
if ( i )
2009-03-31 22:15:33 +04:00
tp_ops - > dev_select ( hwif - > devices [ 0 ] ) ;
2007-11-27 23:35:53 +03:00
2005-04-17 02:20:36 +04:00
return rc ;
}
/**
* ide_undecoded_slave - look for bad CF adapters
2008-10-11 00:39:19 +04:00
* @ dev1 : slave device
2005-04-17 02:20:36 +04:00
*
* Analyse the drives on the interface and attempt to decide if we
* have the same drive viewed twice . This occurs with crap CF adapters
* and PCMCIA sometimes .
*/
2008-10-11 00:39:19 +04:00
void ide_undecoded_slave ( ide_drive_t * dev1 )
2005-04-17 02:20:36 +04:00
{
2009-01-06 19:20:56 +03:00
ide_drive_t * dev0 = dev1 - > hwif - > devices [ 0 ] ;
2005-04-17 02:20:36 +04:00
2008-10-13 23:39:36 +04:00
if ( ( dev1 - > dn & 1 ) = = 0 | | ( dev0 - > dev_flags & IDE_DFLAG_PRESENT ) = = 0 )
2005-04-17 02:20:36 +04:00
return ;
/* If the models don't match they are not the same product */
2008-10-11 00:39:19 +04:00
if ( strcmp ( ( char * ) & dev0 - > id [ ATA_ID_PROD ] ,
( char * ) & dev1 - > id [ ATA_ID_PROD ] ) )
2005-04-17 02:20:36 +04:00
return ;
/* Serial numbers do not match */
2008-10-11 00:39:19 +04:00
if ( strncmp ( ( char * ) & dev0 - > id [ ATA_ID_SERNO ] ,
( char * ) & dev1 - > id [ ATA_ID_SERNO ] , ATA_ID_SERNO_LEN ) )
2005-04-17 02:20:36 +04:00
return ;
/* No serial number, thankfully very rare for CF */
2008-10-11 00:39:19 +04:00
if ( * ( char * ) & dev0 - > id [ ATA_ID_SERNO ] = = 0 )
2005-04-17 02:20:36 +04:00
return ;
/* Appears to be an IDE flash adapter with decode bugs */
printk ( KERN_WARNING " ide-probe: ignoring undecoded slave \n " ) ;
2008-10-13 23:39:36 +04:00
dev1 - > dev_flags & = ~ IDE_DFLAG_PRESENT ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL_GPL ( ide_undecoded_slave ) ;
2008-02-02 01:09:36 +03:00
static int ide_probe_port ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
2005-04-17 02:20:36 +04:00
unsigned int irqd ;
2009-01-06 19:20:56 +03:00
int i , rc = - ENODEV ;
2008-02-02 01:09:36 +03:00
BUG_ON ( hwif - > present ) ;
2005-04-17 02:20:36 +04:00
2009-01-06 19:20:56 +03:00
if ( ( hwif - > devices [ 0 ] - > dev_flags & IDE_DFLAG_NOPROBE ) & &
( hwif - > devices [ 1 ] - > dev_flags & IDE_DFLAG_NOPROBE ) )
2008-02-02 01:09:36 +03:00
return - EACCES ;
2005-04-17 02:20:36 +04:00
/*
* We must always disable IRQ , as probe_for_drive will assert IRQ , but
* we ' ll install our IRQ driver much later . . .
*/
irqd = hwif - > irq ;
if ( irqd )
disable_irq ( hwif - > irq ) ;
2010-03-29 05:58:28 +04:00
if ( ide_port_wait_ready ( hwif ) = = - EBUSY )
printk ( KERN_DEBUG " %s: Wait for ready failed before probe ! \n " , hwif - > name ) ;
2005-04-17 02:20:36 +04:00
/*
2008-03-29 21:48:21 +03:00
* Second drive should only exist if first drive was found ,
* but a lot of cdrom drives are configured as single slaves .
2005-04-17 02:20:36 +04:00
*/
2009-01-06 19:20:56 +03:00
ide_port_for_each_dev ( i , drive , hwif ) {
2005-04-17 02:20:36 +04:00
( void ) probe_for_drive ( drive ) ;
2008-10-13 23:39:36 +04:00
if ( drive - > dev_flags & IDE_DFLAG_PRESENT )
2008-02-02 01:09:36 +03:00
rc = 0 ;
2005-04-17 02:20:36 +04:00
}
2010-03-29 05:58:28 +04:00
2005-04-17 02:20:36 +04:00
/*
* Use cached IRQ number . It might be ( and is . . . ) changed by probe
* code above
*/
if ( irqd )
enable_irq ( irqd ) ;
2008-02-02 01:09:36 +03:00
return rc ;
2008-02-02 01:09:36 +03:00
}
static void ide_port_tune_devices ( ide_hwif_t * hwif )
{
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = hwif - > port_ops ;
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
int i ;
2008-01-26 22:13:03 +03:00
2009-03-25 01:22:41 +03:00
ide_port_for_each_present_dev ( i , drive , hwif ) {
2009-06-07 17:37:09 +04:00
ide_check_nien_quirk_list ( drive ) ;
2009-03-25 01:22:41 +03:00
if ( port_ops & & port_ops - > quirkproc )
port_ops - > quirkproc ( drive ) ;
2008-01-26 22:13:03 +03:00
}
2007-06-08 17:14:29 +04:00
2009-03-25 01:22:41 +03:00
ide_port_for_each_present_dev ( i , drive , hwif ) {
ide_set_max_pio ( drive ) ;
2005-04-17 02:20:36 +04:00
2009-03-25 01:22:41 +03:00
drive - > dev_flags | = IDE_DFLAG_NICE1 ;
2005-04-17 02:20:36 +04:00
2009-03-25 01:22:41 +03:00
if ( hwif - > dma_ops )
ide_set_dma ( drive ) ;
2005-04-17 02:20:36 +04:00
}
}
/*
* init request queue
*/
static int ide_init_queue ( ide_drive_t * drive )
{
2007-07-24 11:28:11 +04:00
struct request_queue * q ;
2009-01-06 19:20:52 +03:00
ide_hwif_t * hwif = drive - > hwif ;
2005-04-17 02:20:36 +04:00
int max_sectors = 256 ;
int max_sg_entries = PRD_ENTRIES ;
/*
* Our default set up assumes the normal IDE case ,
* that is 64 K segmenting , standard PRD setup
* and LBA28 . Some drivers then impose their own
* limits and LBA48 we could raise it but as yet
* do not .
*/
2005-06-23 11:08:19 +04:00
2009-01-02 18:12:50 +03:00
q = blk_init_queue_node ( do_ide_request , NULL , hwif_to_node ( hwif ) ) ;
2005-04-17 02:20:36 +04:00
if ( ! q )
return 1 ;
q - > queuedata = drive ;
blk_queue_segment_boundary ( q , 0xffff ) ;
if ( hwif - > rqsize < max_sectors )
max_sectors = hwif - > rqsize ;
2010-02-26 08:20:38 +03:00
blk_queue_max_hw_sectors ( q , max_sectors ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_PCI
/* When we have an IOMMU, we may have a problem where pci_map_sg()
* creates segments that don ' t completely match our boundary
* requirements and thus need to be broken up again . Because it
* doesn ' t align properly either , we may actually have to break up
* to more segments than what was we got in the first place , a max
* worst case is twice as many .
* This will be fixed once we teach pci_map_sg ( ) about our boundary
* requirements , hopefully soon . * FIXME *
*/
if ( ! PCI_DMA_BUS_IS_PHYS )
max_sg_entries > > = 1 ;
# endif /* CONFIG_PCI */
2010-02-26 08:20:39 +03:00
blk_queue_max_segments ( q , max_sg_entries ) ;
2005-04-17 02:20:36 +04:00
/* assign drive queue */
drive - > queue = q ;
/* needs drive->queue to be set */
ide_toggle_bounce ( drive , 1 ) ;
return 0 ;
}
2009-01-06 19:20:51 +03:00
static DEFINE_MUTEX ( ide_cfg_mtx ) ;
2008-02-02 21:56:41 +03:00
/*
* For any present drive :
* - allocate the block device queue
*/
2008-10-13 23:39:45 +04:00
static int ide_port_setup_devices ( ide_hwif_t * hwif )
2008-02-02 21:56:41 +03:00
{
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
2008-10-13 23:39:45 +04:00
int i , j = 0 ;
2008-02-02 21:56:41 +03:00
2008-04-18 02:46:22 +04:00
mutex_lock ( & ide_cfg_mtx ) ;
2009-03-25 01:22:41 +03:00
ide_port_for_each_present_dev ( i , drive , hwif ) {
2008-02-02 21:56:41 +03:00
if ( ide_init_queue ( drive ) ) {
printk ( KERN_ERR " ide: failed to init %s \n " ,
drive - > name ) ;
2008-10-13 23:39:45 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_PRESENT ;
2008-02-02 21:56:41 +03:00
continue ;
}
2008-10-13 23:39:45 +04:00
j + + ;
2008-02-02 21:56:41 +03:00
}
2008-04-18 02:46:22 +04:00
mutex_unlock ( & ide_cfg_mtx ) ;
2008-10-13 23:39:45 +04:00
return j ;
2008-02-02 21:56:41 +03:00
}
2009-06-23 14:43:00 +04:00
static void ide_host_enable_irqs ( struct ide_host * host )
{
ide_hwif_t * hwif ;
int i ;
ide_host_for_each_port ( i , hwif , host ) {
if ( hwif = = NULL )
continue ;
/* clear any pending IRQs */
hwif - > tp_ops - > read_status ( hwif ) ;
/* unmask IRQs */
if ( hwif - > io_ports . ctl_addr )
hwif - > tp_ops - > write_devctl ( hwif , ATA_DEVCTL_OBS ) ;
}
}
2005-04-17 02:20:36 +04:00
/*
2009-01-06 19:20:50 +03:00
* This routine sets up the IRQ for an IDE interface .
2005-04-17 02:20:36 +04:00
*/
static int init_irq ( ide_hwif_t * hwif )
{
2008-04-27 17:38:32 +04:00
struct ide_io_ports * io_ports = & hwif - > io_ports ;
2009-03-27 14:46:27 +03:00
struct ide_host * host = hwif - > host ;
irq_handler_t irq_handler = host - > irq_handler ;
int sa = host - > irq_flags ;
2005-04-17 02:20:36 +04:00
2009-03-05 18:10:57 +03:00
if ( irq_handler = = NULL )
irq_handler = ide_intr ;
if ( request_irq ( hwif - > irq , irq_handler , sa , hwif - > name , hwif ) )
2009-01-06 19:20:50 +03:00
goto out_up ;
2005-04-17 02:20:36 +04:00
2008-02-06 12:36:29 +03:00
# if !defined(__mc68000__)
2008-07-25 00:53:36 +04:00
printk ( KERN_INFO " %s at 0x%03lx-0x%03lx,0x%03lx on irq %d " , hwif - > name ,
2008-04-27 17:38:32 +04:00
io_ports - > data_addr , io_ports - > status_addr ,
io_ports - > ctl_addr , hwif - > irq ) ;
2005-04-17 02:20:36 +04:00
# else
2008-07-25 00:53:36 +04:00
printk ( KERN_INFO " %s at 0x%08lx on irq %d " , hwif - > name ,
2008-04-27 17:38:32 +04:00
io_ports - > data_addr , hwif - > irq ) ;
2008-02-06 12:36:29 +03:00
# endif /* __mc68000__ */
2009-01-06 19:20:50 +03:00
if ( hwif - > host - > host_flags & IDE_HFLAG_SERIALIZE )
printk ( KERN_CONT " (serialized) " ) ;
2008-07-25 00:53:36 +04:00
printk ( KERN_CONT " \n " ) ;
2008-02-02 21:56:41 +03:00
2005-04-17 02:20:36 +04:00
return 0 ;
out_up :
return 1 ;
}
static int ata_lock ( dev_t dev , void * data )
{
/* FIXME: we want to pin hwif down */
return 0 ;
}
static struct kobject * ata_probe ( dev_t dev , int * part , void * data )
{
ide_hwif_t * hwif = data ;
int unit = * part > > PARTN_BITS ;
2009-01-06 19:20:56 +03:00
ide_drive_t * drive = hwif - > devices [ unit ] ;
2008-10-13 23:39:36 +04:00
if ( ( drive - > dev_flags & IDE_DFLAG_PRESENT ) = = 0 )
2005-04-17 02:20:36 +04:00
return NULL ;
if ( drive - > media = = ide_disk )
request_module ( " ide-disk " ) ;
if ( drive - > media = = ide_cdrom | | drive - > media = = ide_optical )
request_module ( " ide-cd " ) ;
if ( drive - > media = = ide_tape )
request_module ( " ide-tape " ) ;
if ( drive - > media = = ide_floppy )
request_module ( " ide-floppy " ) ;
return NULL ;
}
static struct kobject * exact_match ( dev_t dev , int * part , void * data )
{
struct gendisk * p = data ;
* part & = ( 1 < < PARTN_BITS ) - 1 ;
2008-08-25 14:56:05 +04:00
return & disk_to_dev ( p ) - > kobj ;
2005-04-17 02:20:36 +04:00
}
static int exact_lock ( dev_t dev , void * data )
{
struct gendisk * p = data ;
if ( ! get_disk ( p ) )
return - 1 ;
return 0 ;
}
void ide_register_region ( struct gendisk * disk )
{
blk_register_region ( MKDEV ( disk - > major , disk - > first_minor ) ,
disk - > minors , NULL , exact_match , exact_lock , disk ) ;
}
EXPORT_SYMBOL_GPL ( ide_register_region ) ;
void ide_unregister_region ( struct gendisk * disk )
{
blk_unregister_region ( MKDEV ( disk - > major , disk - > first_minor ) ,
disk - > minors ) ;
}
EXPORT_SYMBOL_GPL ( ide_unregister_region ) ;
void ide_init_disk ( struct gendisk * disk , ide_drive_t * drive )
{
ide_hwif_t * hwif = drive - > hwif ;
2008-10-13 23:39:40 +04:00
unsigned int unit = drive - > dn & 1 ;
2005-04-17 02:20:36 +04:00
disk - > major = hwif - > major ;
disk - > first_minor = unit < < PARTN_BITS ;
sprintf ( disk - > disk_name , " hd%c " , ' a ' + hwif - > index * MAX_DRIVES + unit ) ;
disk - > queue = drive - > queue ;
}
EXPORT_SYMBOL_GPL ( ide_init_disk ) ;
static void drive_release_dev ( struct device * dev )
{
ide_drive_t * drive = container_of ( dev , ide_drive_t , gendev ) ;
2008-04-18 02:46:22 +04:00
ide_proc_unregister_device ( drive ) ;
2009-03-31 22:15:25 +04:00
blk_cleanup_queue ( drive - > queue ) ;
drive - > queue = NULL ;
2008-10-13 23:39:36 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_PRESENT ;
2005-05-26 16:55:34 +04:00
2006-01-10 02:59:27 +03:00
complete ( & drive - > gendev_rel_comp ) ;
2005-04-17 02:20:36 +04:00
}
static int hwif_init ( ide_hwif_t * hwif )
{
if ( ! hwif - > irq ) {
2009-03-25 01:22:52 +03:00
printk ( KERN_ERR " %s: disabled, no IRQ \n " , hwif - > name ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
if ( register_blkdev ( hwif - > major , hwif - > name ) )
return 0 ;
if ( ! hwif - > sg_max_nents )
hwif - > sg_max_nents = PRD_ENTRIES ;
2007-10-22 23:19:53 +04:00
hwif - > sg_table = kmalloc ( sizeof ( struct scatterlist ) * hwif - > sg_max_nents ,
2005-04-17 02:20:36 +04:00
GFP_KERNEL ) ;
if ( ! hwif - > sg_table ) {
printk ( KERN_ERR " %s: unable to allocate SG table. \n " , hwif - > name ) ;
goto out ;
}
2007-10-22 23:19:53 +04:00
sg_init_table ( hwif - > sg_table , hwif - > sg_max_nents ) ;
2005-04-17 02:20:36 +04:00
if ( init_irq ( hwif ) ) {
2009-03-25 01:22:52 +03:00
printk ( KERN_ERR " %s: disabled, unable to get IRQ %d \n " ,
hwif - > name , hwif - > irq ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
2008-02-02 21:56:40 +03:00
blk_register_region ( MKDEV ( hwif - > major , 0 ) , MAX_DRIVES < < PARTN_BITS ,
THIS_MODULE , ata_probe , ata_lock , hwif ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
out :
unregister_blkdev ( hwif - > major , hwif - > name ) ;
return 0 ;
}
2007-10-20 02:32:29 +04:00
static void hwif_register_devices ( ide_hwif_t * hwif )
{
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
2007-10-20 02:32:29 +04:00
unsigned int i ;
2009-03-25 01:22:41 +03:00
ide_port_for_each_present_dev ( i , drive , hwif ) {
2008-02-02 21:56:41 +03:00
struct device * dev = & drive - > gendev ;
int ret ;
2007-10-20 02:32:29 +04:00
2008-12-29 22:27:36 +03:00
dev_set_name ( dev , " %u.%u " , hwif - > index , i ) ;
2009-05-01 01:43:31 +04:00
dev_set_drvdata ( dev , drive ) ;
2008-02-02 21:56:41 +03:00
dev - > parent = & hwif - > gendev ;
dev - > bus = & ide_bus_type ;
dev - > release = drive_release_dev ;
ret = device_register ( dev ) ;
if ( ret < 0 )
printk ( KERN_WARNING " IDE: %s: device_register error: "
" %d \n " , __func__ , ret ) ;
2007-10-20 02:32:29 +04:00
}
}
2008-02-02 21:56:39 +03:00
static void ide_port_init_devices ( ide_hwif_t * hwif )
{
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = hwif - > port_ops ;
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
2008-02-02 21:56:39 +03:00
int i ;
2009-01-06 19:20:56 +03:00
ide_port_for_each_dev ( i , drive , hwif ) {
2008-10-13 23:39:40 +04:00
drive - > dn = i + hwif - > channel * 2 ;
2008-02-02 21:56:39 +03:00
if ( hwif - > host_flags & IDE_HFLAG_IO_32BIT )
drive - > io_32bit = 1 ;
2009-03-25 01:22:38 +03:00
if ( hwif - > host_flags & IDE_HFLAG_NO_IO_32BIT )
drive - > dev_flags | = IDE_DFLAG_NO_IO_32BIT ;
2008-02-02 21:56:39 +03:00
if ( hwif - > host_flags & IDE_HFLAG_UNMASK_IRQS )
2008-10-13 23:39:36 +04:00
drive - > dev_flags | = IDE_DFLAG_UNMASK ;
2008-02-02 21:56:40 +03:00
if ( hwif - > host_flags & IDE_HFLAG_NO_UNMASK_IRQS )
2008-10-13 23:39:36 +04:00
drive - > dev_flags | = IDE_DFLAG_NO_UNMASK ;
2008-02-02 21:56:40 +03:00
2010-01-18 10:20:28 +03:00
drive - > pio_mode = XFER_PIO_0 ;
2008-07-16 22:33:42 +04:00
if ( port_ops & & port_ops - > init_dev )
port_ops - > init_dev ( drive ) ;
}
2008-02-02 21:56:39 +03:00
}
2008-02-02 21:56:31 +03:00
static void ide_init_port ( ide_hwif_t * hwif , unsigned int port ,
const struct ide_port_info * d )
2007-10-20 02:32:31 +04:00
{
2008-06-10 22:56:36 +04:00
hwif - > channel = port ;
2008-02-02 21:56:31 +03:00
2009-05-17 21:12:22 +04:00
hwif - > chipset = d - > chipset ? d - > chipset : ide_pci ;
2008-02-02 21:56:31 +03:00
if ( d - > init_iops )
d - > init_iops ( hwif ) ;
ide: fix early setup of hwif->host_flags
On Thursday 01 May 2008, Jeremy Kerr wrote:
> Hi all,
>
> On QS20 Cell machines, Linus' current git tree explodes on boot:
>
> SiI680: IDE controller (0x1095:0x0680 rev 0x02) at PCI slot
> 0000:00:0a.0
> SiI680: BASE CLOCK == 133
> SiI680: 100% native mode on irq 51
> ide0: MMIO-DMA
> ide1: MMIO-DMA
> Unable to handle kernel paging request for data at address
> 0xa000100081220080
> Faulting instruction address: 0xc000000000024748
> cpu 0x2: Vector: 300 (Data Access) at [c00000001e143420]
> pc: c000000000024748: ._insw_ns+0x10/0x30
> lr: c000000000037fc4: .spiderpci_readsw+0x24/0x6c
> sp: c00000001e1436a0
> msr: 9000000000001032
> dar: a000100081220080
> dsisr: 40000000
> current = 0xc00000003d060000
> paca = 0xc000000000623880
> pid = 1, comm = swapper
> enter ? for help
> [link register ] c000000000037fc4 .spiderpci_readsw+0x24/0x6c
> [c00000001e1436a0] c00000000062ce63 (unreliable)
> [c00000001e143730] c0000000000379d4 .iowa_readsw+0x78/0xa8
> [c00000001e1437c0] c000000000037a98 .iowa_insw+0x94/0xd4
> [c00000001e143850] c00000000022a190 .ata_input_data+0x298/0x2ec
> [c00000001e143910] c00000000022b600 .try_to_identify+0x2c0/0x6d4
> [c00000001e1439d0] c00000000022bb54 .do_probe+0x140/0x35c
> [c00000001e143a80] c00000000022bfbc .ide_probe_port+0x24c/0x670
> [c00000001e143b50] c00000000022d09c .ide_device_add_all+0x2ec/0x690
> [c00000001e143c00] c00000000022d4a4 .ide_device_add+0x64/0x74
> [c00000001e143c90] c00000000022f834 .ide_setup_pci_device+0x58/0x7c
> [c00000001e143d30] c00000000038bdf8
> [c00000001e143e10] c000000000486fb0 .ide_scan_pcibus+0x8c/0x178
> [c00000001e143ea0] c000000000460c00 .kernel_init+0x1c4/0x344
> [c00000001e143f90] c000000000024a1c .kernel_thread+0x4c/0x68
>
> It looks like we're trying to do PIO accesses (which appear to be
> broken, but that's another issue) to this MMIO device. In
> ata_input_data, we see that:
>
> u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
>
> Gives mmio == 0.
>
> (what's the difference between hwif->mmio and ID_HFLAG_MMIO?)
>
> In the siimage driver, hwif->host flags is initially set up correctly
> (host_flags includes IDE_HFLAG_MMIO), but we then *clear* this bit in
> ide_init_port:
>
> hwif->host_flags = d->host_flags;
>
> where d is the struct ide_port_info for this chipset. In my case,
> d->host_flags is 0x0. It looks like this will be the same for all of
> the siimage chipsets.
Don't over-write hwif->host_flags in ide_init_port(), some host drivers
set IDE_HFLAG_MMIO or IDE_HFLAG_NO_IO_32BIT host flag early.
Thanks to Jeremy Kerr for the excellent analysis of the bug.
Reported-by: Jeremy Kerr <jk@ozlabs.org>
Tested-by: Jeremy Kerr <jk@ozlabs.org>
Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Ben Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-05-01 16:08:51 +04:00
/* ->host_flags may be set by ->init_iops (or even earlier...) */
hwif - > host_flags | = d - > host_flags ;
2008-02-02 21:56:31 +03:00
hwif - > pio_mask = d - > pio_mask ;
2008-07-23 21:55:56 +04:00
if ( d - > tp_ops )
hwif - > tp_ops = d - > tp_ops ;
2008-04-27 00:25:14 +04:00
/* ->set_pio_mode for DTC2278 is currently limited to port 0 */
2009-03-27 14:46:28 +03:00
if ( ( hwif - > host_flags & IDE_HFLAG_DTC2278 ) = = 0 | | hwif - > channel = = 0 )
2008-04-27 00:25:14 +04:00
hwif - > port_ops = d - > port_ops ;
2008-02-02 21:56:31 +03:00
hwif - > swdma_mask = d - > swdma_mask ;
hwif - > mwdma_mask = d - > mwdma_mask ;
hwif - > ultra_mask = d - > udma_mask ;
2008-04-27 00:25:22 +04:00
if ( ( d - > host_flags & IDE_HFLAG_NO_DMA ) = = 0 ) {
int rc ;
2009-01-06 19:21:02 +03:00
hwif - > dma_ops = d - > dma_ops ;
2008-04-27 00:25:22 +04:00
if ( d - > init_dma )
rc = d - > init_dma ( hwif , d ) ;
else
rc = ide_hwif_setup_dma ( hwif , d ) ;
if ( rc < 0 ) {
printk ( KERN_INFO " %s: DMA disabled \n " , hwif - > name ) ;
2009-01-06 19:21:02 +03:00
hwif - > dma_ops = NULL ;
2008-07-23 21:55:51 +04:00
hwif - > dma_base = 0 ;
2008-04-27 00:25:22 +04:00
hwif - > swdma_mask = 0 ;
hwif - > mwdma_mask = 0 ;
hwif - > ultra_mask = 0 ;
2009-01-06 19:21:02 +03:00
}
2008-04-27 00:25:22 +04:00
}
2008-02-02 21:56:31 +03:00
2008-05-04 19:03:41 +04:00
if ( ( d - > host_flags & IDE_HFLAG_SERIALIZE ) | |
2008-12-29 22:27:36 +03:00
( ( d - > host_flags & IDE_HFLAG_SERIALIZE_DMA ) & & hwif - > dma_base ) )
hwif - > host - > host_flags | = IDE_HFLAG_SERIALIZE ;
2008-05-04 19:03:41 +04:00
2008-12-29 22:27:34 +03:00
if ( d - > max_sectors )
hwif - > rqsize = d - > max_sectors ;
2009-03-27 14:46:18 +03:00
else {
if ( ( hwif - > host_flags & IDE_HFLAG_NO_LBA48 ) | |
( hwif - > host_flags & IDE_HFLAG_NO_LBA48_DMA ) )
hwif - > rqsize = 256 ;
else
hwif - > rqsize = 65536 ;
}
2008-02-02 21:56:31 +03:00
/* call chipset specific routine for each enabled port */
if ( d - > init_hwif )
d - > init_hwif ( hwif ) ;
2008-04-18 02:46:22 +04:00
}
2008-02-02 21:56:31 +03:00
2008-04-18 02:46:22 +04:00
static void ide_port_cable_detect ( ide_hwif_t * hwif )
{
2008-04-27 00:25:14 +04:00
const struct ide_port_ops * port_ops = hwif - > port_ops ;
if ( port_ops & & port_ops - > cable_detect & & ( hwif - > ultra_mask & 0x78 ) ) {
2008-02-02 21:56:31 +03:00
if ( hwif - > cbl ! = ATA_CBL_PATA40_SHORT )
2008-04-27 00:25:14 +04:00
hwif - > cbl = port_ops - > cable_detect ( hwif ) ;
2008-02-02 21:56:31 +03:00
}
2008-02-02 21:56:31 +03:00
}
2009-01-06 19:20:51 +03:00
static const u8 ide_hwif_to_major [ ] =
{ IDE0_MAJOR , IDE1_MAJOR , IDE2_MAJOR , IDE3_MAJOR , IDE4_MAJOR ,
IDE5_MAJOR , IDE6_MAJOR , IDE7_MAJOR , IDE8_MAJOR , IDE9_MAJOR } ;
static void ide_port_init_devices_data ( ide_hwif_t * hwif )
{
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
int i ;
2009-01-06 19:20:51 +03:00
2009-01-06 19:20:56 +03:00
ide_port_for_each_dev ( i , drive , hwif ) {
u8 j = ( hwif - > index * MAX_DRIVES ) + i ;
2009-06-10 16:37:20 +04:00
u16 * saved_id = drive - > id ;
2009-01-06 19:20:51 +03:00
memset ( drive , 0 , sizeof ( * drive ) ) ;
2009-06-10 16:37:20 +04:00
memset ( saved_id , 0 , SECTOR_SIZE ) ;
drive - > id = saved_id ;
2009-01-06 19:20:51 +03:00
drive - > media = ide_disk ;
2009-01-06 19:20:56 +03:00
drive - > select = ( i < < 4 ) | ATA_DEVICE_OBS ;
2009-01-06 19:20:51 +03:00
drive - > hwif = hwif ;
drive - > ready_stat = ATA_DRDY ;
drive - > bad_wstat = BAD_W_STAT ;
2009-05-17 21:12:21 +04:00
drive - > special_flags = IDE_SFLAG_RECALIBRATE |
IDE_SFLAG_SET_GEOMETRY ;
2009-01-06 19:20:51 +03:00
drive - > name [ 0 ] = ' h ' ;
drive - > name [ 1 ] = ' d ' ;
drive - > name [ 2 ] = ' a ' + j ;
drive - > max_failures = IDE_DEFAULT_MAX_FAILURES ;
INIT_LIST_HEAD ( & drive - > list ) ;
init_completion ( & drive - > gendev_rel_comp ) ;
}
}
static void ide_init_port_data ( ide_hwif_t * hwif , unsigned int index )
{
/* fill in any non-zero initial values */
hwif - > index = index ;
hwif - > major = ide_hwif_to_major [ index ] ;
hwif - > name [ 0 ] = ' i ' ;
hwif - > name [ 1 ] = ' d ' ;
hwif - > name [ 2 ] = ' e ' ;
hwif - > name [ 3 ] = ' 0 ' + index ;
2009-03-25 01:22:39 +03:00
spin_lock_init ( & hwif - > lock ) ;
init_timer ( & hwif - > timer ) ;
hwif - > timer . function = & ide_timer_expiry ;
hwif - > timer . data = ( unsigned long ) hwif ;
2009-01-06 19:20:51 +03:00
init_completion ( & hwif - > gendev_rel_comp ) ;
hwif - > tp_ops = & default_tp_ops ;
ide_port_init_devices_data ( hwif ) ;
}
2009-05-17 21:12:25 +04:00
static void ide_init_port_hw ( ide_hwif_t * hwif , struct ide_hw * hw )
2009-01-06 19:20:51 +03:00
{
memcpy ( & hwif - > io_ports , & hw - > io_ports , sizeof ( hwif - > io_ports ) ) ;
hwif - > irq = hw - > irq ;
hwif - > dev = hw - > dev ;
hwif - > gendev . parent = hw - > parent ? hw - > parent : hw - > dev ;
hwif - > config_data = hw - > config ;
}
2008-07-23 21:55:57 +04:00
static unsigned int ide_indexes ;
2008-04-26 19:36:36 +04:00
/**
2008-07-23 21:55:57 +04:00
* ide_find_port_slot - find free port slot
2008-04-26 19:36:36 +04:00
* @ d : IDE port info
*
2008-07-23 21:55:57 +04:00
* Return the new port slot index or - ENOENT if we are out of free slots .
2008-04-26 19:36:36 +04:00
*/
2008-07-23 21:55:57 +04:00
static int ide_find_port_slot ( const struct ide_port_info * d )
2008-04-26 19:36:36 +04:00
{
2008-07-23 21:55:57 +04:00
int idx = - ENOENT ;
2008-04-26 19:36:36 +04:00
u8 bootable = ( d & & ( d - > host_flags & IDE_HFLAG_NON_BOOTABLE ) ) ? 0 : 1 ;
2009-08-18 22:18:35 +04:00
u8 i = ( d & & ( d - > host_flags & IDE_HFLAG_QD_2ND_PORT ) ) ? 1 : 0 ;
2008-04-26 19:36:36 +04:00
/*
* Claim an unassigned slot .
*
* Give preference to claiming other slots before claiming ide0 / ide1 ,
* just in case there ' s another interface yet - to - be - scanned
* which uses ports 0x1f0 / 0x170 ( the ide0 / ide1 defaults ) .
*
* Unless there is a bootable card that does not use the standard
* ports 0x1f0 / 0x170 ( the ide0 / ide1 defaults ) .
*/
2008-07-23 21:55:57 +04:00
mutex_lock ( & ide_cfg_mtx ) ;
2008-10-13 23:39:33 +04:00
if ( bootable ) {
if ( ( ide_indexes | i ) ! = ( 1 < < MAX_HWIFS ) - 1 )
idx = ffz ( ide_indexes | i ) ;
2008-04-26 19:36:36 +04:00
} else {
2008-10-13 23:39:33 +04:00
if ( ( ide_indexes | 3 ) ! = ( 1 < < MAX_HWIFS ) - 1 )
idx = ffz ( ide_indexes | 3 ) ;
else if ( ( ide_indexes & 3 ) ! = 3 )
idx = ffz ( ide_indexes ) ;
2008-04-26 19:36:36 +04:00
}
2008-07-23 21:55:57 +04:00
if ( idx > = 0 )
ide_indexes | = ( 1 < < idx ) ;
mutex_unlock ( & ide_cfg_mtx ) ;
2008-04-26 19:36:36 +04:00
2008-07-23 21:55:57 +04:00
return idx ;
}
2008-07-16 22:33:39 +04:00
2008-07-23 21:55:57 +04:00
static void ide_free_port_slot ( int idx )
{
mutex_lock ( & ide_cfg_mtx ) ;
ide_indexes & = ~ ( 1 < < idx ) ;
mutex_unlock ( & ide_cfg_mtx ) ;
2008-04-26 19:36:36 +04:00
}
2009-01-06 19:20:56 +03:00
static void ide_port_free_devices ( ide_hwif_t * hwif )
{
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
2009-01-06 19:20:56 +03:00
int i ;
2009-06-10 16:37:20 +04:00
ide_port_for_each_dev ( i , drive , hwif ) {
kfree ( drive - > id ) ;
2009-01-06 19:20:56 +03:00
kfree ( drive ) ;
2009-06-10 16:37:20 +04:00
}
2009-01-06 19:20:56 +03:00
}
static int ide_port_alloc_devices ( ide_hwif_t * hwif , int node )
{
int i ;
for ( i = 0 ; i < MAX_DRIVES ; i + + ) {
ide_drive_t * drive ;
drive = kzalloc_node ( sizeof ( * drive ) , GFP_KERNEL , node ) ;
if ( drive = = NULL )
goto out_nomem ;
2009-06-10 16:37:20 +04:00
/*
* In order to keep things simple we have an id
* block for all drives at all times . If the device
* is pre ATA or refuses ATA / ATAPI identify we
* will add faked data to this .
*
* Also note that 0 everywhere means " can't do X "
*/
drive - > id = kzalloc_node ( SECTOR_SIZE , GFP_KERNEL , node ) ;
if ( drive - > id = = NULL )
goto out_nomem ;
2009-01-06 19:20:56 +03:00
hwif - > devices [ i ] = drive ;
}
return 0 ;
out_nomem :
ide_port_free_devices ( hwif ) ;
return - ENOMEM ;
}
2009-05-17 21:12:25 +04:00
struct ide_host * ide_host_alloc ( const struct ide_port_info * d ,
struct ide_hw * * hws , unsigned int n_ports )
2008-07-23 21:55:57 +04:00
{
struct ide_host * host ;
2009-01-06 19:20:56 +03:00
struct device * dev = hws [ 0 ] ? hws [ 0 ] - > dev : NULL ;
int node = dev ? dev_to_node ( dev ) : - 1 ;
2008-07-23 21:55:57 +04:00
int i ;
2009-01-06 19:20:56 +03:00
host = kzalloc_node ( sizeof ( * host ) , GFP_KERNEL , node ) ;
2008-07-23 21:55:57 +04:00
if ( host = = NULL )
return NULL ;
2009-05-17 21:12:24 +04:00
for ( i = 0 ; i < n_ports ; i + + ) {
2008-07-23 21:55:57 +04:00
ide_hwif_t * hwif ;
2008-07-23 21:55:57 +04:00
int idx ;
2008-07-23 21:55:57 +04:00
if ( hws [ i ] = = NULL )
continue ;
2009-01-06 19:20:56 +03:00
hwif = kzalloc_node ( sizeof ( * hwif ) , GFP_KERNEL , node ) ;
2008-07-23 21:55:58 +04:00
if ( hwif = = NULL )
continue ;
2009-01-06 19:20:56 +03:00
if ( ide_port_alloc_devices ( hwif , node ) < 0 ) {
kfree ( hwif ) ;
continue ;
}
2008-07-23 21:55:57 +04:00
idx = ide_find_port_slot ( d ) ;
if ( idx < 0 ) {
printk ( KERN_ERR " %s: no free slot for interface \n " ,
d ? d - > name : " ide " ) ;
2009-06-10 16:37:20 +04:00
ide_port_free_devices ( hwif ) ;
2008-07-23 21:55:58 +04:00
kfree ( hwif ) ;
2008-07-23 21:55:57 +04:00
continue ;
2008-07-23 21:55:57 +04:00
}
2008-07-23 21:55:57 +04:00
ide_init_port_data ( hwif , idx ) ;
2008-07-25 00:53:15 +04:00
hwif - > host = host ;
2008-07-23 21:55:57 +04:00
host - > ports [ i ] = hwif ;
host - > n_ports + + ;
2008-07-23 21:55:57 +04:00
}
if ( host - > n_ports = = 0 ) {
kfree ( host ) ;
return NULL ;
}
2009-01-06 19:20:56 +03:00
host - > dev [ 0 ] = dev ;
2008-07-25 00:53:14 +04:00
2008-10-11 00:39:32 +04:00
if ( d ) {
host - > init_chipset = d - > init_chipset ;
2009-03-27 14:46:22 +03:00
host - > get_lock = d - > get_lock ;
host - > release_lock = d - > release_lock ;
2008-07-25 00:53:19 +04:00
host - > host_flags = d - > host_flags ;
2009-04-08 16:12:47 +04:00
host - > irq_flags = d - > irq_flags ;
2008-10-11 00:39:32 +04:00
}
2008-07-25 00:53:19 +04:00
2008-07-23 21:55:57 +04:00
return host ;
}
EXPORT_SYMBOL_GPL ( ide_host_alloc ) ;
2009-02-02 22:12:21 +03:00
static void ide_port_free ( ide_hwif_t * hwif )
{
ide_port_free_devices ( hwif ) ;
ide_free_port_slot ( hwif - > index ) ;
kfree ( hwif ) ;
}
static void ide_disable_port ( ide_hwif_t * hwif )
{
struct ide_host * host = hwif - > host ;
int i ;
printk ( KERN_INFO " %s: disabling port \n " , hwif - > name ) ;
for ( i = 0 ; i < MAX_HOST_PORTS ; i + + ) {
if ( host - > ports [ i ] = = hwif ) {
host - > ports [ i ] = NULL ;
host - > n_ports - - ;
}
}
ide_port_free ( hwif ) ;
}
2008-07-23 21:55:57 +04:00
int ide_host_register ( struct ide_host * host , const struct ide_port_info * d ,
2009-05-17 21:12:25 +04:00
struct ide_hw * * hws )
2008-02-02 21:56:31 +03:00
{
ide_hwif_t * hwif , * mate = NULL ;
2008-07-23 21:55:57 +04:00
int i , j = 0 ;
2007-10-20 02:32:31 +04:00
2009-01-06 19:20:56 +03:00
ide_host_for_each_port ( i , hwif , host ) {
2008-07-23 21:55:57 +04:00
if ( hwif = = NULL ) {
2008-02-02 21:56:31 +03:00
mate = NULL ;
continue ;
}
2008-07-23 21:55:50 +04:00
ide_init_port_hw ( hwif , hws [ i ] ) ;
2008-04-27 17:38:23 +04:00
ide_port_apply_params ( hwif ) ;
2009-03-27 14:46:27 +03:00
if ( ( i & 1 ) & & mate ) {
hwif - > mate = mate ;
mate - > mate = hwif ;
2008-10-13 23:39:40 +04:00
}
2008-02-02 21:56:31 +03:00
2009-03-27 14:46:27 +03:00
mate = ( i & 1 ) ? NULL : hwif ;
ide_init_port ( hwif , i & 1 , d ) ;
ide_port_cable_detect ( hwif ) ;
2009-06-15 20:52:54 +04:00
hwif - > port_flags | = IDE_PFLAG_PROBING ;
2008-02-02 21:56:39 +03:00
ide_port_init_devices ( hwif ) ;
2008-02-02 21:56:31 +03:00
}
2009-01-06 19:20:56 +03:00
ide_host_for_each_port ( i , hwif , host ) {
2008-07-23 21:55:57 +04:00
if ( hwif = = NULL )
continue ;
2008-02-02 01:09:36 +03:00
2008-04-27 00:25:17 +04:00
if ( ide_probe_port ( hwif ) = = 0 )
hwif - > present = 1 ;
2008-02-02 01:09:36 +03:00
2009-06-15 20:52:54 +04:00
hwif - > port_flags & = ~ IDE_PFLAG_PROBING ;
2009-03-27 14:46:28 +03:00
if ( ( hwif - > host_flags & IDE_HFLAG_4DRIVES ) = = 0 | |
hwif - > mate = = NULL | | hwif - > mate - > present = = 0 ) {
2009-02-02 22:12:21 +03:00
if ( ide_register_port ( hwif ) ) {
ide_disable_port ( hwif ) ;
continue ;
}
}
2008-02-02 01:09:36 +03:00
2008-04-27 00:25:17 +04:00
if ( hwif - > present )
ide_port_tune_devices ( hwif ) ;
2008-01-26 22:13:04 +03:00
}
2008-01-26 22:13:04 +03:00
2009-06-23 14:43:00 +04:00
ide_host_enable_irqs ( host ) ;
2009-01-06 19:20:56 +03:00
ide_host_for_each_port ( i , hwif , host ) {
2008-07-23 21:55:57 +04:00
if ( hwif = = NULL )
continue ;
2008-01-26 22:13:04 +03:00
if ( hwif_init ( hwif ) = = 0 ) {
printk ( KERN_INFO " %s: failed to initialize IDE "
" interface \n " , hwif - > name ) ;
2009-02-02 22:12:22 +03:00
device_unregister ( & hwif - > gendev ) ;
ide_disable_port ( hwif ) ;
2008-01-26 22:13:04 +03:00
continue ;
}
2008-02-02 21:56:41 +03:00
2008-04-27 00:25:17 +04:00
if ( hwif - > present )
2008-10-13 23:39:45 +04:00
if ( ide_port_setup_devices ( hwif ) = = 0 ) {
hwif - > present = 0 ;
continue ;
}
j + + ;
2008-04-18 02:46:22 +04:00
2009-03-25 01:22:41 +03:00
ide_acpi_init_port ( hwif ) ;
2008-04-27 00:25:17 +04:00
if ( hwif - > present )
ide_acpi_port_init_devices ( hwif ) ;
2008-01-26 22:13:04 +03:00
}
2009-01-06 19:20:56 +03:00
ide_host_for_each_port ( i , hwif , host ) {
2008-07-23 21:55:57 +04:00
if ( hwif = = NULL )
continue ;
2008-02-02 21:56:43 +03:00
2008-04-27 00:25:17 +04:00
ide_sysfs_register_port ( hwif ) ;
ide_proc_register_port ( hwif ) ;
2010-09-02 15:28:39 +04:00
if ( hwif - > present ) {
2008-02-02 21:56:43 +03:00
ide_proc_port_register_devices ( hwif ) ;
2010-09-02 15:28:39 +04:00
hwif_register_devices ( hwif ) ;
}
2007-10-20 02:32:31 +04:00
}
2008-07-23 21:55:57 +04:00
return j ? 0 : - 1 ;
2007-10-20 02:32:31 +04:00
}
2008-07-23 21:55:57 +04:00
EXPORT_SYMBOL_GPL ( ide_host_register ) ;
2008-01-26 22:13:05 +03:00
2009-05-17 21:12:25 +04:00
int ide_host_add ( const struct ide_port_info * d , struct ide_hw * * hws ,
2009-05-17 21:12:24 +04:00
unsigned int n_ports , struct ide_host * * hostp )
ide: add ide_host_add() helper
Add ide_host_add() helper which does ide_host_alloc()+ide_host_register(),
then convert ide_setup_pci_device[s](), ide_legacy_device_add() and some
host drivers to use it.
While at it:
* Fix ide_setup_pci_device[s](), ide_arm.c, gayle.c, ide-4drives.c,
macide.c, q40ide.c, cmd640.c and cs5520.c to return correct error value.
* -ENOENT -> -ENOMEM in rapide.c, ide-h8300.c, ide-generic.c, au1xxx-ide.c
and pmac.c
* -ENODEV -> -ENOMEM in palm_bk3710.c, ide_platform.c and delkin_cb.c
* -1 -> -ENOMEM in ide-pnp.c
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-07-23 21:55:57 +04:00
{
struct ide_host * host ;
2008-07-23 21:55:59 +04:00
int rc ;
ide: add ide_host_add() helper
Add ide_host_add() helper which does ide_host_alloc()+ide_host_register(),
then convert ide_setup_pci_device[s](), ide_legacy_device_add() and some
host drivers to use it.
While at it:
* Fix ide_setup_pci_device[s](), ide_arm.c, gayle.c, ide-4drives.c,
macide.c, q40ide.c, cmd640.c and cs5520.c to return correct error value.
* -ENOENT -> -ENOMEM in rapide.c, ide-h8300.c, ide-generic.c, au1xxx-ide.c
and pmac.c
* -ENODEV -> -ENOMEM in palm_bk3710.c, ide_platform.c and delkin_cb.c
* -1 -> -ENOMEM in ide-pnp.c
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-07-23 21:55:57 +04:00
2009-05-17 21:12:24 +04:00
host = ide_host_alloc ( d , hws , n_ports ) ;
ide: add ide_host_add() helper
Add ide_host_add() helper which does ide_host_alloc()+ide_host_register(),
then convert ide_setup_pci_device[s](), ide_legacy_device_add() and some
host drivers to use it.
While at it:
* Fix ide_setup_pci_device[s](), ide_arm.c, gayle.c, ide-4drives.c,
macide.c, q40ide.c, cmd640.c and cs5520.c to return correct error value.
* -ENOENT -> -ENOMEM in rapide.c, ide-h8300.c, ide-generic.c, au1xxx-ide.c
and pmac.c
* -ENODEV -> -ENOMEM in palm_bk3710.c, ide_platform.c and delkin_cb.c
* -1 -> -ENOMEM in ide-pnp.c
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-07-23 21:55:57 +04:00
if ( host = = NULL )
return - ENOMEM ;
2008-07-23 21:55:59 +04:00
rc = ide_host_register ( host , d , hws ) ;
if ( rc ) {
ide_host_free ( host ) ;
return rc ;
}
ide: add ide_host_add() helper
Add ide_host_add() helper which does ide_host_alloc()+ide_host_register(),
then convert ide_setup_pci_device[s](), ide_legacy_device_add() and some
host drivers to use it.
While at it:
* Fix ide_setup_pci_device[s](), ide_arm.c, gayle.c, ide-4drives.c,
macide.c, q40ide.c, cmd640.c and cs5520.c to return correct error value.
* -ENOENT -> -ENOMEM in rapide.c, ide-h8300.c, ide-generic.c, au1xxx-ide.c
and pmac.c
* -ENODEV -> -ENOMEM in palm_bk3710.c, ide_platform.c and delkin_cb.c
* -1 -> -ENOMEM in ide-pnp.c
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-07-23 21:55:57 +04:00
if ( hostp )
* hostp = host ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( ide_host_add ) ;
2009-01-06 19:20:51 +03:00
static void __ide_port_unregister_devices ( ide_hwif_t * hwif )
{
2009-01-06 19:20:56 +03:00
ide_drive_t * drive ;
2009-01-06 19:20:51 +03:00
int i ;
2009-03-25 01:22:41 +03:00
ide_port_for_each_present_dev ( i , drive , hwif ) {
device_unregister ( & drive - > gendev ) ;
wait_for_completion ( & drive - > gendev_rel_comp ) ;
2009-01-06 19:20:51 +03:00
}
}
void ide_port_unregister_devices ( ide_hwif_t * hwif )
{
mutex_lock ( & ide_cfg_mtx ) ;
__ide_port_unregister_devices ( hwif ) ;
hwif - > present = 0 ;
ide_port_init_devices_data ( hwif ) ;
mutex_unlock ( & ide_cfg_mtx ) ;
}
EXPORT_SYMBOL_GPL ( ide_port_unregister_devices ) ;
/**
* ide_unregister - free an IDE interface
* @ hwif : IDE interface
*
* Perform the final unregister of an IDE interface .
*
* Locking :
* The caller must not hold the IDE locks .
*
* It is up to the caller to be sure there is no pending I / O here ,
* and that the interface will not be reopened ( present / vanishing
* locking isn ' t yet done BTW ) .
*/
static void ide_unregister ( ide_hwif_t * hwif )
{
BUG_ON ( in_interrupt ( ) ) ;
BUG_ON ( irqs_disabled ( ) ) ;
mutex_lock ( & ide_cfg_mtx ) ;
if ( hwif - > present ) {
__ide_port_unregister_devices ( hwif ) ;
hwif - > present = 0 ;
}
ide_proc_unregister_port ( hwif ) ;
free_irq ( hwif - > irq , hwif ) ;
device_unregister ( hwif - > portdev ) ;
device_unregister ( & hwif - > gendev ) ;
wait_for_completion ( & hwif - > gendev_rel_comp ) ;
/*
* Remove us from the kernel ' s knowledge
*/
blk_unregister_region ( MKDEV ( hwif - > major , 0 ) , MAX_DRIVES < < PARTN_BITS ) ;
kfree ( hwif - > sg_table ) ;
unregister_blkdev ( hwif - > major , hwif - > name ) ;
ide_release_dma_engine ( hwif ) ;
mutex_unlock ( & ide_cfg_mtx ) ;
}
2008-07-23 21:55:59 +04:00
void ide_host_free ( struct ide_host * host )
2008-01-26 22:13:05 +03:00
{
2008-07-23 21:55:57 +04:00
ide_hwif_t * hwif ;
2008-01-26 22:13:05 +03:00
int i ;
2007-10-20 02:32:31 +04:00
2009-01-06 19:20:56 +03:00
ide_host_for_each_port ( i , hwif , host ) {
2009-02-02 22:12:21 +03:00
if ( hwif )
ide_port_free ( hwif ) ;
2008-07-23 21:55:50 +04:00
}
2008-01-26 22:13:05 +03:00
2008-07-23 21:55:57 +04:00
kfree ( host ) ;
2008-01-26 22:13:05 +03:00
}
2008-07-23 21:55:59 +04:00
EXPORT_SYMBOL_GPL ( ide_host_free ) ;
void ide_host_remove ( struct ide_host * host )
{
2009-01-06 19:20:56 +03:00
ide_hwif_t * hwif ;
2008-07-23 21:55:59 +04:00
int i ;
2009-01-06 19:20:56 +03:00
ide_host_for_each_port ( i , hwif , host ) {
if ( hwif )
ide_unregister ( hwif ) ;
2008-07-23 21:55:59 +04:00
}
ide_host_free ( host ) ;
}
2008-07-23 21:55:57 +04:00
EXPORT_SYMBOL_GPL ( ide_host_remove ) ;
2008-04-18 02:46:23 +04:00
void ide_port_scan ( ide_hwif_t * hwif )
{
2009-06-15 20:52:54 +04:00
int rc ;
2008-04-27 17:38:23 +04:00
ide_port_apply_params ( hwif ) ;
2008-04-18 02:46:23 +04:00
ide_port_cable_detect ( hwif ) ;
2009-06-15 20:52:54 +04:00
hwif - > port_flags | = IDE_PFLAG_PROBING ;
2008-04-18 02:46:23 +04:00
ide_port_init_devices ( hwif ) ;
2009-06-15 20:52:54 +04:00
rc = ide_probe_port ( hwif ) ;
hwif - > port_flags & = ~ IDE_PFLAG_PROBING ;
if ( rc < 0 )
2008-04-18 02:46:23 +04:00
return ;
hwif - > present = 1 ;
ide_port_tune_devices ( hwif ) ;
ide_port_setup_devices ( hwif ) ;
2009-01-06 19:21:00 +03:00
ide_acpi_port_init_devices ( hwif ) ;
2008-04-18 02:46:23 +04:00
hwif_register_devices ( hwif ) ;
ide_proc_port_register_devices ( hwif ) ;
}
EXPORT_SYMBOL_GPL ( ide_port_scan ) ;