<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 20, 2016 at 2:20 AM, Chris Johns <span dir="ltr"><<a href="mailto:chrisj@rtems.org" target="_blank">chrisj@rtems.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Use the BAR to determine IO and memory mapped support for PCI UART<br>
boards.<br>
---<br>
 c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c | 150 ++++++++++++++++-----<br>
 1 file changed, 113 insertions(+), 37 deletions(-)<br>
<br>
diff --git a/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c b/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c<br>
index 60d35e8..7b48248 100644<br>
--- a/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c<br>
+++ b/c/src/lib/libbsp/i386/pc386/console/uart_bus_pci.c<br>
@@ -36,6 +36,7 @@<br>
 #ifdef __rtems__<br>
 #include <stddef.h><br>
 #include <stdint.h><br>
+#include <i386_io.h><br>
 #else<br>
 #include <sys/cdefs.h><br>
 __FBSDID("$FreeBSD$");<br>
@@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$");<br>
<br>
 #include <dev/uart/uart.h><br>
 #include <dev/uart/uart_bus.h><br>
+<br>
 #endif<br>
<br>
 #define        DEFAULT_RCLK    1843200<br>
@@ -225,11 +227,11 @@ DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL);<br>
 #ifdef __rtems__<br>
<br>
 #include <bsp.h><br>
-// #include <termios.h><br>
+#include <bsp/bspimpl.h><br>
+<br>
 #include <stdio.h><br>
 #include <stdlib.h><br>
<br>
-// #include <rtems/termiostypes.h><br>
 #include <libchip/serial.h><br>
 #include <libchip/ns16550.h><br>
 #include <rtems/bspIo.h><br>
@@ -242,36 +244,58 @@ DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL);<br>
  * Information saved from PCI scan<br>
  */<br>
 typedef struct {<br>
-  bool      found;<br>
-  uint32_t  base;<br>
-  uint8_t   irq;<br>
-  uint8_t   bus;<br>
-  uint8_t   slot;<br>
-  int       ports;<br>
-  uint32_t  clock;<br>
+  bool        found;<br>
+  const char* desc;<br>
+  uint32_t    base;<br>
+  uint8_t     irq;<br>
+  uint8_t     bus;<br>
+  uint8_t     slot;<br>
+  int         ports;<br>
+  uint32_t    clock;<br>
 } port_instance_conf_t;<br>
<br>
 /*<br>
- *  Register Access Routines<br>
+ *  Memory Mapped Register Access Routines<br>
  */<br>
-static uint8_t pci_ns16550_get_register(uint32_t addr, uint8_t i)<br>
+<br>
+#define UART_PCI_IO (0)<br>
+<br>
+static uint8_t pci_ns16550_mem_get_register(uint32_t addr, uint8_t i)<br>
 {<br>
   uint8_t          val = 0;<br>
   volatile uint32_t *reg = (volatile uint32_t *)(addr + (i*4));<br>
-<br>
   val = *reg;<br>
-  /* printk( "RD(%p -> 0x%02x) ", reg, val ); */<br>
+  if (UART_PCI_IO)<br>
+    printk( "RD(%p -> 0x%02x) ", reg, val );<br>
   return val;<br>
 }<br>
<br>
-static void pci_ns16550_set_register(uint32_t addr, uint8_t i, uint8_t val)<br>
+static void pci_ns16550_mem_set_register(uint32_t addr, uint8_t i, uint8_t val)<br>
 {<br>
   volatile uint32_t *reg = (volatile uint32_t *)(addr + (i*4));<br>
-<br>
-  /* printk( "WR(%p <- 0x%02x) ", reg, val ); */<br>
+  if (UART_PCI_IO)<br>
+    printk( "WR(%p <- 0x%02x) ", reg, val );<br>
   *reg = val;<br>
 }<br>
<br>
+/*<br>
+ *  IO Register Access Routines<br>
+ */<br>
+static uint8_t pci_ns16550_io_get_register(uint32_t addr, uint8_t i)<br>
+{<br>
+  uint8_t val = rtems_inb(addr + i);<br>
+  if (UART_PCI_IO)<br>
+    printk( "RD(%p -> 0x%02x) ", addr + i, val );<br>
+  return val;<br>
+}<br>
+<br>
+static void pci_ns16550_io_set_register(uint32_t addr, uint8_t i, uint8_t val)<br>
+{<br>
+  if (UART_PCI_IO)<br>
+    printk( "WR(%p <- 0x%02x) ", addr + i, val );<br>
+  rtems_outb(addr + i, val);<br>
+}<br>
+<br></blockquote><div><br></div><div>Is it possible to use the same com access ports that are used for com1-com4?</div><div>Or at least move to shared ones?</div><div><br></div><div>They are in conscfg.c. It would be good if we could eliminate some code during</div><div>this. :)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 void pci_uart_probe(void)<br>
 {<br>
   port_instance_conf_t  conf[MAX_BOARDS];<br>
@@ -316,27 +340,28 @@ void pci_uart_probe(void)<br>
       if ( status == PCIB_ERR_SUCCESS ) {<br>
        uint8_t  irq;<br>
        uint32_t base;<br>
+       bool io;<br>
<br>
-        boards++;<br>
-        conf[instance].found = true;<br>
-        conf[instance].clock =  pci_ns8250_ids[i].rclk;<br>
-        conf[instance].ports = 1;<br>
-        total_ports += conf[instance].ports;<br>
-<br>
-       pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );<br>
        pci_read_config_dword( bus, dev, fun, PCI_BASE_ADDRESS_0, &base );<br>
<br>
-       conf[instance].irq  = irq;<br>
-       conf[instance].base = base;<br>
-<br>
-        printk(<br>
-          "Found %s #%d at 0x%08x IRQ %d with %d clock\n",<br>
-         pci_ns8250_ids[i].desc,<br>
-         instance,<br>
-         conf[instance].base,<br>
-         conf[instance].irq,<br>
-         conf[instance].clock<br>
-        );<br>
+       /*<br>
+        * Reject memory mapped 64-bit boards. We need 2 BAR registers and the<br>
+        * driver's base field is only 32-bits any way.<br>
+        */<br>
+       io = (base & 1) == 1;<br>
+       if (io || (!io && (((base >> 1) & 3) != 2))) {<br>
+         boards++;<br>
+         conf[instance].found = true;<br>
+         conf[instance].desc = pci_ns8250_ids[i].desc;<br>
+         conf[instance].clock =  pci_ns8250_ids[i].rclk;<br>
+         conf[instance].ports = 1;<br>
+         total_ports += conf[instance].ports;<br>
+<br>
+         pci_read_config_byte( bus, dev, fun, PCI_INTERRUPT_LINE, &irq );<br>
+<br>
+         conf[instance].irq  = irq;<br>
+         conf[instance].base = base;<br>
+       }<br>
       }<br>
     }<br>
   }<br>
