This is the mail archive of the ecos-devel@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Generic serial 8250/16x50 diagnostics support


Hi,

Currently, every platform copies and pastes the diagnostic support for
8250/16x50 compatible UARTs.  This is less than ideal, so I've
implemented generic support for diagnostics via 8250 UARTs.

The platform just needs to provide characteristics of the UARTs (base
address, clock frequency, interrupt vector, any quirks for the UART,
etc.).  As an example, I've converted the ixp4xx hal and the pc hal to
use it.

A couple of points I could use feedback on:

1. uart_write(), uart_read() may not be sufficiently generic (the .base
and .regshift scheme is what the Linux 8250 driver uses so it's probably
good for most platforms).  Should a mechanism be provided for the
platform to provide it's own function to read/write to UART registers?
e.g., function pointers in the serial_8250_channel_data_t structure?

2. Regarding the package name: CYGHWR_HAL_COMMON_8250_SERIAL_DIAG since
it's hardware related or CYGINT_HAL_COMMON_8250_SERIAL_DIAG since it's
an interface?

The attached patches are:

hal-common-serial-8250-diag:
  - The generic 8250 diagnostics driver.

hal-arm-xscale-ixp4xx-use-generic-diag:
  - update the ixp4xx HAL to use the generic diagnostics driver.

hal-i386-pc-use-generic-diag:
  - update the pc HAL to use the generic diagnostics driver.

David Vrabel
-- 
David Vrabel, Design Engineer

Arcom, Clifton Road           Tel: +44 (0)1223 411200 ext. 3233
Cambridge CB1 7EA, UK         Web: http://www.arcom.com/
Index: ecos-working/packages/hal/common/current/cdl/common.cdl
===================================================================
--- ecos-working.orig/packages/hal/common/current/cdl/common.cdl	2005-09-19 15:14:36.000000000 +0100
+++ ecos-working/packages/hal/common/current/cdl/common.cdl	2005-09-19 15:23:37.000000000 +0100
@@ -150,3 +150,9 @@
     }
 }
 
