linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

      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).