From mboxrd@z Thu Jan  1 00:00:00 1970
From: Dirk Stieler <stieler@zess.uni-siegen.de>
Date: Tue, 05 Feb 2002 11:37:20 +0000
Subject: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101290913112826@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

Hello hotplug developers,

I am a "hotplug newbie" and maybe this is not the right place for my
question, so please excuse if this thread is wrong here.

I have a standard personal computer, not really a hotplug system.

But I have developed a PCI-card which is "not present" at boot time
because there is no firmware in the FPGA which is responsible for PCI
communication.

After the configuration of the FPGA I have to determine which
PCI-resources I can use for the card ( IO, mem, IRQ ) and assign this
resources to it.

You know what I mean?

How can I solve this problem?

Maybe it's trivial for you but I haven't found an solution yet.

Thank you, regards,

   Dirk Stieler

_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Matti Aarnio <matti.aarnio+linux-hotplug@zmailer.org>
Date: Tue, 05 Feb 2002 13:55:01 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101291737303871@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

On Tue, Feb 05, 2002 at 12:37:20PM +0100, Dirk Stieler wrote:
> Hello hotplug developers,
> 
> I am a "hotplug newbie" and maybe this is not the right place for my
> question, so please excuse if this thread is wrong here.
> 
> I have a standard personal computer, not really a hotplug system.
> 
> But I have developed a PCI-card which is "not present" at boot time
> because there is no firmware in the FPGA which is responsible for PCI
> communication.

   You really should create circuitry definitions which implement
   the reset-time initial state for PCI "hotplugging".

   - Type data
   - IO address space size
   - MEM address space size
   - Number of IRQs

   (and whatnot else there was..)

   Then any BIOS will do the startup job for you.
   (And even Linux can do it by reworking the PCI configuration datasets.)

> After the configuration of the FPGA I have to determine which
> PCI-resources I can use for the card ( IO, mem, IRQ ) and assign this
> resources to it.
> 
> You know what I mean?
> How can I solve this problem?
> Maybe it's trivial for you but I haven't found an solution yet.

   All of that is just basic PCI specification stuff.

   IF your FPGA isn't loaded from e.g. serial flash, but rather from
   the host processor, then you are screwed...

> Thank you, regards,
>    Dirk Stieler

/Matti Aarnio

_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Stephen Williams <steve@icarus.com>
Date: Wed, 06 Feb 2002 01:17:02 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101295829528441@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

> But I have developed a PCI-card which is "not present" at boot time
> because there is no firmware in the FPGA which is responsible for PCI
> communication.


matti.aarnio+linux-hotplug@zmailer.org said:
> IF your FPGA isn't loaded from e.g. serial flash, but rather from
>    the host processor, then you are screwed...

Actually, what this guy wants to do does have a practical application.

I have in front of me an Adex Electronics PCI bus extender with a
disconnect switch. I would like to use this to plug PCI boards into
a Linux system, configure the device, and turn it on. The idea is to
test hardware, not to provide an end-user tool.

So the question is valid: Is there a way under Linux to grab a bunch
of PCI resources after the system is already running? Detach them
again?

-- 
Steve Williams                "The woods are lovely, dark and deep.
steve at icarus.com           But I have promises to keep,
steve at picturel.com         and lines to code before I sleep,
http://www.picturel.com       And lines to code before I sleep."

abuse@xo.com
uce@ftc.gov



_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Matti Aarnio <matti.aarnio+linux-hotplug@zmailer.org>
Date: Wed, 06 Feb 2002 10:20:10 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101299087001430@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

On Tue, Feb 05, 2002 at 05:17:02PM -0800, Stephen Williams wrote:
> > But I have developed a PCI-card which is "not present" at boot time
> > because there is no firmware in the FPGA which is responsible for PCI
> > communication.
> 
> matti.aarnio+linux-hotplug@zmailer.org said:
> > IF your FPGA isn't loaded from e.g. serial flash, but rather from
> >    the host processor, then you are screwed...
> 
> Actually, what this guy wants to do does have a practical application.
...

  Sure, we do that all the time with CARDBUS cards.
  They are PCI cards in PCMCIA form.

  There still remains an issue of the plugin card needing to
  have proper RESET time content in PCI configuration registers
  so that PCI autoconfiguration will be possible.

  If the FPGA needs to have its "microcode" loaded (ciruitry
  definition, actually) from the host, that just can't be
  supported.   Having a serial-eeprom/flash is simple solution.

  The PCI configuration registers on a PCI device are mostly
  set to zero at the reset time, but some have hardwired
  read content (possibly parts of the registers only,) which
  tells the system various things, including device type,
  and how much it needs resources.  ( plus vendor and other
  minor details... )

....
> -- 
> Steve Williams                "The woods are lovely, dark and deep.

/Matti Aarnio

_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: "Chris Brand" <Chris_Brand@spectrumsignal.com>
Date: Wed, 06 Feb 2002 17:55:56 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101301820917814@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org


>> But I have developed a PCI-card which is "not present" at boot time
>> because there is no firmware in the FPGA which is responsible for PCI
>> communication.
>
>So the question is valid: Is there a way under Linux to grab a bunch
>of PCI resources after the system is already running? Detach them
>again?

Well, I haven't done this under linux of PCI, but I have done it under
VxWorks and Windows2000 and CompactPCI. As I understand it, the PCI
configuration algorithm is the same for both PCI and CompactPCI, so it
should be do-able.

Essentially, what you're trying to do is to hotplug-insert the board,
but without physically inserting it. So the board won't be detected
automatically by the system, but you should be able to use the same
code hotplug uses to do the actual PCI configuration (I'm going to make the
assumption that your FPGA implements the necessary parts of PCI config
space correctly, per the spec). You just need some way of invoking that
code on demand, presumably from a user-space program of some kind.
Unfortunately, it's been a while since I looked at the linux hotplug code,
so I can't be more specific than that, but hopefully somebody else on
the list can...

Chris


_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Greg KH <greg@kroah.com>
Date: Thu, 07 Feb 2002 08:43:29 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101307160722854@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

On Tue, Feb 05, 2002 at 05:17:02PM -0800, Stephen Williams wrote:
> 
> I have in front of me an Adex Electronics PCI bus extender with a
> disconnect switch. I would like to use this to plug PCI boards into
> a Linux system, configure the device, and turn it on. The idea is to
> test hardware, not to provide an end-user tool.
> 
> So the question is valid: Is there a way under Linux to grab a bunch
> of PCI resources after the system is already running? Detach them
> again?

Yes there is.  And I even have patch around here that will do exactly
what you are looking for.  Someone sent it to me a while ago in relation
to the pci hotplug drivers.  I think they had that same extender.

If I remember, the code would basically walk the pci bus when you told
it to (loaded the driver), and create new pci devices for any new
devices found.  Then the module would fail to load, freeing up the
kernel memory again.  Nice idea, but odd implementation :)

The interupt values it would get from the BIOS I think
(IO_APIC_something...), which the IBM PCI Hotplug driver also relies on.
But if you look at the current Compaq pci hotplug driver, it doesn't use
this, and it seems to just recycle interrupts.  Actually that portion of
the Compaq driver seems a bit odd to me now...

I don't think it did anything about removals.

Let me know if you're interested in the code and I'll dig it up.  Enough
interest and I'll port it to the existing pci hotplug core and put it in
the main kernel (but I'd really like to be able to test the driver
myself before I do that...)

thanks,

greg k-h

_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Stephen Williams <steve@icarus.com>
Date: Thu, 07 Feb 2002 16:42:46 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101310020112448@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org


greg@kroah.com said:
> Yes there is.  And I even have patch around here that will do exactly
> what you are looking for.  Someone sent it to me a while ago in
> relation to the pci hotplug drivers.  I think they had that same
> extender.

I spend  lot of time during a typical day powering down, changing
the board and/or soldering wires, and rebooting. I would *love*
to be able to just change a card on a live system.

-- 
Steve Williams                "The woods are lovely, dark and deep.
steve at icarus.com           But I have promises to keep,
steve at picturel.com         and lines to code before I sleep,
http://www.picturel.com       And lines to code before I sleep."

abuse@xo.com
uce@ftc.gov



_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Greg KH <greg@kroah.com>
Date: Thu, 07 Feb 2002 23:51:48 +0000
Subject: Re: PCI hotplug question: resources
MIME-Version: 1
Content-Type: multipart/mixed; boundary="PEIAKu/WMn1b1Hv9"
Message-Id: <marc-linux-hotplug-101312609603679@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
To: linux-hotplug@vger.kernel.org


--PEIAKu/WMn1b1Hv9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Thu, Feb 07, 2002 at 08:42:46AM -0800, Stephen Williams wrote:
> 
> I spend  lot of time during a typical day powering down, changing
> the board and/or soldering wires, and rebooting. I would *love*
> to be able to just change a card on a live system.

Ok, here's the code that I have.  I don't know if this works.  Heck,
I've never even compiled it :)

This code was written by Vladimir Kondratiev.

thanks,

greg k-h

--PEIAKu/WMn1b1Hv9
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pcibus.c"

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/errno.h>
/* for pci_print_IRQ_route */
#include <../arch/i386/kernel/pci-i386.h>

static int assign_irq=0;

/* borrow from pci.c, I need it with no __initdev */
struct pci_dev * pci_scan_device(struct pci_dev *temp)
{
	struct pci_dev *dev;
	u32 l;

	if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l))
		return NULL;

	/* some broken boards return 0 or ~0 if a slot is empty: */
	if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
		return NULL;

	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return NULL;

	memcpy(dev, temp, sizeof(*dev));
	dev->vendor = l & 0xffff;
	dev->device = (l >> 16) & 0xffff;

	/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
	   set this higher, assuming the system even supports it.  */
	dev->dma_mask = 0xffffffff;
	if (pci_setup_device(dev) < 0) {
		kfree(dev);
		dev = NULL;
	}
	return dev;
}
#if 1
/* as in compaq hotplug driver, but print more info */
static int pci_print_IRQ_route (void)
{
	struct irq_routing_table *routing_table;
	int len;
	int loop;

	u8 tbus, tdevice, tslot;

	routing_table = pcibios_get_irq_routing_table();
	if (routing_table == NULL) {
		printk(KERN_ERR "No BIOS Routing Table??? Not good\n");
		return -ENOMEM;
	}

	len = (routing_table->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
	// Make sure I got at least one entry
	if (len == 0) {
		kfree(routing_table);
		return -1;
	}

	printk(KERN_INFO "IRQ router %2x:%2x.%d %04x:%04x\n", 
           (unsigned int)routing_table->rtr_bus,
           (unsigned int)PCI_SLOT(routing_table->rtr_devfn),
           (unsigned int)PCI_FUNC(routing_table->rtr_devfn),
           (unsigned int)routing_table->rtr_vendor,(unsigned int)routing_table->rtr_device);
	printk(KERN_INFO "Exclusive IRQs %04x\n",(unsigned int)routing_table->exclusive_irqs);
	
    printk(KERN_INFO "bus dev func slot\n");
	for (loop = 0; loop < len; ++loop) {
		tbus = routing_table->slots[loop].bus;
		tdevice = routing_table->slots[loop].devfn;
		tslot = routing_table->slots[loop].slot;
		printk(KERN_INFO "%d %d %d %d\n", 
               (unsigned int)tbus, 
               (unsigned int)PCI_SLOT(tdevice), 
               (unsigned int)PCI_FUNC(tdevice), 
               (unsigned int)tslot);
        {
          int i;
          for (i=0;i<4;i++) {
            printk(KERN_INFO "  int%c %02x %04x\n", 'A'+i, 
                   (unsigned int)routing_table->slots[loop].irq[i].link,
                   (unsigned int)routing_table->slots[loop].irq[i].bitmap);
          }
        }

	}
	kfree(routing_table);
	return 0;
}
#endif
#if 0
struct irq_info {
	u8 bus, devfn;			/* Bus, device and function */
	struct {
		u8 link;		/* IRQ line ID, chipset dependent, 0=not routed */
		u16 bitmap;		/* Available IRQs */
	} __attribute__((packed)) irq[4];
	u8 slot;			/* Slot number, 0=onboard */
	u8 rfu;
} __attribute__((packed));

struct irq_routing_table {
	u32 signature;			/* PIRQ_SIGNATURE should be here */
	u16 version;			/* PIRQ_VERSION */
	u16 size;			/* Table size in bytes */
	u8 rtr_bus, rtr_devfn;		/* Where the interrupt router lies */
	u16 exclusive_irqs;		/* IRQs devoted exclusively to PCI usage */
	u16 rtr_vendor, rtr_device;	/* Vendor and device ID of interrupt router */
	u32 miniport_data;		/* Crap */
	u8 rfu[11];
	u8 checksum;			/* Modulo 256 checksum must give zero */
	struct irq_info slots[0];
} __attribute__((packed));
#endif

struct pci_dev* pci_rescan_new_dev(struct pci_dev *dev)
{
  int i;
  for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
    pci_assign_resource(dev,i);
  }
  /* Does this function have an interrupt at all? */
  {
    __u8 irq_pin;
    pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
    if (irq_pin) {
      if ( !dev->irq ) dev->irq = assign_irq;
      pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
    }
  }
  /*pci_name_device(dev);*/
  printk(KERN_INFO "Slot %s New <%s>\n", dev->slot_name, dev->name);
  /* Fix up broken headers */
  #if 0 /* not exported by kernel, init time only */
  pci_fixup_device(PCI_FIXUP_HEADER, dev);
  #endif
  /* FIXME insert new device */
  if (pci_enable_device(dev)) {
    printk(KERN_ERR "pci_enable_device failed\n");
    kfree(dev);
    return NULL;
  }
  pci_insert_device(dev,dev->bus);
  return dev;
}
/**
 * Rescan slot.
 * First, determine whether card in the slot has changed. It is
 * done by compare of old and actual devices for function 0.
 * If change detected, old device(s) removed, other functions
 * scanned if it is multi-function dev, new devices inserted.
 * 
 * @param temp   Device template. Should be set: bus and devfn.
 * @return Device for function 0
 */
