Commit 84c1925b authored by Scott Murray's avatar Scott Murray Committed by Russell King

[PATCH] 2.5.45 CompactPCI driver patch 2/4

This is patch 2 of 4 of my CompactPCI hotplug core and
drivers, consisting of the CompactPCI hotplug driver core.

It is basically a glue layer on top of the PCI hotplug core that exposes
an API roughly similiar in concept to the API implemented by MontaVista
from the PICMG 2.12 specification, minus all the Win32isms and cruft.
parent cb7b6b34
...@@ -2218,6 +2218,14 @@ S: 30 White Tail Lane ...@@ -2218,6 +2218,14 @@ S: 30 White Tail Lane
S: Lafayette, Indiana 47905 S: Lafayette, Indiana 47905
S: USA S: USA
N: Scott Murray
E: scottm@somanetworks.com
E: scott@spiteful.org
D: OPL3-SA2, OPL3-SA3 sound driver
D: CompactPCI hotplug core
S: Toronto, Ontario
S: Canada
N: Trond Myklebust N: Trond Myklebust
E: trond.myklebust@fys.uio.no E: trond.myklebust@fys.uio.no
D: current NFS client hacker. D: current NFS client hacker.
......
...@@ -317,6 +317,13 @@ L: codalist@coda.cs.cmu.edu ...@@ -317,6 +317,13 @@ L: codalist@coda.cs.cmu.edu
W: http://www.coda.cs.cmu.edu/ W: http://www.coda.cs.cmu.edu/
S: Maintained S: Maintained
COMPACTPCI HOTPLUG CORE
P: Scott Murray
M: scottm@somanetworks.com
M: scott@spiteful.org
L: pcihpd-discuss@lists.sourceforge.net
S: Supported
COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
P: Amy Vanzant-Hodge P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com) M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
......
...@@ -73,5 +73,19 @@ config HOTPLUG_PCI_ACPI ...@@ -73,5 +73,19 @@ config HOTPLUG_PCI_ACPI
When in doubt, say N. When in doubt, say N.
config HOTPLUG_PCI_CPCI
tristate "CompactPCI Hotplug driver"
depends on HOTPLUG_PCI
help
Say Y here if you have a CompactPCI system card with CompactPCI
hotswap support per the PICMG 2.1 specification.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called cpci_hotplug.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
When in doubt, say N.
endmenu endmenu
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
# Makefile for the Linux kernel pci hotplug controller drivers. # Makefile for the Linux kernel pci hotplug controller drivers.
# #
export-objs := pci_hotplug_core.o pci_hotplug_util.o export-objs := pci_hotplug_core.o pci_hotplug_util.o cpci_hotplug_core.o
obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI) += cpci_hotplug.o
pci_hotplug-objs := pci_hotplug_core.o \ pci_hotplug-objs := pci_hotplug_core.o \
pci_hotplug_util.o pci_hotplug_util.o
...@@ -28,6 +29,9 @@ acpiphp-objs := acpiphp_core.o \ ...@@ -28,6 +29,9 @@ acpiphp-objs := acpiphp_core.o \
acpiphp_pci.o \ acpiphp_pci.o \
acpiphp_res.o acpiphp_res.o
cpci_hotplug-objs := cpci_hotplug_core.o \
cpci_hotplug_pci.o
ifdef CONFIG_HOTPLUG_PCI_ACPI ifdef CONFIG_HOTPLUG_PCI_ACPI
EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi
ifdef CONFIG_ACPI_DEBUG ifdef CONFIG_ACPI_DEBUG
......
/*
* CompactPCI Hot Plug Core Functions
*
* Copyright (c) 2002 SOMA Networks, Inc.
* Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (c) 2001 IBM Corp.
*
* All rights reserved.
*
* 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, GOOD TITLE or
* NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Send feedback to <scottm@somanetworks.com>
*/
#ifndef _CPCI_HOTPLUG_H
#define _CPCI_HOTPLUG_H
#include <linux/types.h>
#include <linux/pci.h>
/* PICMG 2.12 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
#define HS_CSR_EXT 0x0040
#define HS_CSR_PI 0x0030
#define HS_CSR_LOO 0x0008
#define HS_CSR_PIE 0x0004
#define HS_CSR_EIM 0x0002
#define HS_CSR_DHA 0x0001
#define SLOT_MAGIC 0x67267322
struct slot {
u32 magic;
u8 number;
unsigned int devfn;
struct pci_bus *bus;
struct pci_dev *dev;
unsigned int extracting;
struct hotplug_slot *hotplug_slot;
struct list_head slot_list;
};
struct cpci_hp_controller_ops {
int (*query_enum) (void);
int (*enable_irq) (void);
int (*disable_irq) (void);
int (*check_irq) (void *dev_id);
int (*hardware_test) (struct slot* slot, u32 value);
u8 (*get_power) (struct slot* slot);
int (*set_power) (struct slot* slot, int value);
};
struct cpci_hp_controller {
unsigned int irq;
unsigned long irq_flags;
char *devname;
void *dev_id;
char *name;
struct cpci_hp_controller_ops *ops;
};
extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
extern int cpci_hp_unregister_bus(struct pci_bus *bus);
extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn);
extern int cpci_hp_start(void);
extern int cpci_hp_stop(void);
/*
* Internal function prototypes, these functions should not be used by
* board/chassis drivers.
*/
extern u8 cpci_get_attention_status(struct slot *slot);
extern u8 cpci_get_latch_status(struct slot *slot);
extern u8 cpci_get_adapter_status(struct slot *slot);
extern u16 cpci_get_hs_csr(struct slot * slot);
extern u16 cpci_set_hs_csr(struct slot * slot, u16 hs_csr);
extern int cpci_set_attention_status(struct slot *slot, int status);
extern int cpci_check_and_clear_ins(struct slot * slot);
extern int cpci_check_ext(struct slot * slot);
extern int cpci_clear_ext(struct slot * slot);
extern int cpci_led_on(struct slot * slot);
extern int cpci_led_off(struct slot * slot);
extern int cpci_configure_slot(struct slot *slot);
extern int cpci_unconfigure_slot(struct slot *slot);
#endif /* _CPCI_HOTPLUG_H */
This diff is collapsed.
This diff is collapsed.
...@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn, ...@@ -167,5 +167,9 @@ extern int pci_visit_dev (struct pci_visit *fn,
struct pci_dev_wrapped *wrapped_dev, struct pci_dev_wrapped *wrapped_dev,
struct pci_bus_wrapped *wrapped_parent); struct pci_bus_wrapped *wrapped_parent);
int pci_is_dev_in_use(struct pci_dev *dev);
int pci_remove_device_safe(struct pci_dev *dev);
#endif #endif
...@@ -94,15 +94,12 @@ static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped ...@@ -94,15 +94,12 @@ static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped
static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent) static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_parent)
{ {
struct pci_bus *bus = wrapped_dev->dev->subordinate; struct pci_bus *bus;
struct pci_bus_wrapped wrapped_bus; struct pci_bus_wrapped wrapped_bus;
int result; int result;
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped)); dbg("scanning bridge %02x, %02x\n", PCI_SLOT(wrapped_dev->dev->devfn),
wrapped_bus.bus = bus; PCI_FUNC(wrapped_dev->dev->devfn));
dbg("scanning bridge %02x, %02x\n", wrapped_dev->dev->devfn >> 3,
wrapped_dev->dev->devfn & 0x7);
if (fn->visit_pci_dev) { if (fn->visit_pci_dev) {
result = fn->visit_pci_dev(wrapped_dev, wrapped_parent); result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
...@@ -110,7 +107,13 @@ static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrap ...@@ -110,7 +107,13 @@ static int pci_visit_bridge (struct pci_visit * fn, struct pci_dev_wrapped *wrap
return result; return result;
} }
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev); bus = wrapped_dev->dev->subordinate;
if(bus) {
memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
wrapped_bus.bus = bus;
result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
}
return result; return result;
} }
...@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st ...@@ -153,6 +156,62 @@ int pci_visit_dev (struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev, st
return result; return result;
} }
/**
* pci_is_dev_in_use - query devices' usage
* @dev: PCI device to query
*
* Queries whether a given PCI device is in use by a driver or not.
* Returns 1 if the device is in use, 0 if it is not.
*/
int pci_is_dev_in_use(struct pci_dev *dev)
{
/*
* dev->driver will be set if the device is in use by a new-style
* driver -- otherwise, check the device's regions to see if any
* driver has claimed them.
*/
int i;
int inuse = 0;
if (dev->driver) {
/* Assume driver feels responsible */
return 1;
}
for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
if (!pci_resource_start(dev, i))
continue;
if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
inuse = check_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
} else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
inuse = check_mem_region(pci_resource_start(dev, i),
pci_resource_len(dev, i));
}
}
return inuse;
}
/**
* pci_remove_device_safe - remove an unused hotplug device
* @dev: the device to remove
*
* Delete the device structure from the device lists and
* notify userspace (/sbin/hotplug), but only if the device
* in question is not being used by a driver.
* Returns 0 on success.
*/
int pci_remove_device_safe(struct pci_dev *dev)
{
if (pci_is_dev_in_use(dev)) {
return -EBUSY;
}
pci_remove_device(dev);
return 0;
}
EXPORT_SYMBOL(pci_visit_dev); EXPORT_SYMBOL(pci_visit_dev);
EXPORT_SYMBOL(pci_is_dev_in_use);
EXPORT_SYMBOL(pci_remove_device_safe);
...@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o ...@@ -25,6 +25,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o
obj-$(CONFIG_DDB5476) += setup-bus.o obj-$(CONFIG_DDB5476) += setup-bus.o
obj-$(CONFIG_SGI_IP27) += setup-irq.o obj-$(CONFIG_SGI_IP27) += setup-irq.o
# CompactPCI hotplug requires the pbus_* functions
ifdef CONFIG_HOTPLUG_PCI_CPCI
obj-y += setup-bus.o
endif
ifndef CONFIG_X86 ifndef CONFIG_X86
obj-y += syscall.o obj-y += syscall.o
endif endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment