changeset 86:6512add4f5d6 ecos-sw-2000-05-05

Merge from eCos master repository on 2000-05-05-07:47:05-BST
author jlarmour
date Fri, 05 May 2000 17:31:08 +0000
parents 142b52c7e568
children 008177d90c43
files host/tools/ecostest/ChangeLog host/tools/ecostest/common/eCosTestDownloadFilter.cpp host/tools/ecostest/common/eCosTestMonitorFilter.cpp host/tools/ecostest/common/eCosTestSerialFilter.cpp packages/NEWS packages/io/common/current/ChangeLog packages/io/common/current/include/config_keys.h packages/io/serial/current/ChangeLog packages/io/serial/current/cdl/io_serial.cdl packages/io/serial/current/include/serial.h packages/io/serial/current/include/serialio.h packages/io/serial/current/src/common/serial.c packages/kernel/current/ChangeLog packages/kernel/current/include/instrmnt.h packages/kernel/current/src/intr/intr.cxx packages/kernel/current/tests/intr0.cxx packages/kernel/current/tests/kintr0.c
diffstat 17 files changed, 457 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/host/tools/ecostest/ChangeLog
+++ b/host/tools/ecostest/ChangeLog
@@ -1,3 +1,10 @@
+2000-05-03  Bart Veer  <bartv@redhat.com>
+
+	* common/permtest.cxx (find_ptest):
+	Do a little bit of searching for the permutation file.
+	Catch errors and give a diagnostic, rather than aborting because
+	of an uncaught C++ exception.
+
 2000-04-14 Simon FitzMaurice <sdf@redhat.co.uk>
   * common\ResetAttributes.cpp : do not carry forward values for skipped fields in reset strings
   * common\eCosTest.cpp : Avoid overflow in socket timeouts
--- a/host/tools/ecostest/common/eCosTestDownloadFilter.cpp
+++ b/host/tools/ecostest/common/eCosTestDownloadFilter.cpp
@@ -53,7 +53,7 @@
 #include "eCosStd.h"
 #include "eCosTrace.h"
 
-#define DL_FILTER_VER "$Id: eCosTestDownloadFilter.cpp,v 1.5 2000/04/28 18:18:41 jlarmour Exp $"
+#define DL_FILTER_VER "$Id: eCosTestDownloadFilter.cpp,v 1.6 2000/05/05 17:31:08 jlarmour Exp $"
 #include "eCosTestDownloadFilter.h"
 
 CeCosTestDownloadFilter::CeCosTestDownloadFilter():
--- a/host/tools/ecostest/common/eCosTestMonitorFilter.cpp
+++ b/host/tools/ecostest/common/eCosTestMonitorFilter.cpp
@@ -45,7 +45,7 @@
 
 #include "eCosStd.h"
 
-#define SER_FILTER_VER "$Id: eCosTestMonitorFilter.cpp,v 1.4 2000/04/28 18:18:41 jlarmour Exp $"
+#define SER_FILTER_VER "$Id: eCosTestMonitorFilter.cpp,v 1.5 2000/05/05 17:31:08 jlarmour Exp $"
 #include "eCosTestMonitorFilter.h"
 
 CeCosTestMonitorFilter::CeCosTestMonitorFilter():
--- a/host/tools/ecostest/common/eCosTestSerialFilter.cpp
+++ b/host/tools/ecostest/common/eCosTestSerialFilter.cpp
@@ -51,7 +51,7 @@
 
 #include "eCosStd.h"
 
-#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.5 2000/04/28 18:18:41 jlarmour Exp $"
+#define SER_FILTER_VER "$Id: eCosTestSerialFilter.cpp,v 1.6 2000/05/05 17:31:08 jlarmour Exp $"
 #include "eCosTestSerialFilter.h"
 #include "eCosThreadUtils.h"
 
--- a/packages/NEWS
+++ b/packages/NEWS
@@ -1,3 +1,8 @@
+* IO serial driver
+  The common serial driver has been extended with a configurable option for
+  a non-blocking read/write mode. It has also been given some new callbacks
+  which allow low-level drivers to transfer data in blocks instead of as
+  single characters.
 * SH HAL
   Now provides ROMRAM startup type, copying code and data to RAM before
   executing, improving performance at cost of memory.
--- a/packages/io/common/current/ChangeLog
+++ b/packages/io/common/current/ChangeLog
@@ -1,3 +1,16 @@
+2000-05-05  Grant Edwards  <grante@visi.com>
+
+	* include/config_keys.h: Add key to inquire about serial buffer info
+
+2000-05-03  Jesper Skov  <jskov@redhat.com>
+
+	* include/config_keys.h: Added keys for DSP io.
+	Added key for overflow reset.
+
+2000-05-01  Jesper Skov  <jskov@redhat.com>
+
+	* include/config_keys.h: Added keys for read/write blocking.
+
 2000-03-28  John Dallaway  <jld@cygnus.co.uk>
 
 	* cdl/io.cdl:
--- a/packages/io/common/current/include/config_keys.h
+++ b/packages/io/common/current/include/config_keys.h
@@ -33,10 +33,10 @@
 // ====================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):   gthomas