struct pci_dev* pci_rescan_slot(struct pci_dev *temp)
{
  struct pci_bus *bus = temp->bus;
  struct pci_dev* old_dev=pci_find_slot(bus->number,temp->devfn);
  struct pci_dev *dev=NULL;
  struct pci_dev *first_dev = NULL;
  int func = 0;
  int new_multi = 0;  /* new multifunction device */
  u8 hdr_type;
  /* function 0 */
  if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
    temp->hdr_type = hdr_type & 0x7f;
    dev = pci_scan_device(temp);
    if (dev) {
      /* compare with old device to detect card change */
      if (old_dev) {
        if (old_dev->vendor==dev->vendor && old_dev->device==dev->device) {
          kfree(dev);
          return old_dev;
        } else {
          printk(KERN_INFO "Slot %02x:%02x Device changed!\n",
                 (unsigned int)bus->number,(unsigned int)PCI_SLOT(temp->devfn));
          printk(KERN_INFO "  Old one <%s>\n",old_dev->name);
          printk(KERN_INFO "  New one <%s>\n",dev->name);
          for (func=0;func<8;func++) {
            old_dev=pci_find_slot(bus->number,temp->devfn+func);
            if (old_dev) {
              printk(KERN_INFO "Slot %s Removed <%s>\n", old_dev->slot_name,old_dev->name);
              pci_remove_device(old_dev);
            }
          }
        }
      }
      /* new device found */
      printk(KERN_INFO "Slot %02x:%02x New <%s>\n",
             (unsigned int)bus->number,(unsigned int)PCI_SLOT(temp->devfn),
             dev->name);
      dev=pci_rescan_new_dev(dev);
      first_dev=dev;
      new_multi=hdr_type & 0x80;
    }
  }
  if ( !dev && old_dev ) { /* device removed */
    for (func=0;func<8;func++) {
      old_dev=pci_find_slot(bus->number,temp->devfn+func);
      if (old_dev) {
        printk(KERN_INFO "Slot %s Removed <%s>\n", old_dev->slot_name,old_dev->name);
        pci_remove_device(old_dev);
      }
    }
  }
  if (new_multi) { /* continue scanning for other functions */
    for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) {
        if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
            continue;
        temp->hdr_type = hdr_type & 0x7f;

        dev = pci_scan_device(temp);
        if (dev) {
          dev=pci_rescan_new_dev(dev);
        }
    }
  }
  return first_dev;
}

       /**
        * Rescan PCI bus.
        * Assumed, some slots may have changed its content.
        * Find old information about each slot and the new one.
        * If they match, do nothing. Otherwise,
        * remove/insert proper devices.
        * 
        * @param bus
        */
static void pci_rescan_bus(const struct pci_bus *bus)
{
  unsigned int devfn;
  struct pci_dev dev0;
  
  memset(&dev0, 0, sizeof(dev0));
  dev0.bus = (struct pci_bus*)bus;
  dev0.sysdata = bus->sysdata;
  for (devfn = 0; devfn < 0x100; devfn += 8) {
      dev0.devfn = devfn;
      pci_rescan_slot(&dev0);
  }
}

static void pci_rescan_buses(const struct list_head *list)
{
  const struct list_head *l;
  list_for_each(l,list) {
    const struct pci_bus *b = pci_bus_b(l);
    pci_rescan_bus(b);
    pci_rescan_buses(&b->children);
  }
}

