grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/3] serial: ns8250-compatible PCI UART driver
@ 2017-02-22 10:09 Matthias Lange
  2017-02-22 10:09 ` [PATCH 1/3] serial: Add abstractions to ns8250 driver Matthias Lange
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Matthias Lange @ 2017-02-22 10:09 UTC (permalink / raw)
  To: grub-devel

Hi,

for testing we use a couple of (x86) machines locked away in a server room. To
remotely control what to boot on these machines we use grub2 navigated via a
serial line. Some of those machines don't feature a traditional IO port based
UART. That's why we installed PCI UART cards with an OXSemiconductor chip.
The ns8250-compatible UARTs on those cards are programmed via MMIO.

I am sending three patches to add support for these UARTs to grub2. Basically
the first two patches lay the groundwork and introduce neccessary abstractions
so that patch 3 can implement the driver with a maximum of code reuse from the
existing ns8250 serial driver.

I am asking for guidance on how to get this feature upstream. I think the
driver is an interesting addition to grub and others might be interested in it
as well. At least we have a few customers who would like to use it as well.

I am happy to take your feedback.

Best regards,
Matthias.

Matthias Lange (3):
  serial: Add abstractions to ns8250 driver
  serial: Move static ns8250 functions to ns8250 interface
  serial: Add serial driver for ns8250 compatible PCI UART

 grub-core/Makefile.core.def      |   1 +
 grub-core/term/ns8250-pci-mmio.c | 186 +++++++++++++++++++++++++++++++++++++++
 grub-core/term/ns8250.c          |  59 ++++++++-----
 grub-core/term/serial.c          |   9 +-
 include/grub/ns8250.h            |  48 ++++++++++
 include/grub/pci.h               |   8 ++
 include/grub/serial.h            |  25 ++++++
 7 files changed, 312 insertions(+), 24 deletions(-)
 create mode 100644 grub-core/term/ns8250-pci-mmio.c

-- 
2.7.4



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] serial: Add abstractions to ns8250 driver
  2017-02-22 10:09 [RFC PATCH 0/3] serial: ns8250-compatible PCI UART driver Matthias Lange
@ 2017-02-22 10:09 ` Matthias Lange
  2017-02-22 10:09 ` [PATCH 2/3] serial: Move static ns8250 functions to ns8250 interface Matthias Lange
  2017-02-22 10:09 ` [PATCH 3/3] serial: Add serial driver for ns8250 compatible PCI UART Matthias Lange
  2 siblings, 0 replies; 4+ messages in thread
From: Matthias Lange @ 2017-02-22 10:09 UTC (permalink / raw)
  To: grub-devel

The current implementation of the ns8250 serial driver is closely
tied to use IO ports. In order to support other ns8250 compatible
UART implementations in the future, a set of abstractions for
register/IO port access is needed.

This change introduces two things. Firstly it adds two functions to
the grub_serial_driver structure that a driver can implement to
abstract access to the UART hardware. Secondly it introduces a
grub_serial_board structure to encapsulate properties of the
specific UART hardware.

Further this change adapts the ns8250 serial driver to use the new
set of available abstractions.

Signed-off-by: Matthias Lange <matthias.lange@kernkonzept.com>
---
 grub-core/term/ns8250.c | 51 ++++++++++++++++++++++++++++++++-----------------
 include/grub/serial.h   |  9 +++++++++
 2 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c
index 39809d0..acc05eb 100644
--- a/grub-core/term/ns8250.c
+++ b/grub-core/term/ns8250.c
@@ -44,17 +44,28 @@ static int dead_ports = 0;
 #define DEFAULT_BASE_CLOCK 115200
 #endif
 
+static inline unsigned char
+io_port_read (struct grub_serial_port *port, grub_addr_t reg)
+{
+  return grub_inb (port->port + reg);
+}
+
+static inline void
+io_port_write (struct grub_serial_port *port, unsigned char value, grub_addr_t reg)
+{
+  grub_outb (value, port->port + reg);
+}
 
 /* Convert speed to divisor.  */
 static unsigned short