+cdl_interface CYGHWR_HAL_COMMON_8250_SERIAL_DIAG {
+    display     "Use the generic 8250 serial diagnostics routines"
+
+    compile     hal_serial_8250_diag.c
+}
+
Index: ecos-working/packages/hal/common/current/include/hal_serial_8250_diag.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ecos-working/packages/hal/common/current/include/hal_serial_8250_diag.h	2005-09-19 15:23:37.000000000 +0100
@@ -0,0 +1,69 @@
+#ifndef CYGONCE_HAL_8250_SERIAL_DIAG_H
+#define CYGONCE_HAL_8250_SERIAL_DIAG_H
+/*=============================================================================
+//
+//      hal_8250_serial_diag.h
+//
+//      HAL Support for Kernel Diagnostic Routines for 8250/16x50 UARTs
+//
+//=============================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2005 Arcom Control Systems Ltd.
+//
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    <knud.woehler@microplex.de>
+// Date:         2002-09-03
+//
+//####DESCRIPTIONEND####
+//
+//===========================================================================*/
+
+/*
+ * UART features
+ */
+#define UART_FEATURE_HAVE_UUE  0x1 /* Have UART Unit Enable bit in IER */
+
+typedef struct {
+    unsigned  freq;       /* frequeny of UART clock in Hz */
+    unsigned  base;       /* MMIO address or I/O port */
+    int       regshift;   /* shift to register offset */
+    int       isr_vector;
+    unsigned  uart_features;
+    int       baud_rate;
+    cyg_bool  valid;
+    cyg_int32 msec_timeout;
+} serial_8250_channel_data_t;
+
+externC void cyg_hal_serial_8250_diag_init(serial_8250_channel_data_t *channels, int num);
+
+#endif //CYGONCE_HAL_8250_SERIAL_DIAG_H
Index: ecos-working/packages/hal/common/current/src/hal_serial_8250_diag.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ecos-working/packages/hal/common/current/src/hal_serial_8250_diag.c	2005-09-19 15:54:56.000000000 +0100
@@ -0,0 +1,386 @@
+//=============================================================================
+//
+//      hal_serial_8250_diag.c
+//
+//      HAL diagnostic output code for 8250/16x50 UARTs
+//
+//=============================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2005  Arcom Control Systems Ltd.
+//
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):   <dvrabel@arcom.com>
+// Date:        2005-09-15
+//
+//####DESCRIPTIONEND####
+//
+//=============================================================================
+
+#include <pkgconf/hal.h>
+
+#include <cyg/infra/cyg_type.h>         // base types
+
+#include <cyg/hal/hal_arch.h>           // basic machine info
+#include <cyg/hal/hal_intr.h>           // interrupt macros
+#include <cyg/hal/hal_io.h>             // IO macros
+#include <cyg/hal/drv_api.h>
+#include <cyg/hal/hal_if.h>             // interface API
+#include <cyg/hal/hal_misc.h>
+
+#include <cyg/hal/hal_serial_8250_diag.h>
+
+
+/* 8250/16x50 UART registers */
+#define UART_RBR 0x00  // Receive Buffer Register
+
+#define UART_THR 0x00  // Transmit Holding Register
+
+#define UART_IER 0x01  // Interrupt Enable Register
+#  define UART_IER_RCV  0x01
+#  define UART_IER_XMT  0x02
+#  define UART_IER_LS   0x04
+#  define UART_IER_MS   0x08
+#  define UART_IER_UUE  0x40  // UART Unit Enable bit
+
+#define UART_IIR 0x02  // Interrupt Identification Register
+
+#define UART_FCR 0x02  // FIFO Control Register
+
+#define UART_LCR 0x03  // Line Control Register
+#  define UART_LCR_WLS0 0x01  // word length select bit 0
+#  define UART_LCR_WLS1 0x02  // word length select bit 1
+#  define UART_LCR_STB  0x04  // number of stop bits
+#  define UART_LCR_PEN  0x08  // parity enable
+#  define UART_LCR_EPS  0x10  // even parity select
+#  define UART_LCR_SP   0x20  // stick parity
+#  define UART_LCR_SB   0x40  // set break
+#  define UART_LCR_DLAB 0x80  // divisor latch access bit
+
+#define UART_MCR 0x04  // Modem Control Register
+#  define UART_MCR_DTR  0x01
+#  define UART_MCR_RTS  0x02
+#  define UART_MCR_INT  0x08  // Enable interrupts
+
+#define UART_LSR 0x05   // Line Status Register
+#  define UART_LSR_DR   0x01  // data ready
+#  define UART_LSR_OE   0x02  // overrun error
+#  define UART_LSR_PE   0x04  // parity error
+#  define UART_LSR_FE   0x08  // framing error
+#  define UART_LSR_BI   0x10  // break interrupt
+#  define UART_LSR_THRE 0x20  // transmitter holding register empty
+#  define UART_LSR_TEMT 0x40  // transmitter register empty
+#  define UART_LSR_ERR  0x80  // any error condition
+
+#define UART_MSR 0x06  // Modem Status Register
+#  define UART_MSR_DCTS 0x01  // delta clear to send
+#  define UART_MSR_DDSR 0x02  // delta data set ready
+#  define UART_MSR_TERI 0x04  // trailing edge ring indicator
+#  define UART_MSR_DDCD 0x08  // delta data carrier detect
+#  define UART_MSR_CTS  0x10  // clear to send
+#  define UART_MSR_DSR  0x20  // data set ready
+#  define UART_MSR_RI   0x40  // ring indicator
+#  define UART_MSR_DCD  0x80  // data carrier detect
+
+#define UART_DLL 0x00  // Divisor Latch LSB (if DLAB = 1)
+#define UART_DLM 0x01  // Divisor Latch MSB (if DLAB = 1)
+
+
+static void uart_write(serial_8250_channel_data_t *chan, int reg, cyg_uint8 data)
+{
+    HAL_WRITE_UINT8(chan->base + (reg << chan->regshift), data);
+}
+
+static cyg_uint8 uart_read(serial_8250_channel_data_t *chan, int reg)
+{
+    cyg_uint8 data;
+    HAL_READ_UINT8(chan->base + (reg << chan->regshift), data);
+    return data;
+}
+
+static void set_baud(serial_8250_channel_data_t *chan)
+{
+    unsigned divisor;
+    cyg_uint32 lcr;
+
+    divisor = (chan->freq + 8*chan->baud_rate) / (16*chan->baud_rate);
+
+    lcr = uart_read(chan, UART_LCR);
+    uart_write(chan, UART_LCR, lcr | UART_LCR_DLAB);
+    uart_write(chan, UART_DLL, divisor & 0xff);
+    uart_write(chan, UART_DLM, (divisor >> 8) & 0xff);
+    uart_write(chan, UART_LCR, lcr);
+}
+
+static void init_channel(serial_8250_channel_data_t *chan)
+{
+    cyg_uint8 ier, lsr;
+
+    ier = 0;
+    if (chan->uart_features & UART_FEATURE_HAVE_UUE)
+        ier |= UART_IER_UUE;
+    uart_write(chan, UART_IER, ier);
+    uart_write(chan, UART_MCR, 0);
+
+    set_baud(chan);
+
+    // 8-1-no parity.
+    uart_write(chan, UART_LCR, UART_LCR_WLS0 | UART_LCR_WLS1);
+
+    // Test whether the channel is valid or not. If the status
+    // register reads back all ones, its a fair bet that it is not
+    // actually there!
+    lsr = uart_read(chan, UART_LSR);
+    chan->valid = (lsr != 0xFF);
+
+    uart_write(chan, UART_FCR, 0x07); // Enable & clear FIFO
+}
+
+static void cyg_hal_serial_8250_diag_putc(void *__ch_data, char c)
+{
+    serial_8250_channel_data_t *chan = (serial_8250_channel_data_t *)__ch_data;
+    cyg_uint8 lsr;
+
+    if (!chan->valid)
+            return;
+
+    CYGARC_HAL_SAVE_GP();
+    do {
+        lsr = uart_read(chan, UART_LSR);
+    } while ((lsr & UART_LSR_THRE) == 0);
+
+    uart_write(chan, UART_THR, c);
+
+    CYGARC_HAL_RESTORE_GP();
+}
+
+static cyg_bool cyg_hal_serial_8250_diag_getc_nonblock(void* __ch_data, cyg_uint8* ch)
+{
+    serial_8250_channel_data_t *chan = (serial_8250_channel_data_t *)__ch_data;
+    cyg_uint8 lsr;
+
+    if (!chan->valid)
+        return false;
+
+    lsr = uart_read(chan, UART_LSR);
+    if ((lsr & UART_LSR_DR) == 0)
+        return false;
+
+    *ch = uart_read(chan, UART_RBR);
+
+    return true;
+}
+
+static cyg_uint8 cyg_hal_serial_8250_diag_getc(void* __ch_data)
+{
+    serial_8250_channel_data_t *chan = (serial_8250_channel_data_t *)__ch_data;
+    cyg_uint8 ch;
+
+    if (!chan->valid)
+        return '\n';
+
+    CYGARC_HAL_SAVE_GP();
+
+    while (!cyg_hal_serial_8250_diag_getc_nonblock(__ch_data, &ch));
+
+    CYGARC_HAL_RESTORE_GP();
+
+    return ch;
+}
+
+static void cyg_hal_serial_8250_diag_write(void* __ch_data, const cyg_uint8* __buf,
+                                           cyg_uint32 __len)
+{
+    CYGARC_HAL_SAVE_GP();
+
+    while(__len-- > 0)
+        cyg_hal_serial_8250_diag_putc(__ch_data, *__buf++);
+
+    CYGARC_HAL_RESTORE_GP();
+}
+
+static void cyg_hal_serial_8250_diag_read(void* __ch_data, cyg_uint8 *__buf, cyg_uint32 __len)
+{
+    CYGARC_HAL_SAVE_GP();
+
+    while(__len-- > 0)
+        *__buf++ = cyg_hal_serial_8250_diag_getc(__ch_data);
+
+    CYGARC_HAL_RESTORE_GP();
+}
+
+static cyg_bool cyg_hal_serial_8250_diag_getc_timeout(void* __ch_data, cyg_uint8 *ch)
+{
+    serial_8250_channel_data_t *chan = (serial_8250_channel_data_t *)__ch_data;
+    int delay_count;
+    cyg_bool res;
+
+    CYGARC_HAL_SAVE_GP();
+
+    delay_count = chan->msec_timeout * 10; // delay in 0.1 ms steps
+
+    for(;;) {
+        res = cyg_hal_serial_8250_diag_getc_nonblock(__ch_data, ch);
+        if (res || 0 == delay_count--)
+            break;
+
+        CYGACC_CALL_IF_DELAY_US(100);
+    }
+
+    CYGARC_HAL_RESTORE_GP();
+    return res;
+}
+
+
+static int cyg_hal_serial_8250_diag_control(void *__ch_data, __comm_control_cmd_t __func, ...)
+{
+    serial_8250_channel_data_t *chan = (serial_8250_channel_data_t *)__ch_data;
+    static int irq_state = 0;
+    int ret = 0;
+    cyg_uint8 ier;
+    cyg_uint32 b;
+    va_list ap;
+
+    CYGARC_HAL_SAVE_GP();
+
+    switch (__func) {
+    case __COMMCTL_GETBAUD:
+        ret = chan->baud_rate;
+        break;
+    case __COMMCTL_SETBAUD:
+        chan->baud_rate  = va_arg(ap, cyg_int32);
+        /* FIXME: Should check that the baud rate is valid? */
+        set_baud(chan);
+        break;
+    case __COMMCTL_IRQ_ENABLE:
+        irq_state = 1;
+
+        ier = UART_IER_RCV;
+        if (chan->uart_features & UART_FEATURE_HAVE_UUE)
+            ier |= UART_IER_UUE;
+        uart_write(chan, UART_IER, ier);
+        uart_write(chan, UART_MCR, UART_MCR_INT | UART_MCR_DTR | UART_MCR_RTS);
+
+        HAL_INTERRUPT_UNMASK(chan->isr_vector);
+        break;
+    case __COMMCTL_IRQ_DISABLE:
+        ret = irq_state;
+        irq_state = 0;
+
+        ier = 0;
+        if (chan->uart_features & UART_FEATURE_HAVE_UUE)
+            ier |= UART_IER_UUE;
+        uart_write(chan, UART_IER, ier);
+
+        HAL_INTERRUPT_MASK(chan->isr_vector);
+        break;
+    case __COMMCTL_DBG_ISR_VECTOR:
+        ret = chan->isr_vector;
+        break;
+    case __COMMCTL_SET_TIMEOUT:
+    {
+        va_list ap;
+
+        va_start(ap, __func);
+
+        ret = chan->msec_timeout;
+        chan->msec_timeout = va_arg(ap, cyg_uint32);
+
+        va_end(ap);
+    }
+    default:
+        break;
+    }
+
+    CYGARC_HAL_RESTORE_GP();
+    return ret;
+}
+
+static int cyg_hal_serial_8250_diag_isr(void *__ch_data, int *__ctrlc,
+                                  CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
+{
+    serial_8250_channel_data_t *chan = (serial_8250_channel_data_t *)__ch_data;
+    int res = 0;
+    char c;
+    cyg_uint8 lsr;
+
+    CYGARC_HAL_SAVE_GP();
+
+    cyg_drv_interrupt_acknowledge(chan->isr_vector);
+
+    *__ctrlc = 0;
+    lsr = uart_read(chan, UART_LSR);
+    if ( (lsr & UART_LSR_DR) != 0 ) {
+        c = uart_read(chan, UART_RBR);
+        if (cyg_hal_is_break(&c , 1))
+            *__ctrlc = 1;
+    }
+
+    res = CYG_ISR_HANDLED;
+
+    CYGARC_HAL_RESTORE_GP();
+    return res;
+}
+
+void cyg_hal_serial_8250_diag_init(serial_8250_channel_data_t *channels, int num)
+{
+    hal_virtual_comm_table_t* comm;
+    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
+    int i;
+
+    for (i = 0; i < num; i++) {
+        if (channels[i].baud_rate == 0)
+            channels[i].baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
+
+	HAL_INTERRUPT_MASK(channels[i].isr_vector);
+
+	init_channel(&channels[i]);
+
+	// Setup procs in the vector table
+	CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
+	comm = CYGACC_CALL_IF_CONSOLE_PROCS();
+	CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[i]);
+	CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_serial_8250_diag_write);
+	CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_serial_8250_diag_read);
+	CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_serial_8250_diag_putc);
+	CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_serial_8250_diag_getc);
+	CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_serial_8250_diag_control);
+	CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_serial_8250_diag_isr);
+	CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_serial_8250_diag_getc_timeout);
+    }
+
+    // Restore original console
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
+}
+
+//-----------------------------------------------------------------------------
+// End of hal_serial_8250_diag.c
Index: ecos-working/packages/hal/arm/xscale/ixp425/current/cdl/hal_arm_xscale_ixp425.cdl
===================================================================
--- ecos-working.orig/packages/hal/arm/xscale/ixp425/current/cdl/hal_arm_xscale_ixp425.cdl	2005-05-04 10:33:00.000000000 +0100
+++ ecos-working/packages/hal/arm/xscale/ixp425/current/cdl/hal_arm_xscale_ixp425.cdl	2005-09-19 11:09:34.000000000 +0100
@@ -55,6 +55,8 @@
     implements    CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
     implements    CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT
     implements    CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT
+    implements    CYGHWR_HAL_COMMON_8250_SERIAL_DIAG
+
     hardware
     include_dir   cyg/hal
     define_header hal_arm_xscale_ixp425.h
Index: ecos-working/packages/hal/arm/xscale/ixp425/current/src/ixp425_diag.c
===================================================================
--- ecos-working.orig/packages/hal/arm/xscale/ixp425/current/src/ixp425_diag.c	2003-03-18 13:10:04.000000000 +0000
+++ ecos-working/packages/hal/arm/xscale/ixp425/current/src/ixp425_diag.c	2005-09-19 11:25:59.000000000 +0100
@@ -66,348 +66,41 @@
 #include <cyg/hal/hal_if.h>             // interface API
 #include <cyg/hal/hal_misc.h>           // Helper functions
 
-#if !defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && !defined(CYGSEM_HAL_IXP425_PLF_USES_UART2)
-#define IXP425_NUM_UARTS 0
-#elif defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && defined(CYGSEM_HAL_IXP425_PLF_USES_UART2)
-#define IXP425_NUM_UARTS 2
-#else
-#define IXP425_NUM_UARTS 1
-#endif
-
-#if IXP425_NUM_UARTS > 0
-
-/*---------------------------------------------------------------------------*/
-/* 16550 compatible UARTS */
+#include <cyg/hal/hal_8250_serial_diag.h>
 