-// Contributors:        gthomas
-// Date:        1999-02-04
-// Purpose:     Repository for all get/put config "keys"
+// Author(s):    gthomas
+// Contributors: gthomas,jskov,grante
+// Date:         1999-02-04
+// Purpose:      Repository for all get/put config "keys"
 // Description:
 //
 //####DESCRIPTIONEND####
@@ -46,17 +46,38 @@
 // This file contains all of the 'key' values used by all I/O components.
 // It is placed in this single repository to make it easy to reduce conflicts.
 
+// ======== 0x0100 Serial ====================================================
 // Get/Set configuration 'key' values for low-level serial I/O
 #define CYG_IO_GET_CONFIG_SERIAL_INFO            0x0101
 #define CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN    0x0102
 #define CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH    0x0103
 #define CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH     0x0104
 #define CYG_IO_GET_CONFIG_SERIAL_ABORT           0x0105
+#define CYG_IO_GET_CONFIG_SERIAL_READ_BLOCKING   0x0106
+#define CYG_IO_GET_CONFIG_SERIAL_WRITE_BLOCKING  0x0107
+#define CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO     0x0111
 #define CYG_IO_SET_CONFIG_SERIAL_INFO            0x0181
+#define CYG_IO_SET_CONFIG_SERIAL_READ_BLOCKING   0x0182
+#define CYG_IO_SET_CONFIG_SERIAL_WRITE_BLOCKING  0x0183
 
+// ======== 0x0200 TTY =======================================================
 // Get/Set configuration 'key' values for tty-like driver
 #define CYG_IO_GET_CONFIG_TTY_INFO       0x0201  // Get channel configuration
 #define CYG_IO_SET_CONFIG_TTY_INFO       0x0281  // Set channel configuration
 
+
+// ======== 0x0300 DSP =======================================================
+// Get/Set configuration 'key' values for low-level DSP I/O
+#define CYG_IO_GET_CONFIG_DSP_OUTPUT_DRAIN       0x0301
+#define CYG_IO_GET_CONFIG_DSP_OUTPUT_FLUSH       0x0302
+#define CYG_IO_GET_CONFIG_DSP_INPUT_FLUSH        0x0303
+#define CYG_IO_GET_CONFIG_DSP_ABORT              0x0304
+#define CYG_IO_GET_CONFIG_DSP_READ_BLOCKING      0x0305
+#define CYG_IO_GET_CONFIG_DSP_WRITE_BLOCKING     0x0306
+#define CYG_IO_GET_CONFIG_DSP_INPUT_OVERFLOW_RESET 0x0307
+
+#define CYG_IO_SET_CONFIG_DSP_READ_BLOCKING      0x0381
+#define CYG_IO_SET_CONFIG_DSP_WRITE_BLOCKING     0x0382
+
 #endif  /* CYGONCE_CONFIG_KEYS_H */
 /* EOF config_keys.h */
--- a/packages/io/serial/current/ChangeLog
+++ b/packages/io/serial/current/ChangeLog
@@ -1,3 +1,33 @@
+2000-05-05  Grant Edwards  <grante@visi.com>
+
+	* src/common/serial.c (serial_get_config): Support
+	CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO key to get buffer information
+
+	* include/serialio.h: Add cyg_serial_buf_info_t
+
+2000-05-04  Jesper Skov  <jskov@redhat.com>
+
+	* cdl/io_serial.cdl: Only build tests when drivers enabled.
+
+2000-05-02  Jesper Skov  <jskov@redhat.com>
+
+	* src/common/serial.c (serial_set_config): Set proper parity for
+	blocking options.
+	(serial_get_config): Fix copy'n'paste buglet.
+	
+2000-05-01  Jesper Skov  <jskov@redhat.com>
+
+	* src/common/serial.c: Added non-blocking config and operation for
+	read/write calls.
+	Added block transfer rcv/xmt callbacks.
+	Added (disabled for now) check for rcv overflow. [need to add
+	handling]
+	
+	* include/serial.h: Added non-blocking callbacks.
+
+	* cdl/io_serial.cdl: Added non-blocking option. Added block
+	transfer interface.
+
 2000-04-17  Hugo Tyson  <hmt@cygnus.co.uk>
 
 	* src/PKGconf.mak: remove; it's obsolete.
--- a/packages/io/serial/current/cdl/io_serial.cdl
+++ b/packages/io/serial/current/cdl/io_serial.cdl
@@ -61,6 +61,23 @@ cdl_package CYGPKG_IO_SERIAL {
 	puts $::cdl_header "/****** proc output end ******/"
     }
 