-serial_get_divisor (const struct grub_serial_port *port __attribute__ ((unused)),
+serial_get_divisor (const struct grub_serial_port *port,
 		    const struct grub_serial_config *config)
 {
   grub_uint32_t base_clock;
   grub_uint32_t divisor;
   grub_uint32_t actual_speed, error;
 
-  base_clock = config->base_clock ? (config->base_clock >> 4) : DEFAULT_BASE_CLOCK;
+  base_clock = config->base_clock ? (config->base_clock >> 4) : port->board.base_baud;
 
   divisor = (base_clock + (config->speed / 2)) / config->speed;
   if (config->speed == 0)
@@ -94,43 +105,43 @@ do_real_config (struct grub_serial_port *port)
   divisor = serial_get_divisor (port, &port->config);
 
   /* Turn off the interrupt.  */
-  grub_outb (0, port->port + UART_IER);
+  port->driver->reg_write (port, 0, UART_IER);
 
   /* Set DLAB.  */
-  grub_outb (UART_DLAB, port->port + UART_LCR);
+  port->driver->reg_write (port, UART_DLAB, UART_LCR);
 
   /* Set the baud rate.  */
-  grub_outb (divisor & 0xFF, port->port + UART_DLL);
-  grub_outb (divisor >> 8, port->port + UART_DLH);
+  port->driver->reg_write (port, divisor & 0xFF, UART_DLL);
+  port->driver->reg_write (port, divisor >> 8, UART_DLH);
 
   /* Set the line status.  */
   status |= (parities[port->config.parity]
 	     | (port->config.word_len - 5)
 	     | stop_bits[port->config.stop_bits]);
-  grub_outb (status, port->port + UART_LCR);
+  port->driver->reg_write (port, status, UART_LCR);
 
   if (port->config.rtscts)
     {
       /* Enable the FIFO.  */
-      grub_outb (UART_ENABLE_FIFO_TRIGGER1, port->port + UART_FCR);
+      port->driver->reg_write (port, UART_ENABLE_FIFO_TRIGGER1, UART_FCR);
 
       /* Turn on DTR and RTS.  */
-      grub_outb (UART_ENABLE_DTRRTS, port->port + UART_MCR);
+      port->driver->reg_write (port, UART_ENABLE_DTRRTS, UART_MCR);
     }
   else
     {
       /* Enable the FIFO.  */
-      grub_outb (UART_ENABLE_FIFO_TRIGGER14, port->port + UART_FCR);
+      port->driver->reg_write (port, UART_ENABLE_FIFO_TRIGGER14, UART_FCR);
 
       /* Turn on DTR, RTS, and OUT2.  */
-      grub_outb (UART_ENABLE_DTRRTS | UART_ENABLE_OUT2, port->port + UART_MCR);
+      port->driver->reg_write (port, UART_ENABLE_DTRRTS | UART_ENABLE_OUT2, UART_MCR);
     }
 
   /* Drain the input buffer.  */
   endtime = grub_get_time_ms () + 1000;
-  while (grub_inb (port->port + UART_LSR) & UART_DATA_READY)
+  while (port->driver->reg_read (port, UART_LSR) & UART_DATA_READY)
     {
-      grub_inb (port->port + UART_RX);
+      port->driver->reg_read (port, UART_RX);
       if (grub_get_time_ms () > endtime)
 	{
 	  port->broken = 1;
@@ -146,8 +157,8 @@ static int
 serial_hw_fetch (struct grub_serial_port *port)
 {
   do_real_config (port);
-  if (grub_inb (port->port + UART_LSR) & UART_DATA_READY)
-    return grub_inb (port->port + UART_RX);
+  if (port->driver->reg_read (port, UART_LSR) & UART_DATA_READY)
+    return port->driver->reg_read (port, UART_RX);
 
   return -1;
 }
@@ -167,7 +178,7 @@ serial_hw_put (struct grub_serial_port *port, const int c)
   else
     endtime = grub_get_time_ms () + 200;
   /* Wait until the transmitter holding register is empty.  */
-  while ((grub_inb (port->port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
+  while ((port->driver->reg_read (port, UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)
     {
       if (grub_get_time_ms () > endtime)
 	{
@@ -180,7 +191,7 @@ serial_hw_put (struct grub_serial_port *port, const int c)
   if (port->broken)
     port->broken--;
 
-  grub_outb (c, port->port + UART_TX);
+  port->driver->reg_write (port, c, UART_TX);
 }
 
 /* Initialize a serial device. PORT is the port number for a serial device.
@@ -228,7 +239,9 @@ struct grub_serial_driver grub_ns8250_driver =
   {
     .configure = serial_hw_configure,
     .fetch = serial_hw_fetch,
-    .put = serial_hw_put
+    .put = serial_hw_put,
+    .reg_read = io_port_read,
+    .reg_write = io_port_write,
   };
 
 static char com_names[GRUB_SERIAL_PORT_NUM][20];
@@ -260,6 +273,7 @@ grub_ns8250_init (void)
 	com_ports[i].name = com_names[i];
 	com_ports[i].driver = &grub_ns8250_driver;
 	com_ports[i].port = serial_hw_io_addr[i];
+        com_ports[i].board.base_baud = DEFAULT_BASE_CLOCK;
 	err = grub_serial_config_defaults (&com_ports[i]);
 	if (err)
 	  grub_print_error ();
@@ -312,6 +326,7 @@ grub_serial_ns8250_add_port (grub_port_t port)
   p->driver = &grub_ns8250_driver;
   grub_serial_config_defaults (p);
   p->port = port;
+  p->board.base_baud = DEFAULT_BASE_CLOCK;
   grub_serial_register (p);  
 
   return p->name;
diff --git a/include/grub/serial.h b/include/grub/serial.h
index 67379de..82d127e 100644
--- a/include/grub/serial.h
+++ b/include/grub/serial.h
@@ -43,6 +43,9 @@ struct grub_serial_driver
 			   struct grub_serial_config *config);
   int (*fetch) (struct grub_serial_port *port);
   void (*put) (struct grub_serial_port *port, const int c);
+  void (*reg_write) (struct grub_serial_port *port, unsigned char value,
+                     grub_addr_t reg);
+  unsigned char (*reg_read) (struct grub_serial_port *port, grub_addr_t reg);
   void (*fini) (struct grub_serial_port *port);
 };
 
@@ -71,6 +74,11 @@ struct grub_serial_config
   int rtscts;
 };
 
+struct grub_serial_board
+{
+  unsigned base_baud;
+};
+
 struct grub_serial_port
 {
   struct grub_serial_port *next;
@@ -80,6 +88,7 @@ struct grub_serial_port
   struct grub_serial_config config;
   int configured;
   int broken;
+  struct grub_serial_board board;
 
   /* This should be void *data but since serial is useful as an early console
      when malloc isn't available it's a union.
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] serial: Move static ns8250 functions to ns8250 interface
  2017-02-22 10:09 [RFC PATCH 0/3] serial: ns8250-compatible PCI UART driver Matthias Lange
  2017-02-22 10:09 ` [PATCH 1/3] serial: Add abstractions to ns8250 driver Matthias Lange
@ 2017-02-22 10:09 ` Matthias Lange
  2017-02-22 10:09 ` [PATCH 3/3] serial: Add serial driver for ns8250 compatible PCI UART Matthias Lange
  2 siblings, 0 replies; 4+ messages in thread
From: Matthias Lange @ 2017-02-22 10:09 UTC (permalink / raw)
  To: grub-devel

In order to reuse some ns8250 functions in other ns8250 compatible
drivers this change makes a few functions non-static and adds them
to the ns8250 interface in the ns8250.h header file.

Signed-off-by: Matthias Lange <matthias.lange@kernkonzept.com>
---
 grub-core/term/ns8250.c |  8 ++++----
 include/grub/ns8250.h   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c
index acc05eb..051021a 100644
--- a/grub-core/term/ns8250.c
+++ b/grub-core/term/ns8250.c
@@ -57,7 +57,7 @@ io_port_write (struct grub_serial_port *port, unsigned char value, grub_addr_t r
 }
 
 /* Convert speed to divisor.  */
-static unsigned short
+unsigned short
 serial_get_divisor (const struct grub_serial_port *port,
 		    const struct grub_serial_config *config)
 {
@@ -153,7 +153,7 @@ do_real_config (struct grub_serial_port *port)
 }
 
 /* Fetch a key.  */
-static int
+int
 serial_hw_fetch (struct grub_serial_port *port)
 {
   do_real_config (port);
@@ -164,7 +164,7 @@ serial_hw_fetch (struct grub_serial_port *port)
 }
 
 /* Put a character.  */
-static void
+void
 serial_hw_put (struct grub_serial_port *port, const int c)
 {
   grub_uint64_t endtime;
@@ -201,7 +201,7 @@ serial_hw_put (struct grub_serial_port *port, const int c)
    STOP_BIT_LEN is the length of the stop bit. The possible values for
    WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
    macros.  */
-static grub_err_t
+grub_err_t
 serial_hw_configure (struct grub_serial_port *port,
 		     struct grub_serial_config *config)
 {
diff --git a/include/grub/ns8250.h b/include/grub/ns8250.h
index 7947ba9..8c15855 100644
--- a/include/grub/ns8250.h
+++ b/include/grub/ns8250.h
@@ -20,6 +20,8 @@
 #ifndef GRUB_NS8250_HEADER
 #define GRUB_NS8250_HEADER	1
 
+#include <grub/serial.h>
+
 /* Macros.  */
 
 /* The offsets of UART registers.  */
@@ -75,6 +77,52 @@
 
 grub_port_t
 grub_ns8250_hw_get_port (const unsigned int unit);
+
+/**
+ * \brief Configure and setup a serial port.
+ *
+ * \param port    The serial port that should be set up.
+ * \param config  The configuration that should be applied to the serial port.
+ *
+ * \retval GRUB_ERR_NONE          Serial port setup and configured successfully.
+ * \retval GRUB_ERR_BAD_ARGUMENT  Unsupported serial configuration.
+ */
+grub_err_t
+serial_hw_configure (struct grub_serial_port *port,
+                     struct grub_serial_config *config);
+
+/**
+ * \brief Calculate the divisor for a given baud rate.
+ *
+ * \param port    The serial port for which the divisor needs to be calculated.
+ * \param config  The configuration with the wanted baud rate.
+ *
+ * \retval 0   No divisor could be calculated
+ * \retval >0  The divisor that needs to be programmed into the UART.
+ */
+unsigned short
+serial_get_divisor (const struct grub_serial_port *port,
+                    const struct grub_serial_config *config);
+
+/**
+ * \brief Send a character over a serial port.
+ *
+ * \param port  The serial port over which the character should be send.
+ * \param c     The character to send over the serial port.
+ */
+void
+serial_hw_put (struct grub_serial_port *port, const int c);
+
+/**
+ * \brief Read a character from a serial port.
+ *
+ * \param port  The serial port to read the character from.
+ *
+ * \return  The character read from the serial port.
+ */
+int
+serial_hw_fetch (struct grub_serial_port *port);
+
 #endif
 
 #endif /* ! GRUB_SERIAL_MACHINE_HEADER */
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] serial: Add serial driver for ns8250 compatible PCI UART
  2017-02-22 10:09 [RFC PATCH 0/3] serial: ns8250-compatible PCI UART driver Matthias Lange
  2017-02-22 10:09 ` [PATCH 1/3] serial: Add abstractions to ns8250 driver Matthias Lange
  2017-02-22 10:09 ` [PATCH 2/3] serial: Move static ns8250 functions to ns8250 interface Matthias Lange
@ 2017-02-22 10:09 ` Matthias Lange
  2 siblings, 0 replies; 4+ messages in thread
From: Matthias Lange @ 2017-02-22 10:09 UTC (permalink / raw)
  To: grub-devel

Currently grub only supports ns8250 UARTs using IO ports. However
there are ns8250 compatible UART implementations using PCI and an
MMIO interface.

This change adds support for PCI UARTs using an OXSemiconductor
chip. That UART must be programmed using MMIO.

Signed-off-by: Matthias Lange <matthias.lange@kernkonzept.com>
---
 grub-core/Makefile.core.def      |   1 +
 grub-core/term/ns8250-pci-mmio.c | 186 +++++++++++++++++++++++++++++++++++++++
 grub-core/term/serial.c          |   9 +-
 include/grub/pci.h               |   8 ++
 include/grub/serial.h            |  16 ++++
 5 files changed, 218 insertions(+), 2 deletions(-)
 create mode 100644 grub-core/term/ns8250-pci-mmio.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 2dfa22a..dc1827a 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1887,6 +1887,7 @@ module = {
   name = serial;
   common = term/serial.c;
   x86 = term/ns8250.c;
+  x86 = term/ns8250-pci-mmio.c;
   ieee1275 = term/ieee1275/serial.c;
   mips_arc = term/arc/serial.c;
   efi = term/efi/serial.c;
diff --git a/grub-core/term/ns8250-pci-mmio.c b/grub-core/term/ns8250-pci-mmio.c
new file mode 100644
index 0000000..58beb1d
--- /dev/null
+++ b/grub-core/term/ns8250-pci-mmio.c
@@ -0,0 +1,186 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/serial.h>
+#include <grub/ns8250.h>
+#include <grub/types.h>
+#include <grub/dl.h>
+#include <grub/pci.h>
+
+enum { GRUB_SERIAL_PCI_PORT_NUM = 8 };
+
+static inline void
+mmio_write (struct grub_serial_port *port, unsigned char val, grub_addr_t addr)
+{
+  *((volatile char *)(port->mmio_base + addr)) = val;
+}
+
+static inline unsigned char
+mmio_read (struct grub_serial_port *port, grub_addr_t addr)
+{
+  return *((volatile unsigned char *)(port->mmio_base + addr));
+}
+
+struct grub_serial_driver grub_ns8250_pci_mmio_driver =
+  {
+    .configure = serial_hw_configure,
+    .fetch = serial_hw_fetch,
+    .put = serial_hw_put,
+    .reg_write = mmio_write,
+    .reg_read = mmio_read,
+  };
+
+static char com_names[GRUB_SERIAL_PCI_PORT_NUM][20];
+static struct grub_serial_port ports[GRUB_SERIAL_PCI_PORT_NUM];
+
+struct drv_data
+{
+  unsigned cards;
+  unsigned num_ports;
+};
+
+static void
+read_bars(grub_pci_device_t dev, struct grub_serial_board *board)
+{
+  for (unsigned bar = 0; bar < NUM_BARS; ++bar)
+    {
+      int a = GRUB_PCI_REG_ADDRESSES + bar * 4;
+      grub_pci_address_t addr = grub_pci_make_address(dev, a);
+      unsigned v = grub_pci_read(addr);
+      grub_pci_write(addr, ~0U);
+      unsigned x = grub_pci_read(addr);
+      grub_pci_write(addr, v);
+
+      if (!v)
+        continue;
+
+      int s;
+      for (s = 2; s < 32; ++s)
+        if ((x >> s) & 1)
+          break;
+
+      if (0)
+        grub_printf("bar=%x (%s, sz=%d)\n", v, (v & 1) ? "IO" : "MEM", 1 << s);
+
+      board->bars[bar].base = v & ~3UL;
+      board->bars[bar].len = 1 << s;
+      board->bars[bar].type = (v & 1) ? IO_BAR : MEM_BAR;
+    }
+}
+
+static
+void enable_mmio(grub_pci_device_t dev)
+{
+  grub_pci_address_t addr = grub_pci_make_address(dev, GRUB_PCI_REG_COMMAND);
+  unsigned cmd = grub_pci_read_word(addr);
+  grub_pci_write_word(addr, cmd | GRUB_PCI_COMMAND_MEM_ENABLED);
+}
+
+static int
+ns8250_pci_mmio_iter(grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
+{
+  unsigned vendor, device;
+  struct drv_data *d = (struct drv_data *)data;
+
+  if (d->num_ports >= GRUB_SERIAL_PCI_PORT_NUM)
+    return 0;
+
+  vendor = pciid & 0xffff;
+  device = pciid >> 16;
+
+  if (vendor == 0x1415 && device == 0xc158)
+    {
+      struct grub_serial_port *port = &ports[d->num_ports];
+      struct grub_serial_board *b = &ports[d->num_ports].board;
+
+      if (0)
+        grub_printf("Found OXSEMI PCI UART\n");
+
+      read_bars(dev, b);
+
+      // this card has two serial ports
+      port->board.num_ports = 2;
+      port->board.base_baud = 4000000;
+      port->board.port_offset = 0x200;
+      port->board.base_offset = 0x1000;
+
+      port->pcidev.bus = dev.bus;
+      port->pcidev.device = dev.device;
+      port->pcidev.function = dev.function;
+      port->port_num = 0;
+      port->card = d->cards;
+      port->mmio_base = port->board.bars[0].base + port->board.base_offset +
+                         port->port_num * port->board.port_offset;
+      d->num_ports += 1;
+
+      if (d->num_ports >= GRUB_SERIAL_PCI_PORT_NUM)
+        return 0;
+
+      port = &ports[d->num_ports];
+
+      port->board.num_ports = 2;
+      port->board.base_baud = 4000000;
+      port->board.port_offset = 0x200;
+      port->board.base_offset = 0x1000;
+
+      port->pcidev.bus = dev.bus;
+      port->pcidev.device = dev.device;
+      port->pcidev.function = dev.function;
+      port->port_num = 1;
+      port->card = d->cards;
+      port->mmio_base = port->board.bars[0].base + port->board.base_offset +
+                         port->port_num * port->board.port_offset;
+
+      enable_mmio (dev);
+
+      d->num_ports += 1;
+      d->cards += 1;
+    }
+
+  return 0;
+}
+
+void
+grub_ns8250_pci_mmio_init (void)
+{
+  struct drv_data data = { .cards = 0, .num_ports = 0 };
+  unsigned i;
+
+  for (i = 0; i < GRUB_SERIAL_PCI_PORT_NUM; ++i)
+    {
+      ports[i].card = ~0UL;
+      ports[i].port_num = -1;
+    }
+
+  grub_pci_iterate(ns8250_pci_mmio_iter, &data);
+
+  for (i = 0; i < data.num_ports; i++)
+    {
+      grub_err_t err = 0;
+
+      grub_snprintf (com_names[i], sizeof (com_names[i]), "pci:%lu:%u",
+                     ports[i].card, ports[i].port_num);
+      ports[i].name = com_names[i];
+      ports[i].driver = &grub_ns8250_pci_mmio_driver;
+      err = grub_serial_config_defaults (&ports[i]);
+      if (err)
+        grub_print_error ();
+
+      grub_serial_register (&ports[i]);
+    }
+}
diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c
index db80b3b..8cdea15 100644
--- a/grub-core/term/serial.c
+++ b/grub-core/term/serial.c
@@ -201,8 +201,12 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args)
 
   if (state[OPTION_PORT].set)
     {
-      grub_snprintf (pname, sizeof (pname), "port%lx",
-		     grub_strtoul (state[1].arg, 0, 0));
+      if (grub_memcmp (state[OPTION_PORT].arg, "pci:", 4) == 0)
+          grub_snprintf(pname, sizeof (pname), "%s", state[1].arg);
+      else
+          grub_snprintf (pname, sizeof (pname), "port%lx",
+                         grub_strtoul (state[1].arg, 0, 0));
+
       name = pname;
     }
 
@@ -438,6 +442,7 @@ GRUB_MOD_INIT(serial)
 
 #if !defined (GRUB_MACHINE_EMU) && !defined(GRUB_MACHINE_ARC) && (defined(__mips__) || defined (__i386__) || defined (__x86_64__))
   grub_ns8250_init ();
+  grub_ns8250_pci_mmio_init ();
 #endif
 #ifdef GRUB_MACHINE_IEEE1275
   grub_ofserial_init ();
diff --git a/include/grub/pci.h b/include/grub/pci.h
index 70d9a05..e816d03 100644
--- a/include/grub/pci.h
+++ b/include/grub/pci.h
@@ -102,6 +102,14 @@ enum
 
 typedef grub_uint32_t grub_pci_id_t;
 
+enum { NO_BAR, IO_BAR, MEM_BAR };
+struct grub_pci_resource
+{
+  unsigned type;
+  unsigned long base;
+  unsigned long len;
+};
+
 #ifdef GRUB_MACHINE_EMU
 #include <grub/pciutils.h>
 #else
diff --git a/include/grub/serial.h b/include/grub/serial.h
index 82d127e..acd8b5e 100644
--- a/include/grub/serial.h
+++ b/include/grub/serial.h
@@ -23,6 +23,7 @@
 #include <grub/types.h>
 #if defined(__mips__) || defined (__i386__) || defined (__x86_64__)
 #include <grub/cpu/io.h>
+#include <grub/pci.h>
 #endif
 #include <grub/usb.h>
 #include <grub/list.h>
@@ -74,9 +75,15 @@ struct grub_serial_config
   int rtscts;
 };
 
+enum { NUM_BARS = 6 };
 struct grub_serial_board
 {
+  unsigned num_ports;
   unsigned base_baud;
+  unsigned port_offset;
+  unsigned base_offset;
+
+  struct grub_pci_resource bars[NUM_BARS];
 };
 
 struct grub_serial_port
@@ -100,6 +107,13 @@ struct grub_serial_port
 #endif
     struct
     {
+      grub_pci_device_t pcidev;
+      unsigned long card;
+      grub_port_t port_num;
+      grub_addr_t mmio_base;
+    };
+    struct
+    {
       grub_usb_device_t usbdev;
       int configno;
       int interfno;
@@ -186,6 +200,7 @@ grub_serial_config_defaults (struct grub_serial_port *port)
 
 #if defined(__mips__) || defined (__i386__) || defined (__x86_64__)
 void grub_ns8250_init (void);
+void grub_ns8250_pci_mmio_init (void);
 char *grub_serial_ns8250_add_port (grub_port_t port);
 #endif
 #ifdef GRUB_MACHINE_IEEE1275
@@ -204,6 +219,7 @@ grub_arcserial_add_port (const char *path);
 
 struct grub_serial_port *grub_serial_find (const char *name);
 extern struct grub_serial_driver grub_ns8250_driver;
+extern struct grub_serial_driver grub_ns8250_pci_mmio_driver;
 void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver);
 
 #ifndef GRUB_MACHINE_EMU
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-02-22 10:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-22 10:09 [RFC PATCH 0/3] serial: ns8250-compatible PCI UART driver Matthias Lange
2017-02-22 10:09 ` [PATCH 1/3] serial: Add abstractions to ns8250 driver Matthias Lange
2017-02-22 10:09 ` [PATCH 2/3] serial: Move static ns8250 functions to ns8250 interface Matthias Lange
2017-02-22 10:09 ` [PATCH 3/3] serial: Add serial driver for ns8250 compatible PCI UART Matthias Lange

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).