Support PCI configuration space mechanism #2 if necessary.
authorhpa <hpa>
Wed, 5 Jan 2005 23:03:38 +0000 (23:03 +0000)
committerhpa <hpa>
Wed, 5 Jan 2005 23:03:38 +0000 (23:03 +0000)
com32/include/sys/pci.h
com32/lib/Makefile
com32/lib/pci/cfgtype.c [new file with mode: 0644]
com32/lib/pci/readb.c
com32/lib/pci/readl.c
com32/lib/pci/readw.c
com32/lib/pci/readx.c [new file with mode: 0644]
com32/lib/pci/writeb.c
com32/lib/pci/writel.c
com32/lib/pci/writew.c
com32/lib/pci/writex.c [new file with mode: 0644]

index 03d8884..bfa7e60 100644 (file)
@@ -13,11 +13,19 @@ static inline pciaddr_t pci_mkaddr(uint32_t bus, uint32_t dev,
     ((func & 0x07) << 8) | (reg & 0xff);
 }
 
-uint8_t pci_readb(pciaddr_t a);
-uint16_t pci_readw(pciaddr_t a);
-uint32_t pci_readl(pciaddr_t a);
-void pci_writeb(uint8_t v, pciaddr_t a);
-void pci_writew(uint16_t v, pciaddr_t a);
-void pci_writel(uint32_t v, pciaddr_t a);
+enum pci_config_type {
+  PCI_CFG_AUTO         = 0,    /* autodetect */
+  PCI_CFG_TYPE1                = 1,
+  PCI_CFG_TYPE2                = 2,
+};
+
+void pci_set_config_type(enum pci_config_type);
+
+uint8_t pci_readb(pciaddr_t);
+uint16_t pci_readw(pciaddr_t);
+uint32_t pci_readl(pciaddr_t);
+void pci_writeb(uint8_t, pciaddr_t);
+void pci_writew(uint16_t, pciaddr_t);
+void pci_writel(uint32_t, pciaddr_t);
 
 #endif /* _SYS_PCI_H */
index 18c952e..1379264 100644 (file)
@@ -26,7 +26,7 @@ LIBOBJS = abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o     \
        sys/rawcon_write.o sys/err_read.o sys/err_write.o               \
        sys/null_read.o sys/null_write.o sys/serial_write.o             \
        sys/ansicon_write.o sys/ansiserial_write.o                      \
-       pci/readb.o pci/readw.o pci/readl.o                             \
+       pci/cfgtype.o pci/readb.o pci/readw.o pci/readl.o               \
        pci/writeb.o pci/writew.o pci/writel.o
 
 BINDIR   = /usr/bin