-// Define the serial registers.
-#define CYG_DEV_RBR   0x00 // receiver buffer register, read, dlab = 0
-#define CYG_DEV_THR   0x00 // transmitter holding register, write, dlab = 0
-#define CYG_DEV_DLL   0x00 // divisor latch (LS), read/write, dlab = 1
-#define CYG_DEV_IER   0x01 // interrupt enable register, read/write, dlab = 0
-#define CYG_DEV_DLM   0x01 // divisor latch (MS), read/write, dlab = 1
-#define CYG_DEV_IIR   0x02 // interrupt identification register, read, dlab = 0
-#define CYG_DEV_FCR   0x02 // fifo control register, write, dlab = 0
-#define CYG_DEV_LCR   0x03 // line control register, write
-#define CYG_DEV_MCR   0x04 // modem control register, write
-#define CYG_DEV_LSR   0x05 // line status register, read
-#define CYG_DEV_MSR   0x06 // modem status register, read
-#define CYG_DEV_SCR   0x07 // scratch pad register
-
-// Interrupt Enable Register
-#define SIO_IER_RCV 0x01
-#define SIO_IER_XMT 0x02
-#define SIO_IER_LS  0x04
-#define SIO_IER_MS  0x08
-#define SIO_IER_UUE 0x40  // UART Unit Enable
-
-// The line status register bits.
-#define SIO_LSR_DR      0x01            // data ready
-#define SIO_LSR_OE      0x02            // overrun error
-#define SIO_LSR_PE      0x04            // parity error
-#define SIO_LSR_FE      0x08            // framing error
-#define SIO_LSR_BI      0x10            // break interrupt
-#define SIO_LSR_THRE    0x20            // transmitter holding register empty
-#define SIO_LSR_TEMT    0x40            // transmitter register empty
-#define SIO_LSR_ERR     0x80            // any error condition
-
-// The modem status register bits.
-#define SIO_MSR_DCTS  0x01              // delta clear to send
-#define SIO_MSR_DDSR  0x02              // delta data set ready
-#define SIO_MSR_TERI  0x04              // trailing edge ring indicator
-#define SIO_MSR_DDCD  0x08              // delta data carrier detect
-#define SIO_MSR_CTS   0x10              // clear to send
-#define SIO_MSR_DSR   0x20              // data set ready
-#define SIO_MSR_RI    0x40              // ring indicator
-#define SIO_MSR_DCD   0x80              // data carrier detect
-
-// The line control register bits.
-#define SIO_LCR_WLS0   0x01             // word length select bit 0
-#define SIO_LCR_WLS1   0x02             // word length select bit 1
-#define SIO_LCR_STB    0x04             // number of stop bits
-#define SIO_LCR_PEN    0x08             // parity enable
-#define SIO_LCR_EPS    0x10             // even parity select
-#define SIO_LCR_SP     0x20             // stick parity
-#define SIO_LCR_SB     0x40             // set break
-#define SIO_LCR_DLAB   0x80             // divisor latch access bit
-
-// Modem Control Register
-#define SIO_MCR_DTR    0x01
-#define SIO_MCR_RTS    0x02
-#define SIO_MCR_OUT1   0x04
-#define SIO_MCR_OUT2   0x08
-#define SIO_MCR_LOOP   0x10
-#define SIO_MCR_AFE    0x20
-
-#define UART1_BASE      0xC8000000 
-#define UART2_BASE      0xC8001000
-
-//-----------------------------------------------------------------------------
-typedef struct {
-    cyg_uint32* base;
-    cyg_int32 msec_timeout;
-    int isr_vector;
-    cyg_int32 baud_rate;
-} channel_data_t;
-
-
-//-----------------------------------------------------------------------------
-// Based on 14.7456 MHz xtal
-static int
-set_baud( channel_data_t *chan )
-{
-    cyg_uint32* base = chan->base;
-    cyg_uint16 div = 921600 / chan->baud_rate;
-    cyg_uint32 lcr;
-
-    HAL_READ_UINT32(base+CYG_DEV_LCR, lcr);
-    HAL_WRITE_UINT32(base+CYG_DEV_LCR, lcr|SIO_LCR_DLAB);
-    HAL_WRITE_UINT32(base+CYG_DEV_DLL, div & 0xff);
-    HAL_WRITE_UINT32(base+CYG_DEV_DLM, (div >> 8) & 0xff);
-    HAL_WRITE_UINT32(base+CYG_DEV_LCR, lcr);
-    return 1;
-}
-
-static void
-cyg_hal_plf_serial_init_channel(void* __ch_data)
-{
-    cyg_uint32* base = ((channel_data_t*)__ch_data)->base;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    
-    HAL_WRITE_UINT32(chan->base+CYG_DEV_IER, SIO_IER_UUE);
-
-    // 8-1-no parity.
-    HAL_WRITE_UINT32(base+CYG_DEV_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
-    chan->baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
-    set_baud( chan );
-    HAL_WRITE_UINT32(base+CYG_DEV_FCR, 0x07);  // Enable & clear FIFO
-    HAL_WRITE_UINT32(base+CYG_DEV_MCR, SIO_MCR_OUT2);  // Enable interrupt to core
-}
-
-void
-cyg_hal_plf_serial_putc(void *__ch_data, char c)
-{
-    cyg_uint32* base = ((channel_data_t*)__ch_data)->base;
-    cyg_uint32 lsr, val;
-    CYGARC_HAL_SAVE_GP();
-
-    do {
-       HAL_READ_UINT32(base+CYG_DEV_LSR, lsr);
-    } while ((lsr & SIO_LSR_THRE) == 0);
-    
-    val = c;
-    HAL_WRITE_UINT32(base+CYG_DEV_THR, val);
-
-    CYGARC_HAL_RESTORE_GP();
-}
-
-static cyg_bool
-cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
-{
-    cyg_uint32* base = ((channel_data_t*)__ch_data)->base;
-    cyg_uint32 lsr, val;
+#define UART1_BASE 0xC8000000
+#define UART2_BASE 0xC8001000
 
-    HAL_READ_UINT32(base+CYG_DEV_LSR, lsr);
-    if ((lsr & SIO_LSR_DR) == 0)
-        return false;
-
-    HAL_READ_UINT32(base+CYG_DEV_RBR, val);
-    *ch = val;
-
-    return true;
-}
-
-cyg_uint8
-cyg_hal_plf_serial_getc(void* __ch_data)
-{
-    cyg_uint8 ch;
-    CYGARC_HAL_SAVE_GP();
-
-    while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
-
-    CYGARC_HAL_RESTORE_GP();
-    return ch;
-}
-
-static channel_data_t plf_ser_channels[] = {
-#if defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && !defined(HAL_PLATFORM_UART2_FIRST)
-    { (cyg_uint32*)UART1_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART1 },
-#endif
-#if defined(CYGSEM_HAL_IXP425_PLF_USES_UART2)
-    { (cyg_uint32*)UART2_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART2 }
-#endif
-#if defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && defined(HAL_PLATFORM_UART2_FIRST)
-    { (cyg_uint32*)UART1_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART1 },
+#ifdef  __ARMEB__
+#define REG_OFFSET 3
+#else
+#define REG_OFFSET 0
 #endif
-};
-
-static void
-cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
-                         cyg_uint32 __len)
-{
-    CYGARC_HAL_SAVE_GP();
-
-    while(__len-- > 0)
-        cyg_hal_plf_serial_putc(__ch_data, *__buf++);
 
-    CYGARC_HAL_RESTORE_GP();
-}
-
-static void
-cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
-{
-    CYGARC_HAL_SAVE_GP();
-
-    while(__len-- > 0)
-        *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
-
-    CYGARC_HAL_RESTORE_GP();
-}
-
-cyg_bool
-cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
-{
-    int delay_count;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    cyg_bool res;
-    CYGARC_HAL_SAVE_GP();
-
-    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
-
-    for(;;) {
-        res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
-        if (res || 0 == delay_count--)
-            break;
-        
-        CYGACC_CALL_IF_DELAY_US(100);
-    }
-
-    CYGARC_HAL_RESTORE_GP();
-    return res;
-}
-
-static int
-cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
-{
-    static int irq_state = 0;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    int ret = 0;
-    CYGARC_HAL_SAVE_GP();
-
-    switch (__func) {
-    case __COMMCTL_IRQ_ENABLE:
-        irq_state = 1;
-
-	HAL_WRITE_UINT32(chan->base+CYG_DEV_IER, SIO_IER_RCV | SIO_IER_UUE);
-        HAL_INTERRUPT_UNMASK(chan->isr_vector);
-        break;
-    case __COMMCTL_IRQ_DISABLE:
-        ret = irq_state;
-        irq_state = 0;
-
-	HAL_WRITE_UINT32(chan->base+CYG_DEV_IER, SIO_IER_UUE);
-        HAL_INTERRUPT_MASK(chan->isr_vector);
-        break;
-    case __COMMCTL_DBG_ISR_VECTOR:
-        ret = chan->isr_vector;
-        break;
-    case __COMMCTL_SET_TIMEOUT:
+static channel_data_t ixp4xx_serial_channels[] = {
+#ifdef CYGSEM_HAL_IXP425_PLF_USES_UART1
     {
-        va_list ap;
-
-        va_start(ap, __func);
-
-        ret = chan->msec_timeout;
-        chan->msec_timeout = va_arg(ap, cyg_uint32);
-
-        va_end(ap);
-    }        
-    case __COMMCTL_GETBAUD:
-        ret = chan->baud_rate;
-        break;
-    case __COMMCTL_SETBAUD:
+        .freq          = 14745600,
+        .base          = UART1_BASE + REG_OFFSET,
+        .regshift      = 2,
+        .uart_features = UART_FEATURE_HAVE_UUE,
+        .isr_vector    = CYGNUM_HAL_INTERRUPT_UART1,
+    },
+#endif
+#ifdef CYGSEM_HAL_IXP425_PLF_USES_UART2
     {
-	cyg_uint32 b;
-        va_list ap;
-
-        va_start(ap, __func);
-        b = va_arg(ap, cyg_int32);
-        va_end(ap);
-
-	if (b < 300 || b > 115200)
-	    ret = -1;
-	else {
-	    chan->baud_rate = b;
-	    ret = set_baud(chan);
-	}
-        break;
-    }
-    default:
-        break;
-    }
-    CYGARC_HAL_RESTORE_GP();
-    return ret;
-}
-
-static int
-cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
-                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
-{
-    int res = 0;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    char c;
-    cyg_uint8 lsr;
-    CYGARC_HAL_SAVE_GP();
-
-    cyg_drv_interrupt_acknowledge(chan->isr_vector);
-
-    *__ctrlc = 0;
-    HAL_READ_UINT32(chan->base+CYG_DEV_LSR, lsr);
-    if ( (lsr & SIO_LSR_DR) != 0 ) {
-
-        HAL_READ_UINT32(chan->base+CYG_DEV_RBR, c);
-        if( cyg_hal_is_break( &c , 1 ) )
-            *__ctrlc = 1;
-
-        res = CYG_ISR_HANDLED;
-    }
-
-    CYGARC_HAL_RESTORE_GP();
-    return res;
-}
-
-void
-cyg_hal_ixp425_serial_init(void)
-{
-    hal_virtual_comm_table_t* comm;
-    int i, cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
-
-    for (i = 0; i < IXP425_NUM_UARTS; i++) {
-
-	// Disable interrupts.
-	HAL_INTERRUPT_MASK(plf_ser_channels[i].isr_vector);
+        .freq          = 14745600,
+        .base          = UART2_BASE + REG_OFFSET,
+        .regshift      = 2,
+        .uart_features = UART_FEATURE_HAVE_UUE,
+        .isr_vector    = CYGNUM_HAL_INTERRUPT_UART2,
+    },
+#endif
+};
 
