2005-04-17 02:20:36 +04:00
/*
2008-02-02 01:09:33 +03:00
* Copyright ( C ) 1998 - 2000 Andre Hedrick < andre @ linux - ide . org >
* Copyright ( C ) 1995 - 1998 Mark Lord
2009-06-10 16:37:21 +04:00
* Copyright ( C ) 2007 - 2009 Bartlomiej Zolnierkiewicz
2008-02-02 01:09:33 +03:00
*
2005-04-17 02:20:36 +04:00
* May be copied or modified under the terms of the GNU General Public License
*/
# include <linux/types.h>
# include <linux/kernel.h>
2011-07-17 23:33:58 +04:00
# include <linux/export.h>
2005-04-17 02:20:36 +04:00
# include <linux/pci.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/ide.h>
# include <linux/dma-mapping.h>
# include <asm/io.h>
/**
* 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 .
2008-04-26 19:36:39 +04:00
* Returns 0 on success or an errno code .
2005-04-17 02:20:36 +04:00
*
* 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 ? ?
*/
2008-04-26 19:36:39 +04:00
static int ide_setup_pci_baseregs ( struct pci_dev * dev , const char * name )
2005-04-17 02:20:36 +04:00
{
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 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: device not capable of full "
" native PCI mode \n " , name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
return - EOPNOTSUPP ;
}
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: placing both ports into native PCI "
" mode \n " , name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
( void ) pci_write_config_byte ( dev , PCI_CLASS_PROG , progif | 5 ) ;
if ( pci_read_config_byte ( dev , PCI_CLASS_PROG , & progif ) | |
( progif & 5 ) ! = 5 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: rewrite of PROGIF failed, "
" wanted 0x%04x, got 0x%04x \n " ,
name , pci_name ( dev ) , progif | 5 , progif ) ;
2005-04-17 02:20:36 +04:00
return - EOPNOTSUPP ;
}
}
return 0 ;
}
# ifdef CONFIG_BLK_DEV_IDEDMA_PCI
2008-07-25 00:53:31 +04:00
static int ide_pci_clear_simplex ( unsigned long dma_base , const char * name )
2008-02-02 01:09:30 +03:00
{
u8 dma_stat = inb ( dma_base + 2 ) ;
outb ( dma_stat & 0x60 , dma_base + 2 ) ;
dma_stat = inb ( dma_base + 2 ) ;
2008-07-25 00:53:31 +04:00
return ( dma_stat & 0x80 ) ? 1 : 0 ;
2008-02-02 01:09:30 +03:00
}
2005-04-17 02:20:36 +04:00
/**
2008-04-27 00:25:22 +04:00
* ide_pci_dma_base - setup BMIBA
2007-10-20 02:32:34 +04:00
* @ hwif : IDE interface
2008-04-27 00:25:22 +04:00
* @ d : IDE port info
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 .
2005-04-17 02:20:36 +04:00
*/
2008-04-27 00:25:22 +04:00
unsigned long ide_pci_dma_base ( ide_hwif_t * hwif , const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
2008-02-02 01:09:31 +03:00
struct pci_dev * dev = to_pci_dev ( hwif - > dev ) ;
unsigned long dma_base = 0 ;
2005-04-17 02:20:36 +04:00
2008-07-15 23:21:49 +04:00
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
2005-04-17 02:20:36 +04:00
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 ) ;
2008-01-26 22:12:59 +03:00
if ( dma_base = = 0 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: DMA base is invalid \n " ,
d - > name , pci_name ( dev ) ) ;
2008-01-26 22:12:59 +03:00
return 0 ;
}
2005-04-17 02:20:36 +04:00
}
2008-01-26 22:12:59 +03:00
if ( hwif - > channel )
dma_base + = 8 ;
2008-07-23 21:55:51 +04:00
return dma_base ;
}
EXPORT_SYMBOL_GPL ( ide_pci_dma_base ) ;
int ide_pci_check_simplex ( ide_hwif_t * hwif , const struct ide_port_info * d )
{
2008-07-25 00:53:31 +04:00
struct pci_dev * dev = to_pci_dev ( hwif - > dev ) ;
2008-07-23 21:55:51 +04:00
u8 dma_stat ;
if ( d - > host_flags & ( IDE_HFLAG_MMIO | IDE_HFLAG_CS5520 ) )
2008-02-02 01:09:30 +03:00
goto out ;
if ( d - > host_flags & IDE_HFLAG_CLEAR_SIMPLEX ) {
2008-07-25 00:53:31 +04:00
if ( ide_pci_clear_simplex ( hwif - > dma_base , d - > name ) )
printk ( KERN_INFO " %s %s: simplex device: DMA forced \n " ,
d - > name , pci_name ( dev ) ) ;
2008-02-02 01:09:30 +03:00
goto out ;
}
/*
* If the device claims " simplex " DMA , this means that 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 ) .
*
* FIXME : 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 .
*/
2009-01-06 19:21:02 +03:00
dma_stat = hwif - > dma_ops - > dma_sff_read_status ( hwif ) ;
2008-02-02 01:09:30 +03:00
if ( ( dma_stat & 0x80 ) & & hwif - > mate & & hwif - > mate - > dma_base ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: simplex device: DMA disabled \n " ,
d - > name , pci_name ( dev ) ) ;
2008-07-23 21:55:51 +04:00
return - 1 ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 01:09:30 +03:00
out :
2008-07-23 21:55:51 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2008-07-23 21:55:51 +04:00
EXPORT_SYMBOL_GPL ( ide_pci_check_simplex ) ;
2008-04-27 00:25:21 +04:00
/*
* Set up BM - DMA capability ( PnP BIOS should have done this )
*/
2008-04-27 00:25:22 +04:00
int ide_pci_set_master ( struct pci_dev * dev , const char * name )
2008-04-27 00:25:21 +04:00
{
u16 pcicmd ;
pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) ;
if ( ( pcicmd & PCI_COMMAND_MASTER ) = = 0 ) {
pci_set_master ( dev ) ;
if ( pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) | |
( pcicmd & PCI_COMMAND_MASTER ) = = 0 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: error updating PCICMD \n " ,
name , pci_name ( dev ) ) ;
2008-04-27 00:25:21 +04:00
return - EIO ;
}
}
return 0 ;
}
2008-04-27 00:25:22 +04:00
EXPORT_SYMBOL_GPL ( ide_pci_set_master ) ;
2005-04-17 02:20:36 +04:00
# 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
{
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: IDE controller (0x%04x:0x%04x rev 0x%02x) \n " ,
d - > name , pci_name ( dev ) ,
dev - > vendor , dev - > device , dev - > revision ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL_GPL ( ide_setup_pci_noise ) ;
/**
* ide_pci_enable - do PCI enables
* @ dev : PCI device
2017-10-03 15:17:13 +03:00
* @ bars : PCI BARs mask
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
2007-12-20 07:28:09 +03:00
* but if that fails then we only need IO space . The PCI code should
* have setup the proper resources for us already for controllers in
* legacy mode .
2008-04-26 19:36:39 +04:00
*
2005-04-17 02:20:36 +04:00
* Returns zero on success or an error code
*/
2007-10-20 02:32:34 +04:00
2017-10-03 15:17:13 +03:00
static int ide_pci_enable ( struct pci_dev * dev , int bars ,
const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
2017-10-03 15:17:13 +03:00
int ret ;
2005-04-17 02:20:36 +04:00
if ( pci_enable_device ( dev ) ) {
2007-12-20 07:28:09 +03:00
ret = pci_enable_device_io ( dev ) ;
2005-04-17 02:20:36 +04:00
if ( ret < 0 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_WARNING " %s %s: couldn't enable device \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
2008-07-25 00:53:31 +04:00
printk ( KERN_WARNING " %s %s: BIOS configuration fixed \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
}
/*
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
*/
ide: remove deprecated use of pci api
Replace occurences of the pci api by appropriate call to the dma api.
A simplified version of the semantic patch that finds this problem is as
follows: (http://coccinelle.lip6.fr)
@deprecated@
idexpression id;
position p;
@@
(
pci_dma_supported@p ( id, ...)
|
pci_alloc_consistent@p ( id, ...)
)
@bad1@
idexpression id;
position deprecated.p;
@@
...when != &id->dev
when != pci_get_drvdata ( id )
when != pci_enable_device ( id )
(
pci_dma_supported@p ( id, ...)
|
pci_alloc_consistent@p ( id, ...)
)
@depends on !bad1@
idexpression id;
expression direction;
position deprecated.p;
@@
(
- pci_dma_supported@p ( id,
+ dma_supported ( &id->dev,
...
+ , GFP_ATOMIC
)
|
- pci_alloc_consistent@p ( id,
+ dma_alloc_coherent ( &id->dev,
...
+ , GFP_ATOMIC
)
)
Signed-off-by: Quentin Lambert <lambert.quentin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-04-13 11:26:53 +03:00
ret = dma_set_mask ( & dev - > dev , DMA_BIT_MASK ( 32 ) ) ;
2005-04-17 02:20:36 +04:00
if ( ret < 0 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: can't set DMA mask \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
goto out ;
}
2008-04-27 00:25:19 +04:00
ret = pci_request_selected_regions ( dev , bars , d - > name ) ;
if ( ret < 0 )
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: can't reserve resources \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
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 .
*/
2008-04-26 19:36:39 +04:00
if ( ide_setup_pci_baseregs ( dev , d - > name ) | |
pci_write_config_word ( dev , PCI_COMMAND , pcicmd | PCI_COMMAND_IO ) ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: device disabled (BIOS) \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
return - ENODEV ;
}
if ( pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: error accessing PCI regs \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
if ( ! ( pcicmd & PCI_COMMAND_IO ) ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: unable to enable IDE controller \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
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
*
2008-04-26 19:36:31 +04:00
* Checks if a BAR is configured and points to MMIO space . If so ,
* return an error code . Otherwise return 0
2005-04-17 02:20:36 +04:00
*/
2007-10-20 02:32:34 +04:00
2008-04-26 19:36:31 +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 ) ;
2008-04-26 19:36:39 +04:00
2005-04-17 02:20:36 +04:00
/* Unconfigured ? */
if ( ! flags | | pci_resource_len ( dev , bar ) = = 0 )
return 0 ;
2008-04-26 19:36:31 +04:00
/* I/O space */
if ( flags & IORESOURCE_IO )
2005-04-17 02:20:36 +04:00
return 0 ;
2008-04-26 19:36:39 +04:00
2005-04-17 02:20:36 +04:00
/* Bad */
return - EINVAL ;
}
/**
2009-05-17 21:12:25 +04:00
* ide_hw_configure - configure a struct ide_hw instance
2005-04-17 02:20:36 +04:00
* @ dev : PCI device holding interface
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2008-02-02 21:56:30 +03:00
* @ port : port number
2009-05-17 21:12:25 +04:00
* @ hw : struct ide_hw instance corresponding to this port
2005-04-17 02:20:36 +04:00
*
* 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 .
*
2008-07-23 21:55:57 +04:00
* Returns zero on success or an error code .
2005-04-17 02:20:36 +04:00
*/
2007-10-20 02:32:34 +04:00
2008-07-23 21:55:57 +04:00
static int ide_hw_configure ( struct pci_dev * dev , const struct ide_port_info * d ,
2009-05-17 21:12:25 +04:00
unsigned int port , struct ide_hw * hw )
2005-04-17 02:20:36 +04:00
{
unsigned long ctl = 0 , base = 0 ;
2007-07-20 03:11:55 +04:00
if ( ( d - > host_flags & IDE_HFLAG_ISA_PORTS ) = = 0 ) {
2008-04-26 19:36:31 +04:00
if ( ide_pci_check_iomem ( dev , d , 2 * port ) | |
ide_pci_check_iomem ( dev , d , 2 * port + 1 ) ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: I/O baseregs (BIOS) are "
" reported as MEM for port %d! \n " ,
d - > name , pci_name ( dev ) , port ) ;
2008-07-23 21:55:57 +04:00
return - EINVAL ;
2008-04-26 19:36:31 +04:00
}
2008-04-26 19:36:39 +04:00
2005-04-17 02:20:36 +04:00
ctl = pci_resource_start ( dev , 2 * port + 1 ) ;
base = pci_resource_start ( dev , 2 * port ) ;
2008-07-16 22:33:41 +04:00
} else {
2005-04-17 02:20:36 +04:00
/* Use default values */
ctl = port ? 0x374 : 0x3f4 ;
base = port ? 0x170 : 0x1f0 ;
}
2008-04-26 19:36:31 +04:00
2008-07-16 22:33:41 +04:00
if ( ! base | | ! ctl ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: bad PCI BARs for port %d, skipping \n " ,
d - > name , pci_name ( dev ) , port ) ;
2008-07-23 21:55:57 +04:00
return - EINVAL ;
2008-07-16 22:33:41 +04:00
}
2008-07-23 21:55:50 +04:00
memset ( hw , 0 , sizeof ( * hw ) ) ;
hw - > dev = & dev - > dev ;
ide_std_init_ports ( hw , base , ctl | 2 ) ;
2008-07-23 21:55:57 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 21:56:31 +03:00
# ifdef CONFIG_BLK_DEV_IDEDMA_PCI
2005-04-17 02:20:36 +04:00
/**
* ide_hwif_setup_dma - configure DMA interface
2007-10-20 02:32:34 +04:00
* @ hwif : IDE interface
2008-02-02 21:56:31 +03:00
* @ d : IDE port info
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
2008-04-27 00:25:22 +04:00
int ide_hwif_setup_dma ( ide_hwif_t * hwif , const struct ide_port_info * d )
2005-04-17 02:20:36 +04:00
{
2008-02-02 21:56:31 +03:00
struct pci_dev * dev = to_pci_dev ( hwif - > dev ) ;
2005-04-17 02:20:36 +04:00
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 ) ) ) {
2008-04-27 00:25:22 +04:00
unsigned long base = ide_pci_dma_base ( hwif , d ) ;
2008-04-27 00:25:21 +04:00
2008-07-23 21:55:51 +04:00
if ( base = = 0 )
return - 1 ;
hwif - > dma_base = base ;
2009-01-06 19:21:02 +03:00
if ( hwif - > dma_ops = = NULL )
hwif - > dma_ops = & sff_dma_ops ;
2008-07-23 21:55:51 +04:00
if ( ide_pci_check_simplex ( hwif , d ) < 0 )
return - 1 ;
if ( ide_pci_set_master ( dev , d - > name ) < 0 )
2008-04-27 00:25:22 +04:00
return - 1 ;
2008-04-27 00:25:21 +04:00
2008-07-15 23:21:49 +04:00
if ( hwif - > host_flags & IDE_HFLAG_MMIO )
2008-04-27 00:25:21 +04:00
printk ( KERN_INFO " %s: MMIO-DMA \n " , hwif - > name ) ;
else
printk ( KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx \n " ,
hwif - > name , base , base + 7 ) ;
hwif - > extra_base = base + ( hwif - > channel ? 8 : 16 ) ;
2008-04-27 00:25:22 +04:00
if ( ide_allocate_dma_engine ( hwif ) )
return - 1 ;
}
2008-04-27 00:25:21 +04:00
2008-04-27 00:25:22 +04:00
return 0 ;
2007-10-20 02:32:34 +04:00
}
2008-02-02 21:56:31 +03:00
# endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
2005-04-17 02:20:36 +04:00
/**
* ide_setup_pci_controller - set up IDE PCI
* @ dev : PCI device
2017-10-03 15:17:13 +03:00
* @ bars : PCI BARs mask
2007-10-20 02:32:34 +04:00
* @ d : IDE port info
2005-04-17 02:20:36 +04:00
* @ noisy : verbose flag
*
* 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
2017-10-03 15:17:13 +03:00
static int ide_setup_pci_controller ( struct pci_dev * dev , int bars ,
2008-07-25 00:53:11 +04:00
const struct ide_port_info * d , int noisy )
2005-04-17 02:20:36 +04:00
{
int ret ;
u16 pcicmd ;
if ( noisy )
ide_setup_pci_noise ( dev , d ) ;
2017-10-03 15:17:13 +03:00
ret = ide_pci_enable ( dev , bars , d ) ;
2005-04-17 02:20:36 +04:00
if ( ret < 0 )
goto out ;
ret = pci_read_config_word ( dev , PCI_COMMAND , & pcicmd ) ;
if ( ret < 0 ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_ERR " %s %s: error accessing PCI regs \n " ,
d - > name , pci_name ( dev ) ) ;
2017-10-03 15:17:13 +03:00
goto out_free_bars ;
2005-04-17 02:20:36 +04:00
}
if ( ! ( pcicmd & PCI_COMMAND_IO ) ) { /* is device disabled? */
ret = ide_pci_configure ( dev , d ) ;
if ( ret < 0 )
2017-10-03 15:17:13 +03:00
goto out_free_bars ;
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: device enabled (Linux) \n " ,
d - > name , pci_name ( dev ) ) ;
2005-04-17 02:20:36 +04:00
}
2017-10-03 15:17:13 +03:00
goto out ;
out_free_bars :
pci_release_selected_regions ( dev , bars ) ;
2005-04-17 02:20:36 +04:00
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
2009-05-17 21:12:25 +04:00
* @ hw : struct ide_hw instances corresponding to this PCI IDE device
* @ hws : struct ide_hw pointers 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
2008-07-23 21:55:50 +04:00
void ide_pci_setup_ports ( struct pci_dev * dev , const struct ide_port_info * d ,
2009-05-17 21:12:25 +04:00
struct ide_hw * hw , struct ide_hw * * hws )
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
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 ) {
2009-01-06 19:20:52 +03:00
const struct ide_pci_enablebit * e = & d - > enablebits [ port ] ;
2007-10-20 02:32:34 +04:00
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 ) ) {
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: IDE port disabled \n " ,
d - > name , pci_name ( dev ) ) ;
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
2009-03-25 01:22:53 +03:00
if ( ide_hw_configure ( dev , d , port , hw + port ) )
2005-04-17 02:20:36 +04:00
continue ;
2008-07-23 21:55:50 +04:00
* ( hws + port ) = hw + port ;
2008-02-02 21:56:30 +03:00
}
2005-04-17 02:20:36 +04:00
}
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 ,
2008-07-23 21:55:49 +04:00
u8 noisy )
2005-04-17 02:20:36 +04:00
{
int pciirq , ret ;
/*
* Can we trust the reported IRQ ?
*/
pciirq = dev - > irq ;
2008-07-25 00:53:11 +04:00
/*
* 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 .
*/
2008-07-25 00:53:33 +04:00
ret = d - > init_chipset ? d - > init_chipset ( dev ) : 0 ;
2008-07-25 00:53:11 +04:00
if ( ret < 0 )
goto out ;
2009-01-06 19:20:58 +03:00
if ( ide_pci_is_in_compatibility_mode ( dev ) ) {
2005-04-17 02:20:36 +04:00
if ( noisy )
2008-07-25 00:53:31 +04:00
printk ( KERN_INFO " %s %s: not 100%% native mode: will "
" probe irqs later \n " , d - > name , pci_name ( dev ) ) ;
2009-03-25 01:22:53 +03:00
pciirq = 0 ;
2008-07-25 00:53:31 +04:00
} else if ( ! pciirq & & noisy ) {
printk ( KERN_WARNING " %s %s: bad irq (%d): will probe later \n " ,
d - > name , pci_name ( dev ) , pciirq ) ;
} else if ( noisy ) {
printk ( KERN_INFO " %s %s: 100%% native mode on irq %d \n " ,
d - > name , pci_name ( dev ) , pciirq ) ;
2005-04-17 02:20:36 +04:00
}
2008-07-23 21:55:49 +04:00
ret = pciirq ;
2005-04-17 02:20:36 +04:00
out :
return ret ;
}
2008-07-25 00:53:14 +04:00
int ide_pci_init_two ( struct pci_dev * dev1 , struct pci_dev * dev2 ,
const struct ide_port_info * d , void * priv )
2005-04-17 02:20:36 +04:00
{
struct pci_dev * pdev [ ] = { dev1 , dev2 } ;
2008-07-25 00:53:14 +04:00
struct ide_host * host ;
2017-10-03 15:17:13 +03:00
int ret , i , n_ports = dev2 ? 4 : 2 , bars ;
2009-05-17 21:12:25 +04:00
struct ide_hw hw [ 4 ] , * hws [ ] = { NULL , NULL , NULL , NULL } ;
2005-04-17 02:20:36 +04:00
2017-10-03 15:17:13 +03:00
if ( d - > host_flags & IDE_HFLAG_SINGLE )
bars = ( 1 < < 2 ) - 1 ;
else
bars = ( 1 < < 4 ) - 1 ;
if ( ( d - > host_flags & IDE_HFLAG_NO_DMA ) = = 0 ) {
if ( d - > host_flags & IDE_HFLAG_CS5520 )
bars | = ( 1 < < 2 ) ;
else
bars | = ( 1 < < 4 ) ;
}
2009-06-10 16:37:21 +04:00
for ( i = 0 ; i < n_ports / 2 ; i + + ) {
2017-10-03 15:17:13 +03:00
ret = ide_setup_pci_controller ( pdev [ i ] , bars , d , ! i ) ;
if ( ret < 0 ) {
if ( i = = 1 )
pci_release_selected_regions ( pdev [ 0 ] , bars ) ;
2008-07-25 00:53:12 +04:00
goto out ;
2017-10-03 15:17:13 +03:00
}
2008-07-25 00:53:12 +04:00
2009-03-25 01:22:53 +03:00
ide_pci_setup_ports ( pdev [ i ] , d , & hw [ i * 2 ] , & hws [ i * 2 ] ) ;
2008-07-25 00:53:14 +04:00
}
2008-07-25 00:53:12 +04:00
2009-06-10 16:37:21 +04:00
host = ide_host_alloc ( d , hws , n_ports ) ;
2008-07-25 00:53:14 +04:00
if ( host = = NULL ) {
ret = - ENOMEM ;
2017-10-03 15:17:13 +03:00
goto out_free_bars ;
2008-07-25 00:53:14 +04:00
}
host - > dev [ 0 ] = & dev1 - > dev ;
2009-06-10 16:37:21 +04:00
if ( dev2 )
host - > dev [ 1 ] = & dev2 - > dev ;
2008-07-25 00:53:14 +04:00
host - > host_priv = priv ;
2009-03-27 14:46:27 +03:00
host - > irq_flags = IRQF_SHARED ;
2008-07-25 00:53:19 +04:00
pci_set_drvdata ( pdev [ 0 ] , host ) ;
2009-06-10 16:37:21 +04:00
if ( dev2 )
pci_set_drvdata ( pdev [ 1 ] , host ) ;
2008-07-25 00:53:14 +04:00
2009-06-10 16:37:21 +04:00
for ( i = 0 ; i < n_ports / 2 ; i + + ) {
2008-07-23 21:55:49 +04:00
ret = do_ide_setup_pci_device ( pdev [ i ] , d , ! 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 )
2017-10-03 15:17:13 +03:00
goto out_free_bars ;
2008-07-23 21:55:49 +04:00
2008-07-25 00:53:12 +04:00
/* fixup IRQ */
2009-03-25 01:22:51 +03:00
if ( ide_pci_is_in_compatibility_mode ( pdev [ i ] ) ) {
2009-03-25 01:22:49 +03:00
hw [ i * 2 ] . irq = pci_get_legacy_ide_irq ( pdev [ i ] , 0 ) ;
hw [ i * 2 + 1 ] . irq = pci_get_legacy_ide_irq ( pdev [ i ] , 1 ) ;
2009-03-25 01:22:51 +03:00
} else
hw [ i * 2 + 1 ] . irq = hw [ i * 2 ] . irq = ret ;
2005-04-17 02:20:36 +04:00
}
2008-07-25 00:53:14 +04:00
ret = ide_host_register ( host , d , hws ) ;
if ( ret )
ide_host_free ( host ) ;
2017-10-03 15:17:13 +03:00
else
goto out ;
out_free_bars :
i = n_ports / 2 ;
while ( i - - )
pci_release_selected_regions ( pdev [ i ] , bars ) ;
2005-04-17 02:20:36 +04:00
out :
return ret ;
}
2008-07-25 00:53:14 +04:00
EXPORT_SYMBOL_GPL ( ide_pci_init_two ) ;
2008-07-25 00:53:19 +04:00
2009-06-10 16:37:21 +04:00
int ide_pci_init_one ( struct pci_dev * dev , const struct ide_port_info * d ,
void * priv )
{
return ide_pci_init_two ( dev , NULL , d , priv ) ;
}
EXPORT_SYMBOL_GPL ( ide_pci_init_one ) ;
2008-07-25 00:53:19 +04:00
void ide_pci_remove ( struct pci_dev * dev )
{
struct ide_host * host = pci_get_drvdata ( dev ) ;
struct pci_dev * dev2 = host - > dev [ 1 ] ? to_pci_dev ( host - > dev [ 1 ] ) : NULL ;
int bars ;
if ( host - > host_flags & IDE_HFLAG_SINGLE )
bars = ( 1 < < 2 ) - 1 ;
else
bars = ( 1 < < 4 ) - 1 ;
if ( ( host - > host_flags & IDE_HFLAG_NO_DMA ) = = 0 ) {
if ( host - > host_flags & IDE_HFLAG_CS5520 )
bars | = ( 1 < < 2 ) ;
else
bars | = ( 1 < < 4 ) ;
}
ide_host_remove ( host ) ;
if ( dev2 )
pci_release_selected_regions ( dev2 , bars ) ;
pci_release_selected_regions ( dev , bars ) ;
if ( dev2 )
pci_disable_device ( dev2 ) ;
pci_disable_device ( dev ) ;
}
EXPORT_SYMBOL_GPL ( ide_pci_remove ) ;
2008-10-11 00:39:32 +04:00
# ifdef CONFIG_PM
int ide_pci_suspend ( struct pci_dev * dev , pm_message_t state )
{
pci_save_state ( dev ) ;
pci_disable_device ( dev ) ;
pci_set_power_state ( dev , pci_choose_state ( dev , state ) ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( ide_pci_suspend ) ;
int ide_pci_resume ( struct pci_dev * dev )
{
struct ide_host * host = pci_get_drvdata ( dev ) ;
int rc ;
pci_set_power_state ( dev , PCI_D0 ) ;
rc = pci_enable_device ( dev ) ;
if ( rc )
return rc ;
pci_restore_state ( dev ) ;
pci_set_master ( dev ) ;
if ( host - > init_chipset )
host - > init_chipset ( dev ) ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( ide_pci_resume ) ;
# endif