static int pci_rescan_init(void)
{
  pci_rescan_buses(&pci_root_buses);
  pci_print_IRQ_route();
  return -ENODEV;
}

static void pci_rescan_exit(void)
{}

module_init(pci_rescan_init);
module_exit(pci_rescan_exit);

MODULE_PARM(assign_irq,"i");
MODULE_PARM_DESC(assign_irq,"IRQ to assign to new cards");
MODULE_DESCRIPTION("Force PCI bus rescan");
MODULE_AUTHOR("Vladimir Kondratiev, vladimir.kondratiev@intel.com");


--PEIAKu/WMn1b1Hv9--

_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Donald Becker <becker@scyld.com>
Date: Fri, 08 Feb 2002 01:06:01 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101313037813542@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

On Thu, 7 Feb 2002, Greg KH wrote:
> On Tue, Feb 05, 2002 at 05:17:02PM -0800, Stephen Williams wrote:
> > I have in front of me an Adex Electronics PCI bus extender with a
> > disconnect switch. I would like to use this to plug PCI boards into
...
> I don't think it did anything about removals.

I wrote PCI hotplug code for a similar board, primarily for testing
my drivers.  It hooked into the CardBus/hotplug interface ("pci-scan")
that I use.

I handled the removal (actually power-off) case just by polling the
vendor ID register in PCI configuration space in a normal add_timer().

This initially looks sleazy, but it's very low overhead and the
semantics match CardBus controllers.  ("Oh, yeah, the card was ejected
two seconds ago.  I assumed that you knew that when you got 0xffffffff
when reading.  Here is your eject callback so that you can clean up.")

Donald Becker				becker@scyld.com
Scyld Computing Corporation		http://www.scyld.com
410 Severn Ave. Suite 210		Second Generation Beowulf Clusters
Annapolis MD 21403			410-990-9993


_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: Martin Diehl <lists@mdiehl.de>
Date: Fri, 08 Feb 2002 01:34:12 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101313194317021@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

On Thu, 7 Feb 2002, Greg KH wrote:

> On Thu, Feb 07, 2002 at 08:42:46AM -0800, Stephen Williams wrote:
> > 
> > I spend  lot of time during a typical day powering down, changing
> > the board and/or soldering wires, and rebooting. I would *love*
> > to be able to just change a card on a live system.
> 
> Ok, here's the code that I have.  I don't know if this works.  Heck,
> I've never even compiled it :)
> 
> This code was written by Vladimir Kondratiev.

Wow - thanks!

When I saw your hotplug-skeleton I was thinking I should try something
like this for my OB800: it has an built-in scsi-HA which is detected
during pci-busscan only if the proprietary cable is connected (My guess is
the power is simply routed thru some magic in the plug...) Hence one has
to reboot to make use of the scsi if booted without the cable connected.

But all one would need is to rescan the bus later whenever one wants to
connect or disconnect. Note that there is no real hotplug controller there
to create (un)plug notifications. But there are some changing registers
in the northbridge so one could even poll with say 1 sec intervall for
connections. Anyway, there is probably nothing which provides real hot
(un)plugging on the active scsi bus. So I really prefer to do this by
hand whenever I switch scsi cabling.

I just tried this patch and it seems to be almost exactly what I was
looking for. However, I first had to disable the "print IRQ routing" path
because it Oopsed for me (in pcibios_get_irq_routing_table(), fwiw).
No big deal and now its working really fine:

cable connected, insmod pcibus:
  scsi-HA detected+registered, bar's allocated, lspci -vvvxxx looks fine

modprobe ncr53c8xx and friends:
  PIRQ routed, HA detected, scsi-device found

mount /dev/scd0 -> normal operation

reverse unmount, rmmod, disconnect and then insmod pcibus again:
  pci-device removed, lspci and /proc/ioports cleaned

Turns out it's a real useful tool for me. I'm going to improve it a little
bit (probably next weekend...)

Thanks.

Martin


_______________________________________________
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

From mboxrd@z Thu Jan  1 00:00:00 1970
From: John Carlson <carlsj@yahoo.com>
Date: Fri, 08 Feb 2002 15:44:14 +0000
Subject: Re: PCI hotplug question: resources
Message-Id: <marc-linux-hotplug-101318310111131@msgid-missing>
List-Id: <linux-hotplug.vger.kernel.org>
References: <marc-linux-hotplug-101290913112826@msgid-missing>
In-Reply-To: <marc-linux-hotplug-101290913112826@msgid-missing>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
To: linux-hotplug@vger.kernel.org

  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