+    cdl_option CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING {
+        display       "Support non-blocking read and write calls"
+        default_value 0
+        description   "
+            This option enables extra code in the generic serial driver
+            which allows clients to switch read() and write() call
+            semantics from blocking to non-blocking."
+    }
+
+    cdl_interface CYGINT_IO_SERIAL_BLOCK_TRANSFER {
+        display       "Driver requires block transfer callback functions"
+        description   "
+            Some low-level drivers can be optimized to transfer blocks
+            of data instead of a single character at a time. These usually
+            rely on a hardware FIFO of some sort."
+    }
+
     cdl_component CYGPKG_IO_SERIAL_TTY {
         display       "TTY-mode serial device drivers"
         flavor        bool
@@ -140,7 +157,7 @@ cdl_package CYGPKG_IO_SERIAL {
             display "Serial device driver tests"
             flavor  data
             no_define
-            calculated { "tests/serial1 tests/serial2 tests/serial3 tests/serial4 tests/serial5 tests/tty1 tests/tty2" }
+            calculated { CYGPKG_IO_SERIAL_DEVICES ? "tests/serial1 tests/serial2 tests/serial3 tests/serial4 tests/serial5 tests/tty1 tests/tty2" : "" }
             description   "
                 This option specifies the set of tests for the serial device drivers."
         }
--- a/packages/io/serial/current/include/serial.h
+++ b/packages/io/serial/current/include/serial.h
@@ -46,6 +46,8 @@
 // Serial I/O interfaces
 
 #include <pkgconf/system.h>
+#include <pkgconf/io_serial.h>
+
 #include <cyg/infra/cyg_type.h>
 #include <cyg/io/io.h>
 #include <cyg/io/serialio.h>
@@ -62,14 +64,40 @@ typedef struct {
     void (*xmt_char)(serial_channel *chan);
     // Consume an input character
     void (*rcv_char)(serial_channel *chan, unsigned char c);
+
+#ifdef CYGINT_IO_SERIAL_BLOCK_TRANSFER
+    // Request space for input characters
+    bool (*data_rcv_req)(serial_channel *chan, int avail, 
+                         int* space_avail, unsigned char** space);
+    // Receive operation completed
+    void (*data_rcv_done)(serial_channel *chan);
+    // Request characters for transmission
+    bool (*data_xmt_req)(serial_channel *chan, int space,
+                         int* chars_avail, unsigned char** chars);
+    // Transmit operation completed
+    void (*data_xmt_done)(serial_channel *chan);
+#endif // CYGINT_IO_SERIAL_BLOCK_TRANSFER
 } serial_callbacks_t;
 
+#ifdef CYGINT_IO_SERIAL_BLOCK_TRANSFER
+#define SERIAL_CALLBACKS(_l,_init,_xmt_char,_rcv_char, _data_rcv_req, _data_rcv_done, _data_xmt_req, _data_xmt_done)  \
+serial_callbacks_t _l = {                               \
+    _init,                                              \
+    _xmt_char,                                          \
+    _rcv_char,                                          \
+    _data_rcv_req,                                      \
+    _data_rcv_done,                                     \
+    _data_xmt_req,                                      \
+    _data_xmt_done                                      \
+};
+#else 
 #define SERIAL_CALLBACKS(_l,_init,_xmt_char,_rcv_char)  \
 serial_callbacks_t _l = {                               \
     _init,                                              \
     _xmt_char,                                          \
     _rcv_char                                           \
 };
+#endif
 
 extern serial_callbacks_t cyg_io_serial_callbacks;
 
@@ -82,6 +110,9 @@ typedef struct {
     cyg_drv_cond_t           wait;
     cyg_drv_mutex_t          lock;
     bool                     waiting;
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+    bool                     blocking;
+#endif
     volatile bool            abort;       // Set by an outsider to kill processing
     volatile cyg_int32       pending;     // This many bytes waiting to be sent
 } cbuf_t;
--- a/packages/io/serial/current/include/serialio.h
+++ b/packages/io/serial/current/include/serialio.h
@@ -116,6 +116,14 @@ typedef struct {
     cyg_uint32               flags;
 } cyg_serial_info_t;
 
+typedef struct {  
+    cyg_int32 rx_bufsize;
+    cyg_int32 rx_count;
+    cyg_int32 tx_bufsize;
+    cyg_int32 tx_count;
+} cyg_serial_buf_info_t;
+
+
 #define CYG_SERIAL_INFO_INIT(_baud,_stop,_parity,_word_length,_flags) \
   { _baud, _stop, _parity, _word_length, _flags}
 
--- a/packages/io/serial/current/src/common/serial.c
+++ b/packages/io/serial/current/src/common/serial.c
@@ -31,10 +31,10 @@
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):   gthomas
-// Contributors:  gthomas
-// Date:        1999-02-04
-// Purpose:     Top level serial driver
+// Author(s):    gthomas
+// Contributors: gthomas, grante
+// Date:         1999-02-04
+// Purpose:      Top level serial driver
 // Description: 
 //
 //####DESCRIPTIONEND####
@@ -42,6 +42,8 @@
 //==========================================================================
 
 #include <pkgconf/io.h>
+#include <pkgconf/io_serial.h>
+
 #include <cyg/io/io.h>
 #include <cyg/io/devtab.h>
 #include <cyg/io/serial.h>
