* Patch to control VGA bus routing and active VGA device.
@ 2005-01-18 3:43 Jon Smirl
2005-01-18 17:46 ` Jesse Barnes
[not found] ` <41ED3BD2.1090105@pobox.com>
0 siblings, 2 replies; 31+ messages in thread
From: Jon Smirl @ 2005-01-18 3:43 UTC (permalink / raw)
To: Alan Cox, Egbert Eich, Linux Kernel Mailing List, Jesse Barnes
[-- Attachment #1: Type: text/plain, Size: 1671 bytes --]
Attached is a patch to control VGA bus routing and the active VGA
device. It works by adding sysfs attributes to bridge and VGA devices.
The bridge attribute is read only and indicates if the bridge is
routing VGA. The attribute on the device has four values:
/* echo these values to the sysfs vga attribute on a VGA device */
enum eEnable {
VGA_DISABLE_THIS = 0, /* If this VGA is enabled, disable it. */
VGA_ENABLE_THIS = 1, /* Disable all VGAs then enable this VGA, mark
as active VGA */
/* Used while resetting a board, board being reset may not be the active VGA */
VGA_DISABLE_ALL = 2, /* Remember active VGA then disable all VGAa and
devices */
VGA_ENABLE_ACTIVE = 3, /* Make sure all VGAs are disabled, then
reenable active VGA */
};
States 2 and 3 are using during a reset cycle. You need to disable the
active VGA, run the reset on the new card, turn it off and then
restore the active one.
I cannot get this code to work. I have a machine with three buses, the
main one, a PCI one and an AGP one. If I turn off routing from one
bridge and turn it on on the other, I cannot get the VGA card to
respond to the IO requests. There must be something more to routing
VGA than what is in this code. The patch is pretty simple so it
shouldn't be too hard to find the problem. I know my machine can route
VGA since vbios.vm86 does it when reseting my secondary cards.
Can any of you PCI/VGA experts tell me what is wrong? Patch is against
current Linus BK.
This code, plus the ROM code already in the kernel, plus a tiny piece
to generate a hotplug event, is enough to let me write a user space
app for secondary card reset.
--
Jon Smirl
jonsmirl@gmail.com
[-- Attachment #2: patch --]
[-- Type: application/octet-stream, Size: 11029 bytes --]
diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
--- a/arch/i386/pci/fixup.c 2005-01-17 22:40:51 -05:00
+++ b/arch/i386/pci/fixup.c 2005-01-17 22:40:51 -05:00
@@ -375,6 +375,6 @@
}
bus = bus->parent;
}
- pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+ pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW | IORESOURCE_VGA_ACTIVE;
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
diff -Nru a/drivers/pci/Kconfig b/drivers/pci/Kconfig
--- a/drivers/pci/Kconfig 2005-01-17 22:40:51 -05:00
+++ b/drivers/pci/Kconfig 2005-01-17 22:40:51 -05:00
@@ -47,3 +47,13 @@
When in doubt, say Y.
+config VGA_CONTROL
+ bool "VGA Control"
+ depends on PCI
+ ---help---
+ Provides sysfs attributes for ensuring that only a single VGA
+ device can be enabled per PCI domain. If a VGA device is removed
+ via hotplug, display is routed to another VGA device if available.
+
+ If you have more than one VGA device, say Y.
+
diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile
--- a/drivers/pci/Makefile 2005-01-17 22:40:51 -05:00
+++ b/drivers/pci/Makefile 2005-01-17 22:40:51 -05:00
@@ -28,6 +28,7 @@
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
obj-$(CONFIG_PCI_MSI) += msi.o
+obj-$(CONFIG_VGA_CONTROL) += vga.o
#
# ACPI Related PCI FW Functions
diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c
--- a/drivers/pci/bus.c 2005-01-17 22:40:51 -05:00
+++ b/drivers/pci/bus.c 2005-01-17 22:40:51 -05:00
@@ -85,6 +85,9 @@
pci_proc_attach_device(dev);
pci_create_sysfs_dev_files(dev);
+#if CONFIG_VGA_CONTROL
+ pci_vga_add_device(dev);
+#endif
}
/**
diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h 2005-01-17 22:40:51 -05:00
+++ b/drivers/pci/pci.h 2005-01-17 22:40:51 -05:00
@@ -11,6 +11,8 @@
void (*alignf)(void *, struct resource *,
unsigned long, unsigned long),
void *alignf_data);
+extern int pci_vga_add_device(struct pci_dev *pdev);
+extern int pci_vga_remove_device(struct pci_dev *pdev);
/* PCI /proc functions */
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c
--- a/drivers/pci/remove.c 2005-01-17 22:40:51 -05:00
+++ b/drivers/pci/remove.c 2005-01-17 22:40:51 -05:00
@@ -26,6 +26,9 @@
static void pci_destroy_dev(struct pci_dev *dev)
{
+#if CONFIG_VGA_CONTROL
+ pci_vga_remove_device(dev);
+#endif
pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
device_unregister(&dev->dev);
diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c 2005-01-17 22:40:51 -05:00
+++ b/drivers/pci/setup-bus.c 2005-01-17 22:40:51 -05:00
@@ -64,7 +64,9 @@
if (class == PCI_CLASS_DISPLAY_VGA ||
class == PCI_CLASS_NOT_DEFINED_VGA)
- bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
+ /* only route to the active VGA, ignore inactive ones */
+ if (dev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE)
+ bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
pdev_sort_resources(dev, &head);
}
diff -Nru a/drivers/pci/vga.c b/drivers/pci/vga.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/pci/vga.c 2005-01-17 22:40:51 -05:00
@@ -0,0 +1,250 @@
+/*
+ * linux/drivers/pci/vga.c
+ *
+ * (C) Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
+ *
+ * VGA control logic for ensuring only a single enabled VGA device
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/pci.h>
+#include <linux/major.h>
+
+static int vga_initialized = 0;
+static struct pci_dev *vga_active = NULL;
+
+static void bridge_yes(struct pci_dev *pdev)
+{
+ struct pci_dev *bridge;
+ struct pci_bus *bus;
+
+ /* Make sure the bridges route to us */
+ bus = pdev->bus;
+ while (bus) {
+ bridge = bus->self;
+ if (bridge) {
+ printk(KERN_DEBUG "bridge_yes %p %s\n", bus, pci_name(bridge));
+ bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
+ }
+ bus = bus->parent;
+ }
+}
+
+static void bridge_no(struct pci_dev *pdev)
+{
+ struct pci_dev *bridge;
+ struct pci_bus *bus;
+
+ /* Make sure the bridges don't route to us */
+ bus = pdev->bus;
+ while (bus) {
+ bridge = bus->self;
+ if (bridge) {
+ printk(KERN_DEBUG "bridge_no %p %s\n", bus, pci_name(bridge));
+ bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA;
+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
+ }
+ bus = bus->parent;
+ }
+}
+
+static void vga_enable(struct pci_dev *pdev, unsigned int enable)
+{
+ printk(KERN_DEBUG "vga_enable: enable %d pdev %p %s\n", enable, pdev, pci_name(pdev));
+
+ bridge_yes(pdev);
+
+ if (enable) {
+ /* this assumes all other potential VGA devices are disabled */
+ outb(0x01 | inb(0x3C3), 0x3C3); /* 0 - enable */
+ outb(0x08 | inb(0x46e8), 0x46e8);
+ outb(0x01 | inb(0x102), 0x102);
+ pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_VGA_ACTIVE;
+ vga_active = pdev;
+ return;
+ }
+
+ outb(~0x01 & inb(0x3C3), 0x3C3);
+ outb(~0x08 & inb(0x46e8), 0x46e8);
+ outb(~0x01 & inb(0x102), 0x102);
+ pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_VGA_ACTIVE;
+ if (pdev == vga_active)
+ vga_active = NULL;
+ bridge_no(pdev);
+}
+
+/* echo these values to the sysfs vga attribute on a VGA device */
+enum eEnable {
+ VGA_DISABLE_THIS = 0, /* If this VGA is enabled, disable it. */
+ VGA_ENABLE_THIS = 1, /* Disable all VGAs then enable this VGA, mark as active VGA */
+ /* Used while resetting a board, board being reset may not be the active VGA */
+ VGA_DISABLE_ALL = 2, /* Remember active VGA then disable all VGAa and devices */
+ VGA_ENABLE_ACTIVE = 3, /* Make sure all VGAs are disabled, then reenable active VGA */
+};
+
+static void set_state(struct pci_dev *pdev, enum eEnable enable)
+{
+ struct pci_dev *pcidev = NULL;
+ unsigned int class;
+
+ printk(KERN_DEBUG "set_state: enable is %d pdev %p %s\n", enable, pdev, pci_name(pdev));
+
+ if (enable == VGA_DISABLE_THIS)
+ if (vga_active != pdev)
+ return;
+
+ vga_enable(vga_active, 0);
+
+ /* loop over all devices and make sure no multiple routings */
+ while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) {
+ class = pcidev->class >> 8;
+
+ if (class == PCI_CLASS_DISPLAY_VGA)
+ bridge_no(pcidev);
+ }
+
+ /* loop over all devices and make sure everyone is disabled */
+ while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) {
+ class = pcidev->class >> 8;
+
+ if (class == PCI_CLASS_DISPLAY_VGA)
+ vga_enable(pcidev, 0);
+ }
+
+ switch (enable) {
+ case VGA_DISABLE_THIS:
+ case VGA_DISABLE_ALL:
+ break;
+
+ /* Mark us active if requested */
+ case VGA_ENABLE_THIS:
+ vga_enable(pdev, 1);
+ break;
+
+ /* Restore active device if requested */
+ case VGA_ENABLE_ACTIVE:
+ vga_enable(vga_active, 1);
+ break;
+ }
+}
+
+/* sysfs store for VGA device */
+static ssize_t vga_device_store(struct device *dev, const char *buf, size_t count)
+{
+ char *last;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ enum eEnable enable;
+
+ /* sysfs strings are terminated by \n */
+ enable = simple_strtoul(buf, &last, 0);
+ if (last == buf)
+ return -EINVAL;
+
+ if ((enable < VGA_DISABLE_THIS) || (enable > VGA_ENABLE_ACTIVE))
+ return -EINVAL;
+
+ set_state(pdev, enable);
+
+ return count;
+}
+
+/* sysfs show for VGA device */
+static ssize_t vga_device_show(struct device *dev, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ return sprintf(buf, "%d\n", (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) != 0);
+}
+
+static struct device_attribute vga_device_attr = __ATTR(vga, S_IRUGO|S_IWUSR, vga_device_show, vga_device_store);
+
+/* sysfs show for VGA routing bridge */
+static ssize_t vga_bridge_show(struct device *dev, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ u16 l;
+
+ /* don't trust the shadow PCI_BRIDGE_CTL_VGA in pdev */
+ /* user space may change hardware without telling the kernel */
+ pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &l);
+ return sprintf(buf, "%d\n", (l & PCI_BRIDGE_CTL_VGA) != 0);
+}
+
+static struct device_attribute vga_bridge_attr = __ATTR(vga, S_IRUGO, vga_bridge_show, NULL);
+
+/* If the device is a VGA or a bridge, add a VGA sysfs attribute */
+int pci_vga_add_device(struct pci_dev *pdev)
+{
+ int class = pdev->class >> 8;
+
+ if (!vga_initialized)
+ return -EACCES;
+
+ if (class == PCI_CLASS_DISPLAY_VGA) {
+ device_create_file(&pdev->dev, &vga_device_attr);
+
+ /* record the active boot device when located */
+ if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE)
+ vga_active = pdev;
+ return 0;
+ }
+
+ if ((class == PCI_CLASS_BRIDGE_PCI) || (class == PCI_CLASS_BRIDGE_CARDBUS)) {
+ device_create_file(&pdev->dev, &vga_bridge_attr);
+ }
+ return 0;
+}
+
+/* If the device is a VGA or a bridge, remove the VGA sysfs attribute */
+int pci_vga_remove_device(struct pci_dev *pdev)
+{
+ struct pci_dev *pcidev = NULL;
+ int class = pdev->class >> 8;
+
+ if (!vga_initialized)
+ return -EACCES;
+
+ if (class == PCI_CLASS_DISPLAY_VGA) {
+ device_remove_file(&pdev->dev, &vga_device_attr);
+
+ /* record the active boot device when located */
+ if (vga_active == pdev) {
+ while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) {
+ class = pcidev->class >> 8;
+ if (class != PCI_CLASS_DISPLAY_VGA)
+ continue;
+ if (pcidev == pdev)
+ continue;
+ set_state(pcidev, VGA_ENABLE_THIS);
+ break;
+ }
+ if (pcidev == NULL)
+ set_state(NULL, VGA_DISABLE_ALL);
+
+ }
+ return 0;
+ }
+
+ if ((class == PCI_CLASS_BRIDGE_PCI) || (class == PCI_CLASS_BRIDGE_CARDBUS))
+ device_remove_file(&pdev->dev, &vga_bridge_attr);
+
+ return 0;
+}
+
+/* Initialize by scanning all devices */
+static int __init vga_init(void)
+{
+ struct pci_dev *pdev = NULL;
+
+ vga_initialized = 1;
+
+ while ((pdev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
+ pci_vga_add_device(pdev);
+
+ return 0;
+}
+
+__initcall(vga_init);
+
diff -Nru a/include/linux/ioport.h b/include/linux/ioport.h
--- a/include/linux/ioport.h 2005-01-17 22:40:51 -05:00
+++ b/include/linux/ioport.h 2005-01-17 22:40:51 -05:00
@@ -41,7 +41,6 @@
#define IORESOURCE_CACHEABLE 0x00004000
#define IORESOURCE_RANGELENGTH 0x00008000
#define IORESOURCE_SHADOWABLE 0x00010000
-#define IORESOURCE_BUS_HAS_VGA 0x00080000
#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
@@ -86,6 +85,7 @@
#define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
#define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */
+#define IORESOURCE_VGA_ACTIVE (1<<3) /* VGA device is active */
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource;
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Patch to control VGA bus routing and active VGA device. 2005-01-18 3:43 Patch to control VGA bus routing and active VGA device Jon Smirl @ 2005-01-18 17:46 ` Jesse Barnes 2005-01-18 19:38 ` H. Peter Anvin [not found] ` <41ED3BD2.1090105@pobox.com> 1 sibling, 1 reply; 31+ messages in thread From: Jesse Barnes @ 2005-01-18 17:46 UTC (permalink / raw) To: Jon Smirl; +Cc: Alan Cox, Egbert Eich, Linux Kernel Mailing List On Monday, January 17, 2005 7:43 pm, Jon Smirl wrote: > Attached is a patch to control VGA bus routing and the active VGA > device. It works by adding sysfs attributes to bridge and VGA devices. > The bridge attribute is read only and indicates if the bridge is > routing VGA. The attribute on the device has four values: How is it supposed to work? Is VGA routing determined by the chipset? Is it separate from other legacy I/O and memory addresses? Thanks, Jesse P.S. Can you fix your mailer to set a mimetype other than "unspecified binary data" for patches to make them easier to read? ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Patch to control VGA bus routing and active VGA device. 2005-01-18 17:46 ` Jesse Barnes @ 2005-01-18 19:38 ` H. Peter Anvin 2005-01-18 21:06 ` Jesse Barnes 0 siblings, 1 reply; 31+ messages in thread From: H. Peter Anvin @ 2005-01-18 19:38 UTC (permalink / raw) To: linux-kernel Followup to: <200501180946.47026.jbarnes@engr.sgi.com> By author: Jesse Barnes <jbarnes@engr.sgi.com> In newsgroup: linux.dev.kernel > > On Monday, January 17, 2005 7:43 pm, Jon Smirl wrote: > > Attached is a patch to control VGA bus routing and the active VGA > > device. It works by adding sysfs attributes to bridge and VGA devices. > > The bridge attribute is read only and indicates if the bridge is > > routing VGA. The attribute on the device has four values: > > How is it supposed to work? Is VGA routing determined by the chipset? Is it > separate from other legacy I/O and memory addresses? > Yes, there are special control bits in any PCI bridge header for the VGA ports. -hpa ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Patch to control VGA bus routing and active VGA device. 2005-01-18 19:38 ` H. Peter Anvin @ 2005-01-18 21:06 ` Jesse Barnes 2005-01-22 19:04 ` Jon Smirl 0 siblings, 1 reply; 31+ messages in thread From: Jesse Barnes @ 2005-01-18 21:06 UTC (permalink / raw) To: H.Peter Anvin; +Cc: linux-kernel On Tuesday, January 18, 2005 11:38 am, H. Peter Anvin wrote: > > On Monday, January 17, 2005 7:43 pm, Jon Smirl wrote: > > > Attached is a patch to control VGA bus routing and the active VGA > > > device. It works by adding sysfs attributes to bridge and VGA devices. > > > The bridge attribute is read only and indicates if the bridge is > > > routing VGA. The attribute on the device has four values: > > > > How is it supposed to work? Is VGA routing determined by the chipset? > > Is it separate from other legacy I/O and memory addresses? > > Yes, there are special control bits in any PCI bridge header for the > VGA ports. Well, not all of them, which is why I asked. Though obviously this patch will need some very platform specific bits at any rate. Jesse ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Patch to control VGA bus routing and active VGA device. 2005-01-18 21:06 ` Jesse Barnes @ 2005-01-22 19:04 ` Jon Smirl 2005-01-24 17:25 ` Jesse Barnes 0 siblings, 1 reply; 31+ messages in thread From: Jon Smirl @ 2005-01-22 19:04 UTC (permalink / raw) To: Jesse Barnes; +Cc: H.Peter Anvin, linux-kernel On Tue, 18 Jan 2005 13:06:03 -0800, Jesse Barnes <jbarnes@engr.sgi.com> wrote: > On Tuesday, January 18, 2005 11:38 am, H. Peter Anvin wrote: > > > On Monday, January 17, 2005 7:43 pm, Jon Smirl wrote: > > > > Attached is a patch to control VGA bus routing and the active VGA > > > > device. It works by adding sysfs attributes to bridge and VGA devices. > > > > The bridge attribute is read only and indicates if the bridge is > > > > routing VGA. The attribute on the device has four values: > > > > > > How is it supposed to work? Is VGA routing determined by the chipset? > > > Is it separate from other legacy I/O and memory addresses? > > > > Yes, there are special control bits in any PCI bridge header for the > > VGA ports. > > Well, not all of them, which is why I asked. Though obviously this patch will > need some very platform specific bits at any rate. What is a case of where the VGA forwarding bit isn't in the bridge control? It's part of the PCI spec to have it. There are two components to this, bus routing and card control. When each VGA device is on it's own bus the card specific control code isn't required. Instead you can control the active VGA by shutting down the bus routing. It's only when you have multiple cards on the same bus that you need the card specific control. But the point of this code is to allow reset of secondary cards. After resetting a secondary card it will be left as the active VGA device instead of the boot one. This moves your console from screen to screen. Instead I want to remember the active device, run reset, and then restore the original console. In my machine I have one PCI and one AGP card. Bus routing is sufficient to choose between the two. Opteron systems with AGP cards on local buses can also use this code. Another example is where the primary VGA device is on AGP and there are multiple PCI cards. You just want all of the PCI VGA devices turned off. We ultimately need both pieces of code, VGA bus routing, and card specific VGA enabling code. Even without the card specific code the routing code is still useful. -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Patch to control VGA bus routing and active VGA device. 2005-01-22 19:04 ` Jon Smirl @ 2005-01-24 17:25 ` Jesse Barnes 2005-01-24 17:53 ` Jesse Barnes 0 siblings, 1 reply; 31+ messages in thread From: Jesse Barnes @ 2005-01-24 17:25 UTC (permalink / raw) To: Jon Smirl; +Cc: H.Peter Anvin, linux-kernel On Saturday, January 22, 2005 11:04 am, Jon Smirl wrote: > > Well, not all of them, which is why I asked. Though obviously this patch > > will need some very platform specific bits at any rate. > > What is a case of where the VGA forwarding bit isn't in the bridge > control? It's part of the PCI spec to have it. Hmm... lemme check my specs. It doesn't look like we support that aspect of the PCI spec in our bridges. > We ultimately need both pieces of code, VGA bus routing, and card > specific VGA enabling code. Even without the card specific code the > routing code is still useful. Oh right, doing card specific up/down will allow multiple cards to share the same bus, which would be nice. Jesse ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Patch to control VGA bus routing and active VGA device. 2005-01-24 17:25 ` Jesse Barnes @ 2005-01-24 17:53 ` Jesse Barnes 0 siblings, 0 replies; 31+ messages in thread From: Jesse Barnes @ 2005-01-24 17:53 UTC (permalink / raw) To: Jon Smirl; +Cc: H.Peter Anvin, linux-kernel On Monday, January 24, 2005 9:25 am, Jesse Barnes wrote: > On Saturday, January 22, 2005 11:04 am, Jon Smirl wrote: > > > Well, not all of them, which is why I asked. Though obviously this > > > patch will need some very platform specific bits at any rate. > > > > What is a case of where the VGA forwarding bit isn't in the bridge > > control? It's part of the PCI spec to have it. > > Hmm... lemme check my specs. It doesn't look like we support that aspect > of the PCI spec in our bridges. Btw, I don't think this is the only chipset that doesn't support the VGA routing bit, so new code shouldn't assume that it's ok to access VGA ports w/o an offset based on the PCI bus the device is on. Jesse ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <41ED3BD2.1090105@pobox.com>]
[parent not found: <9e473391050122083822a7f81c@mail.gmail.com>]
[parent not found: <200501240847.51208.jbarnes@sgi.com>]
[parent not found: <20050124175131.GM31455@parcelfarce.linux.theplanet.co.uk>]
* Re: Fwd: Patch to control VGA bus routing and active VGA device. [not found] ` <20050124175131.GM31455@parcelfarce.linux.theplanet.co.uk> @ 2005-01-24 19:17 ` Jon Smirl 2005-01-24 19:42 ` Jeff Garzik 2005-01-24 20:22 ` Matthew Wilcox 0 siblings, 2 replies; 31+ messages in thread From: Jon Smirl @ 2005-01-24 19:17 UTC (permalink / raw) To: Matthew Wilcox; +Cc: Jesse Barnes, Jeff Garzik, linux-pci, lkml On Mon, 24 Jan 2005 17:51:31 +0000, Matthew Wilcox <matthew@wil.cx> wrote: > Yes -- *very* platform specific. Some are even configurable as to how > much they support. See http://ftp.parisc-linux.org/docs/chips/zx1-mio.pdf Is this a justification for doing device drivers for bridge chips? It has been mentioned before but no one has done it. Any ideas why the code I sent won't work on the x86? I can shut routing off but I can't get it back on again. The motivation behind the code is to get X to quit doing this from user space. -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-24 19:17 ` Fwd: " Jon Smirl @ 2005-01-24 19:42 ` Jeff Garzik 2005-01-24 19:55 ` Russell King 2005-01-24 20:14 ` Matthew Wilcox 2005-01-24 20:22 ` Matthew Wilcox 1 sibling, 2 replies; 31+ messages in thread From: Jeff Garzik @ 2005-01-24 19:42 UTC (permalink / raw) To: Jon Smirl; +Cc: Matthew Wilcox, Jesse Barnes, linux-pci, lkml Jon Smirl wrote: > Is this a justification for doing device drivers for bridge chips? It > has been mentioned before but no one has done it. Yeah, people are usually slack and work around the problem. A bridge driver is really wanted for several situations in today's hardware... Jeff ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-24 19:42 ` Jeff Garzik @ 2005-01-24 19:55 ` Russell King 2005-01-24 23:11 ` Jon Smirl 2005-01-25 4:24 ` Greg KH 2005-01-24 20:14 ` Matthew Wilcox 1 sibling, 2 replies; 31+ messages in thread From: Russell King @ 2005-01-24 19:55 UTC (permalink / raw) To: Jeff Garzik; +Cc: Jon Smirl, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Mon, Jan 24, 2005 at 02:42:57PM -0500, Jeff Garzik wrote: > Jon Smirl wrote: > > Is this a justification for doing device drivers for bridge chips? It > > has been mentioned before but no one has done it. > > > Yeah, people are usually slack and work around the problem. > > A bridge driver is really wanted for several situations in today's > hardware... There's a very good reason not to have a bridge driver at the moment - some PCI to PCI bridges need special drivers. Currently, as the device model stands today, we can only have ONE PCI to PCI bridge driver for all P2P bridges, which is bad news if you need a specific driver for, eg, a mobility docking station P2P bridge. As I said back in 2002, the device model needs a way to have driver priories - how well a driver matches the hardware. My idea was for the bus match function to return the "goodness" factor of the match. For PCI, matching on just the class IDs would be low goodness, but an exact match with both the vendor and device IDs would yeild a good match. When the device model has a driver or device added, it scans all current devices or drivers (respectively) and chooses the best matched pair. If the device already has an existing driver, it calls the ->remove method to unbind the current device driver relationship before handing it over to the more specific driver. Unfortunately, I never got around to writing the mobility P2P bridge driver because I didn't see much chance of this idea being adopted. However, if we're going to start having generic drivers for such hardware, this kind of functionality needs to be thought about. -- Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/ 2.6 Serial core ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-24 19:55 ` Russell King @ 2005-01-24 23:11 ` Jon Smirl 2005-01-25 4:24 ` Greg KH 1 sibling, 0 replies; 31+ messages in thread From: Jon Smirl @ 2005-01-24 23:11 UTC (permalink / raw) To: Jeff Garzik, Jon Smirl, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Mon, 24 Jan 2005 19:55:23 +0000, Russell King <rmk+lkml@arm.linux.org.uk> wrote: > There's a very good reason not to have a bridge driver at the moment - > some PCI to PCI bridges need special drivers. Currently, as the device > model stands today, we can only have ONE PCI to PCI bridge driver for > all P2P bridges, which is bad news if you need a specific driver for, > eg, a mobility docking station P2P bridge. There is no requirement that the bridge driver be generic code. I agree that it is simpler but there is nothing stopping a "generic" driver from just having PCI IDs for all of the existing bridges built into it and then load it like a normal driver. Loading all of the bridge PCI IDs into the "generic" driver gets rid of the need for driver priorities. -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-24 19:55 ` Russell King 2005-01-24 23:11 ` Jon Smirl @ 2005-01-25 4:24 ` Greg KH 2005-01-27 9:59 ` Jon Smirl 2005-01-30 7:51 ` Jon Smirl 1 sibling, 2 replies; 31+ messages in thread From: Greg KH @ 2005-01-25 4:24 UTC (permalink / raw) To: Russell King Cc: Jeff Garzik, Jon Smirl, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Mon, Jan 24, 2005 at 07:55:23PM +0000, Russell King wrote: > On Mon, Jan 24, 2005 at 02:42:57PM -0500, Jeff Garzik wrote: > > Jon Smirl wrote: > > > Is this a justification for doing device drivers for bridge chips? It > > > has been mentioned before but no one has done it. > > > > > > Yeah, people are usually slack and work around the problem. > > > > A bridge driver is really wanted for several situations in today's > > hardware... > > There's a very good reason not to have a bridge driver at the moment - > some PCI to PCI bridges need special drivers. Currently, as the device > model stands today, we can only have ONE PCI to PCI bridge driver for > all P2P bridges, which is bad news if you need a specific driver for, > eg, a mobility docking station P2P bridge. > > As I said back in 2002, the device model needs a way to have driver > priories - how well a driver matches the hardware. > > My idea was for the bus match function to return the "goodness" > factor of the match. For PCI, matching on just the class IDs would > be low goodness, but an exact match with both the vendor and device > IDs would yeild a good match. This can be done today in the bus specific match functions. And because of that, I would argue that this belongs in the bus specific code, and not in the driver core, as it's up to the bus to know what the different types of "matches" that can happen, and what the priority is. And yes, I agree that this needs to be done, I've been talking with a few other people who are interested in it. I think the lock-rework code needs to be finished before it can happen properly, so that we can do the "unbind from one driver and give it to another one" type logic properly. thanks, greg k-h ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-25 4:24 ` Greg KH @ 2005-01-27 9:59 ` Jon Smirl 2005-01-27 16:28 ` Jesse Barnes 2005-02-01 6:38 ` Greg KH 2005-01-30 7:51 ` Jon Smirl 1 sibling, 2 replies; 31+ messages in thread From: Jon Smirl @ 2005-01-27 9:59 UTC (permalink / raw) To: Greg KH Cc: Russell King, Jeff Garzik, Matthew Wilcox, Jesse Barnes, linux-pci, lkml [-- Attachment #1: Type: text/plain, Size: 1214 bytes --] On Mon, 24 Jan 2005 20:24:59 -0800, Greg KH <greg@kroah.com> wrote: > This can be done today in the bus specific match functions. And because > of that, I would argue that this belongs in the bus specific code, and > not in the driver core, as it's up to the bus to know what the different > types of "matches" that can happen, and what the priority is. Here's a version of the VGA control code that actually works. It helps if I pci_enable() the device before using it. There was nothing wrong with the routing code. I can also control multiple cards on the same bus by turning on/off their response to IO space and then enabling VGA via the standard ports. I can use this to move my console from card to card. I have this code in drivers/pci because it needs to know add/remove from hotplug. Is there a better way to structure it? Note that this is not a VGA device, it is just a mechanism for controlling which VGA device is active. Another item I need to add is generating an initial hotplug event for each secondary card. This event has to happen even if there is a card specific driver loaded. The event will be used to run the reset program needed by secondary cards. -- Jon Smirl jonsmirl@gmail.com [-- Attachment #2: patch --] [-- Type: application/octet-stream, Size: 11001 bytes --] diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c --- a/arch/i386/pci/fixup.c 2005-01-27 04:01:08 -05:00 +++ b/arch/i386/pci/fixup.c 2005-01-27 04:01:08 -05:00 @@ -375,6 +375,6 @@ } bus = bus->parent; } - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW | IORESOURCE_VGA_ACTIVE; } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); diff -Nru a/drivers/pci/Kconfig b/drivers/pci/Kconfig --- a/drivers/pci/Kconfig 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/Kconfig 2005-01-27 04:01:08 -05:00 @@ -47,3 +47,13 @@ When in doubt, say Y. +config VGA_CONTROL + bool "VGA Control" + depends on PCI + ---help--- + Provides sysfs attributes for ensuring that only a single VGA + device can be enabled per PCI domain. If a VGA device is removed + via hotplug, display is routed to another VGA device if available. + + If you have more than one VGA device, say Y. + diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/Makefile 2005-01-27 04:01:08 -05:00 @@ -28,6 +28,7 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_PCI_MSI) += msi.o +obj-$(CONFIG_VGA_CONTROL) += vga.o # # ACPI Related PCI FW Functions diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c --- a/drivers/pci/bus.c 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/bus.c 2005-01-27 04:01:08 -05:00 @@ -85,6 +85,9 @@ pci_proc_attach_device(dev); pci_create_sysfs_dev_files(dev); +#if CONFIG_VGA_CONTROL + pci_vga_add_device(dev); +#endif } /** diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h --- a/drivers/pci/pci.h 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/pci.h 2005-01-27 04:01:08 -05:00 @@ -11,6 +11,8 @@ void (*alignf)(void *, struct resource *, unsigned long, unsigned long), void *alignf_data); +extern int pci_vga_add_device(struct pci_dev *pdev); +extern int pci_vga_remove_device(struct pci_dev *pdev); /* PCI /proc functions */ #ifdef CONFIG_PROC_FS extern int pci_proc_attach_device(struct pci_dev *dev); diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c --- a/drivers/pci/remove.c 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/remove.c 2005-01-27 04:01:08 -05:00 @@ -26,6 +26,9 @@ static void pci_destroy_dev(struct pci_dev *dev) { +#if CONFIG_VGA_CONTROL + pci_vga_remove_device(dev); +#endif pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); device_unregister(&dev->dev); diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/setup-bus.c 2005-01-27 04:01:08 -05:00 @@ -64,7 +64,9 @@ if (class == PCI_CLASS_DISPLAY_VGA || class == PCI_CLASS_NOT_DEFINED_VGA) - bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; + /* only route to the active VGA, ignore inactive ones */ + if (dev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) + bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; pdev_sort_resources(dev, &head); } diff -Nru a/drivers/pci/vga.c b/drivers/pci/vga.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/pci/vga.c 2005-01-27 04:01:08 -05:00 @@ -0,0 +1,254 @@ +/* + * linux/drivers/pci/vga.c + * + * (C) Copyright 2004 Jon Smirl <jonsmirl@gmail.com> + * + * VGA control logic for ensuring only a single enabled VGA device + */ + +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/pci.h> +#include <linux/major.h> + +static int vga_initialized = 0; +static struct pci_dev *vga_active = NULL; + +static void bridge_yes(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + + /* Make sure the bridges route to us */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); + } + bus = bus->parent; + } +} + +static void bridge_no(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + + /* Make sure the bridges don't route to us */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); + } + bus = bus->parent; + } +} + +static void vga_enable(struct pci_dev *pdev, unsigned int enable) +{ + u16 command; + + bridge_yes(pdev); + + if (enable) { + pci_enable_device(pdev); + /* this assumes all other potential VGA devices are disabled */ + outb(0x01 | inb(0x3C3), 0x3C3); /* 0 - enable */ + outb(0x08 | inb(0x46e8), 0x46e8); + outb(0x01 | inb(0x102), 0x102); + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_VGA_ACTIVE; + vga_active = pdev; + + /* return and leave the card enabled */ + return; + } + + pci_read_config_word(pdev, PCI_COMMAND, &command); + pci_write_config_word(pdev, PCI_COMMAND, command | PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + + outb(~0x01 & inb(0x3C3), 0x3C3); + outb(~0x08 & inb(0x46e8), 0x46e8); + outb(~0x01 & inb(0x102), 0x102); + pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_VGA_ACTIVE; + if (pdev == vga_active) + vga_active = NULL; + bridge_no(pdev); + + pci_write_config_word(pdev, PCI_COMMAND, command); +} + +/* echo these values to the sysfs vga attribute on a VGA device */ +enum eEnable { + VGA_DISABLE_THIS = 0, /* If this VGA is enabled, disable it. */ + VGA_ENABLE_THIS = 1, /* Disable all VGAs then enable this VGA, mark as active VGA */ + /* Used while resetting a board, board being reset may not be the active VGA */ + VGA_DISABLE_ALL = 2, /* Remember active VGA then disable all VGAa and devices */ + VGA_ENABLE_ACTIVE = 3, /* Make sure all VGAs are disabled, then reenable active VGA */ +}; + +static void set_state(struct pci_dev *pdev, enum eEnable enable) +{ + struct pci_dev *pcidev = NULL; + unsigned int class; + + if (enable == VGA_DISABLE_THIS) + if (vga_active != pdev) + return; + + vga_enable(vga_active, 0); + + /* loop over all devices and make sure no multiple routings */ + while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) { + class = pcidev->class >> 8; + + if (class == PCI_CLASS_DISPLAY_VGA) + bridge_no(pcidev); + } + + /* loop over all devices and make sure everyone is disabled */ + while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) { + class = pcidev->class >> 8; + + if (class == PCI_CLASS_DISPLAY_VGA) + vga_enable(pcidev, 0); + } + + switch (enable) { + case VGA_DISABLE_THIS: + case VGA_DISABLE_ALL: + break; + + /* Mark us active if requested */ + case VGA_ENABLE_THIS: + vga_enable(pdev, 1); + break; + + /* Restore active device if requested */ + case VGA_ENABLE_ACTIVE: + vga_enable(vga_active, 1); + break; + } +} + +/* sysfs store for VGA device */ +static ssize_t vga_device_store(struct device *dev, const char *buf, size_t count) +{ + char *last; + struct pci_dev *pdev = to_pci_dev(dev); + enum eEnable enable; + + /* sysfs strings are terminated by \n */ + enable = simple_strtoul(buf, &last, 0); + if (last == buf) + return -EINVAL; + + if ((enable < VGA_DISABLE_THIS) || (enable > VGA_ENABLE_ACTIVE)) + return -EINVAL; + + set_state(pdev, enable); + + return count; +} + +/* sysfs show for VGA device */ +static ssize_t vga_device_show(struct device *dev, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + return sprintf(buf, "%d\n", (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) != 0); +} + +static struct device_attribute vga_device_attr = __ATTR(vga, S_IRUGO|S_IWUSR, vga_device_show, vga_device_store); + +/* sysfs show for VGA routing bridge */ +static ssize_t vga_bridge_show(struct device *dev, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + u16 l; + + /* don't trust the shadow PCI_BRIDGE_CTL_VGA in pdev */ + /* user space may change hardware without telling the kernel */ + pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &l); + return sprintf(buf, "%d\n", (l & PCI_BRIDGE_CTL_VGA) != 0); +} + +static struct device_attribute vga_bridge_attr = __ATTR(vga, S_IRUGO, vga_bridge_show, NULL); + +/* If the device is a VGA or a bridge, add a VGA sysfs attribute */ +int pci_vga_add_device(struct pci_dev *pdev) +{ + int class = pdev->class >> 8; + + if (!vga_initialized) + return -EACCES; + + if (class == PCI_CLASS_DISPLAY_VGA) { + device_create_file(&pdev->dev, &vga_device_attr); + + /* record the active boot device when located */ + if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) + vga_active = pdev; + return 0; + } + + if ((class == PCI_CLASS_BRIDGE_PCI) || (class == PCI_CLASS_BRIDGE_CARDBUS)) { + device_create_file(&pdev->dev, &vga_bridge_attr); + } + return 0; +} + +/* If the device is a VGA or a bridge, remove the VGA sysfs attribute */ +int pci_vga_remove_device(struct pci_dev *pdev) +{ + struct pci_dev *pcidev = NULL; + int class = pdev->class >> 8; + + if (!vga_initialized) + return -EACCES; + + if (class == PCI_CLASS_DISPLAY_VGA) { + device_remove_file(&pdev->dev, &vga_device_attr); + + /* record the active boot device when located */ + if (vga_active == pdev) { + while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) { + class = pcidev->class >> 8; + if (class != PCI_CLASS_DISPLAY_VGA) + continue; + if (pcidev == pdev) + continue; + set_state(pcidev, VGA_ENABLE_THIS); + break; + } + if (pcidev == NULL) + set_state(NULL, VGA_DISABLE_ALL); + + } + return 0; + } + + if ((class == PCI_CLASS_BRIDGE_PCI) || (class == PCI_CLASS_BRIDGE_CARDBUS)) + device_remove_file(&pdev->dev, &vga_bridge_attr); + + return 0; +} + +/* Initialize by scanning all devices */ +static int __init vga_init(void) +{ + struct pci_dev *pdev = NULL; + + vga_initialized = 1; + + while ((pdev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) + pci_vga_add_device(pdev); + + return 0; +} + +__initcall(vga_init); + diff -Nru a/include/linux/ioport.h b/include/linux/ioport.h --- a/include/linux/ioport.h 2005-01-27 04:01:08 -05:00 +++ b/include/linux/ioport.h 2005-01-27 04:01:08 -05:00 @@ -41,7 +41,6 @@ #define IORESOURCE_CACHEABLE 0x00004000 #define IORESOURCE_RANGELENGTH 0x00008000 #define IORESOURCE_SHADOWABLE 0x00010000 -#define IORESOURCE_BUS_HAS_VGA 0x00080000 #define IORESOURCE_DISABLED 0x10000000 #define IORESOURCE_UNSET 0x20000000 @@ -86,6 +85,7 @@ #define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ #define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ #define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ +#define IORESOURCE_VGA_ACTIVE (1<<3) /* VGA device is active */ /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ extern struct resource ioport_resource; ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-27 9:59 ` Jon Smirl @ 2005-01-27 16:28 ` Jesse Barnes 2005-01-28 17:32 ` Grant Grundler 2005-02-01 6:38 ` Greg KH 1 sibling, 1 reply; 31+ messages in thread From: Jesse Barnes @ 2005-01-27 16:28 UTC (permalink / raw) To: Jon Smirl Cc: Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Thursday, January 27, 2005 1:59 am, Jon Smirl wrote: > Another item I need to add is generating an initial hotplug event for > each secondary card. This event has to happen even if there is a card > specific driver loaded. The event will be used to run the reset > program needed by secondary cards. Makes sense, having hotplug events would be nice. I've got a standalone bios emulator (based on the X int10 library) that I hope to open source soon, we could use that as a starting piont for the reset app. +static void vga_enable(struct pci_dev *pdev, unsigned int enable) ... + outb(~0x01 & inb(0x3C3), 0x3C3); + outb(~0x08 & inb(0x46e8), 0x46e8); + outb(~0x01 & inb(0x102), 0x102); + pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_VGA_ACTIVE; + if (pdev == vga_active) + vga_active = NULL; + bridge_no(pdev); Those ins and outs won't work on all platforms unless they have a base address (assigned by arch code) associated with them. But then again, I suppose if a platform supports more than one legacy I/O space, it also supports multiple active VGAs, so maybe this enable/disable code isn't needed for them... Jesse ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-27 16:28 ` Jesse Barnes @ 2005-01-28 17:32 ` Grant Grundler 2005-01-28 18:36 ` Jon Smirl 2005-01-28 18:41 ` Jesse Barnes 0 siblings, 2 replies; 31+ messages in thread From: Grant Grundler @ 2005-01-28 17:32 UTC (permalink / raw) To: Jesse Barnes Cc: Jon Smirl, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Thu, Jan 27, 2005 at 08:28:43AM -0800, Jesse Barnes wrote: > But then again, > I suppose if a platform supports more than one legacy I/O space, Eh?! there can only be *one* legacy I/O space. We can support multipl IO port spaces, but only one can be the "legacy". Moving the VGA device can only function within that legacy space the way the code is written now (using hard coded addresses). If it is intended to work with multiple IO Port address spaces, then it needs to use the pci_dev->resource[] and mangle that appropriately. grant ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 17:32 ` Grant Grundler @ 2005-01-28 18:36 ` Jon Smirl 2005-01-28 19:15 ` Grant Grundler 2005-01-28 18:41 ` Jesse Barnes 1 sibling, 1 reply; 31+ messages in thread From: Jon Smirl @ 2005-01-28 18:36 UTC (permalink / raw) To: Grant Grundler Cc: Jesse Barnes, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Fri, 28 Jan 2005 10:32:22 -0700, Grant Grundler <grundler@parisc-linux.org> wrote: > Moving the VGA device can only function within that legacy space > the way the code is written now (using hard coded addresses). > If it is intended to work with multiple IO Port address spaces, > then it needs to use the pci_dev->resource[] and mangle that appropriately. Post a patch an I will incorporate it. -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 18:36 ` Jon Smirl @ 2005-01-28 19:15 ` Grant Grundler 2005-01-28 19:26 ` Jon Smirl 0 siblings, 1 reply; 31+ messages in thread From: Grant Grundler @ 2005-01-28 19:15 UTC (permalink / raw) To: Jon Smirl Cc: Grant Grundler, Jesse Barnes, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Fri, Jan 28, 2005 at 01:36:48PM -0500, Jon Smirl wrote: > > If it is intended to work with multiple IO Port address spaces, > > then it needs to use the pci_dev->resource[] and mangle that appropriately. > > Post a patch an I will incorporate it. Sorry - I only wanted to point out the short coming. I don't care if it gets fixed (or not) since I don't use or need to support multiple VGA cards. If someone else (in HP) does, it's just nice to warn them what's broken. thanks, grant ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 19:15 ` Grant Grundler @ 2005-01-28 19:26 ` Jon Smirl 2005-01-28 19:34 ` Grant Grundler 0 siblings, 1 reply; 31+ messages in thread From: Jon Smirl @ 2005-01-28 19:26 UTC (permalink / raw) To: Grant Grundler Cc: Jesse Barnes, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Fri, 28 Jan 2005 12:15:49 -0700, Grant Grundler <grundler@parisc-linux.org> wrote: > I don't care if it gets fixed (or not) since I don't use > or need to support multiple VGA cards. If someone else (in Next year we are going to see a lot of multiple VGAs. Depending on configuration the Nvidia4 chipset can support from one up to eight PCI Express video cards simultaneously. I would like to get this fixed in the kernel so that apps like X won't do it from user space. Every time X does a read/alter/write to PCI config space from user space is a place where bad things can happen. The goal of this is to remove the PCI bus probing code from X. -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 19:26 ` Jon Smirl @ 2005-01-28 19:34 ` Grant Grundler 0 siblings, 0 replies; 31+ messages in thread From: Grant Grundler @ 2005-01-28 19:34 UTC (permalink / raw) To: Jon Smirl Cc: Grant Grundler, Jesse Barnes, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Fri, Jan 28, 2005 at 02:26:40PM -0500, Jon Smirl wrote: > Next year we are going to see a lot of multiple VGAs. Depending on > configuration the Nvidia4 chipset can support from one up to eight PCI > Express video cards simultaneously. Oh geez....someone is going to implement IO port space on PCI express device?! /me gets out the cluebat... grant ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 17:32 ` Grant Grundler 2005-01-28 18:36 ` Jon Smirl @ 2005-01-28 18:41 ` Jesse Barnes 2005-01-28 19:33 ` Grant Grundler 1 sibling, 1 reply; 31+ messages in thread From: Jesse Barnes @ 2005-01-28 18:41 UTC (permalink / raw) To: Grant Grundler Cc: Jon Smirl, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Friday, January 28, 2005 9:32 am, Grant Grundler wrote: > On Thu, Jan 27, 2005 at 08:28:43AM -0800, Jesse Barnes wrote: > > But then again, > > I suppose if a platform supports more than one legacy I/O space, > > Eh?! there can only be *one* legacy I/O space. > We can support multipl IO port spaces, but only one can be the "legacy". What do you mean? If you define legacy I/O space to be 0x0000000000000000-0x000000000000ffff, then yes of course you're right. But if you mean being able to access legacy ports at all, then no. On SGI machines, there's a per-bus base address that can be used as the base for port I/O, which is what I was getting at. > Moving the VGA device can only function within that legacy space > the way the code is written now (using hard coded addresses). > If it is intended to work with multiple IO Port address spaces, > then it needs to use the pci_dev->resource[] and mangle that appropriately. There is no resource for some of the I/O port space that cards respond to. I can set the I/O BAR of my VGA card to 0x400 and it'll still respond to accesses at 0x3bc for example. That's what I mean by legacy space--space that cards respond to but don't report in their PCI resources. Jesse ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 18:41 ` Jesse Barnes @ 2005-01-28 19:33 ` Grant Grundler 2005-01-28 19:41 ` Jesse Barnes 2005-01-28 20:00 ` Matthew Wilcox 0 siblings, 2 replies; 31+ messages in thread From: Grant Grundler @ 2005-01-28 19:33 UTC (permalink / raw) To: Jesse Barnes Cc: Grant Grundler, Jon Smirl, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Fri, Jan 28, 2005 at 10:41:41AM -0800, Jesse Barnes wrote: > > Eh?! there can only be *one* legacy I/O space. > > We can support multipl IO port spaces, but only one can be the "legacy". > > What do you mean? If you define legacy I/O space to be > 0x0000000000000000-0x000000000000ffff, then yes of course you're right. Yes - exactly. > But > if you mean being able to access legacy ports at all, then no. On SGI > machines, there's a per-bus base address that can be used as the base for > port I/O, which is what I was getting at. Ok - my point was "0x3fc" will get routed to exactly one of those IO port address spaces. > > If it is intended to work with multiple IO Port address spaces, > > then it needs to use the pci_dev->resource[] and mangle that appropriately. > > There is no resource for some of the I/O port space that cards respond to. Yes - I've heard several graphics cards are horrible broken WRT address decoding. Are PCI quirks supposed to handle that sort of thing? Another example was Xf86 was poking around in MMIO space to determine if such broken cards are installed. > I can set the I/O BAR of my VGA card to 0x400 and it'll still respond to > accesses at 0x3bc for example. That's what I mean by legacy space--space > that cards respond to but don't report in their PCI resources. Can't PCI quirks fix up the resources to reflect this? I think one needs to fix up PCI IO Port resources to adjust for "The One" legacy IO port space getting routed to a different PCI segment - assuming no one submits a patch to change current behavior of using hard coded addresses. HP parisc and ia64 platforms implement seperate PCI segments under each PCI host bus controller. Linux PCI "BIOS" support provides the illusion it's all in one PCI segment on most (not all) platforms. Some HP chipsets also provide a "Legacy" IO Port space that gets routed to a chosen PCI Host bus controller. parisc PCI BIOS adds the controller instance number to the IO port space resource to help "inb()" generate the IO port cycle on the right PCI segment. This needs to be fixed up if we decide a different PCI segment should be segment 0 (and thus get references to 0x3fc). I expect other arches with multi-segment support to do similar fix ups. Am I making more sense now? thanks, grant ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 19:33 ` Grant Grundler @ 2005-01-28 19:41 ` Jesse Barnes 2005-01-28 20:12 ` Grant Grundler 2005-01-28 20:00 ` Matthew Wilcox 1 sibling, 1 reply; 31+ messages in thread From: Jesse Barnes @ 2005-01-28 19:41 UTC (permalink / raw) To: Grant Grundler Cc: Jon Smirl, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Friday, January 28, 2005 11:33 am, Grant Grundler wrote: > > But > > if you mean being able to access legacy ports at all, then no. On SGI > > machines, there's a per-bus base address that can be used as the base for > > port I/O, which is what I was getting at. > > Ok - my point was "0x3fc" will get routed to exactly one of those > IO port address spaces. Agreed, or it will cause a machine check if legacy I/O remapping isn't supported (like on SGI). > > There is no resource for some of the I/O port space that cards respond > > to. > > Yes - I've heard several graphics cards are horrible broken WRT address > decoding. Are PCI quirks supposed to handle that sort of thing? I'm not sure if broken is the right work. All this stuff predates PCI by quite a bit, so certain device classes claimed certain port ranges way before cards were required to have programmable address decoders. VGA cards are probably the most tenacious example of this, they respond to certain well known ports after reset, regardless of BAR values. > > I can set the I/O BAR of my VGA card to 0x400 and it'll still respond to > > accesses at 0x3bc for example. That's what I mean by legacy space--space > > that cards respond to but don't report in their PCI resources. > > Can't PCI quirks fix up the resources to reflect this? Not sure, the I/O BAR may correspond to real registers too--and they may not overlap with the ones in the well known space. > I think one needs to fix up PCI IO Port resources to adjust > for "The One" legacy IO port space getting routed to a different > PCI segment - assuming no one submits a patch to change current > behavior of using hard coded addresses. I think we might just need a new resource for these well known ports, if my last statement is true. > Am I making more sense now? Yeah, I think I understand. We could probably do the same thing on sn2 as you do on parisc--add a 'segment 0' offset to the port so that it's routed correctly. I think that's a little less flexible than adding a new resource though, since it makes it harder for drivers to support more than one device or devices on non-segment 0 busses. Jesse ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 19:41 ` Jesse Barnes @ 2005-01-28 20:12 ` Grant Grundler 0 siblings, 0 replies; 31+ messages in thread From: Grant Grundler @ 2005-01-28 20:12 UTC (permalink / raw) To: Jesse Barnes Cc: Grant Grundler, Jon Smirl, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml On Fri, Jan 28, 2005 at 11:41:16AM -0800, Jesse Barnes wrote: > Yeah, I think I understand. We could probably do the same thing on sn2 > as you do on parisc--add a 'segment 0' offset to the port so that it's routed > correctly. I think that's a little less flexible than adding a new resource > though, since it makes it harder for drivers to support more than one device > or devices on non-segment 0 busses. To be clear, the parisc code defines this in include/asm-parisc/pci.h: #define HBA_PORT_SPACE_BITS 16 #define PCI_PORT_HBA(a) ((a) >> HBA_PORT_SPACE_BITS) and PCI_PORT_HBA gets used in arch/parisc/kernel/pci.c. Offhand, I don't know if ia64 has the equivalent. But it sounds like it might need it. grant ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 19:33 ` Grant Grundler 2005-01-28 19:41 ` Jesse Barnes @ 2005-01-28 20:00 ` Matthew Wilcox 2005-01-28 20:07 ` Russell King 2005-01-31 16:01 ` Alan Cox 1 sibling, 2 replies; 31+ messages in thread From: Matthew Wilcox @ 2005-01-28 20:00 UTC (permalink / raw) To: Grant Grundler Cc: Jesse Barnes, Jon Smirl, Greg KH, Russell King, Jeff Garzik, Matthew Wilcox, linux-pci, lkml, Russell King On Fri, Jan 28, 2005 at 12:33:20PM -0700, Grant Grundler wrote: > > > If it is intended to work with multiple IO Port address spaces, > > > then it needs to use the pci_dev->resource[] and mangle that appropriately. > > > > There is no resource for some of the I/O port space that cards respond to. > > Yes - I've heard several graphics cards are horrible broken WRT address > decoding. Are PCI quirks supposed to handle that sort of thing? No, PCI quirks are for fixing broken things. VGA cards are entitled to 3c0-3df and all their 10-bit aliases. I've been thinking for a while that we should mark the 10-bit aliases of ISA devices as used ... ie: x100-x3ff x500-x7ff x900-xbff xd00-xfff Unfortunately, that may break some legitimate setups, but is hinted at being a good idea in the EISA docs I've read. My laptop uses only the 10-bit aliases of motherboard space (x000-x0ff, x400-x4ff, x800-x8ff, xc00-xcff) for devices, except for the ISA bridge, which gets: 1180-11bf : 0000:00:1f.0 1180-11bf : pnp 00:0b The K6-2 is similar; only 10-bit aliases of motherboard space except for: 0a79-0a79 : isapnp write Possibly a better solution (less likely to break things) would be to allow drivers to reserve the 10-bit aliases too. Something like this: static inline void request_isa_alias_regions(unsigned long start, unsigned long n, const char *name) { int base; for (base = 0x400; base < 0x10000; base += 0x400) { request_region(base + start, n, name); } } and then call that in drivers/video/console/vgacon.c Russell, would that allay your issues with the kernel io resource database? -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 20:00 ` Matthew Wilcox @ 2005-01-28 20:07 ` Russell King 2005-01-31 16:01 ` Alan Cox 1 sibling, 0 replies; 31+ messages in thread From: Russell King @ 2005-01-28 20:07 UTC (permalink / raw) To: Matthew Wilcox Cc: Grant Grundler, Jesse Barnes, Jon Smirl, Greg KH, Jeff Garzik, linux-pci, lkml On Fri, Jan 28, 2005 at 08:00:10PM +0000, Matthew Wilcox wrote: > I've been thinking for a while that we should mark the 10-bit aliases > of ISA devices as used ISTR that windows does this. > Russell, would that allay your issues with the kernel io resource database? It makes the situation a whole lot clearer from the point of working out what is free and what isn't, making it less likely that we'll trample over some magic port which your VGA card needs. This, along with throwing in the ports found via ACPI (which Dominik has hinted) should (maybe that's the wrong word) give us a complete picture and allow things like PCMCIA to do reliable resource allocation. The same goes for Cardbus/PCI as well of course. Maybe at this point the idea that you need to tell PCMCIA about which resources it can validly use can finally be eliminated, which is a big step towards eliminating it's dependence on userspace. (I hope this is what you were talking about and I haven't just produced a load of unrelated waffle!) -- Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of: 2.6 PCMCIA - http://pcmcia.arm.linux.org.uk/ 2.6 Serial core ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-28 20:00 ` Matthew Wilcox 2005-01-28 20:07 ` Russell King @ 2005-01-31 16:01 ` Alan Cox 1 sibling, 0 replies; 31+ messages in thread From: Alan Cox @ 2005-01-31 16:01 UTC (permalink / raw) To: Matthew Wilcox Cc: Grant Grundler, Jesse Barnes, Jon Smirl, Greg KH, Russell King, Jeff Garzik, linux-pci, lkml, Russell King On Gwe, 2005-01-28 at 20:00, Matthew Wilcox wrote: > Possibly a better solution (less likely to break things) would be to allow > drivers to reserve the 10-bit aliases too. Something like this: > > static inline void request_isa_alias_regions(unsigned long start, > unsigned long n, const char *name) > { > int base; > for (base = 0x400; base < 0x10000; base += 0x400) { > request_region(base + start, n, name); > } > } > > and then call that in drivers/video/console/vgacon.c Almost every x86 I/O device in ISA space has this problem so it would be better if request_region learned to take a decode mask instead of adding another 500 entries ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-27 9:59 ` Jon Smirl 2005-01-27 16:28 ` Jesse Barnes @ 2005-02-01 6:38 ` Greg KH 2005-02-01 16:24 ` Jon Smirl 1 sibling, 1 reply; 31+ messages in thread From: Greg KH @ 2005-02-01 6:38 UTC (permalink / raw) To: Jon Smirl Cc: Russell King, Jeff Garzik, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Thu, Jan 27, 2005 at 04:59:45AM -0500, Jon Smirl wrote: > On Mon, 24 Jan 2005 20:24:59 -0800, Greg KH <greg@kroah.com> wrote: > > This can be done today in the bus specific match functions. And because > > of that, I would argue that this belongs in the bus specific code, and > > not in the driver core, as it's up to the bus to know what the different > > types of "matches" that can happen, and what the priority is. > > Here's a version of the VGA control code that actually works. It helps > if I pci_enable() the device before using it. There was nothing wrong > with the routing code. > > I can also control multiple cards on the same bus by turning on/off > their response to IO space and then enabling VGA via the standard > ports. I can use this to move my console from card to card. > > I have this code in drivers/pci because it needs to know add/remove > from hotplug. Is there a better way to structure it? Note that this is > not a VGA device, it is just a mechanism for controlling which VGA > device is active. > > Another item I need to add is generating an initial hotplug event for > each secondary card. This event has to happen even if there is a card > specific driver loaded. The event will be used to run the reset > program needed by secondary cards. Ick, patch wasn't inline for me to comment on it :( Anyway, get rid of the ifdefs in the kernel .c code to start with. thanks, greg k-h ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-02-01 6:38 ` Greg KH @ 2005-02-01 16:24 ` Jon Smirl 0 siblings, 0 replies; 31+ messages in thread From: Jon Smirl @ 2005-02-01 16:24 UTC (permalink / raw) To: Greg KH Cc: Russell King, Jeff Garzik, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Mon, 31 Jan 2005 22:38:17 -0800, Greg KH <greg@kroah.com> wrote: > Ick, patch wasn't inline for me to comment on it :( Here's the patch inline. Big things that need to be addressed... 1) Generating the user space reset event. I tried using the pci hotplug event but ran into the fb blacklist. The reset events need to be serialized across multiple cards. Make a temp kobj or just use call_userspacehelp? 2) Things need to be set up so that it will generate the reset event when compiled in. So the event has to come after early user space is set up. 3) Where does this code go? It's not a specific device driver since it doesn't attach to a single piece of hardware. I also run into interference from existing fb driver as a normal device driver. It needs to tie into drivers for bus chips when those happen. 4) It needs to monitor hotplug add/remove. If you pull the bus with the console on it, it will try to move the console to another VGA device. diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c --- a/arch/i386/pci/fixup.c 2005-01-27 04:01:08 -05:00 +++ b/arch/i386/pci/fixup.c 2005-01-27 04:01:08 -05:00 @@ -375,6 +375,6 @@ } bus = bus->parent; } - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW | IORESOURCE_VGA_ACTIVE; } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); diff -Nru a/drivers/pci/Kconfig b/drivers/pci/Kconfig --- a/drivers/pci/Kconfig 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/Kconfig 2005-01-27 04:01:08 -05:00 @@ -47,3 +47,13 @@ When in doubt, say Y. +config VGA_CONTROL + bool "VGA Control" + depends on PCI + ---help--- + Provides sysfs attributes for ensuring that only a single VGA + device can be enabled per PCI domain. If a VGA device is removed + via hotplug, display is routed to another VGA device if available. + + If you have more than one VGA device, say Y. + diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/Makefile 2005-01-27 04:01:08 -05:00 @@ -28,6 +28,7 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_PCI_MSI) += msi.o +obj-$(CONFIG_VGA_CONTROL) += vga.o # # ACPI Related PCI FW Functions diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c --- a/drivers/pci/bus.c 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/bus.c 2005-01-27 04:01:08 -05:00 @@ -85,6 +85,9 @@ pci_proc_attach_device(dev); pci_create_sysfs_dev_files(dev); +#if CONFIG_VGA_CONTROL + pci_vga_add_device(dev); +#endif } /** diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h --- a/drivers/pci/pci.h 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/pci.h 2005-01-27 04:01:08 -05:00 @@ -11,6 +11,8 @@ void (*alignf)(void *, struct resource *, unsigned long, unsigned long), void *alignf_data); +extern int pci_vga_add_device(struct pci_dev *pdev); +extern int pci_vga_remove_device(struct pci_dev *pdev); /* PCI /proc functions */ #ifdef CONFIG_PROC_FS extern int pci_proc_attach_device(struct pci_dev *dev); diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c --- a/drivers/pci/remove.c 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/remove.c 2005-01-27 04:01:08 -05:00 @@ -26,6 +26,9 @@ static void pci_destroy_dev(struct pci_dev *dev) { +#if CONFIG_VGA_CONTROL + pci_vga_remove_device(dev); +#endif pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); device_unregister(&dev->dev); diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c 2005-01-27 04:01:08 -05:00 +++ b/drivers/pci/setup-bus.c 2005-01-27 04:01:08 -05:00 @@ -64,7 +64,9 @@ if (class == PCI_CLASS_DISPLAY_VGA || class == PCI_CLASS_NOT_DEFINED_VGA) - bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; + /* only route to the active VGA, ignore inactive ones */ + if (dev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) + bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; pdev_sort_resources(dev, &head); } diff -Nru a/drivers/pci/vga.c b/drivers/pci/vga.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/pci/vga.c 2005-01-27 04:01:08 -05:00 @@ -0,0 +1,254 @@ +/* + * linux/drivers/pci/vga.c + * + * (C) Copyright 2004 Jon Smirl <jonsmirl@gmail.com> + * + * VGA control logic for ensuring only a single enabled VGA device + */ + +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/pci.h> +#include <linux/major.h> + +static int vga_initialized = 0; +static struct pci_dev *vga_active = NULL; + +static void bridge_yes(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + + /* Make sure the bridges route to us */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); + } + bus = bus->parent; + } +} + +static void bridge_no(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + + /* Make sure the bridges don't route to us */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); + } + bus = bus->parent; + } +} + +static void vga_enable(struct pci_dev *pdev, unsigned int enable) +{ + u16 command; + + bridge_yes(pdev); + + if (enable) { + pci_enable_device(pdev); + /* this assumes all other potential VGA devices are disabled */ + outb(0x01 | inb(0x3C3), 0x3C3); /* 0 - enable */ + outb(0x08 | inb(0x46e8), 0x46e8); + outb(0x01 | inb(0x102), 0x102); + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_VGA_ACTIVE; + vga_active = pdev; + + /* return and leave the card enabled */ + return; + } + + pci_read_config_word(pdev, PCI_COMMAND, &command); + pci_write_config_word(pdev, PCI_COMMAND, command | PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + + outb(~0x01 & inb(0x3C3), 0x3C3); + outb(~0x08 & inb(0x46e8), 0x46e8); + outb(~0x01 & inb(0x102), 0x102); + pdev->resource[PCI_ROM_RESOURCE].flags &= ~IORESOURCE_VGA_ACTIVE; + if (pdev == vga_active) + vga_active = NULL; + bridge_no(pdev); + + pci_write_config_word(pdev, PCI_COMMAND, command); +} + +/* echo these values to the sysfs vga attribute on a VGA device */ +enum eEnable { + VGA_DISABLE_THIS = 0, /* If this VGA is enabled, disable it. */ + VGA_ENABLE_THIS = 1, /* Disable all VGAs then enable this VGA, mark as active VGA */ + /* Used while resetting a board, board being reset may not be the active VGA */ + VGA_DISABLE_ALL = 2, /* Remember active VGA then disable all VGAa and devices */ + VGA_ENABLE_ACTIVE = 3, /* Make sure all VGAs are disabled, then reenable active VGA */ +}; + +static void set_state(struct pci_dev *pdev, enum eEnable enable) +{ + struct pci_dev *pcidev = NULL; + unsigned int class; + + if (enable == VGA_DISABLE_THIS) + if (vga_active != pdev) + return; + + vga_enable(vga_active, 0); + + /* loop over all devices and make sure no multiple routings */ + while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) { + class = pcidev->class >> 8; + + if (class == PCI_CLASS_DISPLAY_VGA) + bridge_no(pcidev); + } + + /* loop over all devices and make sure everyone is disabled */ + while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) { + class = pcidev->class >> 8; + + if (class == PCI_CLASS_DISPLAY_VGA) + vga_enable(pcidev, 0); + } + + switch (enable) { + case VGA_DISABLE_THIS: + case VGA_DISABLE_ALL: + break; + + /* Mark us active if requested */ + case VGA_ENABLE_THIS: + vga_enable(pdev, 1); + break; + + /* Restore active device if requested */ + case VGA_ENABLE_ACTIVE: + vga_enable(vga_active, 1); + break; + } +} + +/* sysfs store for VGA device */ +static ssize_t vga_device_store(struct device *dev, const char *buf, size_t count) +{ + char *last; + struct pci_dev *pdev = to_pci_dev(dev); + enum eEnable enable; + + /* sysfs strings are terminated by \n */ + enable = simple_strtoul(buf, &last, 0); + if (last == buf) + return -EINVAL; + + if ((enable < VGA_DISABLE_THIS) || (enable > VGA_ENABLE_ACTIVE)) + return -EINVAL; + + set_state(pdev, enable); + + return count; +} + +/* sysfs show for VGA device */ +static ssize_t vga_device_show(struct device *dev, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + return sprintf(buf, "%d\n", (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) != 0); +} + +static struct device_attribute vga_device_attr = __ATTR(vga, S_IRUGO|S_IWUSR, vga_device_show, vga_device_store); + +/* sysfs show for VGA routing bridge */ +static ssize_t vga_bridge_show(struct device *dev, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + u16 l; + + /* don't trust the shadow PCI_BRIDGE_CTL_VGA in pdev */ + /* user space may change hardware without telling the kernel */ + pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &l); + return sprintf(buf, "%d\n", (l & PCI_BRIDGE_CTL_VGA) != 0); +} + +static struct device_attribute vga_bridge_attr = __ATTR(vga, S_IRUGO, vga_bridge_show, NULL); + +/* If the device is a VGA or a bridge, add a VGA sysfs attribute */ +int pci_vga_add_device(struct pci_dev *pdev) +{ + int class = pdev->class >> 8; + + if (!vga_initialized) + return -EACCES; + + if (class == PCI_CLASS_DISPLAY_VGA) { + device_create_file(&pdev->dev, &vga_device_attr); + + /* record the active boot device when located */ + if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_VGA_ACTIVE) + vga_active = pdev; + return 0; + } + + if ((class == PCI_CLASS_BRIDGE_PCI) || (class == PCI_CLASS_BRIDGE_CARDBUS)) { + device_create_file(&pdev->dev, &vga_bridge_attr); + } + return 0; +} + +/* If the device is a VGA or a bridge, remove the VGA sysfs attribute */ +int pci_vga_remove_device(struct pci_dev *pdev) +{ + struct pci_dev *pcidev = NULL; + int class = pdev->class >> 8; + + if (!vga_initialized) + return -EACCES; + + if (class == PCI_CLASS_DISPLAY_VGA) { + device_remove_file(&pdev->dev, &vga_device_attr); + + /* record the active boot device when located */ + if (vga_active == pdev) { + while ((pcidev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pcidev)) != NULL) { + class = pcidev->class >> 8; + if (class != PCI_CLASS_DISPLAY_VGA) + continue; + if (pcidev == pdev) + continue; + set_state(pcidev, VGA_ENABLE_THIS); + break; + } + if (pcidev == NULL) + set_state(NULL, VGA_DISABLE_ALL); + + } + return 0; + } + + if ((class == PCI_CLASS_BRIDGE_PCI) || (class == PCI_CLASS_BRIDGE_CARDBUS)) + device_remove_file(&pdev->dev, &vga_bridge_attr); + + return 0; +} + +/* Initialize by scanning all devices */ +static int __init vga_init(void) +{ + struct pci_dev *pdev = NULL; + + vga_initialized = 1; + + while ((pdev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) + pci_vga_add_device(pdev); + + return 0; +} + +__initcall(vga_init); + diff -Nru a/include/linux/ioport.h b/include/linux/ioport.h --- a/include/linux/ioport.h 2005-01-27 04:01:08 -05:00 +++ b/include/linux/ioport.h 2005-01-27 04:01:08 -05:00 @@ -41,7 +41,6 @@ #define IORESOURCE_CACHEABLE 0x00004000 #define IORESOURCE_RANGELENGTH 0x00008000 #define IORESOURCE_SHADOWABLE 0x00010000 -#define IORESOURCE_BUS_HAS_VGA 0x00080000 #define IORESOURCE_DISABLED 0x10000000 #define IORESOURCE_UNSET 0x20000000 @@ -86,6 +85,7 @@ #define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ #define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ #define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ +#define IORESOURCE_VGA_ACTIVE (1<<3) /* VGA device is active */ /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ extern struct resource ioport_resource; -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-25 4:24 ` Greg KH 2005-01-27 9:59 ` Jon Smirl @ 2005-01-30 7:51 ` Jon Smirl 1 sibling, 0 replies; 31+ messages in thread From: Jon Smirl @ 2005-01-30 7:51 UTC (permalink / raw) To: Greg KH Cc: Russell King, Jeff Garzik, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Mon, 24 Jan 2005 20:24:59 -0800, Greg KH <greg@kroah.com> wrote: > And yes, I agree that this needs to be done, I've been talking with a > few other people who are interested in it. I think the lock-rework code > needs to be finished before it can happen properly, so that we can do > the "unbind from one driver and give it to another one" type logic > properly. Unbind/give does not address what VGA control needs. VGA control needs to track hotplug remove events so that it can route the display to another VGA card if the active display is pulled. As far as I can tell there is no way to monitor hotplug remove events, that's why I had to add a callout in pci_destroy_dev(). VGA control also can't just install a device driver since that will prevent the real DRM/FB device drivers from installing. It looks to me like VGA control is more of a strange property of the PCI bus architecture than a device driver. Another strategy would be to create the concept of a PCI class driver which a normal device driver would inherit from instead of replacing it. But is there a need for another PCI class driver other than VGA? -- Jon Smirl jonsmirl@gmail.com ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-24 19:42 ` Jeff Garzik 2005-01-24 19:55 ` Russell King @ 2005-01-24 20:14 ` Matthew Wilcox 1 sibling, 0 replies; 31+ messages in thread From: Matthew Wilcox @ 2005-01-24 20:14 UTC (permalink / raw) To: Jeff Garzik; +Cc: Jon Smirl, Matthew Wilcox, Jesse Barnes, linux-pci, lkml On Mon, Jan 24, 2005 at 02:42:57PM -0500, Jeff Garzik wrote: > Jon Smirl wrote: > >Is this a justification for doing device drivers for bridge chips? It > >has been mentioned before but no one has done it. > > Yeah, people are usually slack and work around the problem. > > A bridge driver is really wanted for several situations in today's > hardware... Annoyingly, we already have one, it's just special-cased for PCI Express. On my todo for this week is to take it out of the pcie directory and fix it. -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Fwd: Patch to control VGA bus routing and active VGA device. 2005-01-24 19:17 ` Fwd: " Jon Smirl 2005-01-24 19:42 ` Jeff Garzik @ 2005-01-24 20:22 ` Matthew Wilcox 1 sibling, 0 replies; 31+ messages in thread From: Matthew Wilcox @ 2005-01-24 20:22 UTC (permalink / raw) To: Jon Smirl; +Cc: Matthew Wilcox, Jesse Barnes, Jeff Garzik, linux-pci, lkml On Mon, Jan 24, 2005 at 02:17:15PM -0500, Jon Smirl wrote: > On Mon, 24 Jan 2005 17:51:31 +0000, Matthew Wilcox <matthew@wil.cx> wrote: > > Yes -- *very* platform specific. Some are even configurable as to how > > much they support. See http://ftp.parisc-linux.org/docs/chips/zx1-mio.pdf > > Is this a justification for doing device drivers for bridge chips? It > has been mentioned before but no one has done it. I don't think this is ... the bridges mentioned are host->pci bridges. > Any ideas why the code I sent won't work on the x86? I can shut > routing off but I can't get it back on again. > > The motivation behind the code is to get X to quit doing this from user space. I suppose we could log all access X does and compare to what your code ends up doing ... -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2005-02-01 16:24 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-18 3:43 Patch to control VGA bus routing and active VGA device Jon Smirl
2005-01-18 17:46 ` Jesse Barnes
2005-01-18 19:38 ` H. Peter Anvin
2005-01-18 21:06 ` Jesse Barnes
2005-01-22 19:04 ` Jon Smirl
2005-01-24 17:25 ` Jesse Barnes
2005-01-24 17:53 ` Jesse Barnes
[not found] ` <41ED3BD2.1090105@pobox.com>
[not found] ` <9e473391050122083822a7f81c@mail.gmail.com>
[not found] ` <200501240847.51208.jbarnes@sgi.com>
[not found] ` <20050124175131.GM31455@parcelfarce.linux.theplanet.co.uk>
2005-01-24 19:17 ` Fwd: " Jon Smirl
2005-01-24 19:42 ` Jeff Garzik
2005-01-24 19:55 ` Russell King
2005-01-24 23:11 ` Jon Smirl
2005-01-25 4:24 ` Greg KH
2005-01-27 9:59 ` Jon Smirl
2005-01-27 16:28 ` Jesse Barnes
2005-01-28 17:32 ` Grant Grundler
2005-01-28 18:36 ` Jon Smirl
2005-01-28 19:15 ` Grant Grundler
2005-01-28 19:26 ` Jon Smirl
2005-01-28 19:34 ` Grant Grundler
2005-01-28 18:41 ` Jesse Barnes
2005-01-28 19:33 ` Grant Grundler
2005-01-28 19:41 ` Jesse Barnes
2005-01-28 20:12 ` Grant Grundler
2005-01-28 20:00 ` Matthew Wilcox
2005-01-28 20:07 ` Russell King
2005-01-31 16:01 ` Alan Cox
2005-02-01 6:38 ` Greg KH
2005-02-01 16:24 ` Jon Smirl
2005-01-30 7:51 ` Jon Smirl
2005-01-24 20:14 ` Matthew Wilcox
2005-01-24 20:22 ` Matthew Wilcox
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox