From: John Carlson <carlsj@yahoo.com>
To: linux-hotplug@vger.kernel.org
Subject: Re: PCI hotplug question: resources
Date: Fri, 08 Feb 2002 15:44:14 +0000 [thread overview]
Message-ID: <marc-linux-hotplug-101318310111131@msgid-missing> (raw)
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
Here is the method used by the company I am employed
by to rescan the PCI bus after the FPGA has been
loaded (via ISA bus). The routine was a quick hack
and therefor, is not complete. There is no module
exit routine for cleanup, the routine cannot remove a
device, and it will only look for a specific device.
I have already shared this routine with Dirk Stieler
who reports that it works for him.
regards,
John Carlson
IFR Systems, Inc
Wichita, KS
<<---------------------CUT HERE------------------->>
/*
* rescan-pci.c:
*
* This program is now a standalone driver which
will allow the user
* to rescan the pci bus looking for new devices.
This was necessary
* because the core logic of the fpga has not been
loaded during the
* initial pci bus scan at startup. Once the kernel
is initialized and
* has downloaded the core logic to the fpga, the
pci bus must be re-scanned
* so that the boards pci interface can be
registered with the kernel
* and inserted into the pci_dev tree.
*
* The proper use of this driver is as follows:
*
* download the core logic into the fpga
* issue 'modprobe pci-rescan'
*
* Copyright (C) 2000, Olivier Lebaillif, IFR
Systems, Inc.
* Copyright (C) 2001, John Carlson, IFR Systems,
Inc.
*
* This program is a part of the Linux kernel, and
may be freely
* copied under the terms of the GNU General Public
License (GPL),
* version 2, or at your option any later version.
*
* $Log: rescan-pci.c,v $
* Revision 1.1 2001/10/31 17:16:28 jcarlson
* Initial Version
*
*/
/*
* The standard includes
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <linux/cai.h>/*
* Including this file requires that this
* routine must be built after the normal
* pci routines.
*/
#include "../arch/i386/kernel/pci-i386.h"
#define DEBUG
static char version[] __devinitdata = "PCI Bus
Rescanner: Version 1.1";
static char Copyright[] __devinitdata "Copyright (C) 2001, John Carlson, IFR
Systems, Inc";
unsigned int pci_probe = PCI_PROBE_BIOS |
PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
static int debug = -1;
static int irq = 0;
MODULE_AUTHOR ("John Carlson
<John.Carlson@ifrsys.com>");
MODULE_DESCRIPTION ("Bus re-scan driver for PCI Bus");
MODULE_LICENSE("GPL");
MODULE_PARM (debug, "i");
MODULE_PARM (irq, "i");
struct pci_device_info {
unsigned short device;
unsigned short seen;
const char *name;
};
struct pci_vendor_info {
unsigned short vendor;
unsigned short nr;
const char *name;
struct pci_device_info *devices;
};
/*
* This is ridiculous, but we want the strings in
* the .init section so that they don't take up
* real memory.. Parse the same file multiple times
* to get all the info.
*/
#define VENDOR( vendor, name ) static const char
__vendorstr_##vendor[] __initdata = name;
#define ENDVENDOR()
#define DEVICE( vendor, device, name ) static const
char __devicestr_##vendor##device[] __init
data = name;#include "../drivers/pci/devlist.h"
#define VENDOR( vendor, name ) static struct
pci_device_info __devices_##vendor[] __initdata {
#define ENDVENDOR() };
#define DEVICE( vendor, device, name ) { 0x##device,
0, __devicestr_##vendor##device },
#include "../drivers/pci/devlist.h"
static const struct pci_vendor_info __initdata
pci_vendor_list[] = {
#define VENDOR( vendor, name ) { 0x##vendor,
sizeof(__devices_##vendor) / sizeof(struct pci_de
vice_info), __vendorstr_##vendor, __devices_##vendor
},
#define ENDVENDOR()
#define DEVICE( vendor, device, name )
#include "../drivers/pci/devlist.h"
};
#define VENDORS (sizeof(pci_vendor_list)/sizeof(struct
pci_vendor_info))
void __init pci_name_device (struct pci_dev *dev)
{
const struct pci_vendor_info *vendor_p pci_vendor_list;
int i = VENDORS;
char *name = dev->name;
do {
if (vendor_p->vendor = dev->vendor)
goto match_vendor;
vendor_p++;
} while (--i);
if (debug >= 2)
printk (KERN_ERR "Vendor & Device not
found for %04x:%04x\n",
dev->vendor, dev->device);
/*
* Couldn't find either the vendor nor the
device
*/
sprintf (name, "PCI device %04x:%04x",
dev->vendor, dev->device);
return;
match_vendor:
{
struct pci_device_info *device_p vendor_p->devices;
int i = vendor_p->nr;
while (i > 0) {
if (device_p->device =
dev->device)
goto match_device;
device_p++;
i--;
}
if (debug >= 2)
printk (KERN_ERR "Vendor %s
found for %04x:%04x\n",
vendor_p->name,
dev->vendor, dev->device);
/*
* Ok, found the vendor, but unknown
device
*/
sprintf (name, "PCI device %04x:%04x
(%s)", dev->vendor,
dev->device, vendor_p->name);
return;
/* Full match */
match_device:
{
char *n = name + sprintf
(name, "%s %s", vendor_p->name,
device_p->name);
int nr = device_p->seen + 1;
if (debug >= 2)
printk (KERN_ERR
"Device Found %s\n", name);
device_p->seen = nr;
if (nr > 1)
sprintf (n, " (#%d)",
nr);
}
}
}
/*
* This function detects the presence of the PCI core
from XIlinx and
* creates an entry in the PCI tree structure of the
kernel. Initialization
* of the config registers will be done as well as the
allocation of an
* IRQ line
*/int __init check_hw (void)
{
u8 b;
u8 irq_pin;
u32 l;
int r;
int devfn;
struct pci_bus *bus;
struct pci_dev dev0, *dev = NULL;
/* a little announce */
DBG (KERN_INFO "rescan-pci.c: check_hw\n");
/*
* get access to the bus 0. We are not looking
on all the
* other buses. The xilinx FPGA must be on
bus 0 unless we
* have to add a bridge in our design
*/
bus = pci_bus_b (pci_root_buses.next);
if (debug >= 3)
printk (KERN_ERR "Bus = %x\n",
bus->number);
/* Create a device template */
memset (&dev0, 0, sizeof (dev0));
dev0.bus = bus;
dev0.sysdata = bus->sysdata;
/*
* Go find all devices function 0, we don't
look
* at the functions 1 to 7
*/
devfn = 0;
while ((devfn < 0x100) && (!dev)) {
dev0.devfn = devfn;
/*
* read the PCI device header and
store it
* (masking the multi-function bit)
*/
pci_read_config_byte (&dev0,
PCI_HEADER_TYPE, &b);
dev0.hdr_type = b & 0x7f;
/* read the vendor and device Ids */
pci_read_config_dword (&dev0,
PCI_VENDOR_ID, &l);
if (l = PCI_ID_CAI) {
/*
* we found our board. Let's
make sure it has
* the proper header, if not
return no device found
*/
if (b !PCI_HEADER_TYPE_NORMAL)
return -ENODEV;
/* we now have to configure
and register it */
/* first allocate memory for
the device */
dev = kmalloc (sizeof (*dev),
GFP_KERNEL);
if (!dev)
return -ENOMEM;
/* copy the data existing in
the temporary device */
memcpy (dev, &dev0, sizeof
(*dev));
/* set the vendo id and device
id */
dev->vendor = l & 0xffff;
dev->device = (l >> 16) &
0xffff;
dev->bus = bus;
dev->sysdata = bus->sysdata;
dev->devfn = devfn;
dev->hdr_type = b & 0x7f;
/* Does this function have an
interrupt at all? */
pci_read_config_byte (dev,
PCI_INTERRUPT_PIN, &irq_pin);
if (irq_pin) {
dev->irq = irq;
pci_write_config_byte
(dev, PCI_INTERRUPT_LINE,
irq);
}
if (pci_setup_device (dev)) {
kfree (dev);
printk (KERN_ERR
"Could not setup device\n");
return -ENODEV;
}
/*
* Go let the kernel allocate
* the requested resources
*/
for (r = 0; r < 7; r++) {
struct resource *res dev->resource + r;
if (res->flags)
pci_assign_resource (dev, r);
}
if (pci_enable_device (dev)) {
kfree (dev);
printk (KERN_ERR
"Could not enable device\n");
return -ENODEV;
}
/* try to get the name of the
actual device */
pci_name_device (dev);
/* get the revision
information */
pci_read_config_dword (dev,
PCI_CLASS_REVISION, &l);
dev->class = l >> 8;
/* read the subsystem id and
subsystem vendor id */
pci_read_config_word (dev,
PCI_SUBSYSTEM_VENDOR_ID,
&dev->subsystem_vendor);
pci_read_config_word (dev,
PCI_SUBSYSTEM_ID,
&dev->subsystem_device);
/*
* Link the device to both the
global PCI device
* chain and the per-bus list
of devices.
*/
pci_insert_device (dev, bus);
if (debug >= 1)
printk (KERN_ERR
"Xilinx device
linked to PCI device chain\n");
/* we are all set return 0 */
return 0;
}
/* go check the next device */
devfn += 8;
}
/* if we reach this point the device has not
been found */
return -ENODEV;
}
/* Initialization entry point for the module */
int __init pci_cai_init_module (void)
{
struct pci_dev *dev = NULL;
unsigned long flags;
int ret;
printk (KERN_ERR "\n%s\n%s\n", version,
Copyright);
__save_flags (flags);
__cli ();
dev = pci_find_device (PCI_VENDOR_ID_XILINX,
PCI_DEVICE_ID_CAI, dev);
if (!dev) {
/* initialize our hardware */
if ((ret = check_hw ()) < 0) {
__restore_flags (flags);
if (debug >= 2)
printk (KERN_ERR
"check_hw returned error %x\n",
ret);
printk (KERN_ERR
"Cannot initialize the
Xilinx HW, pci device not installed.");
return -ENODEV;
}
}
__restore_flags (flags);
return 0;
}
module_init (pci_cai_init_module);
<<-----------------END----------------->>
__________________________________________________
Do You Yahoo!?
Send FREE Valentine eCards with Yahoo! Greetings!
http://greetings.yahoo.com
_______________________________________________
Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel
prev parent reply other threads:[~2002-02-08 15:44 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-02-05 11:37 PCI hotplug question: resources Dirk Stieler
2002-02-05 13:55 ` Matti Aarnio
2002-02-06 1:17 ` Stephen Williams
2002-02-06 10:20 ` Matti Aarnio
2002-02-06 17:55 ` Chris Brand
2002-02-07 8:43 ` Greg KH
2002-02-07 16:42 ` Stephen Williams
2002-02-07 23:51 ` Greg KH
2002-02-08 1:06 ` Donald Becker
2002-02-08 1:34 ` Martin Diehl
2002-02-08 15:44 ` John Carlson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-hotplug-101318310111131@msgid-missing \
--to=carlsj@yahoo.com \
--cc=linux-hotplug@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.