2005-04-17 02:20:36 +04:00
/*
* pci_bind . c - ACPI PCI Device Binding ( $ Revision : 2 $ )
*
* Copyright ( C ) 2001 , 2002 Andy Grover < andrew . grover @ intel . com >
* Copyright ( C ) 2001 , 2002 Paul Diefenbaugh < paul . s . diefenbaugh @ intel . com >
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or ( at
* your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA .
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/pci.h>
# include <linux/acpi.h>
# include <acpi/acpi_bus.h>
# include <acpi/acpi_drivers.h>
# define _COMPONENT ACPI_PCI_COMPONENT
2007-02-13 06:42:12 +03:00
ACPI_MODULE_NAME ( " pci_bind " ) ;
2005-04-17 02:20:36 +04:00
struct acpi_pci_data {
2005-08-05 08:44:28 +04:00
struct acpi_pci_id id ;
struct pci_bus * bus ;
struct pci_dev * dev ;
2005-04-17 02:20:36 +04:00
} ;
2009-06-10 23:55:09 +04:00
static int acpi_pci_bind ( struct acpi_device * device ) ;
2007-10-24 20:24:42 +04:00
static int acpi_pci_unbind ( struct acpi_device * device ) ;
2005-09-03 01:16:48 +04:00
static void acpi_pci_data_handler ( acpi_handle handle , u32 function ,
void * context )
2005-04-17 02:20:36 +04:00
{
/* TBD: Anything we need to do here? */
2006-06-27 08:41:40 +04:00
return ;
2005-04-17 02:20:36 +04:00
}
/**
2005-04-28 11:25:53 +04:00
* acpi_get_pci_id
2005-04-17 02:20:36 +04:00
* - - - - - - - - - - - - - - - - - -
* This function is used by the ACPI Interpreter ( a . k . a . Core Subsystem )
* to resolve PCI information for ACPI - PCI devices defined in the namespace .
* This typically occurs when resolving PCI operation region information .
*/
2005-08-05 08:44:28 +04:00
acpi_status acpi_get_pci_id ( acpi_handle handle , struct acpi_pci_id * id )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
int result = 0 ;
acpi_status status = AE_OK ;
struct acpi_device * device = NULL ;
struct acpi_pci_data * data = NULL ;
2005-04-17 02:20:36 +04:00
if ( ! id )
2006-06-27 08:41:40 +04:00
return AE_BAD_PARAMETER ;
2005-04-17 02:20:36 +04:00
result = acpi_bus_get_device ( handle , & device ) ;
if ( result ) {
2006-06-27 07:41:38 +04:00
printk ( KERN_ERR PREFIX
" Invalid ACPI Bus context for device %s \n " ,
acpi_device_bid ( device ) ) ;
2006-06-27 08:41:40 +04:00
return AE_NOT_EXIST ;
2005-04-17 02:20:36 +04:00
}
2005-08-05 08:44:28 +04:00
status = acpi_get_data ( handle , acpi_pci_data_handler , ( void * * ) & data ) ;
2005-04-28 11:25:53 +04:00
if ( ACPI_FAILURE ( status ) | | ! data ) {
2006-06-27 07:58:43 +04:00
ACPI_EXCEPTION ( ( AE_INFO , status ,
" Invalid ACPI-PCI context for device %s " ,
acpi_device_bid ( device ) ) ) ;
2006-06-27 08:41:40 +04:00
return status ;
2005-04-17 02:20:36 +04:00
}
* id = data - > id ;
2005-08-05 08:44:28 +04:00
2005-04-17 02:20:36 +04:00
/*
2005-08-05 08:44:28 +04:00
id - > segment = data - > id . segment ;
id - > bus = data - > id . bus ;
id - > device = data - > id . device ;
id - > function = data - > id . function ;
*/
2005-04-17 02:20:36 +04:00
2005-08-05 08:44:28 +04:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO ,
2008-12-09 07:30:05 +03:00
" Device %s has PCI address %04x:%02x:%02x.%d \n " ,
2005-08-05 08:44:28 +04:00
acpi_device_bid ( device ) , id - > segment , id - > bus ,
id - > device , id - > function ) ) ;
2005-04-17 02:20:36 +04:00
2006-06-27 08:41:40 +04:00
return AE_OK ;
2005-04-17 02:20:36 +04:00
}
2005-08-05 08:44:28 +04:00
2005-04-28 11:25:53 +04:00
EXPORT_SYMBOL ( acpi_get_pci_id ) ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:25 +04:00
static int acpi_pci_unbind ( struct acpi_device * device )
{
2009-06-10 23:55:30 +04:00
struct pci_dev * dev ;
2009-06-10 23:55:25 +04:00
2009-06-10 23:55:30 +04:00
dev = acpi_get_pci_dev ( device - > handle ) ;
if ( ! dev )
return 0 ;
2009-06-10 23:55:25 +04:00
2009-06-10 23:55:30 +04:00
if ( dev - > subordinate )
2009-06-10 23:55:40 +04:00
acpi_pci_irq_del_prt ( dev - > subordinate ) ;
2009-06-10 23:55:25 +04:00
2009-06-10 23:55:30 +04:00
pci_dev_put ( dev ) ;
return 0 ;
2009-06-10 23:55:25 +04:00
}
2009-06-10 23:55:09 +04:00
static int acpi_pci_bind ( struct acpi_device * device )
2005-04-17 02:20:36 +04:00
{
2008-12-31 06:44:33 +03:00
acpi_status status ;
acpi_handle handle ;
2009-06-10 23:55:35 +04:00
struct pci_bus * bus ;
2009-06-10 23:55:30 +04:00
struct pci_dev * dev ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
dev = acpi_get_pci_dev ( device - > handle ) ;
if ( ! dev )
return 0 ;
2005-04-17 02:20:36 +04:00
/*
2009-06-10 23:55:30 +04:00
* Install the ' bind ' function to facilitate callbacks for
* children of the P2P bridge .
2005-04-17 02:20:36 +04:00
*/
2009-06-10 23:55:30 +04:00
if ( dev - > subordinate ) {
2005-08-05 08:44:28 +04:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO ,
2008-12-09 07:30:05 +03:00
" Device %04x:%02x:%02x.%d is a PCI bridge \n " ,
2009-06-10 23:55:30 +04:00
pci_domain_nr ( dev - > bus ) , dev - > bus - > number ,
PCI_SLOT ( dev - > devfn ) , PCI_FUNC ( dev - > devfn ) ) ) ;
2005-04-17 02:20:36 +04:00
device - > ops . bind = acpi_pci_bind ;
device - > ops . unbind = acpi_pci_unbind ;
}
/*
2009-06-10 23:55:30 +04:00
* Evaluate and parse _PRT , if exists . This code allows parsing of
* _PRT objects within the scope of non - bridge devices . Note that
* _PRTs within the scope of a PCI bridge assume the bridge ' s
* subordinate bus number .
2005-04-17 02:20:36 +04:00
*
* TBD : Can _PRTs exist within the scope of non - bridge PCI devices ?
*/
status = acpi_get_handle ( device - > handle , METHOD_NAME__PRT , & handle ) ;
2009-06-10 23:55:30 +04:00
if ( ACPI_FAILURE ( status ) )
goto out ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
if ( dev - > subordinate )
2009-06-10 23:55:35 +04:00
bus = dev - > subordinate ;
2009-06-10 23:55:30 +04:00
else
2009-06-10 23:55:35 +04:00
bus = dev - > bus ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:35 +04:00
acpi_pci_irq_add_prt ( device - > handle , bus ) ;
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
out :
pci_dev_put ( dev ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
2009-06-10 23:55:30 +04:00
int acpi_pci_bind_root ( struct acpi_device * device )
{
2005-04-17 02:20:36 +04:00
device - > ops . bind = acpi_pci_bind ;
device - > ops . unbind = acpi_pci_unbind ;
2009-06-10 23:55:30 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}