On Tue, Dec 20, 2016 at 03:01:52PM +0100, Ricardo Ribalda Delgado wrote:
Some chipsets have memory mapped serial ports. The
protocol is the same
as an standard uart, but with memory read/write instead of inb/outb.
Thanks. See my comments below.
[...]
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -532,6 +532,9 @@ menu "Debugging"
default 0x3f8
help
Base port for serial - generally 0x3f8, 0x2f8, 0x3e8, or 0x2e8.
+ On some boards the serial port is memory mapped, in those cases
+ provide the 32 bit address. E.g. 0xFEDC6000 for the AMD Kern
+ (a.k.a Hudson UART).
Does this chipset hardcode the uart at that memory address or is that
address part of a PCI BAR? If it's on a PCI device it would be
preferable to do a pci scan and find the address.
config DEBUG_IO
depends on QEMU_HARDWARE && DEBUG_LEVEL != 0
diff --git a/src/hw/serialio.c b/src/hw/serialio.c
index 6486fc086b1c..d02ab65f6e9b 100644
--- a/src/hw/serialio.c
+++ b/src/hw/serialio.c
@@ -17,6 +17,20 @@
#define DEBUG_TIMEOUT 100000
+static void
+serial_outb(u8 val, u32 port, u8 offset){
+ if (port < 0x10000)
+ return outb(val, port + offset);
+ writeb((void *)port + 4*offset, val);
+}
+
+static u8
+serial_inb(u32 port, u8 offset){
+ if (port < 0x10000)
+ return inb(port + offset);
+ return readb((void *)port + 4*offset);
+}
+
// Setup the debug serial port for output.
void
serial_debug_preinit(void)
@@ -25,12 +39,12 @@ serial_debug_preinit(void)
return;
// setup for serial logging: 8N1
u8 oldparam, newparam = 0x03;
- oldparam = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR);
- outb(newparam, CONFIG_DEBUG_SERIAL_PORT+SEROFF_LCR);
+ oldparam = serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_LCR);
+ serial_outb(newparam, CONFIG_DEBUG_SERIAL_PORT, SEROFF_LCR);
// Disable irqs
u8 oldier, newier = 0;
- oldier = inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER);
- outb(newier, CONFIG_DEBUG_SERIAL_PORT+SEROFF_IER);
+ oldier = serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_IER);
+ serial_outb(newier, CONFIG_DEBUG_SERIAL_PORT, SEROFF_IER);
if (oldparam != newparam || oldier != newier)
dprintf(1, "Changing serial settings was %x/%x now %x/%x\n"
@@ -44,11 +58,11 @@ serial_debug(char c)
if (!CONFIG_DEBUG_SERIAL)
return;
int timeout = DEBUG_TIMEOUT;
- while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x20) != 0x20)
+ while ((serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_LSR) & 0x20) != 0x20)
if (!timeout--)
// Ran out of time.
return;
- outb(c, CONFIG_DEBUG_SERIAL_PORT+SEROFF_DATA);
+ serial_outb(c, CONFIG_DEBUG_SERIAL_PORT, SEROFF_DATA);
}
The above code (along with serial_debug_flush() ) can be called in
16bit mode and writing to a 32bit memory address there can cause
failures (crashes or memory corruption). Simplest solution is
probably to only write to memory if !MODE_SEGMENT - thus providing
debug support only in 32bit mode (init and boot phases).
void
@@ -66,7 +80,7 @@ serial_debug_flush(void)
if (!CONFIG_DEBUG_SERIAL)
return;
int timeout = DEBUG_TIMEOUT;
- while ((inb(CONFIG_DEBUG_SERIAL_PORT+SEROFF_LSR) & 0x60) != 0x60)
+ while ((serial_inb(CONFIG_DEBUG_SERIAL_PORT, SEROFF_LSR) & 0x60) != 0x60)
if (!timeout--)
// Ran out of time.
return;
diff --git a/src/serial.c b/src/serial.c
index 88349c8a9267..27710cb19af9 100644
--- a/src/serial.c
+++ b/src/serial.c
@@ -21,7 +21,7 @@
static u16
detect_serial(u16 port, u8 timeout, u8 count)
{
- if (CONFIG_DEBUG_SERIAL && port == CONFIG_DEBUG_SERIAL_PORT
+ if (CONFIG_DEBUG_SERIAL && port == (u16) CONFIG_DEBUG_SERIAL_PORT
&& !romfile_loadint("etc/advertise-serial-debug-port", 1))
return 0;
outb(0x02, port+SEROFF_IER);
-Kevin