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