<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>