@@ -62,10 +64,28 @@ DEVIO_TABLE(cyg_io_serial_devio,
 static void serial_init(serial_channel *chan);
 static void serial_xmt_char(serial_channel *chan);
 static void serial_rcv_char(serial_channel *chan, unsigned char c);
+#ifdef CYGINT_IO_SERIAL_BLOCK_TRANSFER
+static bool serial_data_rcv_req(serial_channel *chan, int avail, 
+                                int* space_avail, unsigned char** space);
+static void serial_data_rcv_done(serial_channel *chan);
+static bool serial_data_xmt_req(serial_channel *chan, int space,
+                                int* chars_avail, unsigned char** chars);
+static void serial_data_xmt_done(serial_channel *chan);
+SERIAL_CALLBACKS(cyg_io_serial_callbacks, 
+                 serial_init, 
+                 serial_xmt_char, 
+                 serial_rcv_char,
+                 serial_data_rcv_req,
+                 serial_data_rcv_done,
+                 serial_data_xmt_req,
+                 serial_data_xmt_done);
+#else
 SERIAL_CALLBACKS(cyg_io_serial_callbacks, 
                  serial_init, 
                  serial_xmt_char, 
                  serial_rcv_char);
+#endif
+
 
 static void
 serial_init(serial_channel *chan)
@@ -77,6 +97,9 @@ serial_init(serial_channel *chan)
 #endif
         chan->out_cbuf.waiting = false;
         chan->out_cbuf.abort = false;
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+        chan->out_cbuf.blocking = true;
+#endif
         chan->out_cbuf.pending = 0;
         cyg_drv_mutex_init(&chan->out_cbuf.lock);
         cyg_drv_cond_init(&chan->out_cbuf.wait, &chan->out_cbuf.lock);
@@ -88,6 +111,9 @@ serial_init(serial_channel *chan)
 #endif
         chan->in_cbuf.waiting = false;
         chan->in_cbuf.abort = false;
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+        chan->in_cbuf.blocking = true;
+#endif
         cyg_drv_mutex_init(&chan->in_cbuf.lock);
         cyg_drv_cond_init(&chan->in_cbuf.wait, &chan->in_cbuf.lock);
     }
