2005-04-17 02:20:36 +04:00
/*
* linux / drivers / ide / setup - pci . c Version 1.10 2002 / 08 / 19
*
* Copyright ( c ) 1998 - 2000 Andre Hedrick < andre @ linux - ide . org >
*
* Copyright ( c ) 1995 - 1998 Mark Lord
* May be copied or modified under the terms of the GNU General Public License
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/pci.h>
# include <linux/init.h>
# include <linux/timer.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/ide.h>
# include <linux/dma-mapping.h>
# include <asm/io.h>
# include <asm/irq.h>
/**
* ide_match_hwif - match a PCI IDE against an ide_hwif
* @ io_base : I / O base of device
* @ bootable : set if its bootable
* @ name : name of device
*
* Match a PCI IDE port against an entry in ide_hwifs [ ] ,
* based on io_base port if possible . Return the matching hwif ,
* or a new hwif . If we find an error ( clashing , out of devices , etc )
* return NULL
*
* FIXME : we need to handle mmio matches here too
*/
static ide_hwif_t * ide_match_hwif ( unsigned long io_base , u8 bootable , const char * name )
{
int h ;
ide_hwif_t * hwif ;
/*
* Look for a hwif with matching io_base specified using
* parameters to ide_setup ( ) .
*/
for ( h = 0 ; h < MAX_HWIFS ; + + h ) {
hwif = & ide_hwifs [ h ] ;
if ( hwif - > io_ports [ IDE_DATA_OFFSET ] = = io_base ) {
if ( hwif - > chipset = = ide_forced )
return hwif ; /* a perfect match */
}
}
/*
* Look for a hwif with matching io_base default value .
* If chipset is " ide_unknown " , then claim that hwif slot .
* Otherwise , some other chipset has already claimed it . . : (
*/
for ( h = 0 ; h < MAX_HWIFS ; + + h ) {
hwif = & ide_hwifs [ h ] ;
if ( hwif - > io_ports [ IDE_DATA_OFFSET ] = = io_base ) {
if ( hwif - > chipset = = ide_unknown )
return hwif ; /* match */
printk ( KERN_ERR " %s: port 0x%04lx already claimed by %s \n " ,
name , io_base , hwif - > name ) ;
return NULL ; /* already claimed */
}
}
/*
* Okay , there is no hwif matching our io_base ,
* so we ' ll just 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 1f 0 / 170 ( the ide0 / ide1 defaults ) .
*
* Unless there is a bootable card that does not use the standard
* ports 1f 0 / 170 ( the ide0 / ide1 defaults ) . The ( bootable ) flag .
*/
if ( bootable ) {
for ( h = 0 ; h < MAX_HWIFS ; + + h ) {
hwif = & ide_hwifs [ h ] ;
if ( hwif - > chipset = = ide_unknown )
return hwif ; /* pick an unused entry */
}
} else {
for ( h = 2 ; h < MAX_HWIFS ; + + h ) {
hwif = ide_hwifs + h ;
if ( hwif - > chipset = = ide_unknown )
return hwif ; /* pick an unused entry */
}
}
2006-10-03 12:14:16 +04:00
for ( h = 0 ; h < 2 & & h < MAX_HWIFS ; + + h ) {
2005-04-17 02:20:36 +04:00
hwif = ide_hwifs + h ;
if ( hwif - > chipset = = ide_unknown )
return hwif ; /* pick an unused entry */
}
printk ( KERN_ERR " %s: too many IDE interfaces, no room in table \n " , name ) ;
return NULL ;
}
/**
* ide_setup_pci_baseregs - place a PCI IDE controller native
* @ dev : PCI device of interface to switch native
* @ name : Name of interface
*
* We attempt to place the PCI interface into PCI native mode . If
* we succeed the BARs are ok and the controller is in PCI mode .
* Returns 0 on success or an errno code .
*
* FIXME : if we program the interface and then fail to set the BARS
* we don ' t switch it back to legacy mode . Do we actually care ? ?
*/
static int ide_setup_pci_baseregs ( struct pci_dev * dev , const char * name )
{
u8 progif = 0 ;
/*
* Place both IDE interfaces into PCI " native " mode :
*/
if ( pci_read_config_byte ( dev , PCI_CLASS_PROG , & progif ) | |
( progif & 5 ) ! = 5 ) {
if ( ( progif & 0xa ) ! = 0xa ) {
printk ( KERN_INFO " %s: device not capable of full "
" native PCI mode \n " , name ) ;
return - EOPNOTSUPP ;
}
printk ( " %s: placing both ports into native PCI mode \n " , name ) ;
( void ) pci_write_config_byte ( dev , PCI_CLASS_PROG , progif | 5 ) ;
if ( pci_read_config_byte ( dev , PCI_CLASS_PROG , & progif ) | |
( progif & 5 ) ! = 5 ) {
printk ( KERN_ERR " %s: rewrite of PROGIF failed, wanted "
" 0x%04x, got 0x%04x \n " ,
name , progif | 5 , progif ) ;
return - EOPNOTSUPP ;
}
}
return 0 ;
}
# ifdef CONFIG_BLK_DEV_IDEDMA_PCI
/**
* ide_get_or_set_dma_base - setup BMIBA
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
* @ hwif : IDE interface
2005-04-17 02:20:36 +04:00
*
2007-10-17 00:29:56 +04:00
* Fetch the DMA Bus - Master - I / O - Base - Address ( BMIBA ) from PCI space .
* Where a device has a partner that is already in DMA mode we check
* and enforce IDE simplex rules .
2005-04-17 02:20:36 +04:00
*/
2007-10-20 02:32:34 +04:00
static unsigned long ide_get_or_set_dma_base ( const struct ide_port_info * d , ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
unsigned long dma_base = 0 ;
struct pci_dev * dev = hwif - > pci_dev ;
if ( hwif - > mmio )
return hwif - > dma_base ;
if ( hwif - > mate & & hwif - > mate - > dma_base ) {
dma_base = hwif - > mate - > dma_base - ( hwif - > channel ? 0 : 8 ) ;
} else {
2007-10-19 02:30:07 +04:00
u8 baridx = ( d - > host_flags & IDE_HFLAG_CS5520 ) ? 2 : 4 ;
dma_base = pci_resource_start ( dev , baridx ) ;
if ( dma_base = = 0 )
printk ( KERN_ERR " %s: DMA base is invalid \n " , d - > name ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-19 02:30:07 +04:00
if ( ( d - > host_flags & IDE_HFLAG_CS5520 ) = = 0 & & dma_base ) {
2005-04-17 02:20:36 +04:00
u8 simplex_stat = 0 ;
dma_base + = hwif - > channel ? 8 : 0 ;
switch ( dev - > device ) {
case PCI_DEVICE_ID_AL_M5219 :
case PCI_DEVICE_ID_AL_M5229 :
case PCI_DEVICE_ID_AMD_VIPER_7409 :
case PCI_DEVICE_ID_CMD_643 :
case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE :
2005-08-19 00:27:07 +04:00
case PCI_DEVICE_ID_REVOLUTION :
2007-10-19 02:30:08 +04:00
simplex_stat = inb ( dma_base + 2 ) ;
outb ( simplex_stat & 0x60 , dma_base + 2 ) ;
simplex_stat = inb ( dma_base + 2 ) ;
2005-04-17 02:20:36 +04:00
if ( simplex_stat & 0x80 ) {
printk ( KERN_INFO " %s: simplex device: "
2007-10-19 02:30:07 +04:00
" DMA forced \n " ,
d - > name ) ;
2005-04-17 02:20:36 +04:00
}
break ;
default :
/*
* If the device claims " simplex " DMA ,
* this means only one of the two interfaces
* can be trusted with DMA at any point in time .
* So we should enable DMA only on one of the
* two interfaces .
*/
simplex_stat = hwif - > INB ( dma_base + 2 ) ;
if ( simplex_stat & 0x80 ) {
/* simplex device? */
/*
* At this point we haven ' t probed the drives so we can ' t make the
* appropriate decision . Really we should defer this problem
* until we tune the drive then try to grab DMA ownership if we want
* to be the DMA end . This has to be become dynamic to handle hot
* plug .
*/
if ( hwif - > mate & & hwif - > mate - > dma_base ) {
printk ( KERN_INFO " %s: simplex device: "
2007-10-19 02:30:07 +04:00
" DMA disabled \n " ,
d - > name ) ;
2005-04-17 02:20:36 +04:00
dma_base = 0 ;
}
}
}
}
return dma_base ;
}
# endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
2007-10-20 02:32:34 +04:00
void ide_setup_pci_noise ( struct pci_dev * dev , const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
2007-10-20 02:32:36 +04:00
printk ( KERN_INFO " %s: IDE controller (0x%04x:0x%04x rev 0x%02x) at "
" PCI slot %s \n " , d - > name , dev - > vendor , dev - > device ,
dev - > revision , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL_GPL ( ide_setup_pci_noise ) ;
/**
* ide_pci_enable - do PCI enables
* @ dev : PCI device
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2005-04-17 02:20:36 +04:00
*
* Enable the IDE PCI device . We attempt to enable the device in full
* but if that fails then we only need BAR4 so we will enable that .
*
* Returns zero on success or an error code
*/
2007-10-20 02:32:34 +04:00
2007-10-20 02:32:34 +04:00
static int ide_pci_enable ( struct pci_dev * dev , const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
int ret ;
if ( pci_enable_device ( dev ) ) {
ret = pci_enable_device_bars ( dev , 1 < < 4 ) ;
if ( ret < 0 ) {
printk ( KERN_WARNING " %s: (ide_setup_pci_device:) "
" Could not enable device. \n " , d - > name ) ;
goto out ;
}
printk ( KERN_WARNING " %s: BIOS configuration fixed. \n " , d - > name ) ;
}
/*
2007-10-20 02:32:34 +04:00
* assume all devices can do 32 - bit DMA for now , we can add
* a DMA mask field to the struct ide_port_info if we need it
* ( or let lower level driver set the DMA mask )
2005-04-17 02:20:36 +04:00
*/
ret = pci_set_dma_mask ( dev , DMA_32BIT_MASK ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " %s: can't set dma mask \n " , d - > name ) ;
goto out ;
}
/* FIXME: Temporary - until we put in the hotplug interface logic
Check that the bits we want are not in use by someone else . */
ret = pci_request_region ( dev , 4 , " ide_tmp " ) ;
if ( ret < 0 )
goto out ;
pci_release_region ( dev , 4 ) ;
out :
return ret ;
}
/**
* ide_pci_configure - configure an unconfigured device
* @ dev : PCI device
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2005-04-17 02:20:36 +04:00
*
* Enable and configure the PCI device we have been passed .
* Returns zero on success or an error code .
*/
2007-10-20 02:32:34 +04:00
2007-10-20 02:32:34 +04:00
static int ide_pci_configure ( struct pci_dev * dev , const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
u16 pcicmd = 0 ;
/*
* PnP BIOS was * supposed * to have setup this device , but we
* can do it ourselves , so long as the BIOS has assigned an IRQ
* ( or possibly the device is using a " legacy header " for IRQs ) .
* Maybe the user deliberately * disabled * the device ,
* but we ' ll eventually ignore it again if no drives respond .
*/
if ( ide_setup_pci_baseregs ( dev , d - > name ) | | pci_write_config_word ( dev , PCI_COMMAND , pcicmd | PCI_COMMAND_IO ) )
{
printk ( KERN_INFO " %s: device disabled (BIOS) \n " , d - > name ) ;
return - ENODEV ;
}
if ( pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) ) {
printk ( KERN_ERR " %s: error accessing PCI regs \n " , d - > name ) ;
return - EIO ;
}
if ( ! ( pcicmd & PCI_COMMAND_IO ) ) {
printk ( KERN_ERR " %s: unable to enable IDE controller \n " , d - > name ) ;
return - ENXIO ;
}
return 0 ;
}
/**
* ide_pci_check_iomem - check a register is I / O
2007-10-20 02:32:34 +04:00
* @ dev : PCI device
* @ d : IDE port info
* @ bar : BAR number
2005-04-17 02:20:36 +04:00
*
* Checks if a BAR is configured and points to MMIO space . If so
* print an error and return an error code . Otherwise return 0
*/
2007-10-20 02:32:34 +04:00
2007-10-20 02:32:34 +04:00
static int ide_pci_check_iomem ( struct pci_dev * dev , const struct ide_port_info * d , int bar )
2005-04-17 02:20:36 +04:00
{
ulong flags = pci_resource_flags ( dev , bar ) ;
/* Unconfigured ? */
if ( ! flags | | pci_resource_len ( dev , bar ) = = 0 )
return 0 ;
/* I/O space */
if ( flags & PCI_BASE_ADDRESS_IO_MASK )
return 0 ;
/* Bad */
printk ( KERN_ERR " %s: IO baseregs (BIOS) are reported "
" as MEM, report to "
" <andre@linux-ide.org>. \n " , d - > name ) ;
return - EINVAL ;
}
/**
* ide_hwif_configure - configure an IDE interface
* @ dev : PCI device holding interface
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2005-04-17 02:20:36 +04:00
* @ mate : Paired interface if any
*
* Perform the initial set up for the hardware interface structure . This
* is done per interface port rather than per PCI device . There may be
* more than one port per device .
*
* Returns the new hardware interface structure , or NULL on a failure
*/
2007-10-20 02:32:34 +04:00
2007-10-20 02:32:34 +04:00
static ide_hwif_t * ide_hwif_configure ( struct pci_dev * dev , const struct ide_port_info * d , ide_hwif_t * mate , int port , int irq )
2005-04-17 02:20:36 +04:00
{
unsigned long ctl = 0 , base = 0 ;
ide_hwif_t * hwif ;
2007-10-19 02:30:06 +04:00
u8 bootable = ( d - > host_flags & IDE_HFLAG_BOOTABLE ) ? 1 : 0 ;
2005-04-17 02:20:36 +04:00
2007-07-20 03:11:55 +04:00
if ( ( d - > host_flags & IDE_HFLAG_ISA_PORTS ) = = 0 ) {
2005-04-17 02:20:36 +04:00
/* Possibly we should fail if these checks report true */
ide_pci_check_iomem ( dev , d , 2 * port ) ;
ide_pci_check_iomem ( dev , d , 2 * port + 1 ) ;
ctl = pci_resource_start ( dev , 2 * port + 1 ) ;
base = pci_resource_start ( dev , 2 * port ) ;
if ( ( ctl & & ! base ) | | ( base & & ! ctl ) ) {
printk ( KERN_ERR " %s: inconsistent baseregs (BIOS) "
" for port %d, skipping \n " , d - > name , port ) ;
return NULL ;
}
}
if ( ! ctl )
{
/* Use default values */
ctl = port ? 0x374 : 0x3f4 ;
base = port ? 0x170 : 0x1f0 ;
}
2007-10-19 02:30:06 +04:00
if ( ( hwif = ide_match_hwif ( base , bootable , d - > name ) ) = = NULL )
2005-04-17 02:20:36 +04:00
return NULL ; /* no room in ide_hwifs[] */
if ( hwif - > io_ports [ IDE_DATA_OFFSET ] ! = base | |
hwif - > io_ports [ IDE_CONTROL_OFFSET ] ! = ( ctl | 2 ) ) {
2007-10-20 02:32:33 +04:00
hw_regs_t hw ;
memset ( & hw , 0 , sizeof ( hw ) ) ;
2007-10-20 02:32:32 +04:00
# ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT
2007-10-20 02:32:33 +04:00
ide_std_init_ports ( & hw , base , ctl | 2 ) ;
2005-04-17 02:20:36 +04:00
# else
2007-10-20 02:32:33 +04:00
ide_init_hwif_ports ( & hw , base , ctl | 2 , NULL ) ;
2005-04-17 02:20:36 +04:00
# endif
2007-10-20 02:32:33 +04:00
memcpy ( hwif - > io_ports , hw . io_ports , sizeof ( hwif - > io_ports ) ) ;
2005-04-17 02:20:36 +04:00
hwif - > noprobe = ! hwif - > io_ports [ IDE_DATA_OFFSET ] ;
}
2007-10-20 02:32:30 +04:00
hwif - > chipset = d - > chipset ? d - > chipset : ide_pci ;
2005-04-17 02:20:36 +04:00
hwif - > pci_dev = dev ;
2007-10-20 02:32:34 +04:00
hwif - > cds = d ;
2005-04-17 02:20:36 +04:00
hwif - > channel = port ;
if ( ! hwif - > irq )
hwif - > irq = irq ;
if ( mate ) {
hwif - > mate = mate ;
mate - > mate = hwif ;
}
return hwif ;
}
/**
* ide_hwif_setup_dma - configure DMA interface
* @ dev : PCI device
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
* @ hwif : IDE interface
2005-04-17 02:20:36 +04:00
*
* Set up the DMA base for the interface . Enable the master bits as
* necessary and attempt to bring the device DMA into a ready to use
* state
*/
2007-10-20 02:32:34 +04:00
2007-10-20 02:32:34 +04:00
static void ide_hwif_setup_dma ( struct pci_dev * dev , const struct ide_port_info * d , ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
2007-10-20 02:32:34 +04:00
# ifdef CONFIG_BLK_DEV_IDEDMA_PCI
2005-04-17 02:20:36 +04:00
u16 pcicmd ;
2007-10-19 02:30:06 +04:00
2005-04-17 02:20:36 +04:00
pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) ;
2007-10-19 02:30:06 +04:00
if ( ( d - > host_flags & IDE_HFLAG_NO_AUTODMA ) = = 0 | |
2005-04-17 02:20:36 +04:00
( ( dev - > class > > 8 ) = = PCI_CLASS_STORAGE_IDE & &
( dev - > class & 0x80 ) ) ) {
2007-10-19 02:30:07 +04:00
unsigned long dma_base = ide_get_or_set_dma_base ( d , hwif ) ;
2005-04-17 02:20:36 +04:00
if ( dma_base & & ! ( pcicmd & PCI_COMMAND_MASTER ) ) {
/*
* Set up BM - DMA capability
* ( PnP BIOS should have done this )
*/
pci_set_master ( dev ) ;
if ( pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) | | ! ( pcicmd & PCI_COMMAND_MASTER ) ) {
printk ( KERN_ERR " %s: %s error updating PCICMD \n " ,
hwif - > name , d - > name ) ;
dma_base = 0 ;
}
}
if ( dma_base ) {
if ( d - > init_dma ) {
d - > init_dma ( hwif , dma_base ) ;
} else {
ide_setup_dma ( hwif , dma_base , 8 ) ;
}
} else {
printk ( KERN_INFO " %s: %s Bus-Master DMA disabled "
" (BIOS) \n " , hwif - > name , d - > name ) ;
}
}
# endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
2007-10-20 02:32:34 +04:00
}
2005-04-17 02:20:36 +04:00
/**
* ide_setup_pci_controller - set up IDE PCI
* @ dev : PCI device
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2005-04-17 02:20:36 +04:00
* @ noisy : verbose flag
* @ config : returned as 1 if we configured the hardware
*
* Set up the PCI and controller side of the IDE interface . This brings
* up the PCI side of the device , checks that the device is enabled
* and enables it if need be
*/
2007-10-20 02:32:34 +04:00
2007-10-20 02:32:34 +04:00
static int ide_setup_pci_controller ( struct pci_dev * dev , const struct ide_port_info * d , int noisy , int * config )
2005-04-17 02:20:36 +04:00
{
int ret ;
u16 pcicmd ;
if ( noisy )
ide_setup_pci_noise ( dev , d ) ;
ret = ide_pci_enable ( dev , d ) ;
if ( ret < 0 )
goto out ;
ret = pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " %s: error accessing PCI regs \n " , d - > name ) ;
goto out ;
}
if ( ! ( pcicmd & PCI_COMMAND_IO ) ) { /* is device disabled? */
ret = ide_pci_configure ( dev , d ) ;
if ( ret < 0 )
goto out ;
* config = 1 ;
printk ( KERN_INFO " %s: device enabled (Linux) \n " , d - > name ) ;
}
out :
return ret ;
}
/**
* ide_pci_setup_ports - configure ports / devices on PCI IDE
* @ dev : PCI device
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2005-04-17 02:20:36 +04:00
* @ pciirq : IRQ line
2007-10-20 02:32:31 +04:00
* @ idx : ATA index table to update
2005-04-17 02:20:36 +04:00
*
* Scan the interfaces attached to this device and do any
* necessary per port setup . Attach the devices and ask the
* generic DMA layer to do its work for us .
*
* Normally called automaticall from do_ide_pci_setup_device ,
* but is also used directly as a helper function by some controllers
* where the chipset setup is not the default PCI IDE one .
*/
2007-10-20 02:32:31 +04:00
2007-10-20 02:32:34 +04:00
void ide_pci_setup_ports ( struct pci_dev * dev , const struct ide_port_info * d , int pciirq , u8 * idx )
2005-04-17 02:20:36 +04:00
{
2007-07-20 03:11:55 +04:00
int channels = ( d - > host_flags & IDE_HFLAG_SINGLE ) ? 1 : 2 , port ;
2005-04-17 02:20:36 +04:00
ide_hwif_t * hwif , * mate = NULL ;
u8 tmp ;
/*
* Set up the IDE ports
*/
2007-10-20 02:32:29 +04:00
2007-07-20 03:11:55 +04:00
for ( port = 0 ; port < channels ; + + port ) {
2007-10-20 02:32:34 +04:00
const ide_pci_enablebit_t * e = & ( d - > enablebits [ port ] ) ;
2005-04-17 02:20:36 +04:00
if ( e - > reg & & ( pci_read_config_byte ( dev , e - > reg , & tmp ) | |
2007-10-20 02:32:29 +04:00
( tmp & e - > mask ) ! = e - > val ) ) {
printk ( KERN_INFO " %s: IDE port disabled \n " , d - > name ) ;
2005-04-17 02:20:36 +04:00
continue ; /* port not enabled */
2007-10-20 02:32:29 +04:00
}
2005-04-17 02:20:36 +04:00
if ( ( hwif = ide_hwif_configure ( dev , d , mate , port , pciirq ) ) = = NULL )
continue ;
/* setup proper ancestral information */
hwif - > gendev . parent = & dev - > dev ;
2007-10-20 02:32:31 +04:00
* ( idx + port ) = hwif - > index ;
2005-04-17 02:20:36 +04:00
if ( d - > init_iops )
d - > init_iops ( hwif ) ;
2007-10-19 02:30:07 +04:00
if ( ( d - > host_flags & IDE_HFLAG_NO_DMA ) = = 0 )
2005-04-17 02:20:36 +04:00
ide_hwif_setup_dma ( dev , d , hwif ) ;
2007-10-19 02:30:07 +04:00
2007-10-20 02:32:30 +04:00
if ( ( ! hwif - > irq & & ( d - > host_flags & IDE_HFLAG_LEGACY_IRQS ) ) | |
( d - > host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS ) )
2007-10-19 02:30:11 +04:00
hwif - > irq = port ? 15 : 14 ;
2007-10-20 02:32:31 +04:00
hwif - > fixup = d - > fixup ;
2007-07-20 03:11:58 +04:00
hwif - > host_flags = d - > host_flags ;
2007-07-20 03:11:59 +04:00
hwif - > pio_mask = d - > pio_mask ;
2007-07-20 03:11:58 +04:00
2007-10-19 02:30:10 +04:00
if ( ( d - > host_flags & IDE_HFLAG_SERIALIZE ) & & hwif - > mate )
hwif - > mate - > serialized = hwif - > serialized = 1 ;
2007-10-20 02:32:30 +04:00
if ( d - > host_flags & IDE_HFLAG_IO_32BIT ) {
hwif - > drives [ 0 ] . io_32bit = 1 ;
hwif - > drives [ 1 ] . io_32bit = 1 ;
}
if ( d - > host_flags & IDE_HFLAG_UNMASK_IRQS ) {
hwif - > drives [ 0 ] . unmask = 1 ;
hwif - > drives [ 1 ] . unmask = 1 ;
}
2007-10-19 02:30:07 +04:00
if ( hwif - > dma_base ) {
hwif - > swdma_mask = d - > swdma_mask ;
hwif - > mwdma_mask = d - > mwdma_mask ;
hwif - > ultra_mask = d - > udma_mask ;
}
2007-10-19 02:30:12 +04:00
hwif - > drives [ 0 ] . autotune = 1 ;
hwif - > drives [ 1 ] . autotune = 1 ;
2007-10-20 02:32:30 +04:00
if ( d - > host_flags & IDE_HFLAG_RQSIZE_256 )
hwif - > rqsize = 256 ;
2005-04-17 02:20:36 +04:00
if ( d - > init_hwif )
/* Call chipset-specific routine
* for each enabled hwif
*/
d - > init_hwif ( hwif ) ;
mate = hwif ;
}
}
EXPORT_SYMBOL_GPL ( ide_pci_setup_ports ) ;
/*
* ide_setup_pci_device ( ) looks at the primary / secondary interfaces
* on a PCI IDE device and , if they are enabled , prepares the IDE driver
* for use with them . This generic code works for most PCI chipsets .
*
* One thing that is not standardized is the location of the
* primary / secondary interface " enable/disable " bits . For chipsets that
2007-10-20 02:32:34 +04:00
* we " know " about , this information is in the struct ide_port_info ;
2005-04-17 02:20:36 +04:00
* for all other chipsets , we just assume both interfaces are enabled .
*/
2007-10-20 02:32:34 +04:00
static int do_ide_setup_pci_device ( struct pci_dev * dev ,
2007-10-20 02:32:34 +04:00
const struct ide_port_info * d ,
2007-10-20 02:32:31 +04:00
u8 * idx , u8 noisy )
2005-04-17 02:20:36 +04:00
{
int tried_config = 0 ;
int pciirq , ret ;
ret = ide_setup_pci_controller ( dev , d , noisy , & tried_config ) ;
if ( ret < 0 )
goto out ;
/*
* Can we trust the reported IRQ ?
*/
pciirq = dev - > irq ;
/* Is it an "IDE storage" device in non-PCI mode? */
if ( ( dev - > class > > 8 ) = = PCI_CLASS_STORAGE_IDE & & ( dev - > class & 5 ) ! = 5 ) {
if ( noisy )
printk ( KERN_INFO " %s: not 100%% native mode: "
" will probe irqs later \n " , d - > name ) ;
/*
* This allows offboard ide - pci cards the enable a BIOS ,
* verify interrupt settings of split - mirror pci - config
* space , place chipset into init - mode , and / or preserve
* an interrupt if the card is not native ide support .
*/
ret = d - > init_chipset ? d - > init_chipset ( dev , d - > name ) : 0 ;
if ( ret < 0 )
goto out ;
pciirq = ret ;
} else if ( tried_config ) {
if ( noisy )
printk ( KERN_INFO " %s: will probe irqs later \n " , d - > name ) ;
pciirq = 0 ;
} else if ( ! pciirq ) {
if ( noisy )
printk ( KERN_WARNING " %s: bad irq (%d): will probe later \n " ,
d - > name , pciirq ) ;
pciirq = 0 ;
} else {
if ( d - > init_chipset ) {
ret = d - > init_chipset ( dev , d - > name ) ;
if ( ret < 0 )
goto out ;
}
if ( noisy )
printk ( KERN_INFO " %s: 100%% native mode on irq %d \n " ,
d - > name , pciirq ) ;
}
/* FIXME: silent failure can happen */
2007-10-20 02:32:31 +04:00
ide_pci_setup_ports ( dev , d , pciirq , idx ) ;
2005-04-17 02:20:36 +04:00
out :
return ret ;
}
2007-10-20 02:32:34 +04:00
int ide_setup_pci_device ( struct pci_dev * dev , const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
2007-10-20 02:32:31 +04:00
u8 idx [ 4 ] = { 0xff , 0xff , 0xff , 0xff } ;
2005-04-17 02:20:36 +04:00
int ret ;
2007-10-20 02:32:31 +04:00
ret = do_ide_setup_pci_device ( dev , d , & idx [ 0 ] , 1 ) ;
2005-04-17 02:20:36 +04:00
2007-10-20 02:32:31 +04:00
if ( ret > = 0 )
ide_device_add ( idx ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
EXPORT_SYMBOL_GPL ( ide_setup_pci_device ) ;
int ide_setup_pci_devices ( struct pci_dev * dev1 , struct pci_dev * dev2 ,
2007-10-20 02:32:34 +04:00
const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
struct pci_dev * pdev [ ] = { dev1 , dev2 } ;
int ret , i ;
2007-10-20 02:32:31 +04:00
u8 idx [ 4 ] = { 0xff , 0xff , 0xff , 0xff } ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < 2 ; i + + ) {
2007-10-20 02:32:31 +04:00
ret = do_ide_setup_pci_device ( pdev [ i ] , d , & idx [ i * 2 ] , ! i ) ;
2005-04-17 02:20:36 +04:00
/*
* FIXME : Mom , mom , they stole me the helper function to undo
* do_ide_setup_pci_device ( ) on the first device !
*/
if ( ret < 0 )
goto out ;
}
2007-10-20 02:32:31 +04:00
ide_device_add ( idx ) ;
2005-04-17 02:20:36 +04:00
out :
return ret ;
}
EXPORT_SYMBOL_GPL ( ide_setup_pci_devices ) ;
2007-05-10 02:01:11 +04:00
# ifdef CONFIG_IDEPCI_PCIBUS_ORDER
2005-04-17 02:20:36 +04:00
/*
* Module interfaces
*/
static int pre_init = 1 ; /* Before first ordered IDE scan */
static LIST_HEAD ( ide_pci_drivers ) ;
/*
2005-11-19 01:11:24 +03:00
* __ide_pci_register_driver - attach IDE driver
2005-04-17 02:20:36 +04:00
* @ driver : pci driver
2005-10-28 01:12:54 +04:00
* @ module : owner module of the driver
2005-04-17 02:20:36 +04:00
*
* Registers a driver with the IDE layer . The IDE layer arranges that
* boot time setup is done in the expected device order and then
* hands the controllers off to the core PCI code to do the rest of
* the work .
*
* Returns are the same as for pci_register_driver
*/
2007-01-15 22:50:02 +03:00
int __ide_pci_register_driver ( struct pci_driver * driver , struct module * module ,
const char * mod_name )
2005-04-17 02:20:36 +04:00
{
if ( ! pre_init )
2007-01-15 22:50:02 +03:00
return __pci_register_driver ( driver , module , mod_name ) ;
2005-10-28 01:12:54 +04:00
driver - > driver . owner = module ;
2005-04-17 02:20:36 +04:00
list_add_tail ( & driver - > node , & ide_pci_drivers ) ;
return 0 ;
}
2005-10-28 01:12:54 +04:00
EXPORT_SYMBOL_GPL ( __ide_pci_register_driver ) ;
2005-04-17 02:20:36 +04:00
/**
* ide_scan_pcidev - find an IDE driver for a device
* @ dev : PCI device to check
*
* Look for an IDE driver to handle the device we are considering .
* This is only used during boot up to get the ordering correct . After
* boot up the pci layer takes over the job .
*/
static int __init ide_scan_pcidev ( struct pci_dev * dev )
{
struct list_head * l ;
struct pci_driver * d ;
2007-09-12 00:28:34 +04:00
list_for_each ( l , & ide_pci_drivers ) {
2005-04-17 02:20:36 +04:00
d = list_entry ( l , struct pci_driver , node ) ;
2007-09-12 00:28:34 +04:00
if ( d - > id_table ) {
const struct pci_device_id * id = pci_match_id ( d - > id_table ,
dev ) ;
if ( id ! = NULL & & d - > probe ( dev , id ) > = 0 ) {
dev - > driver = d ;
pci_dev_get ( dev ) ;
return 1 ;
2005-04-17 02:20:36 +04:00
}
}
}
return 0 ;
}
/**
* ide_scan_pcibus - perform the initial IDE driver scan
* @ scan_direction : set for reverse order scanning
*
* Perform the initial bus rather than driver ordered scan of the
* PCI drivers . After this all IDE pci handling becomes standard
* module ordering not traditionally ordered .
*/
void __init ide_scan_pcibus ( int scan_direction )
{
struct pci_dev * dev = NULL ;
struct pci_driver * d ;
struct list_head * l , * n ;
pre_init = 0 ;
2007-09-12 00:28:34 +04:00
if ( ! scan_direction )
while ( ( dev = pci_get_device ( PCI_ANY_ID , PCI_ANY_ID , dev ) ) ! = NULL )
2005-04-17 02:20:36 +04:00
ide_scan_pcidev ( dev ) ;
2007-09-12 00:28:34 +04:00
else
while ( ( dev = pci_get_device_reverse ( PCI_ANY_ID , PCI_ANY_ID , dev ) )
! = NULL )
2005-04-17 02:20:36 +04:00
ide_scan_pcidev ( dev ) ;
/*
* Hand the drivers over to the PCI layer now we
* are post init .
*/
2007-07-04 00:28:36 +04:00
list_for_each_safe ( l , n , & ide_pci_drivers ) {
2005-04-17 02:20:36 +04:00
list_del ( l ) ;
d = list_entry ( l , struct pci_driver , node ) ;
2007-09-12 00:28:34 +04:00
if ( __pci_register_driver ( d , d - > driver . owner , d - > driver . mod_name ) )
printk ( KERN_ERR " %s: failed to register driver for %s \n " ,
__FUNCTION__ , d - > driver . mod_name ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-05-10 02:01:11 +04:00
# endif