Source
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2005-2006 Silicon Graphics, Inc. All Rights Reserved.
*/
/* This file contains the master driver module for use by SGI IOC4 subdrivers.
*
* It allocates any resources shared between multiple subdevices, and
* provides accessor functions (where needed) and the like for those
* resources. It also provides a mechanism for the subdevice modules
* to support loading and unloading.
*
* Non-shared resources (e.g. external interrupt A_INT_OUT register page
* alias, serial port and UART registers) are handled by the subdevice
* modules themselves.
*
* This is all necessary because IOC4 is not implemented as a multi-function
* PCI device, but an amalgamation of disparate registers for several
* types of device (ATA, serial, external interrupts). The normal
* resource management in the kernel doesn't have quite the right interfaces
* to handle this situation (e.g. multiple modules can't claim the same
* PCI ID), thus this IOC4 master module.
*/
/***************
* Definitions *
***************/
/* Tweakable values */
/* PCI bus speed detection/calibration */
/* Calibration cycle period */
/* Average over this many cycles */
/* Discard first few cycles */
/* Lower bound on bus speed sanity */
/* Upper bound on bus speed sanity */
/* Assumed if sanity check fails */
/************************
* Submodule management *
************************/
static DEFINE_MUTEX(ioc4_mutex);
static LIST_HEAD(ioc4_devices);
static LIST_HEAD(ioc4_submodules);
/* Register an IOC4 submodule */
int
ioc4_register_submodule(struct ioc4_submodule *is)
{
struct ioc4_driver_data *idd;
mutex_lock(&ioc4_mutex);
list_add(&is->is_list, &ioc4_submodules);
/* Initialize submodule for each IOC4 */
if (!is->is_probe)
goto out;
list_for_each_entry(idd, &ioc4_devices, idd_list) {
if (is->is_probe(idd)) {
printk(KERN_WARNING
"%s: IOC4 submodule %s probe failed "
"for pci_dev %s",
__func__, module_name(is->is_owner),
pci_name(idd->idd_pdev));
}
}
out:
mutex_unlock(&ioc4_mutex);
return 0;
}
/* Unregister an IOC4 submodule */
void
ioc4_unregister_submodule(struct ioc4_submodule *is)
{
struct ioc4_driver_data *idd;