@@ -352,6 +377,10 @@ void pci_uart_probe(void)<br>
       port_p = ports;<br>
       device_instance = 1;<br>
       for (b = 0; b < MAX_BOARDS; b++) {<br>
+       uint32_t base = 0;<br>
+       bool io;<br>
+       const char* locatable = "";<br>
+       const char* prefectable = locatable;<br>
        char name[32];<br>
        if ( conf[b].found == false )<br>
          continue;<br>
@@ -369,21 +398,68 @@ void pci_uart_probe(void)<br>
          port_p->pDeviceFns    = &ns16550_fns_polled;<br>
        }<br>
<br>
+       /*<br>
+        * PCI BAR (<a href="http://wiki.osdev.org/PCI#Base_Address_Registers" rel="noreferrer" target="_blank">http://wiki.osdev.org/PCI#Base_Address_Registers</a>):<br>
+        *<br>
+        *  Bit 0: 0 = memory, 1 = IO<br>
+        *<br>
+        * Memory:<br>
+        *  Bit 2-1  : 0 = any 32bit address,<br>
+        *             1 = < 1M<br>
+        *             2 = any 64bit address<br>
+        *  Bit 3    : 0 = no, 1 = yes<br>
+        *  Bit 31-4 : base address (16-byte aligned)<br>
+        *<br>
+        * IO:<br>
+        *  Bit 1    : reserved<br>
+        *  Bit 31-2 : base address (4-byte aligned)<br>
+        */<br>
+<br>
+       io = (conf[b].base & 1) == 1;<br>
+<br>
+       if (io) {<br>
+         base = conf[b].base & 0xfffffffc;<br>
+       } else {<br>
+         int loc = (conf[b].base >> 1) & 3;<br>
+         if (loc == 0) {<br>
+           base = conf[b].base & 0xfffffff0;<br>
+           locatable = ",A32";<br>
+         } else if (loc == 1) {<br>
+           base = conf[b].base & 0x0000fff0;<br>
+           locatable = ",A16";<br>
+         }<br>
+         prefectable = (conf[b].base & (1 << 3)) == 0 ? ",no-prefech" : ",prefetch";<br>
+       }<br>
+<br>
        port_p->deviceProbe   = NULL;<br>
        port_p->pDeviceFlow   = NULL;<br>
        port_p->ulMargin      = 16;<br>
        port_p->ulHysteresis  = 8;<br>
        port_p->pDeviceParams = (void *) 9600;<br>
-       port_p->ulCtrlPort1   = conf[b].base;<br>
+       port_p->ulCtrlPort1   = base;<br>
        port_p->ulCtrlPort2   = 0;                   /* NA */<br>
        port_p->ulDataPort    = 0;                   /* NA */<br>
-       port_p->getRegister   = pci_ns16550_get_register;<br>
-       port_p->setRegister   = pci_ns16550_set_register;<br>
+       if (io) {<br>
+         port_p->getRegister = pci_ns16550_io_get_register;<br>
+         port_p->setRegister = pci_ns16550_io_set_register;<br>
+       } else {<br>
+         port_p->getRegister = pci_ns16550_mem_get_register;<br>
+         port_p->setRegister = pci_ns16550_mem_set_register;<br>
+       }<br>
        port_p->getData       = NULL;                /* NA */<br>
        port_p->setData       = NULL;                /* NA */<br>
        port_p->ulClock       = conf[b].clock;<br>
        port_p->ulIntVector   = conf[b].irq;<br>
<br>
+<br>
+        printk(<br>
+          "%s:%d:%s,%s:0x%x%s%s,irq:%d,clk:%d\n", /*  */<br>
+         name, b, conf[b].desc,<br>
+         io ? "io" : "mem", base, locatable, prefectable,<br>
+         conf[b].irq, conf[b].clock<br>
+        );<br>
+<br>
+<br>
        port_p++;<br>
       }    /* end boards */<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.4.6<br>
<br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</font></span></blockquote></div><br></div></div>