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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).