diff --git a/com32/lib/pci/cfgtype.c b/com32/lib/pci/cfgtype.c
new file mode 100644 (file)
index 0000000..5fa72be
--- /dev/null
@@ -0,0 +1,23 @@
+#include "pci/pci.h"
+
+enum pci_config_type __pci_cfg_type;
+
+void pci_set_config_type(enum pci_config_type type)
+{
+  uint32_t oldcf8;
+
+  if ( type == PCI_CFG_AUTO ) {
+    /* Try to detect CM #1 */
+    cli();
+    oldcf8 = inl(0xcf8);
+    outl(~0, 0xcf8);
+    if ( inl(0xcf8) == pci_mkaddr(255,31,7,252) )
+      type = PCI_CFG_TYPE1;
+    else
+      type = PCI_CFG_TYPE2;    /* ... it better be ... */
+    outl(oldcf8, 0xcf8);
+    sti();
+  }
+
+  __pci_cfg_type = type;
+}
index ac0efaa..bfc544f 100644 (file)
@@ -1,15 +1,3 @@
-#include <inttypes.h>
-#include <sys/io.h>
-#include <sys/pci.h>
-
-uint8_t pci_readb(pciaddr_t a)
-{
-  uint32_t oldcf8 = inl(0xcf8);
-  uint8_t r;
-
-  outl(a, 0xcf8);
-  r = inb(0xcfc + (a & 3));
-  outl(oldcf8, 0xcf8);
-
-  return r;
-}
+#define TYPE uint8_t
+#define BWL(x) x ## b
+#include "pci/readx.c"
index 1cd43c0..ef3fdd6 100644 (file)
@@ -1,15 +1,3 @@
-#include <inttypes.h>
-#include <sys/io.h>
-#include <sys/pci.h>
-
-uint32_t pci_readl(pciaddr_t a)
-{
-  uint32_t oldcf8 = inl(0xcf8);
-  uint32_t r;
-
-  outl(a, 0xcf8);
-  r = inl(0xcfc + (a & 3));
-  outl(oldcf8, 0xcf8);
-
-  return r;
-}
+#define TYPE uint32_t
+#define BWL(x) x ## l
+#include "pci/readx.c"
index b7558a6..6889229 100644 (file)
@@ -1,15 +1,3 @@
-#include <inttypes.h>
-#include <sys/io.h>
-#include <sys/pci.h>
-
-uint16_t pci_readw(pciaddr_t a)
-{
-  uint32_t oldcf8 = inl(0xcf8);
-  uint16_t r;
-
-  outl(a, 0xcf8);
-  r = inw(0xcfc + (a & 3));
-  outl(oldcf8, 0xcf8);
-
-  return r;
-}
+#define TYPE uint16_t
+#define BWL(x) x ## w
+#include "pci/readx.c"
diff --git a/com32/lib/pci/readx.c b/com32/lib/pci/readx.c
new file mode 100644 (file)
index 0000000..f1e542d
--- /dev/null
@@ -0,0 +1,48 @@
+#include "pci/pci.h"
+
+TYPE BWL(pci_read) (pciaddr_t a)
+{
+  TYPE r;
+
+  for (;;) {
+    switch ( __pci_cfg_type ) {
+    case PCI_CFG_AUTO:
+      pci_set_config_type(PCI_CFG_AUTO);
+      break;                   /* Try again */
+      
+    case PCI_CFG_TYPE1:
+      {
+       uint32_t oldcf8;
+       cli();
+       oldcf8 = inl(0xcf8);
+       outl(a, 0xcf8);
+       r = BWL(in) (0xcfc + (a & 3));
+       outl(oldcf8, 0xcf8);
+       sti();
+      }
+      return r;
+      
+    case PCI_CFG_TYPE2:
+      {
+       uint8_t oldcf8, oldcfa;
+       
+       if ( a & (0x10 << 11) )
+         return (TYPE)~0;
+       
+       cli();
+       oldcf8 = inb(0xcf8);
+       oldcfa = inb(0xcfa);
+       outb(0xf0 + ((a >> (8-1)) & 0x0e), 0xcf8);
+       outb(a >> 16, 0xcfa);
+       r = BWL(in) (0xc000 + ((a >> (11-8)) & 0xf00) + (a & 0xff));
+       outb(oldcf8, 0xcf8);
+       outb(oldcfa, 0xcfa);
+       sti();
+      }
+      return r;
+      
+    default:
+      return (TYPE)~0;
+    }
+  }
+}
index db399cd..a63fcf1 100644 (file)
@@ -1,12 +1,3 @@
-#include <inttypes.h>
-#include <sys/io.h>
-#include <sys/pci.h>
-
-void pci_writeb(uint8_t v, pciaddr_t a)
-{
-  uint32_t oldcf8 = inl(0xcf8);
-
-  outl(a, 0xcf8);
-  outb(v, 0xcfc + (a & 3));
-  outl(oldcf8, 0xcf8);
-}
+#define TYPE uint8_t
+#define BWL(x) x ## b
+#include "pci/writex.c"
index cfe58d6..f608baa 100644 (file)
@@ -1,12 +1,3 @@
-#include <inttypes.h>
-#include <sys/io.h>
-#include <sys/pci.h>
-
-void pci_writel(uint32_t v, pciaddr_t a)
-{
-  uint32_t oldcf8 = inl(0xcf8);
-
-  outl(a, 0xcf8);
-  outl(v, 0xcfc + (a & 3));
-  outl(oldcf8, 0xcf8);
-}
+#define TYPE uint32_t
+#define BWL(x) x ## l
+#include "pci/writex.c"
index 805ca50..4399d71 100644 (file)
@@ -1,12 +1,3 @@
-#include <inttypes.h>
-#include <sys/io.h>
-#include <sys/pci.h>
-
-void pci_writew(uint16_t v, pciaddr_t a)
-{
-  uint32_t oldcf8 = inl(0xcf8);
-
-  outl(a, 0xcf8);
-  outw(v, 0xcfc + (a & 3));
-  outl(oldcf8, 0xcf8);
-}
+#define TYPE uint16_t
+#define BWL(x) x ## w
+#include "pci/writex.c"
diff --git a/com32/lib/pci/writex.c b/com32/lib/pci/writex.c
new file mode 100644 (file)
index 0000000..c7e715e
--- /dev/null
@@ -0,0 +1,45 @@
+#include "pci/pci.h"
+
+void BWL(pci_write) (TYPE v, pciaddr_t a)
+{
+  for (;;) {
+    switch ( __pci_cfg_type ) {
+    case PCI_CFG_AUTO:
+      pci_set_config_type(PCI_CFG_AUTO);
+      break;                   /* Try again */
+
+    case PCI_CFG_TYPE1:
+      {
+       uint32_t oldcf8;
+       cli();
+       oldcf8 = inl(0xcf8);
+       outl(a, 0xcf8);
+       BWL(out) (v, 0xcfc + (a & 3));
+       outl(oldcf8, 0xcf8);
+       sti();
+      }
+      return;
+
+    case PCI_CFG_TYPE2:
+      {
+       uint8_t oldcf8, oldcfa;
+       
+       if ( a & (0x10 << 11) )
+         return;
+       
+       cli();
+       oldcf8 = inb(0xcf8);
+       oldcfa = inb(0xcfa);
+       outb(0xf0 + ((a >> (8-1)) & 0x0e), 0xcf8);
+       outb(a >> 16, 0xcfa);
+       BWL(out) (v, 0xc000 + ((a >> (11-8)) & 0xf00) + (a & 0xff));
+       outb(oldcf8, 0xcf8);
+       outb(oldcfa, 0xcfa);
+       sti();
+      }
+
+    default:
+      return;                  /* Do nothing */
+    }
+  }
+}