On Mon, 27 Apr 2009 10:14:02 +0200, Stefan Reinauer stepan@coresystems.de wrote:
On 27.04.2009 9:55 Uhr, Joseph Smith wrote:
Well, I have confirmed the problem. Looks there is something crazy about how the ethernet and modem (even though the IP1000 doesn't actually have
a
modem) are setup. If I disable the ICH4 ethernet and enable the AC97
ICH4
modem, sure as shit it boots up everytime (VGA too) and all IRQS look great. If I enable both of them EVERYTHING gets IRQ 0, and I have
issues.
If I enable ethernet and disable the modem (this is the way it should
be)
EVERYTHING gets IRQ 0, and I have issues.....
Anyone seen this kind of thing before? I have no idea how to fix this one....
Well now were getting somewhere. It is as I thought. The modem and Ethernet were not playing nice causing io read/write issues under 0x200, hence the unexpected exception errors. The IRQ 0 problems also make sense because the interrupt controllers live in that io area correct? I guess on this board they were not designed to coincide...there isn't an actual on-board modem anyways.
So here is what I did to get it working, and this is the part I need help with.
1. In auto.c I disabled the modem right off through the LPC device:
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0);
/* Disable Modem. */ pci_write_config8(dev, 0xf2, 0x40);
2. I completely removed the modem code from src/mainboard/thomson/ip1000/Config.lb
- device pci 1f.6 off end # AC'97 modem
3. Then I completely removed the modem code from src/southbridge/intel/i82801xx/i82801xx_ac97.c
-static const struct pci_driver i82801db_ac97_modem __pci_driver = { - .ops = &ac97_ops, - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_AC97_MODEM, -};
And boom :-) I am booting like a rocket ship in action:-)
I have tried Just step 1 with no luck, and step 1 & 2 with no luck. So even with the device disabled via the LPC and coreboot something from the i82801db_ac97_modem() is still partially initializing causing this io crazyness. I can submit a patch for steps 1-2 but....my question is how can I completely disable the i82801db_ac97_modem() driver without having to manually delete code every time I use a new revision???
Maybe a #ifdef to global disable modem define???
On Tue, Apr 28, 2009 at 8:38 PM, Joseph Smith joe@settoplinux.org wrote:
On Mon, 27 Apr 2009 10:14:02 +0200, Stefan Reinauer stepan@coresystems.de wrote:
On 27.04.2009 9:55 Uhr, Joseph Smith wrote:
Well, I have confirmed the problem. Looks there is something crazy about how the ethernet and modem (even though the IP1000 doesn't actually have
a
modem) are setup. If I disable the ICH4 ethernet and enable the AC97
ICH4
modem, sure as shit it boots up everytime (VGA too) and all IRQS look great. If I enable both of them EVERYTHING gets IRQ 0, and I have
issues.
If I enable ethernet and disable the modem (this is the way it should
be)
EVERYTHING gets IRQ 0, and I have issues.....
Anyone seen this kind of thing before? I have no idea how to fix this one....
Well now were getting somewhere. It is as I thought. The modem and Ethernet were not playing nice causing io read/write issues under 0x200, hence the unexpected exception errors. The IRQ 0 problems also make sense because the interrupt controllers live in that io area correct? I guess on this board they were not designed to coincide...there isn't an actual on-board modem anyways.
So here is what I did to get it working, and this is the part I need help with.
- In auto.c I disabled the modem right off through the LPC device:
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0);
/* Disable Modem. */ pci_write_config8(dev, 0xf2, 0x40);
- I completely removed the modem code from
src/mainboard/thomson/ip1000/Config.lb
- device pci 1f.6 off end # AC'97 modem
- Then I completely removed the modem code from
src/southbridge/intel/i82801xx/i82801xx_ac97.c
-static const struct pci_driver i82801db_ac97_modem __pci_driver = {
- .ops = &ac97_ops,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801DB_AC97_MODEM,
-};
And boom :-) I am booting like a rocket ship in action:-)
I have tried Just step 1 with no luck, and step 1 & 2 with no luck. So even with the device disabled via the LPC and coreboot something from the i82801db_ac97_modem() is still partially initializing causing this io crazyness. I can submit a patch for steps 1-2 but....my question is how can I completely disable the i82801db_ac97_modem() driver without having to manually delete code every time I use a new revision???
Maybe a #ifdef to global disable modem define???
You've got this working but you are kind of abusing the build system, esp. if you are modifying files like i82801xx_ac97.c. I will leave it to someone else to discuss why you don't want to do step 3 ... I'm gonna go sleep now :-)
ron
On Tue, 28 Apr 2009 22:46:54 -0700, ron minnich rminnich@gmail.com wrote:
On Tue, Apr 28, 2009 at 8:38 PM, Joseph Smith joe@settoplinux.org
wrote:
On Mon, 27 Apr 2009 10:14:02 +0200, Stefan Reinauer
wrote:
On 27.04.2009 9:55 Uhr, Joseph Smith wrote:
Well, I have confirmed the problem. Looks there is something crazy
about
how the ethernet and modem (even though the IP1000 doesn't actually
have
a
modem) are setup. If I disable the ICH4 ethernet and enable the AC97
ICH4
modem, sure as shit it boots up everytime (VGA too) and all IRQS look great. If I enable both of them EVERYTHING gets IRQ 0, and I have
issues.
If I enable ethernet and disable the modem (this is the way it should
be)
EVERYTHING gets IRQ 0, and I have issues.....
Anyone seen this kind of thing before? I have no idea how to fix this one....
Well now were getting somewhere. It is as I thought. The modem and
Ethernet
were not playing nice causing io read/write issues under 0x200, hence
the
unexpected exception errors. The IRQ 0 problems also make sense because
the
interrupt controllers live in that io area correct? I guess on this
board
they were not designed to coincide...there isn't an actual on-board
modem
anyways.
So here is what I did to get it working, and this is the part I need
help
with.
- In auto.c I disabled the modem right off through the LPC device:
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0);
/* Disable Modem. */ pci_write_config8(dev, 0xf2, 0x40);
- I completely removed the modem code from
src/mainboard/thomson/ip1000/Config.lb
- device pci 1f.6 off end # AC'97 modem
- Then I completely removed the modem code from
src/southbridge/intel/i82801xx/i82801xx_ac97.c
-static const struct pci_driver i82801db_ac97_modem __pci_driver = {
- .ops = &ac97_ops,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801DB_AC97_MODEM,
-};
And boom :-) I am booting like a rocket ship in action:-)
I have tried Just step 1 with no luck, and step 1 & 2 with no luck. So even with the device disabled via the LPC and coreboot something from
the
i82801db_ac97_modem() is still partially initializing causing this io crazyness. I can submit a patch for steps 1-2 but....my question is how
can
I completely disable the i82801db_ac97_modem() driver without having to manually delete code every time I use a new revision???
Maybe a #ifdef to global disable modem define???
You've got this working but you are kind of abusing the build system, esp. if you are modifying files like i82801xx_ac97.c. I will leave it to someone else to discuss why you don't want to do step 3 ... I'm gonna go sleep now :-)
Yes, in a perfect world I should just have to turn the device off in src/mainboard/thomson/ip1000/Config.lb and I would never see any traces of the device.
Quote from the 82801DB datasheet LPC register 0xF2: "Software sets this bit to disable the AC ’97 modem controller function. BIOS must not enable I/O or memory address space decode, interrupt generation, or any other functionality of functions that are to be disabled."
But just turning the device off is not performing all of the above functions required by the southbridge. If anyone has any suggestions on how to really disable this device without touching src/southbridge/intel/i82801xx/i82801xx_ac97.c I would be glad to hear them....
On Wed, 29 Apr 2009 08:27:17 -0400, Joseph Smith joe@settoplinux.org wrote:
On Tue, 28 Apr 2009 22:46:54 -0700, ron minnich rminnich@gmail.com wrote:
On Tue, Apr 28, 2009 at 8:38 PM, Joseph Smith joe@settoplinux.org
wrote:
On Mon, 27 Apr 2009 10:14:02 +0200, Stefan Reinauer
wrote:
On 27.04.2009 9:55 Uhr, Joseph Smith wrote:
Well, I have confirmed the problem. Looks there is something crazy
about
how the ethernet and modem (even though the IP1000 doesn't actually
have
a
modem) are setup. If I disable the ICH4 ethernet and enable the AC97
ICH4
modem, sure as shit it boots up everytime (VGA too) and all IRQS look great. If I enable both of them EVERYTHING gets IRQ 0, and I have
issues.
If I enable ethernet and disable the modem (this is the way it should
be)
EVERYTHING gets IRQ 0, and I have issues.....
Anyone seen this kind of thing before? I have no idea how to fix this one....
Well now were getting somewhere. It is as I thought. The modem and
Ethernet
were not playing nice causing io read/write issues under 0x200, hence
the
unexpected exception errors. The IRQ 0 problems also make sense because
the
interrupt controllers live in that io area correct? I guess on this
board
they were not designed to coincide...there isn't an actual on-board
modem
anyways.
So here is what I did to get it working, and this is the part I need
help
with.
- In auto.c I disabled the modem right off through the LPC device:
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0);
/* Disable Modem. */ pci_write_config8(dev, 0xf2, 0x40);
- I completely removed the modem code from
src/mainboard/thomson/ip1000/Config.lb
- device pci 1f.6 off end # AC'97 modem
- Then I completely removed the modem code from
src/southbridge/intel/i82801xx/i82801xx_ac97.c
-static const struct pci_driver i82801db_ac97_modem __pci_driver = {
- .ops = &ac97_ops,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801DB_AC97_MODEM,
-};
And boom :-) I am booting like a rocket ship in action:-)
I have tried Just step 1 with no luck, and step 1 & 2 with no luck.
So
even with the device disabled via the LPC and coreboot something from
the
i82801db_ac97_modem() is still partially initializing causing this io crazyness. I can submit a patch for steps 1-2 but....my question is how
can
I completely disable the i82801db_ac97_modem() driver without having to manually delete code every time I use a new revision???
Maybe a #ifdef to global disable modem define???
You've got this working but you are kind of abusing the build system, esp. if you are modifying files like i82801xx_ac97.c. I will leave it to someone else to discuss why you don't want to do step 3 ... I'm gonna go sleep now :-)
Yes, in a perfect world I should just have to turn the device off in src/mainboard/thomson/ip1000/Config.lb and I would never see any traces
of
the device.
Quote from the 82801DB datasheet LPC register 0xF2: "Software sets this bit to disable the AC ’97 modem controller
function.
BIOS must not enable I/O or memory address space decode, interrupt generation, or any other functionality of functions that are to be disabled."
But just turning the device off is not performing all of the above functions required by the southbridge. If anyone has any suggestions on how to really disable this device without touching src/southbridge/intel/i82801xx/i82801xx_ac97.c I would be glad to hear them....
By the way why are the AC97 audio and modem in one file? They are their own PCI device and have thier own PCI config register, they should have thier own file (this is leading into something into the future for some audio specific stuff and modem specific stuff). If no one minds I would like to spit this two into thier own file.
On 29.04.2009 14:27 Uhr, Joseph Smith wrote:
Yes, in a perfect world I should just have to turn the device off in src/mainboard/thomson/ip1000/Config.lb and I would never see any traces of the device.
Quote from the 82801DB datasheet LPC register 0xF2: "Software sets this bit to disable the AC ’97 modem controller function. BIOS must not enable I/O or memory address space decode, interrupt generation, or any other functionality of functions that are to be disabled."
But just turning the device off is not performing all of the above functions required by the southbridge. If anyone has any suggestions on how to really disable this device without touching src/southbridge/intel/i82801xx/i82801xx_ac97.c I would be glad to hear them....
The code in src/southbridhe/i82801xx/i82801xx.c tries to take care of the F2 register settings. So, if you don't have a device pci 1f.6 off end in your config.lb it might just get enabled by i82801xx.c again
On Wed, 29 Apr 2009 15:11:23 +0200, Stefan Reinauer stepan@coresystems.de wrote:
On 29.04.2009 14:27 Uhr, Joseph Smith wrote:
Yes, in a perfect world I should just have to turn the device off in src/mainboard/thomson/ip1000/Config.lb and I would never see any traces
of
the device.
Quote from the 82801DB datasheet LPC register 0xF2: "Software sets this bit to disable the AC ’97 modem controller
function.
BIOS must not enable I/O or memory address space decode, interrupt generation, or any other functionality of functions that are to be disabled."
But just turning the device off is not performing all of the above functions required by the southbridge. If anyone has any suggestions on
how
to really disable this device without touching src/southbridge/intel/i82801xx/i82801xx_ac97.c I would be glad to hear them....
The code in src/southbridhe/i82801xx/i82801xx.c tries to take care of the F2 register settings. So, if you don't have a device pci 1f.6 off end in your config.lb it might just get enabled by i82801xx.c again
Right and i82801xx_enable() works ok for me but it apears to do it backwards...in each device file. For example in i82801xx_ac97.c ac97_ops:
static const struct device_operations ac97_ops = { .read_resources = pci_dev_read_resources, .set_resources = pci_dev_set_resources, .enable_resources = pci_dev_enable_resources, .init = 0, .scan_bus = 0, .enable = i82801xx_enable,
It appears the .enable = i82801xx_enable, is happening last. Therefore up to this point coreboot is pci_dev_read_resources, pci_dev_set_resources, and pci_dev_enable_resources. Just because it is turned off in the mainboard Config.lb The LPC device (not coreboot) is still allocating resources because it doesn't know the device is disabled until the end (at this point it is too late). You might not see the device in Linux but the resources are still allocated to it. Am I correct in this theory? It should be setup so that if the device is indeed turned off in mainboard Config.lb that the i82801xx_enable() is set first and then if the device is indeed turned off ignores the resource functions.
I will test this theory tonight and post back the results, but I think this is what is happening here.
ron minnich wrote:
You've got this working but you are kind of abusing the build system, esp. if you are modifying files like i82801xx_ac97.c. I will leave it to someone else to discuss why you don't want to do step 3 ...
Problem is, I think you're one of the few who knows why.. I still don't.
//Peter
On Tue, Apr 28, 2009 at 8:38 PM, Joseph Smith joe@settoplinux.org wrote:
- In auto.c I disabled the modem right off through the LPC device:
/* Set the LPC device statically. */ dev = PCI_DEV(0x0, 0x1f, 0x0);
/* Disable Modem. */ pci_write_config8(dev, 0xf2, 0x40);
What is the effect of this? Does it make it so that the modem is not visible in PCI config space? If that is indeed what you are doing, that's good. It's the kind of thing that we have to do all the time.
- I completely removed the modem code from
src/mainboard/thomson/ip1000/Config.lb
- device pci 1f.6 off end # AC'97 modem
This should not really matter either way if step 1 worked. I suspect that step 1 is having no effect.
What this means is that if this pci device is found it should no be enabled. But this is in the sense of the CMD register, not in the sense of visibility in pci config space.
- Then I completely removed the modem code from
src/southbridge/intel/i82801xx/i82801xx_ac97.c
Icky. You should never touch this type of file. If you have to then something is quite broken. Note that if step (1) above really removes the device from config space, then the presence of this code is not important.
-static const struct pci_driver i82801db_ac97_modem __pci_driver = {
- .ops = &ac97_ops,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801DB_AC97_MODEM,
-};
If you really disabled the device in the 'not visible in config space' sense then the device code for the device will not get run. So I suspect step 1 had no real effect.
I have tried Just step 1 with no luck, and step 1 & 2 with no luck. So even with the device disabled via the LPC and coreboot something from the i82801db_ac97_modem() is still partially initializing causing this io crazyness. I can submit a patch for steps 1-2 but....my question is how can I completely disable the i82801db_ac97_modem() driver without having to manually delete code every time I use a new revision???
I think something in step 1 is not working the way you think it is.
Don't forget: there is a difference between 'not visible in config space' and 'not enabled but visible'.
Maybe a #ifdef to global disable modem define???
definitely not :-)
Thanks for your patience on this. I admire your persistence. We'll get it.
ron
What? Eithor something changed between r4227 (that I was testing with last night and r4232) or I am going completely crazy! Anyways, everything is working fine. Maybe my board is just f'd up...
On Wed, Apr 29, 2009 at 8:34 PM, Joseph Smith joe@settoplinux.org wrote:
What? Eithor something changed between r4227 (that I was testing with last night and r4232) or I am going completely crazy! Anyways, everything is working fine. Maybe my board is just f'd up...
hardware is like that :-)
Let's hope that's what it is ...
ron
On Wed, 29 Apr 2009 21:13:33 -0700, ron minnich rminnich@gmail.com wrote:
On Wed, Apr 29, 2009 at 8:34 PM, Joseph Smith joe@settoplinux.org
wrote:
What? Eithor something changed between r4227 (that I was testing with
last
night and r4232) or I am going completely crazy! Anyways, everything is working fine. Maybe my board is just f'd up...
hardware is like that :-)
Let's hope that's what it is ...
Well, along the way I did learn a lot more about irq tables. Like each line in irq_tables.c is not actually a device but a route to the device/s. There can be multiple devices on a route. For example all of my USB devices are on the same route:
|- USB #1 |- USB #2 |- USB #3 |- EHCI {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
is the same as:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [A] USB UHCI 1 */ {0x00,(0x1d<<3)|0x1, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [B] USB UHCI 2 */ {0x00,(0x1d<<3)|0x2, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x00, 0x00000}}, 0x0, 0x0}, /* [C] USB UHCI 3 */ {0x00,(0x1d<<3)|0x7, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0}, /* [D] EHCI */
It is just condensed into one line instead of four.
I never really understood this until now. Also the "bus, dev|fn," can be diseaving becuase it only tells you the first device on the route INTA.
If no one objects I would really like to add a section to the http://www.coreboot.org/Creating_Valid_IRQ_Tables page breaking down irq_tables.c and explaining what each part means. I think this would help people understand this very confusing process a little more.
On Thu, Apr 30, 2009 at 5:37 AM, Joseph Smith joe@settoplinux.org wrote:
Well, along the way I did learn a lot more about irq tables. Like each line in irq_tables.c is not actually a device but a route to the device/s. There can be multiple devices on a route. For example all of my USB devices are on the same route:
I think this is a mistinterpretaion. In PCI-speak, there is one device. Each device has several functions.
A device itself has only one wire -- there is one physical wire for that chip or device. It is called the interrupt line.
For reasons too long to go into here (basically, the PCI SIG made a slight mistake in designing interrupts) we need to have the IRQ table so we know mapping of IRQ wire from device to IRQ wire of bus/interrupt router, e.g. INTA of a chip/device may map to INTC of the bus and hence the interrupt router.
|- USB #1 |- USB #2 |- USB #3 |- EHCI {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
is the same as:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [A] USB UHCI 1 */ {0x00,(0x1d<<3)|0x1, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [B] USB UHCI 2 */ {0x00,(0x1d<<3)|0x2, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x00, 0x00000}}, 0x0, 0x0}, /* [C] USB UHCI 3 */ {0x00,(0x1d<<3)|0x7, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0}, /* [D] EHCI */
no, not really. Functions don't have interrupts. The device itself has an interrupt.
I never really understood this until now. Also the "bus, dev|fn," can be diseaving becuase it only tells you the first device on the route INTA.
It tells you about that device. Those other things you mentioned are functions of that device.
If no one objects I would really like to add a section to the http://www.coreboot.org/Creating_Valid_IRQ_Tables page breaking down irq_tables.c and explaining what each part means. I think this would help people understand this very confusing process a little more.
I think your explanation is not really correct; you might want to re-read the spec fot that table to see what it's about. As it is you're going to confuse people :-)
I made this mistake myself on geode once before marc pointed it out to me.
I will be glad when this aspect of PCI is gone. ron
On Thu, 30 Apr 2009 07:55:24 -0700, ron minnich rminnich@gmail.com wrote:
On Thu, Apr 30, 2009 at 5:37 AM, Joseph Smith joe@settoplinux.org
wrote:
Well, along the way I did learn a lot more about irq tables. Like each
line
in irq_tables.c is not actually a device but a route to the device/s.
There
can be multiple devices on a route. For example all of my USB devices
are
on the same route:
I think this is a mistinterpretaion. In PCI-speak, there is one device. Each device has several functions.
A device itself has only one wire -- there is one physical wire for that chip or device. It is called the interrupt line.
For reasons too long to go into here (basically, the PCI SIG made a slight mistake in designing interrupts) we need to have the IRQ table so we know mapping of IRQ wire from device to IRQ wire of bus/interrupt router, e.g. INTA of a chip/device may map to INTC of the bus and hence the interrupt router.
|- USB #1 |- USB #2
|- USB #3 |-
EHCI {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
is the same as:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [A] USB UHCI 1 */ {0x00,(0x1d<<3)|0x1, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [B] USB UHCI 2 */ {0x00,(0x1d<<3)|0x2, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x00, 0x00000}}, 0x0, 0x0}, /* [C] USB UHCI 3 */ {0x00,(0x1d<<3)|0x7, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0}, /* [D] EHCI */
no, not really. Functions don't have interrupts. The device itself has an interrupt.
I never really understood this until now. Also the "bus, dev|fn," can be diseaving becuase it only tells you the first device on the route INTA.
It tells you about that device. Those other things you mentioned are functions of that device.
If no one objects I would really like to add a section to the http://www.coreboot.org/Creating_Valid_IRQ_Tables page breaking down irq_tables.c and explaining what each part means. I think this would
help
people understand this very confusing process a little more.
I think your explanation is not really correct; you might want to re-read the spec fot that table to see what it's about. As it is you're going to confuse people :-)
I made this mistake myself on geode once before marc pointed it out to
me.
I will be glad when this aspect of PCI is gone.
Me too! Now you got me really confused just when I thought I had finally figured it out :-( Can you point me to some good reference docs then?
Someone more knowledgeable than I pointed that I got this wrong. Sorry.
On Thu, Apr 30, 2009 at 7:55 AM, ron minnich rminnich@gmail.com wrote:
A device itself has only one wire -- there is one physical wire for that chip or device. It is called the interrupt line.
A device can actually connect to up to all four wires. This is way more common than I realized -- I have not paid attention lately.
The device can be wired such that different functions on the device are wired to different physical interrupt lines that are then wired to the bus/irq router. example on the m57sli: [rminnich@amd64 ~]$ setpci -s 0:5.2 3d.b 03 [rminnich@amd64 ~]$ setpci -s 0:5.1 3d.b 02 [rminnich@amd64 ~]$ setpci -s 0:5.0 3d.b 01
But the spec I referred you to does not list functions in the PIRQ table, only devices. You would use the value of the 3d register to then map from the table to the actual line which these are wired to. You can find out what IRQ it got in 3c.b [rminnich@amd64 ~]$ setpci -s 0:5.2 3c.b 0f [rminnich@amd64 ~]$ setpci -s 0:5.1 3c.b 0b [rminnich@amd64 ~]$ setpci -s 0:5.0 3c.b 0a [rminnich@amd64 ~]$
Functions have interrupts, but the only interrupts listed in a PIRQ are for the device.
Sorry for sowing confusion.
ron
On Thu, 30 Apr 2009 10:10:04 -0700, ron minnich rminnich@gmail.com wrote:
Someone more knowledgeable than I pointed that I got this wrong. Sorry.
On Thu, Apr 30, 2009 at 7:55 AM, ron minnich rminnich@gmail.com wrote:
A device itself has only one wire -- there is one physical wire for that chip or device. It is called the interrupt line.
A device can actually connect to up to all four wires. This is way more common than I realized -- I have not paid attention lately.
The device can be wired such that different functions on the device are wired to different physical interrupt lines that are then wired to the bus/irq router. example on the m57sli: [rminnich@amd64 ~]$ setpci -s 0:5.2 3d.b 03 [rminnich@amd64 ~]$ setpci -s 0:5.1 3d.b 02 [rminnich@amd64 ~]$ setpci -s 0:5.0 3d.b 01
But the spec I referred you to does not list functions in the PIRQ table, only devices. You would use the value of the 3d register to then map from the table to the actual line which these are wired to. You can find out what IRQ it got in 3c.b [rminnich@amd64 ~]$ setpci -s 0:5.2 3c.b 0f [rminnich@amd64 ~]$ setpci -s 0:5.1 3c.b 0b [rminnich@amd64 ~]$ setpci -s 0:5.0 3c.b 0a [rminnich@amd64 ~]$
Functions have interrupts, but the only interrupts listed in a PIRQ are for the device.
Sorry for sowing confusion.
Right. So in my example: |- USB #1 |- USB #2 |- USB #3 |-EHCI {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
is the same as:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [A] USB UHCI 1 */ {0x00,(0x1d<<3)|0x1, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [B] USB UHCI 2 */ {0x00,(0x1d<<3)|0x2, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x00, 0x00000}}, 0x0, 0x0}, /* [C] USB UHCI 3 */ {0x00,(0x1d<<3)|0x7, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0}, /* [D] EHCI */
PIRQA(0X60 0x03 PIRQB(0X61) 0x05 PIRQC(0X62) 0x06 PIRQD(0X63) 0x07 PIRQE(0X68) 0x09 PIRQF(0X69) 0x0A PIRQG(0X6A) 0x0B PIRQH(0X6B) 0x0C
Also in Linux dmesg it shows what Int the device is connected to on the interrupt router:
[A] USB UHCI 1 [B] USB UHCI 2 [C] USB UHCI 3 [D] EHCI
3 of the four devices have multiple INT lines running through them so a physical map would look like the attached file.
Basicly what I am saying is routing up all four devices like in the image can be done in one line of code:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
On Thu, Apr 30, 2009 at 1:22 PM, Joseph Smith joe@settoplinux.org wrote:
Basicly what I am saying is routing up all four devices like in the image can be done in one line of code:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
Give that they are not devices, they are functions of a device, this is true.
ron
On Thu, Apr 30, 2009 at 1:11 PM, Joseph Smith joe@settoplinux.org wrote:
Right. So in my example: |- USB #1 |- USB #2 |- USB #3 |-EHCI {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
is the same as:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [A] USB UHCI 1 */ {0x00,(0x1d<<3)|0x1, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [B] USB UHCI 2 */ {0x00,(0x1d<<3)|0x2, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x00, 0x00000}}, 0x0, 0x0}, /* [C] USB UHCI 3 */ {0x00,(0x1d<<3)|0x7, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0}, /* [D] EHCI */
yes, but what I have been trying to explain (badly) is that you don't want to think of those functions as devices. They're functions. So, in your sample table above, all the entries save the first one are illegal -- PIRQ tables don't have non-zero functions. They only describe how the (one or more) wires from a device are hooked up.
[A] USB UHCI 1 [B] USB UHCI 2 [C] USB UHCI 3 [D] EHCI
I still think your diagram is misleading in that it implies wires that are not really there -- correct me if I got this wrong again.
But the way I view it is that the device (which used to be a multi-function board or chip) is what is physically wired to the four IRQ lines. To put it another way, the swizzling you show occurfing inside the device doesn't really occur; that kind of INT swizzling is done on the mainboard itself. It's not possible, for example, for USB UHCI2 to use INTA -- the wires don't exist. But your diagram implies any of the four functions can use any of the four interrupts, which is not correct.
So I draw it differently, with one device with INT A,B,C,D and the functions wired internally, one to each INT.
ron
On Thu, 30 Apr 2009 13:34:37 -0700, ron minnich rminnich@gmail.com wrote:
On Thu, Apr 30, 2009 at 1:11 PM, Joseph Smith joe@settoplinux.org
wrote:
Right. So in my example: |- USB #1 |- USB #2
|- USB #3
|-EHCI {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
is the same as:
{0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [A] USB UHCI 1 */ {0x00,(0x1d<<3)|0x1, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x00, 0x0000}, {0x00, 0x00000}}, 0x0, 0x0}, /* [B] USB UHCI 2 */ {0x00,(0x1d<<3)|0x2, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x00, 0x00000}}, 0x0, 0x0}, /* [C] USB UHCI 3 */ {0x00,(0x1d<<3)|0x7, {{0x60, 0x1ef8}, {0x63, 0x1ef8}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0}, /* [D] EHCI */
yes, but what I have been trying to explain (badly) is that you don't want to think of those functions as devices. They're functions. So, in your sample table above, all the entries save the first one are illegal -- PIRQ tables don't have non-zero functions. They only describe how the (one or more) wires from a device are hooked up.
[A] USB UHCI 1 [B] USB UHCI 2 [C] USB UHCI 3 [D] EHCI
I still think your diagram is misleading in that it implies wires that are not really there -- correct me if I got this wrong again.
But the way I view it is that the device (which used to be a multi-function board or chip) is what is physically wired to the four IRQ lines. To put it another way, the swizzling you show occurfing inside the device doesn't really occur; that kind of INT swizzling is done on the mainboard itself. It's not possible, for example, for USB UHCI2 to use INTA -- the wires don't exist. But your diagram implies any of the four functions can use any of the four interrupts, which is not correct.
Right the INT lines A,B,C, and D are hard wired. But you can asign any PIRQ to a function and any available IRQ to the PIRQ these are software controlled.
So I draw it differently, with one device with INT A,B,C,D and the functions wired internally, one to each INT.
Hmm. That is another way of looking at it. The doc does say the "device" acts as a interrupt router (which is INTA in this case). So the other three are directly connected to it? Like the attached image?
On Thu, Apr 30, 2009 at 2:01 PM, Joseph Smith joe@settoplinux.org wrote:
Right the INT lines A,B,C, and D are hard wired. But you can asign any PIRQ to a function and any available IRQ to the PIRQ these are software controlled.
The 3d register lists what functions can assert what interrupt lines. what is the value of 3d for each of these four device functions? You can use setpci to see. setpci -s bus:dev.fn 3d.b
Hmm. That is another way of looking at it. The doc does say the "device" acts as a interrupt router (which is INTA in this case). So the other three are directly connected to it? Like the attached image?
I doubt that is exactly it but I think it's closer to my internal picture. What the 3d register will tell you is what INT is wired to each function. So, e.g., I would guest that 3d is like this:
USB1 1 USB2 2 USB3 3 EHCI 4
0 would mean no interrupt line is wired.
The picture in my mind is that there is a very simple interrupt controller on the device that connections the four USB functions to the external INT lines.
ron
ron
On Thu, 30 Apr 2009 14:55:59 -0700, ron minnich rminnich@gmail.com wrote:
On Thu, Apr 30, 2009 at 2:01 PM, Joseph Smith joe@settoplinux.org
wrote:
Right the INT lines A,B,C, and D are hard wired. But you can asign any
PIRQ
to a function and any available IRQ to the PIRQ these are software controlled.
The 3d register lists what functions can assert what interrupt lines. what is the value of 3d for each of these four device functions? You can use setpci to see. setpci -s bus:dev.fn 3d.b
Hmm. That is another way of looking at it. The doc does say the "device" acts as a interrupt router (which is INTA in this case). So the other
three
are directly connected to it? Like the attached image?
I doubt that is exactly it but I think it's closer to my internal picture.
I wish you could make your internal picture external, so I could see what it is then. So to test this I theory I should just be able to pluck out oh lets say function 2 on INTB. If everythings works great except USB2 than that theory is correct. On the otherhand if we loose USB2, USB3, and EHCI than we know they are routed through each other. Correct? Like this: {0x00,(0x1d<<3)|0x0, {{0x60, 0x1ef8}, {0x00, 0x00000}, {0x62, 0x1ef8}, {0x6b, 0x01ef8}}, 0x0, 0x0},
What the 3d register will tell you is what INT is wired to each function. So, e.g., I would guest that 3d is like this:
USB1 1 USB2 2 USB3 3 EHCI 4
Yup. 00:1d.0 USB Controller #1 - 0x3d = 0x01 00:1d.1 USB Controller #2 - 0x3d = 0x02 00:1d.2 USB Controller #3 - 0x3d = 0x03 00:1d.7 USB Controller EHCI - 0x3d = 0x04
What the 3d register will tell you is what INT is wired to each function. So, e.g., I would guest that 3d is like this:
USB1 1 USB2 2 USB3 3 EHCI 4
Yup. 00:1d.0 USB Controller #1 - 0x3d = 0x01 00:1d.1 USB Controller #2 - 0x3d = 0x02 00:1d.2 USB Controller #3 - 0x3d = 0x03 00:1d.7 USB Controller EHCI - 0x3d = 0x04
FYI, here is what the ICH4 data sheet says about these 0x3d registers. Looks like the PIRQ is internally specific.
USB 1,2, & 3 0x3d Interrupt Pin (INT_PN) — RO. The values of 01h, 02h, and 03h in function 0, 1, and 2, respectively, indicate to software that the corresponding ICH4 UHCI USB controllers drive the INTA#, INTB#, and INTC# PCI signals. Note that this does not determine the mapping to the ICH4 PIRQ inputs. Function 0 will drive PIRQA. Function 1 will drive PIRQD. Function 2 will drive PIRQC. Function 1 does not use the corresponding mapping in order to spread the interrupts with AC97, which has historically been mapped to PIRQB.
EHCI 0x3d Interrupt Pin (INT_PN) — RO. The value of 04h indicates that the USB EHCI function within the ICH4’s multi-function USB device will drive the fourth interrupt pin from the device (INTD# in PCI terms). The value of 04h in function 7 is required because the PCI specification does not recognize more than 4 interrupts and older APM-based OSs require that each function within a multi-function device has a different Interrupt Pin Register value. NOTE: Internally the USB EHCI controller uses PIRQ[H]#.
Joseph Smith wrote:
FYI, here is what the ICH4 data sheet says about these 0x3d registers. Looks like the PIRQ is internally specific.
The ICH4 is a southbridge and contains many different PCI devices and legacy devices including the PIC and the PIRQ routing hardware to map the PIRQs to PIC int lines. As such it is not a good place to try and draw inferences from as it has a lot of capabilities not included in a normal PCI device.
Andrew
Joseph Smith wrote:
I wish you could make your internal picture external, so I could see what it is then.
Interrupts are a little complex. I'll try to add some things.
The PCI bus allows each PCI device (by device I mean chip, with a device id, and possibly with several functions) to use at most four interrupt signals. They are called INTA, INTB, INTC and INTD.
Each PCI device is allowed to use (=activate) zero or more of them. Devices with several functions can benefit from using more interrupt signals, because then each function can get it's own interrupt signal, which helps throughput. When multiple bus INTx signals are connected to a device, how the device INTx pins are connected internally in the device to the various functions is described by the mapping in register 3d for each function, as Ron mentioned.
Many devices only generate one interrupt signal, and that will always be INTA on the device. Some generate more than one signal.
The mainboard designer can swizzle interrupt signals between devices, in order to spread out interrupt load so that four devices all signalling on "their" INTA do not have to share the INTA bus signal.
The four PCI bus interrupt signals do not (and should not!) connect to all PCI devices in parallell. The PCI bus INTA may be connected to device 1 INTA, and device 2 INTB. This routing is what irq_tables.c expresses, and unfortunately it cannot be probed. It's really a small part of the mainboard netlist.
There's one device per line in irq_tables.c. How many of the four fields in irq_tables.c which require values depends on how many interrupt signals that are connected to that device.
So much for the PCI bus.
Between the bus and the CPU there's more logic. Different chipsets have different complexity. This is the PIC/XPIC/APIC/IOAPIC. It needs to be configured by firmware to pass on the PCI bus interrupt signals to the CPU, and it can usually map the four bus interrupts onto any of the 16 first CPU interrupts. The original PC had the same PIC which remains today.
The PIC mapping determines which CPU interrupts can be assigned to the devices and have them actually work.
Originally it was hoped that operating systems would do interrupt assignment, but that did not work out. The firmware has to do most if not all of this work with mapping the system and telling devices about which CPU interrupts they are generating.
Register 3c is not really used by hardware, it just stores the interrupt assignment for each device, it is written by the resource allocator and read by the operating system device driver.
There's no connection between register 3c and the PIC mapping either, so the resource allocator has to keep track of the PCI bus as well as the PIC mapping in order to assign working interrupts to devices.
http://tldp.org/LDP/tlk/dd/pci.html has more info about the PCI bus.
I hope this helps. :)
//Peter
Good writeup. Might be worth putting on the wiki!
ron