-	// Init channels
-	cyg_hal_plf_serial_init_channel(&plf_ser_channels[i]);
-
-	// Setup procs in the vector table
-	CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
-	comm = CYGACC_CALL_IF_CONSOLE_PROCS();
-	CYGACC_COMM_IF_CH_DATA_SET(*comm, &plf_ser_channels[i]);
-	CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
-	CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
-	CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
-	CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
-	CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
-	CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
-	CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
-    }
-    // Restore original console
-    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
-}
+/* FIXME: Move somewhere common */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
-// If the platform provides some channels of its own, then this function will be
-// provided by that platform.
-#if !defined(CYGNUM_HAL_IXP425_PLF_SERIAL_CHANNELS) || !CYGNUM_HAL_IXP425_PLF_SERIAL_CHANNELS 
 void
 cyg_hal_plf_comms_init(void)
 {
@@ -418,11 +111,8 @@
 
     initialized = 1;
 
-    cyg_hal_ixp425_serial_init();
+    cyg_hal_8250_serial_diag_init(ixp4xx_serial_channels, ARRAY_SIZE(ixp4xx_serial_channels));
 }
-#endif
-
-#endif // IXP425_NUM_UARTS > 0
 
 /*---------------------------------------------------------------------------*/
 
Index: ecos-working/packages/hal/i386/pc/current/cdl/hal_i386_pc.cdl
===================================================================
--- ecos-working.orig/packages/hal/i386/pc/current/cdl/hal_i386_pc.cdl	2005-09-05 16:22:55.000000000 +0100
+++ ecos-working/packages/hal/i386/pc/current/cdl/hal_i386_pc.cdl	2005-09-16 15:51:07.000000000 +0100
@@ -64,6 +64,7 @@
     implements    CYGINT_HAL_DEBUG_GDB_STUBS_BREAK
     implements	  CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT
     implements	  CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT_GUARANTEED