@@ -108,6 +134,7 @@ serial_write(cyg_io_handle_t handle, con
 
     cbuf->abort = false;
     cyg_drv_mutex_lock(&cbuf->lock);
+
     if (cbuf->len == 0) {
         // Non interrupt driven (i.e. polled) operation
         while (size-- > 0) {
@@ -123,14 +150,24 @@ serial_write(cyg_io_handle_t handle, con
                 cbuf->waiting = true;
                 // Buffer full - wait for space
                 (funs->start_xmit)(chan);  // Make sure xmit is running
+                // Check flag: 'start_xmit' may have obviated the need to wait :-)
                 if (cbuf->waiting) {
-                    // Note: 'start_xmit' may have obviated the need to wait :-)
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+                    // Optionally return if configured for non-blocking mode.
+                    if (!cbuf->blocking) {
+                        *len -= size;   // number of characters actually sent
+                        cbuf->waiting = false;
+                        res = -EAGAIN;
+                        break;
+                    }
+#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
                     cbuf->pending += size;  // Have this much more to send [eventually]
                     cyg_drv_cond_wait(&cbuf->wait);
                     cbuf->pending -= size;
                 }
                 if (cbuf->abort) {
                     // Give up!
+                    *len -= size;   // number of characters actually sent
                     cbuf->abort = false;
                     cbuf->waiting = false;
                     res = -EINTR;
@@ -168,6 +205,7 @@ serial_read(cyg_io_handle_t handle, void
 
     cbuf->abort = false;
     cyg_drv_mutex_lock(&cbuf->lock);
+
     if (cbuf->len == 0) {
         // Non interrupt driven (i.e. polled) operation
         while (size++ < *len) {
@@ -181,6 +219,13 @@ serial_read(cyg_io_handle_t handle, void
                 if (++cbuf->get == cbuf->len) cbuf->get = 0;
                 size++;
             } else {
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+                if (!cbuf->blocking) {
+                    *len = size;        // characters actually read
+                    res = -EAGAIN;
+                    break;
+                }
+#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
                 cbuf->waiting = true;
 #ifdef XX_CYGDBG_DIAG_BUF
             enable_diag_uart = 0;
@@ -199,6 +244,7 @@ serial_read(cyg_io_handle_t handle, void
 #endif // CYGDBG_DIAG_BUF
                 if (cbuf->abort) {
                     // Give up!
+                    *len = size;        // characters actually read
                     cbuf->abort = false;
                     cbuf->waiting = false;
                     res = -EINTR;
@@ -228,7 +274,8 @@ serial_get_config(cyg_io_handle_t handle
     serial_channel *chan = (serial_channel *)t->priv;
     cyg_serial_info_t *buf = (cyg_serial_info_t *)xbuf;
     Cyg_ErrNo res = ENOERR;
-    cbuf_t *cbuf = &chan->out_cbuf;
+    cbuf_t *out_cbuf = &chan->out_cbuf;
+    cbuf_t *in_cbuf = &chan->in_cbuf;
     serial_funs *funs = chan->funs;
 
     switch (key) {
@@ -239,64 +286,112 @@ serial_get_config(cyg_io_handle_t handle
         *buf = chan->config;
         *len = sizeof(chan->config);
         break;       
+
+    case CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO:
+        // return rx/tx buffer sizes and counts
+        {
+            cyg_serial_buf_info_t *p;
+            if (*len < sizeof(cyg_serial_buf_info_t))
+                return -EINVAL;
+          
+            *len = sizeof(cyg_serial_buf_info_t);
+            p = (cyg_serial_buf_info_t *)xbuf;
+            
+            p->rx_bufsize = chan->in_cbuf.len;
+            if (p->rx_bufsize) {
+                p->rx_count = chan->in_cbuf.put - chan->in_cbuf.get;
+                if (p->rx_count < 0) 
+                    p->rx_count += p->rx_bufsize;
+            }
+            else
+                p->rx_count = 0;
+            
+            p->tx_bufsize = chan->out_cbuf.len;
+            if (p->tx_bufsize) {
+                p->tx_count = chan->out_cbuf.put - chan->out_cbuf.get;
+                if (p->tx_count < 0) 
+                    p->tx_count += p->tx_bufsize;
+            }
+            else
+                p->tx_count = 0;
+        }
+      break;
+      
     case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN:
 // Wait for any pending output to complete
-        if (cbuf->len == 0) break;  // Nothing to do if not buffered
-        cyg_drv_mutex_lock(&cbuf->lock);  // Stop any further output processing
+        if (out_cbuf->len == 0) break;  // Nothing to do if not buffered
+        cyg_drv_mutex_lock(&out_cbuf->lock);  // Stop any further output processing
         cyg_drv_dsr_lock();
-        while (cbuf->pending || (cbuf->get != cbuf->put)) {
-            cbuf->waiting = true;
-            cyg_drv_cond_wait(&cbuf->wait);
+        while (out_cbuf->pending || (out_cbuf->get != out_cbuf->put)) {
+            out_cbuf->waiting = true;
+            cyg_drv_cond_wait(&out_cbuf->wait);
         }
         cyg_drv_dsr_unlock();
-        cyg_drv_mutex_unlock(&cbuf->lock);
+        cyg_drv_mutex_unlock(&out_cbuf->lock);
         break;
+
     case CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH:
         // Flush any buffered input
-        cbuf = &chan->in_cbuf;
-        if (cbuf->len == 0) break;  // Nothing to do if not buffered
-        cyg_drv_mutex_lock(&cbuf->lock);  // Stop any further input processing
+        if (in_cbuf->len == 0) break;  // Nothing to do if not buffered
+        cyg_drv_mutex_lock(&in_cbuf->lock);  // Stop any further input processing
         cyg_drv_dsr_lock();
-        if (cbuf->waiting) {
-            cbuf->abort = true;
-            cyg_drv_cond_signal(&cbuf->wait);
-            cbuf->waiting = false;
+        if (in_cbuf->waiting) {
+            in_cbuf->abort = true;
+            cyg_drv_cond_signal(&in_cbuf->wait);
+            in_cbuf->waiting = false;
         }
-        cbuf->get = cbuf->put;  // Flush buffered input
+        in_cbuf->get = in_cbuf->put;  // Flush buffered input
         cyg_drv_dsr_unlock();
-        cyg_drv_mutex_unlock(&cbuf->lock);
+        cyg_drv_mutex_unlock(&in_cbuf->lock);
         break;
+
     case CYG_IO_GET_CONFIG_SERIAL_ABORT:
         // Abort any outstanding I/O, including blocked reads
         // Caution - assumed to be called from 'timeout' (i.e. DSR) code
-        cbuf = &chan->in_cbuf;
-        if (cbuf->len != 0) {
-            cbuf->abort = true;
-            cyg_drv_cond_signal(&cbuf->wait);
+        if (in_cbuf->len != 0) {
+            in_cbuf->abort = true;
+            cyg_drv_cond_signal(&in_cbuf->wait);
         }
-        cbuf = &chan->out_cbuf;
-        if (cbuf->len != 0) {
-            cbuf->abort = true;
-            cyg_drv_cond_signal(&cbuf->wait);
+        if (out_cbuf->len != 0) {
+            out_cbuf->abort = true;
+            cyg_drv_cond_signal(&out_cbuf->wait);
         }
         break;
+
     case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH:
 // Throw away any pending output
-        if (cbuf->len == 0) break;  // Nothing to do if not buffered
-        cyg_drv_mutex_lock(&cbuf->lock);  // Stop any further output processing
+        if (out_cbuf->len == 0) break;  // Nothing to do if not buffered
+        cyg_drv_mutex_lock(&out_cbuf->lock);  // Stop any further output processing
         cyg_drv_dsr_lock();
-        if (cbuf->get != cbuf->put) {
-            cbuf->get = cbuf->put;  // Empties queue!
+        if (out_cbuf->get != out_cbuf->put) {
+            out_cbuf->get = out_cbuf->put;  // Empties queue!
             (funs->stop_xmit)(chan);  // Done with transmit
         }
-        if (cbuf->waiting) {
-            cbuf->abort = true;
-            cyg_drv_cond_signal(&cbuf->wait);
-            cbuf->waiting = false;
+        if (out_cbuf->waiting) {
+            out_cbuf->abort = true;
+            cyg_drv_cond_signal(&out_cbuf->wait);
+            out_cbuf->waiting = false;
         }
         cyg_drv_dsr_unlock();
-        cyg_drv_mutex_unlock(&cbuf->lock);
+        cyg_drv_mutex_unlock(&out_cbuf->lock);
+        break;
+
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+    case CYG_IO_GET_CONFIG_SERIAL_READ_BLOCKING:
+        if (*len < sizeof(cyg_uint32)) {
+            return -EINVAL;
+        }
+        *(cyg_uint32*)xbuf = (in_cbuf->blocking) ? 1 : 0;
         break;
+
+    case CYG_IO_GET_CONFIG_SERIAL_WRITE_BLOCKING:
+        if (*len < sizeof(cyg_uint32)) {
+            return -EINVAL;
+        }
+        *(cyg_uint32*)xbuf = (out_cbuf->blocking) ? 1 : 0;
+        break;
+#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+
     default:
         res = -EINVAL;
     }
@@ -309,6 +404,10 @@ serial_set_config(cyg_io_handle_t handle
     Cyg_ErrNo res = ENOERR;
     cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;
     serial_channel *chan = (serial_channel *)t->priv;
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+    cbuf_t *out_cbuf = &chan->out_cbuf;
+    cbuf_t *in_cbuf = &chan->in_cbuf;
+#endif
     serial_funs *funs = chan->funs;
     cyg_serial_info_t *buf = (cyg_serial_info_t *)xbuf;
 
@@ -322,6 +421,20 @@ serial_set_config(cyg_io_handle_t handle
             res = -EINVAL;
         }
         break;
+#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
+    case CYG_IO_SET_CONFIG_SERIAL_READ_BLOCKING:
+        if (*len < sizeof(cyg_uint32) || 0 == in_cbuf->len) {
+            return -EINVAL;
+        }
+        in_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
+        break;
+    case CYG_IO_SET_CONFIG_SERIAL_WRITE_BLOCKING:
+        if (*len < sizeof(cyg_uint32) || 0 == out_cbuf->len) {
+            return -EINVAL;
+        }
+        out_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;
+        break;
+#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING
     default:
         res = -EINVAL;
     }
@@ -366,6 +479,15 @@ serial_rcv_char(serial_channel *chan, un
 {
     cbuf_t *cbuf = &chan->in_cbuf;
 
+#if 0
+    // FIXME: add error handling
+    int space;
+    // Check for overflow
+    space = (cbuf->len + cbuf->put - cbuf->get) % cbuf->len;
+    if (space == (cbuf->len - 1))
+        ;                               // full since put==get means empty
+#endif
+
     cbuf->data[cbuf->put++] = c;
     if (cbuf->put == cbuf->len) cbuf->put = 0;
     if (cbuf->waiting) {
@@ -385,3 +507,109 @@ serial_rcv_char(serial_channel *chan, un
     }
 }
 
+//----------------------------------------------------------------------------
+// Block transfer functions. Not all drivers require these.
+#ifdef CYGINT_IO_SERIAL_BLOCK_TRANSFER
+
+static bool
+serial_data_rcv_req(serial_channel *chan, int avail, 
+                    int* space_avail, unsigned char** space)
+{
+    cbuf_t *cbuf = &chan->in_cbuf;
+    int gap;
+
+    // Check for space
+    gap = (cbuf->len + cbuf->put - cbuf->get) % cbuf->len;
+    if (gap == (cbuf->len - 1))
+        return false;                   // full since put==get means empty
+
+    if (0 == gap) {
+        // Buffer is empty. Reset put/get indexes to get max transfer in
+        // one chunk.
+        cbuf->get = 0;
+        cbuf->put = 0;
+        gap = cbuf->len - 1;
+    } else {
+        // Free space (G = get, P = put, x = data, . = empty)
+        //  positive: xxxxP.....Gxxx
+        //  negative: ..GxxxxxP.....        [offer last chunk only]
+
+        // First try for a gap between put and get locations
+        gap = cbuf->get - cbuf->put - 1;
+        if (gap < 0) {
+            // If failed, the gap is between put and the end of buffer
+            gap = cbuf->len - cbuf->put - 1;
+        }
+    }
+
+    if (avail < gap) gap = avail;   // bound by what's available from hw
+    
+    *space_avail = gap;
+    *space = &cbuf->data[cbuf->put];
+    cbuf->put += gap;
+
+    if (cbuf->put == cbuf->len) cbuf->put = 0;
+
+    return true;
+}
+
+static void
+serial_data_rcv_done(serial_channel *chan)
+{
+    cbuf_t *cbuf = &chan->in_cbuf;
+    if (cbuf->waiting) {
+        cbuf->waiting = false;
+        cyg_drv_cond_signal(&cbuf->wait);
+    }
+}
+
+static bool
+serial_data_xmt_req(serial_channel *chan, int space,
+                    int* chars_avail, unsigned char** chars)
+{
+    cbuf_t *cbuf = &chan->out_cbuf;
+    int avail;
+
+    // Available data (G = get, P = put, x = data, . = empty)
+    //  0:        no data
+    //  negative: xxxxP.....Gxxx        [offer last chunk only]
+    //  positive: ..GxxxxxP.....
+    avail = cbuf->put - cbuf->get;
+    if (0 == avail)
+        return false;
+    if (avail < 0) {
+        avail = cbuf->len - cbuf->get;
+    }
+
+    if (avail > space) avail = space;   // bound by space in hardware
+    
+    *chars_avail = avail;
+    *chars = &cbuf->data[cbuf->get];
+    cbuf->get += avail;
+
+    if (cbuf->get == cbuf->len) cbuf->get = 0;
+
+    return true;
+}
+
+static void
+serial_data_xmt_done(serial_channel *chan)
+{
+    cbuf_t *cbuf = &chan->out_cbuf;
+    serial_funs *funs = chan->funs;
+    int space;
+
+    (funs->stop_xmit)(chan);  // Done with transmit
+
+    if (cbuf->waiting) {
+        // See if there is now enough room to restart writer
+        space = (cbuf->len + cbuf->get) - cbuf->put;
+        if (space > cbuf->len) space -= cbuf->len;
+        if (space >= cbuf->low_water) {
+            cbuf->waiting = false;
+            cyg_drv_cond_broadcast(&cbuf->wait);
+        }
+    }
+}
+
+#endif // CYGINT_IO_SERIAL_BLOCK_TRANSFER
--- a/packages/kernel/current/ChangeLog
+++ b/packages/kernel/current/ChangeLog
@@ -1,3 +1,16 @@
+2000-05-04  Jonathan Larmour  <jlarmour@redhat.co.uk>
+
+	* include/instrmnt.h: Remove all CYG_UNUSED_PARAMs as they could
+	cause problems when used with volatile arguments
+	* src/intr/intr.cxx: Use CYG_UNUSED_PARAM to silence warning that
+	appears because of the above change.
+
+2000-05-02  Gary Thomas  <gthomas@redhat.com>
+
+	* tests/kintr0.c:
+	* tests/intr0.cxx: Correct test for cases when VSR_MIN or
+	ISR_MIN are not zero (bad assumption).
+
 2000-04-26  Jesper Skov  <jskov@redhat.com>
 
 	* tests/kcache1.c: Also to flush testing with unified caches.
--- a/packages/kernel/current/include/instrmnt.h
+++ b/packages/kernel/current/include/instrmnt.h
@@ -34,13 +34,19 @@
 //==========================================================================
 //#####DESCRIPTIONBEGIN####
 //
-// Author(s):   nickg
-// Contributors:        nickg
-// Date:        1997-10-24
-// Purpose:     Define kernel instrumentation
-// Description: A set of definitions and macros used to implement an
-//              instrumentation interface for the kernel.
-// Usage:       #include <cyg/kernel/instrmnt.hxx>
+// Author(s):    nickg
+// Contributors: nickg
+// Date:         2000-05-04
+// Purpose:      Define kernel instrumentation
+// Description:  A set of definitions and macros used to implement an
+//               instrumentation interface for the kernel.
+//               NOTE: Don't use CYG_UNUSED_PARAM (or similar) here to
+//               silence warnings about unused variables when using the
+//               empty macro definitions. Otherwise this can cause problems
+//               with volatile arguments and cause other side-effects.
+//               Instead it is up to the caller to ensure that unused
+//               arguments don't cause warnings
+// Usage:        #include <cyg/kernel/instrmnt.hxx>
 //
 //####DESCRIPTIONEND####
 //
@@ -78,11 +84,7 @@ externC void cyg_instrument_disable( cyg
 
 #else   // ifdef CYGPKG_KERNEL_INSTRUMENT
 
-#define CYG_INSTRUMENT(_type_,_arg1_,_arg2_)                    \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT(_type_,_arg1_,_arg2_)
 
 #endif  // ifdef CYGPKG_KERNEL_INSTRUMENT
 
@@ -240,11 +242,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_SCHED(_event_,_arg1_,_arg2_)             \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_SCHED(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -258,11 +256,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_THREAD(_event_,_arg1_,_arg2_)            \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_THREAD(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -276,11 +270,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_INTR(_event_,_arg1_,_arg2_)              \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_INTR(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -294,11 +284,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_MUTEX(_event_,_arg1_,_arg2_)             \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_MUTEX(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -312,11 +298,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_CONDVAR(_event_,_arg1_,_arg2_)           \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_CONDVAR(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -330,11 +312,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_BINSEM(_event_,_arg1_,_arg2_)            \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_BINSEM(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -348,11 +326,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_CNTSEM(_event_,_arg1_,_arg2_)            \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_CNTSEM(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -366,11 +340,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_CLOCK(_event_,_arg1_,_arg2_)             \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_CLOCK(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -384,11 +354,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_ALARM(_event_,_arg1_,_arg2_)             \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_ALARM(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -402,11 +368,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_MBOXT(_event_,_arg1_,_arg2_)             \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_MBOXT(_event_,_arg1_,_arg2_)
 
 #endif
 
@@ -420,11 +382,7 @@ externC void cyg_instrument_disable( cyg
 
 #else
 
-#define CYG_INSTRUMENT_USER(_event_,_arg1_,_arg2_)              \
-    CYG_MACRO_START                                             \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg1_));     \
-    CYG_UNUSED_PARAM(CYG_ADDRWORD, (CYG_ADDRWORD)(_arg2_));     \
-    CYG_MACRO_END
+#define CYG_INSTRUMENT_USER(_event_,_arg1_,_arg2_)
 
 #endif
 
--- a/packages/kernel/current/src/intr/intr.cxx
+++ b/packages/kernel/current/src/intr/intr.cxx
@@ -270,9 +270,10 @@ interrupt_end(
 
     // Sometimes we have a NULL intr object pointer.
     cyg_vector vector = (intr!=NULL)?intr->vector:0;
-    
+
     CYG_INSTRUMENT_INTR(END, vector, isr_ret);
     
+    CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
     
 #ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
 
--- a/packages/kernel/current/tests/intr0.cxx
+++ b/packages/kernel/current/tests/intr0.cxx
@@ -87,7 +87,7 @@ static void dsr1(cyg_vector vector, cyg_
 
 static bool flash( void )
 {
-    Cyg_Interrupt intr0 = Cyg_Interrupt( 0, 0, (CYG_ADDRWORD)333, isr0, dsr0 );
+    Cyg_Interrupt intr0 = Cyg_Interrupt(CYGNUM_HAL_ISR_MIN, 0, (CYG_ADDRWORD)333, isr0, dsr0 );
 
     return true;
 }
@@ -120,13 +120,13 @@ void intr0_main( void )
 
     // Make sure the chosen levels are not already in use.
     int in_use;
-    cyg_vector lvl1 = 1 % (CYGNUM_HAL_ISR_COUNT);
+    cyg_vector lvl1 = (CYGNUM_HAL_ISR_MIN + 1) % (CYGNUM_HAL_ISR_COUNT);
     HAL_INTERRUPT_IN_USE( lvl1, in_use );
     Cyg_Interrupt* intr0 = NULL;
     if (!in_use)
         intr0 = new((void *)&intr0_obj[0]) Cyg_Interrupt( lvl1, 1, (CYG_ADDRWORD)777, isr0, dsr0 );
      
-    cyg_vector lvl2 = 15 % (CYGNUM_HAL_ISR_COUNT);
+    cyg_vector lvl2 = (CYGNUM_HAL_ISR_MIN + 15) % (CYGNUM_HAL_ISR_COUNT);
     HAL_INTERRUPT_IN_USE( lvl2, in_use );
     Cyg_Interrupt* intr1 = NULL;
     if (!in_use && lvl1 != lvl2)
@@ -149,7 +149,7 @@ void intr0_main( void )
     // instead of adding to it we could be in a big mess if the
     // vector is being used by something important.
         
-    cyg_vector v = 11 % CYGNUM_HAL_VSR_COUNT;
+    cyg_vector v = (CYGNUM_HAL_VSR_MIN + 11) % CYGNUM_HAL_VSR_COUNT;
     cyg_VSR *old_vsr, *new_vsr;
     Cyg_Interrupt::set_vsr( v, vsr0, &old_vsr );
     Cyg_Interrupt::get_vsr( v, &new_vsr );
@@ -179,7 +179,7 @@ void intr0_main( void )
         v1 = 12 % CYGNUM_HAL_ISR_COUNT;
     else /* NOTE TRAILING ELSE... */
 #endif
-    v1 = 6 % CYGNUM_HAL_ISR_COUNT;
+    v1 = (CYGNUM_HAL_ISR_MIN + 6) % CYGNUM_HAL_ISR_COUNT;
 
     Cyg_Interrupt::mask_interrupt(v1);
     Cyg_Interrupt::unmask_interrupt(v1);
--- a/packages/kernel/current/tests/kintr0.c
+++ b/packages/kernel/current/tests/kintr0.c
@@ -93,7 +93,8 @@ static bool flash( void )
     cyg_handle_t handle;
     cyg_interrupt intr;
 
-    cyg_interrupt_create(0, 0, (cyg_addrword_t)333, isr0, dsr0, &handle, &intr );
+    cyg_interrupt_create(CYGNUM_HAL_ISR_MIN, 0, (cyg_addrword_t)333, 
+                         isr0, dsr0, &handle, &intr );
     cyg_interrupt_delete(handle);
 
     return true;
@@ -120,10 +121,10 @@ static void vsr0()
 
 void kintr0_main( void )
 {
-    cyg_vector_t v = 11 % CYGNUM_HAL_VSR_COUNT;
+    cyg_vector_t v = (CYGNUM_HAL_VSR_MIN + 11) % CYGNUM_HAL_VSR_COUNT;
     cyg_vector_t v1;
-    cyg_vector_t lvl1 = 1 % (CYGNUM_HAL_ISR_COUNT);
-    cyg_vector_t lvl2 = 15 % (CYGNUM_HAL_ISR_COUNT);
+    cyg_vector_t lvl1 = (CYGNUM_HAL_ISR_MIN + 1) % (CYGNUM_HAL_ISR_COUNT);
+    cyg_vector_t lvl2 = (CYGNUM_HAL_ISR_MIN + 15) % (CYGNUM_HAL_ISR_COUNT);
     int in_use;
 
     cyg_VSR_t *old_vsr, *new_vsr;
@@ -136,7 +137,7 @@ void kintr0_main( void )
         v1 = 12 % CYGNUM_HAL_ISR_COUNT;
     else /* NOTE TRAILING ELSE... */
 #endif
-    v1 = 6 % CYGNUM_HAL_ISR_COUNT;
+    v1 = (CYGNUM_HAL_ISR_MIN + 6) % CYGNUM_HAL_ISR_COUNT;
 
     CHECK(flash());
     CHECK(flash());