((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 */
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
--- /dev/null
+#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;
+}
-#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"
-#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"
-#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"
--- /dev/null
+#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;
+ }
+ }
+}
-#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"
-#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"
-#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"
--- /dev/null
+#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 */
+ }
+ }
+}