+    implements    CYGINT_HAL_COMMON_8250_SERIAL_DIAG
 
     define_proc {
         puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H   <pkgconf/hal_i386.h>"
Index: ecos-working/packages/hal/i386/pc/current/src/hal_diag.c
===================================================================
--- ecos-working.orig/packages/hal/i386/pc/current/src/hal_diag.c	2002-05-24 00:03:13.000000000 +0100
+++ ecos-working/packages/hal/i386/pc/current/src/hal_diag.c	2005-09-19 14:16:30.000000000 +0100
@@ -70,54 +70,62 @@
 #include <cyg/hal/hal_if.h>             // interface API
 #include <cyg/hal/hal_misc.h>           // Helper functions
 
-#include <cyg/hal/pcmb_serial.h>
+#include <cyg/hal/hal_serial_8250_diag.h>
+#include <cyg/hal/pcmb_screen.h>
 
 //=============================================================================
 
 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \
     || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
 
-channel_data_t pc_ser_channels[CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS];
+static serial_8250_channel_data_t pc_ser_channels[] = {
+#if (defined(CYGSEM_HAL_I386_PC_DIAG_SCREEN) && CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS >= 2) \
+    || (!defined(CYGSEM_HAL_I386_PC_DIAG_SCREEN) && CYGNUM_HAL_VIRTUAL_VECTORS >= 1)
+    {
+        .freq         = 1843200,
+        .base         = 0x3f8,
+        .msec_timeout = 1000,
+        .isr_vector   = 36,
+    },
+#endif
+#if (defined(CYGSEM_HAL_I386_PC_DIAG_SCREEN) && CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS >= 3) \
+    || (!defined(CYGSEM_HAL_I386_PC_DIAG_SCREEN) && CYGNUM_HAL_VIRTUAL_VECTORS >= 2)
+    {
+        .freq         = 1843200,
+        .base         = 0x2f8,
+        .msec_timeout = 1000,
+        .isr_vector   = 35,
+    },
+#endif
+};
+
+#ifdef CYGSEM_HAL_I386_PC_DIAG_SCREEN
+static pcmb_screen_channel_data_t pc_screen_channel = {
+    .isr_vector   = 33,
+    .msec_timeout = 1000,
+};
+#endif
+
+/* FIXME: Move somewhere common */
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 void
 cyg_hal_plf_comms_init(void)
 {
     static int initialized = 0;
-    int num_serial;
 
     if (initialized)
         return;
 
     initialized = 1;
 
-    num_serial = CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;
-#ifdef CYGSEM_HAL_I386_PC_DIAG_SCREEN
-    --num_serial;
-#endif
-    if (num_serial > 0) {
-	// COM1
-	pc_ser_channels[0].base = 0x3F8;
-	pc_ser_channels[0].msec_timeout = 1000;
-	pc_ser_channels[0].isr_vector = 36;
-    }
-    if (num_serial > 1) {
-	// COM2
-	pc_ser_channels[1].base = 0x2F8;
-	pc_ser_channels[1].msec_timeout = 1000;
-	pc_ser_channels[1].isr_vector = 35;
-    }
-
-    cyg_hal_plf_serial_init();
+    cyg_hal_serial_8250_diag_init(pc_ser_channels, ARRAY_SIZE(pc_ser_channels));
 
 #ifdef CYGSEM_HAL_I386_PC_DIAG_SCREEN
-    
-    pc_ser_channels[num_serial].base = 0x060;
-    pc_ser_channels[num_serial].msec_timeout = 1000;
-    pc_ser_channels[num_serial].isr_vector = 33;
 
-    cyg_hal_plf_screen_init();
+    cyg_hal_plf_screen_init(&pc_screen_channel);
 
-#endif    
+#endif
 }
 
 //=============================================================================
Index: ecos-working/packages/hal/i386/pcmb/current/cdl/hal_i386_pcmb.cdl
===================================================================
--- ecos-working.orig/packages/hal/i386/pcmb/current/cdl/hal_i386_pcmb.cdl	2005-05-04 10:33:29.000000000 +0100
+++ ecos-working/packages/hal/i386/pcmb/current/cdl/hal_i386_pcmb.cdl	2005-09-16 16:19:22.000000000 +0100
@@ -66,7 +66,7 @@
     found on modern motherboards, such as ethernet, sound and
     video devices. These are supported by drivers elsewhere."
 
-    compile      pcmb_misc.c pcmb_serial.c 
+    compile      pcmb_misc.c
 
     implements   CYGINT_HAL_I386_MEM_REAL_REGION_TOP
     implements   CYGINT_HAL_PLF_IF_IDE
Index: ecos-working/packages/hal/i386/pcmb/current/include/pcmb_screen.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ecos-working/packages/hal/i386/pcmb/current/include/pcmb_screen.h	2005-09-19 14:07:58.000000000 +0100
@@ -0,0 +1,50 @@
+#ifndef CYGONCE_HAL_PCMB_SCREEN_H
+#define CYGONCE_HAL_PCMB_SCREEN_H
+
+//==========================================================================
+//
+//      pcmb_screen.h
+//
+//      i386/pc Motherboard screen device support
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos 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 2 or (at your option) any later version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+
+typedef struct {
+    int       isr_vector;
+    cyg_int32 msec_timeout;
+} pcmb_screen_channel_data_t;
+
+#endif /* CYGONCE_HAL_PCMB_SCREEN_H */
Index: ecos-working/packages/hal/i386/pcmb/current/include/pcmb_serial.h
===================================================================
--- ecos-working.orig/packages/hal/i386/pcmb/current/include/pcmb_serial.h	2005-01-22 15:11:31.000000000 +0000
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,96 +0,0 @@
-#ifndef CYGONCE_HAL_PCMB_SERIAL_H
-#define CYGONCE_HAL_PCMB_SERIAL_H
-
-//==========================================================================
-//
-//      pcmb_serial.h
-//
-//      i386/pc Motherboard serial device support
-//
-//==========================================================================
-//####ECOSGPLCOPYRIGHTBEGIN####
-// -------------------------------------------
-// This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-//
-// eCos 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 2 or (at your option) any later version.
-//
-// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
-// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-//
-// As a special exception, if other files instantiate templates or use macros
-// or inline functions from this file, or you compile this file and link it
-// with other works to produce a work based on this file, this file does not
-// by itself cause the resulting work to be covered by the GNU General Public
-// License. However the source code for this file must still be made available
-// in accordance with section (3) of the GNU General Public License.
-//
-// This exception does not invalidate any other reasons why a work based on
-// this file might be covered by the GNU General Public License.
-//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
-// -------------------------------------------
-//####ECOSGPLCOPYRIGHTEND####
-//==========================================================================
-//#####DESCRIPTIONBEGIN####
-//
-// Author(s):    nickg
-// Contributors: 
-// Date:         2001-03-07
-// Purpose:      PC serial support
-// Description:  
-//               
-//               
-//               
-//               
-//               
-//              
-// Usage:
-//               #include <cyg/hal/pcmb_serial.h>
-//               ...
-//
-//####DESCRIPTIONEND####
-//
-//==========================================================================
-
-#include <pkgconf/hal.h>
-#include <pkgconf/hal_i386.h>
-#include <pkgconf/hal_i386_pcmb.h>
-
-#include <cyg/infra/cyg_type.h>
-
-//---------------------------------------------------------------------------
-
-//=============================================================================
-
-typedef struct {
-    cyg_uint16  base;
-    cyg_uint16  valid;
-    cyg_int32   msec_timeout;
-    cyg_int32   isr_vector;
-} channel_data_t;
-
-__externC channel_data_t pc_ser_channels[];
-
-//=============================================================================
-
-__externC void cyg_hal_plf_serial_init(void);
-
-#if CYGINT_HAL_I386_PCMB_SCREEN_SUPPORT > 0
-
-__externC void cyg_hal_plf_screen_init(void);
-__externC void cyg_hal_plf_screen_position(int *x, int *y);
-#endif
-
-//---------------------------------------------------------------------------
-#endif // ifndef CYGONCE_HAL_PCMB_SERIAL_H
-// End of pcmb_serial.h
Index: ecos-working/packages/hal/i386/pcmb/current/src/pcmb_screen.c
===================================================================
--- ecos-working.orig/packages/hal/i386/pcmb/current/src/pcmb_screen.c	2005-01-22 15:11:31.000000000 +0000
+++ ecos-working/packages/hal/i386/pcmb/current/src/pcmb_screen.c	2005-09-19 14:09:14.000000000 +0100
@@ -64,10 +64,9 @@
 #include <cyg/hal/hal_if.h>             // interface API
 #include <cyg/hal/hal_misc.h>
 
-#include <cyg/hal/pcmb_serial.h>
+#include <cyg/hal/pcmb_screen.h>
 
-// Index into pc_ser_channels[] for screen entry.
-#define PCMB_PORT_INDEX (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS - 1)
+#define SCREEN_CHANNEL_IDX (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS - 1)
 
 //-----------------------------------------------------------------------------
 // Screen output definitions...
@@ -728,7 +727,7 @@
 cyg_hal_plf_screen_getc_timeout(void* __ch_data, cyg_uint8* ch)
 {
     int delay_count;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
+    pcmb_screen_channel_data_t* chan = (pcmb_screen_channel_data_t*)__ch_data;
     cyg_bool res;
     CYGARC_HAL_SAVE_GP();
 
@@ -750,7 +749,7 @@
 cyg_hal_plf_screen_control(void *__ch_data, __comm_control_cmd_t __func, ...)
 {
     static int irq_state = 0;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
+    pcmb_screen_channel_data_t* chan = (pcmb_screen_channel_data_t*)__ch_data;
     int ret = 0;
     CYGARC_HAL_SAVE_GP();
 
@@ -792,7 +791,7 @@
                        CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
 {
     int res = 0;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
+    pcmb_screen_channel_data_t* chan = (pcmb_screen_channel_data_t*)__ch_data;
     char c;
 
     CYGARC_HAL_SAVE_GP();
@@ -815,23 +814,23 @@
     return res;
 }
 
-void cyg_hal_plf_screen_init(void)
+void cyg_hal_plf_screen_init(pcmb_screen_channel_data_t *chan)
 {
     hal_virtual_comm_table_t* comm;
     int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
 
     // Disable interrupts.
-    HAL_INTERRUPT_MASK(pc_ser_channels[PCMB_PORT_INDEX].isr_vector);
+    HAL_INTERRUPT_MASK(chan->isr_vector);
 
     // Init channels
-    cyg_hal_plf_screen_init_channel(&pc_ser_channels[PCMB_PORT_INDEX]);
+    cyg_hal_plf_screen_init_channel(chan);
 
     // Setup procs in the vector table
 
     // Set channel 2
-    CYGACC_CALL_IF_SET_CONSOLE_COMM(PCMB_PORT_INDEX);
+    CYGACC_CALL_IF_SET_CONSOLE_COMM(SCREEN_CHANNEL_IDX);
     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
-    CYGACC_COMM_IF_CH_DATA_SET(*comm, &pc_ser_channels[PCMB_PORT_INDEX]);
+    CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_screen_write);
     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_screen_read);
     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_screen_putc);
Index: ecos-working/packages/hal/i386/pcmb/current/src/pcmb_serial.c
===================================================================
--- ecos-working.orig/packages/hal/i386/pcmb/current/src/pcmb_serial.c	2005-06-16 16:05:11.000000000 +0100
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,404 +0,0 @@
-//=============================================================================
-//
-//      pcmb_serial.c
-//
-//      HAL diagnostic output code
-//
-//=============================================================================
-//####ECOSGPLCOPYRIGHTBEGIN####
-// -------------------------------------------
-// This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-//
-// eCos 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 2 or (at your option) any later version.
-//
-// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
-// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-//
-// As a special exception, if other files instantiate templates or use macros
-// or inline functions from this file, or you compile this file and link it
-// with other works to produce a work based on this file, this file does not
-// by itself cause the resulting work to be covered by the GNU General Public
-// License. However the source code for this file must still be made available
-// in accordance with section (3) of the GNU General Public License.
-//
-// This exception does not invalidate any other reasons why a work based on
-// this file might be covered by the GNU General Public License.
-//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
-// -------------------------------------------
-//####ECOSGPLCOPYRIGHTEND####
-//=============================================================================
-//#####DESCRIPTIONBEGIN####
-//
-// Author(s):   proven
-// Contributors:proven
-// Date:        1998-10-05
-// Purpose:     HAL diagnostic output
-// Description: Implementations of HAL diagnostic output support.
-//
-//####DESCRIPTIONEND####
-//
-//=============================================================================
-
-#include <pkgconf/hal.h>
-
-#include <cyg/infra/cyg_type.h>         // base types
-
-#include <cyg/hal/hal_arch.h>           // basic machine info
-#include <cyg/hal/hal_intr.h>           // interrupt macros
-#include <cyg/hal/hal_io.h>             // IO macros
-#include <cyg/hal/drv_api.h>
-#include <cyg/hal/hal_if.h>             // interface API
-#include <cyg/hal/hal_misc.h>
-
-#include <cyg/hal/pcmb_serial.h>
-
-
-/*---------------------------------------------------------------------------*/
-/* From serial_16550.h */
-#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==9600
-#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
-#define CYG_DEVICE_SERIAL_BAUD_LSB        0x0C
-#endif
-#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==19200
-#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
-#define CYG_DEVICE_SERIAL_BAUD_LSB        0x06
-#endif
-#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==38400
-#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
-#define CYG_DEVICE_SERIAL_BAUD_LSB        0x03
-#endif
-#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==57600
-#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
-#define CYG_DEVICE_SERIAL_BAUD_LSB        0x02
-#endif
-#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==115200
-#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
-#define CYG_DEVICE_SERIAL_BAUD_LSB        0x01
-#endif
-
-#ifndef CYG_DEVICE_SERIAL_BAUD_MSB
-#error Missing/incorrect serial baud rate defined - CDL error?
-#endif
-
-// Define the serial registers.
-#define CYG_DEV_RBR 0x00   // receiver buffer register, read, dlab = 0
-#define CYG_DEV_THR 0x00   // transmitter holding register, write, dlab = 0
-#define CYG_DEV_DLL 0x00   // divisor latch (LS), read/write, dlab = 1
-#define CYG_DEV_IER 0x01   // interrupt enable register, read/write, dlab = 0
-#define CYG_DEV_DLM 0x01   // divisor latch (MS), read/write, dlab = 1
-#define CYG_DEV_IIR 0x02   // interrupt identification register, read, dlab = 0
-#define CYG_DEV_FCR 0x02   // fifo control register, write, dlab = 0
-#define CYG_DEV_LCR 0x03   // line control register, read/write
-#define CYG_DEV_MCR 0x04   // modem control register, read/write
-#define CYG_DEV_LSR 0x05   // line status register, read
-#define CYG_DEV_MSR 0x06   // modem status register, read
-
-// Interrupt Enable Register
-#define SIO_IER_RCV 0x01
-#define SIO_IER_XMT 0x02
-#define SIO_IER_LS  0x04
-#define SIO_IER_MS  0x08
-
-// The line status register bits.
-#define SIO_LSR_DR      0x01            // data ready
-#define SIO_LSR_OE      0x02            // overrun error
-#define SIO_LSR_PE      0x04            // parity error
-#define SIO_LSR_FE      0x08            // framing error
-#define SIO_LSR_BI      0x10            // break interrupt
-#define SIO_LSR_THRE    0x20            // transmitter holding register empty
-#define SIO_LSR_TEMT    0x40            // transmitter register empty
-#define SIO_LSR_ERR     0x80            // any error condition
-
-// The modem status register bits.
-#define SIO_MSR_DCTS  0x01              // delta clear to send
-#define SIO_MSR_DDSR  0x02              // delta data set ready
-#define SIO_MSR_TERI  0x04              // trailing edge ring indicator
-#define SIO_MSR_DDCD  0x08              // delta data carrier detect
-#define SIO_MSR_CTS   0x10              // clear to send
-#define SIO_MSR_DSR   0x20              // data set ready
-#define SIO_MSR_RI    0x40              // ring indicator
-#define SIO_MSR_DCD   0x80              // data carrier detect
-
-// The line control register bits.
-#define SIO_LCR_WLS0   0x01             // word length select bit 0
-#define SIO_LCR_WLS1   0x02             // word length select bit 1
-#define SIO_LCR_STB    0x04             // number of stop bits
-#define SIO_LCR_PEN    0x08             // parity enable
-#define SIO_LCR_EPS    0x10             // even parity select
-#define SIO_LCR_SP     0x20             // stick parity
-#define SIO_LCR_SB     0x40             // set break
-#define SIO_LCR_DLAB   0x80             // divisor latch access bit
-
-// Modem Control Register
-#define SIO_MCR_DTR 0x01
-#define SIO_MCR_RTS 0x02
-#define SIO_MCR_INT 0x08   // Enable interrupts
-
-//=============================================================================
-// Basic channel functions
-
-static void
-cyg_hal_plf_serial_init_channel(void* __ch_data)
-{
-    cyg_uint16 base = ((channel_data_t*)__ch_data)->base;
-    cyg_uint8 lsr;
-    
-    HAL_WRITE_UINT8(base+CYG_DEV_IER, 0);	
-    HAL_WRITE_UINT8(base+CYG_DEV_IER, 0);
-    HAL_WRITE_UINT8(base+CYG_DEV_MCR, 0);    
-    	
-    HAL_WRITE_UINT8(base+CYG_DEV_LCR, SIO_LCR_DLAB);
-    HAL_WRITE_UINT8(base+CYG_DEV_DLL, CYG_DEVICE_SERIAL_BAUD_LSB);
-    HAL_WRITE_UINT8(base+CYG_DEV_DLM, CYG_DEVICE_SERIAL_BAUD_MSB);
-    // 8-1-no parity.
-    HAL_WRITE_UINT8(base+CYG_DEV_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
-
-    // Test whether the channel is valid or not. If the status
-    // register reads back all ones, its a fair bet that it is not
-    // actually there!
-    HAL_READ_UINT8(base+CYG_DEV_LSR, lsr);
-    ((channel_data_t*)__ch_data)->valid = (lsr != 0xFF);
-    
-    HAL_WRITE_UINT8(base+CYG_DEV_FCR, 0x07);  // Enable & clear FIFO
-}
-
-//-----------------------------------------------------------------------------
-
-void
-cyg_hal_plf_serial_putc(void *__ch_data, char c)
-{
-    cyg_uint16 base = ((channel_data_t*)__ch_data)->base;
-    cyg_uint8 lsr;
-
-    if( !((channel_data_t*)__ch_data)->valid )
-            return;
-    
-    CYGARC_HAL_SAVE_GP();
-    do {
-        HAL_READ_UINT8(base+CYG_DEV_LSR, lsr);
-    } while ((lsr & SIO_LSR_THRE) == 0);
-
-    HAL_WRITE_UINT8(base+CYG_DEV_THR, c);
-
-    CYGARC_HAL_RESTORE_GP();
-}
-
-//-----------------------------------------------------------------------------
-
-static cyg_bool
-cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
-{
-    cyg_uint16 base = ((channel_data_t*)__ch_data)->base;
-    cyg_uint8 lsr;
-
-    if( !((channel_data_t*)__ch_data)->valid )
-            return false;
-    
-    HAL_READ_UINT8(base+CYG_DEV_LSR, lsr);
-    if ((lsr & SIO_LSR_DR) == 0)
-        return false;
-
-    HAL_READ_UINT8(base+CYG_DEV_RBR, *ch);
-
-    return true;
-}
-
-//-----------------------------------------------------------------------------
-
-cyg_uint8
-cyg_hal_plf_serial_getc(void* __ch_data)
-{
-    cyg_uint8 ch;
-
-    if( !((channel_data_t*)__ch_data)->valid )
-            return '\n';
-    
-    CYGARC_HAL_SAVE_GP();
-
-    while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
-
-    CYGARC_HAL_RESTORE_GP();
-
-    return ch;
-}
-
-//=============================================================================
-// Call IF support
-
-#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \
-    || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
-
-static void
-cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
-                         cyg_uint32 __len)
-{
-    CYGARC_HAL_SAVE_GP();
-
-    while(__len-- > 0)
-        cyg_hal_plf_serial_putc(__ch_data, *__buf++);
-
-    CYGARC_HAL_RESTORE_GP();
-}
-
-static void
-cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
-{
-    CYGARC_HAL_SAVE_GP();
-
-    while(__len-- > 0)
-        *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
-
-    CYGARC_HAL_RESTORE_GP();
-}
-
-static cyg_bool
-cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
-{
-    int delay_count;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    cyg_bool res;
-    CYGARC_HAL_SAVE_GP();
-
-    delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
-
-    for(;;) {
-        res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
-        if (res || 0 == delay_count--)
-            break;
-        
-        CYGACC_CALL_IF_DELAY_US(100);
-    }
-
-    CYGARC_HAL_RESTORE_GP();
-    return res;
-}
-
-
-static int
-cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
-{
-    static int irq_state = 0;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    int ret = 0;
-    CYGARC_HAL_SAVE_GP();
-
-    switch (__func) {
-    case __COMMCTL_IRQ_ENABLE:
-        irq_state = 1;
-
-        HAL_WRITE_UINT8(chan->base+CYG_DEV_IER, SIO_IER_RCV);
-        HAL_WRITE_UINT8(chan->base+CYG_DEV_MCR, SIO_MCR_INT|SIO_MCR_DTR|SIO_MCR_RTS);
-
-        HAL_INTERRUPT_UNMASK(chan->isr_vector);
-        break;
-    case __COMMCTL_IRQ_DISABLE:
-        ret = irq_state;
-        irq_state = 0;
-
-        HAL_WRITE_UINT8(chan->base+CYG_DEV_IER, 0);
-
-        HAL_INTERRUPT_MASK(chan->isr_vector);
-        break;
-    case __COMMCTL_DBG_ISR_VECTOR:
-        ret = chan->isr_vector;
-        break;
-    case __COMMCTL_SET_TIMEOUT:
-    {
-        va_list ap;
-
-        va_start(ap, __func);
-
-        ret = chan->msec_timeout;
-        chan->msec_timeout = va_arg(ap, cyg_uint32);
-
-        va_end(ap);
-    }        
-    default:
-        break;
-    }
-
-    
-    CYGARC_HAL_RESTORE_GP();
-    return ret;
-}
-
-static int
-cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
-                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
-{
-    int res = 0;
-    channel_data_t* chan = (channel_data_t*)__ch_data;
-    char c;
-    cyg_uint8 lsr;
-    CYGARC_HAL_SAVE_GP();
-
-    cyg_drv_interrupt_acknowledge(chan->isr_vector);
-
-    *__ctrlc = 0;
-    HAL_READ_UINT8(chan->base+CYG_DEV_LSR, lsr);
-    if ( (lsr & SIO_LSR_DR) != 0 ) {
-
-        HAL_READ_UINT8(chan->base+CYG_DEV_RBR, c);
-        if( cyg_hal_is_break( &c , 1 ) )
-            *__ctrlc = 1;
-
-    }
-
-    res = CYG_ISR_HANDLED;
-    
-    CYGARC_HAL_RESTORE_GP();
-    return res;
-}
-
-void cyg_hal_plf_serial_init(void)
-{
-    hal_virtual_comm_table_t* comm;
-    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
-    int i, num_serial = CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS;
-
-#ifdef CYGSEM_HAL_I386_PC_DIAG_SCREEN
-    --num_serial;
-#endif
-
-    for (i = 0; i < num_serial; i++) {
-	// Disable interrupts.
-	HAL_INTERRUPT_MASK(pc_ser_channels[i].isr_vector);
-
-	// Init
-	cyg_hal_plf_serial_init_channel(&pc_ser_channels[i]);
-
-	// Setup procs in the vector table
-
-	// Set channel 0
-	CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
-	comm = CYGACC_CALL_IF_CONSOLE_PROCS();
-	CYGACC_COMM_IF_CH_DATA_SET(*comm, &pc_ser_channels[i]);
-	CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
-	CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
-	CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
-	CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
-	CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
-	CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
-	CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
-    }
-    
-    // Restore original console
-    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
-}
-
-#endif  //defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG)
-	//  || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
-
-//-----------------------------------------------------------------------------
-// End of pcmb_serial.c

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]