* Re: ioctl32 warning on framebuffer
2007-07-27 19:23 ioctl32 warning on framebuffer Meelis Roos
2007-07-27 20:47 ` David Miller
@ 2007-07-29 7:39 ` David Miller
2007-07-29 16:32 ` Meelis Roos
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2007-07-29 7:39 UTC (permalink / raw)
To: sparclinux
From: Meelis Roos <mroos@linux.ee>
Date: Fri, 27 Jul 2007 22:23:53 +0300 (EEST)
> ioctl32(Xorg:1892): Unknown cmd fd(6) cmd(40584606){t:'F';sz:88} arg(ffdabb4c) on /dev/fb0
> ioctl32(Xorg:1892): Unknown cmd fd(6) cmd(40184600){t:'F';sz:24} arg(ffdabb54) on /dev/fb0
Please give this patch a try:
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 34ef859..963a454 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -190,17 +190,6 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
EXPORT_SYMBOL(sbusfb_ioctl_helper);
#ifdef CONFIG_COMPAT
-struct fbcmap32 {
- int index; /* first element (0 origin) */
- int count;
- u32 red;
- u32 green;
- u32 blue;
-};
-
-#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
-#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
-
static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct fbcmap32 __user *argp = (void __user *)arg;
@@ -223,20 +212,6 @@ static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long
(unsigned long)p);
}
-struct fbcursor32 {
- short set; /* what to set, choose from the list above */
- short enable; /* cursor on/off */
- struct fbcurpos pos; /* cursor position */
- struct fbcurpos hot; /* cursor hot spot */
- struct fbcmap32 cmap; /* color map info */
- struct fbcurpos size; /* cursor bit map size */
- u32 image; /* cursor image bits */
- u32 mask; /* cursor mask bits */
-};
-
-#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
-#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
-
static int fbiogscursor(struct fb_info *info, unsigned long arg)
{
struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index e440a7b..2bc1428 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -115,6 +115,10 @@
#include <linux/dvb/video.h>
#include <linux/lp.h>
+#ifdef CONFIG_SPARC
+#include <asm/fbio.h>
+#endif
+
static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
unsigned long arg, struct file *f)
{
@@ -3493,6 +3497,22 @@ IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
/* loop */
IGNORE_IOCTL(LOOP_CLR_FD)
+
+#ifdef CONFIG_SPARC
+/* Sparc framebuffers, handled in sbusfb_compat_ioctl() */
+IGNORE_IOCTL(FBIOGTYPE)
+IGNORE_IOCTL(FBIOSATTR)
+IGNORE_IOCTL(FBIOGATTR)
+IGNORE_IOCTL(FBIOSVIDEO)
+IGNORE_IOCTL(FBIOGVIDEO)
+IGNORE_IOCTL(FBIOSCURPOS)
+IGNORE_IOCTL(FBIOGCURPOS)
+IGNORE_IOCTL(FBIOGCURMAX)
+IGNORE_IOCTL(FBIOPUTCMAP32)
+IGNORE_IOCTL(FBIOGETCMAP32)
+IGNORE_IOCTL(FBIOSCURSOR32)
+IGNORE_IOCTL(FBIOGCURSOR32)
+#endif
};
#define IOCTL_HASHSIZE 256
diff --git a/include/asm-sparc64/fbio.h b/include/asm-sparc64/fbio.h
index 500026d..b9215a0 100644
--- a/include/asm-sparc64/fbio.h
+++ b/include/asm-sparc64/fbio.h
@@ -2,6 +2,7 @@
#define __LINUX_FBIO_H
#include <linux/compiler.h>
+#include <linux/types.h>
/* Constants used for fbio SunOS compatibility */
/* (C) 1996 Miguel de Icaza */
@@ -299,4 +300,31 @@ struct fb_clut32 {
#define LEO_LD_GBL_MAP 0x01009000
#define LEO_UNK2_MAP 0x0100a000
+#ifdef __KERNEL__
+struct fbcmap32 {
+ int index; /* first element (0 origin) */
+ int count;
+ u32 red;
+ u32 green;
+ u32 blue;
+};
+
+#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
+
+struct fbcursor32 {
+ short set; /* what to set, choose from the list above */
+ short enable; /* cursor on/off */
+ struct fbcurpos pos; /* cursor position */
+ struct fbcurpos hot; /* cursor hot spot */
+ struct fbcmap32 cmap; /* color map info */
+ struct fbcurpos size; /* cursor bit map size */
+ u32 image; /* cursor image bits */
+ u32 mask; /* cursor mask bits */
+};
+
+#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
+#endif
+
#endif /* __LINUX_FBIO_H */
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: ioctl32 warning on framebuffer
2007-07-27 19:23 ioctl32 warning on framebuffer Meelis Roos
` (4 preceding siblings ...)
2007-07-30 3:41 ` David Miller
@ 2007-07-30 3:48 ` David Miller
2007-07-30 11:42 ` Meelis Roos
6 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2007-07-30 3:48 UTC (permalink / raw)
To: sparclinux
From: Jim Watson <jim@amarooas.com.au>
Date: Mon, 30 Jul 2007 08:38:11 +1000
> Meelis Roos wrote:
> > Fatal server error:
> > xf86MapPciMem: Could not mmap PCI memory [base=0xe2000000,hostbase=0xe2000000,size 00] (Inappropriate ioctl for device)
> >
> >
> A similar error message was reported here:
>
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bugB2077
Not similar at all, that bug is fixed by the patch at the
end of this email.
Meelis's bug is more likely due to the procfs regression of
->compat_ioctl() handling that 2.6.23-rc1 had until yesterday.
commit 27997abfcb1f8bb534720b18f3487de3906c7ac6
Author: David S. Miller <davem@sunset.davemloft.net>
Date: Wed Jul 25 23:30:16 2007 -0700
[SPARC64]: Fix sun4u PCI config space accesses on sun4u.
Don't provide fake PCI config space for sun4u.
Also, put back the funny host controller space handling that
at least Sabre needs. You have to read PCI host controller
registers at their nature size otherwise you get zeros instead
of correct values.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 55ad1b8..77449a0 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -422,10 +422,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
dev->multifunction = 0; /* maybe a lie? */
if (host_controller) {
- dev->vendor = 0x108e;
- dev->device = 0x8000;
- dev->subsystem_vendor = 0x0000;
- dev->subsystem_device = 0x0000;
+ if (tlb_type != hypervisor) {
+ pci_read_config_word(dev, PCI_VENDOR_ID,
+ &dev->vendor);
+ pci_read_config_word(dev, PCI_DEVICE_ID,
+ &dev->device);
+ } else {
+ dev->vendor = PCI_VENDOR_ID_SUN;
+ dev->device = 0x80f0;
+ }
dev->cfg_size = 256;
dev->class = PCI_CLASS_BRIDGE_HOST << 8;
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
@@ -818,7 +823,7 @@ int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
{
static u8 fake_pci_config[] = {
0x8e, 0x10, /* Vendor: 0x108e (Sun) */
- 0x00, 0x80, /* Device: 0x8000 (PBM) */
+ 0xf0, 0x80, /* Device: 0x80f0 (Fire) */
0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 4249214..2f61c4b 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -44,6 +44,67 @@ static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
return (void *) (pbm->config_space | bus | devfn | reg);
}
+/* At least on Sabre, it is necessary to access all PCI host controller
+ * registers at their natural size, otherwise zeros are returned.
+ * Strange but true, and I see no language in the UltraSPARC-IIi
+ * programmer's manual that mentions this even indirectly.
+ */
+static int sun4u_read_pci_cfg_host(struct pci_pbm_info *pbm,
+ unsigned char bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ u32 tmp32, *addr;
+ u16 tmp16;
+ u8 tmp8;
+
+ addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ switch (size) {
+ case 1:
+ if (where < 8) {
+ unsigned long align = (unsigned long) addr;
+
+ align &= ~1;
+ pci_config_read16((u16 *)align, &tmp16);
+ if (where & 1)
+ *value = tmp16 >> 8;
+ else
+ *value = tmp16 & 0xff;
+ } else {
+ pci_config_read8((u8 *)addr, &tmp8);
+ *value = (u32) tmp8;
+ }
+ break;
+
+ case 2:
+ if (where < 8) {
+ pci_config_read16((u16 *)addr, &tmp16);
+ *value = (u32) tmp16;
+ } else {
+ pci_config_read8((u8 *)addr, &tmp8);
+ *value = (u32) tmp8;
+ pci_config_read8(((u8 *)addr) + 1, &tmp8);
+ *value |= ((u32) tmp8) << 8;
+ }
+ break;
+
+ case 4:
+ tmp32 = 0xffffffff;
+ sun4u_read_pci_cfg_host(pbm, bus, devfn,
+ where, 2, &tmp32);
+ *value = tmp32;
+
+ tmp32 = 0xffffffff;
+ sun4u_read_pci_cfg_host(pbm, bus, devfn,
+ where + 2, 2, &tmp32);
+ *value |= tmp32 << 16;
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
int where, int size, u32 *value)
{
@@ -53,10 +114,6 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
u16 tmp16;
u8 tmp8;
- if (bus_dev = pbm->pci_bus && devfn = 0x00)
- return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
- size, value);
-
switch (size) {
case 1:
*value = 0xff;
@@ -69,6 +126,10 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
break;
}
+ if (!bus_dev->number && !PCI_SLOT(devfn))
+ return sun4u_read_pci_cfg_host(pbm, bus, devfn, where,
+ size, value);
+
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
if (!addr)
return PCIBIOS_SUCCESSFUL;
@@ -101,6 +162,53 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
return PCIBIOS_SUCCESSFUL;
}
+static int sun4u_write_pci_cfg_host(struct pci_pbm_info *pbm,
+ unsigned char bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ u32 *addr;
+
+ addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+ if (!addr)
+ return PCIBIOS_SUCCESSFUL;
+
+ switch (size) {
+ case 1:
+ if (where < 8) {
+ unsigned long align = (unsigned long) addr;
+ u16 tmp16;
+
+ align &= ~1;
+ pci_config_read16((u16 *)align, &tmp16);
+ if (where & 1) {
+ tmp16 &= 0x00ff;
+ tmp16 |= value << 8;
+ } else {
+ tmp16 &= 0xff00;
+ tmp16 |= value;
+ }
+ pci_config_write16((u16 *)align, tmp16);
+ } else
+ pci_config_write8((u8 *)addr, value);
+ break;
+ case 2:
+ if (where < 8) {
+ pci_config_write16((u16 *)addr, value);
+ } else {
+ pci_config_write8((u8 *)addr, value & 0xff);
+ pci_config_write8(((u8 *)addr) + 1, value >> 8);
+ }
+ break;
+ case 4:
+ sun4u_write_pci_cfg_host(pbm, bus, devfn,
+ where, 2, value & 0xffff);
+ sun4u_write_pci_cfg_host(pbm, bus, devfn,
+ where + 2, 2, value >> 16);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
int where, int size, u32 value)
{
@@ -108,9 +216,10 @@ static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
unsigned char bus = bus_dev->number;
u32 *addr;
- if (bus_dev = pbm->pci_bus && devfn = 0x00)
- return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
- size, value);
+ if (!bus_dev->number && !PCI_SLOT(devfn))
+ return sun4u_write_pci_cfg_host(pbm, bus, devfn, where,
+ size, value);
+
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
if (!addr)
return PCIBIOS_SUCCESSFUL;
^ permalink raw reply related [flat|nested] 8+ messages in thread