Mercurial > ecos
annotate packages/io/serial/current/src/common/serial.c @ 66:bf00f99aec69 ecos-sw-2000-02-02
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
| author | jlarmour |
|---|---|
| date | Wed, 02 Feb 2000 19:57:02 +0000 |
| parents | c38311975d4f |
| children | 6736c52df507 |
| rev | line source |
|---|---|
| 2 | 1 //========================================================================== |
| 2 // | |
| 3 // io/serial/common/serial.c | |
| 4 // | |
| 5 // High level serial driver | |
| 6 // | |
| 7 //========================================================================== | |
| 8 //####COPYRIGHTBEGIN#### | |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
9 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
10 // ------------------------------------------- |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
11 // The contents of this file are subject to the Red Hat eCos Public License |
|
66
bf00f99aec69
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
jlarmour
parents:
64
diff
changeset
|
12 // Version 1.1 (the "License"); you may not use this file except in |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
13 // compliance with the License. You may obtain a copy of the License at |
|
66
bf00f99aec69
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
jlarmour
parents:
64
diff
changeset
|
14 // http://www.redhat.com/ |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
15 // |
|
66
bf00f99aec69
Merge from eCos master repository on 2000-02-02-19:16:44-GMT
jlarmour
parents:
64
diff
changeset
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
64
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
18 // License for the specific language governing rights and limitations under |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
19 // the License. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
20 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
21 // The Original Code is eCos - Embedded Configurable Operating System, |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
22 // released September 30, 1998. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
23 // |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
24 // The Initial Developer of the Original Code is Red Hat. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
25 // Portions created by Red Hat are |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
27 // All Rights Reserved. |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
28 // ------------------------------------------- |
|
c38311975d4f
Merge from eCos master repository on 2000-01-28-04:28:11-GMT
jlarmour
parents:
62
diff
changeset
|
29 // |
| 2 | 30 //####COPYRIGHTEND#### |
| 31 //========================================================================== | |
| 32 //#####DESCRIPTIONBEGIN#### | |
| 33 // | |
| 34 // Author(s): gthomas | |
| 35 // Contributors: gthomas | |
| 36 // Date: 1999-02-04 | |
| 37 // Purpose: Top level serial driver | |
| 38 // Description: | |
| 39 // | |
| 40 //####DESCRIPTIONEND#### | |
| 41 // | |
| 42 //========================================================================== | |
| 43 | |
| 44 #include <pkgconf/io.h> | |
| 45 #include <cyg/io/io.h> | |
| 46 #include <cyg/io/devtab.h> | |
| 47 #include <cyg/io/serial.h> | |
| 48 #include <cyg/infra/diag.h> | |
| 49 | |
| 50 static Cyg_ErrNo serial_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len); | |
| 51 static Cyg_ErrNo serial_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len); | |
| 52 static Cyg_ErrNo serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len); | |
| 53 static Cyg_ErrNo serial_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len); | |
| 54 | |
|
62
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
55 DEVIO_TABLE(cyg_io_serial_devio, |
| 2 | 56 serial_write, |
| 57 serial_read, | |
| 58 serial_get_config, | |
| 59 serial_set_config | |
| 60 ); | |
| 61 | |
| 62 static void serial_init(serial_channel *chan); | |
| 63 static void serial_xmt_char(serial_channel *chan); | |
| 64 static void serial_rcv_char(serial_channel *chan, unsigned char c); | |
|
62
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
65 SERIAL_CALLBACKS(cyg_io_serial_callbacks, |
| 2 | 66 serial_init, |
| 67 serial_xmt_char, | |
| 68 serial_rcv_char); | |
| 69 | |
| 70 static void | |
| 71 serial_init(serial_channel *chan) | |
| 72 { | |
| 73 if (chan->init) return; | |
| 74 if (chan->out_cbuf.len != 0) { | |
| 75 #ifdef CYGDBG_IO_INIT | |
| 76 diag_printf("Set output buffer - buf: %x len: %d\n", chan->out_cbuf.data, chan->out_cbuf.len); | |
| 77 #endif | |
| 78 chan->out_cbuf.waiting = false; | |
| 79 chan->out_cbuf.abort = false; | |
| 80 chan->out_cbuf.pending = 0; | |
| 81 cyg_drv_mutex_init(&chan->out_cbuf.lock); | |
| 82 cyg_drv_cond_init(&chan->out_cbuf.wait, &chan->out_cbuf.lock); | |
| 83 chan->out_cbuf.low_water = chan->out_cbuf.len / 4; | |
| 84 } | |
| 85 if (chan->in_cbuf.len != 0) { | |
| 86 #ifdef CYGDBG_IO_INIT | |
| 87 diag_printf("Set input buffer - buf: %x len: %d\n", chan->in_cbuf.data, chan->in_cbuf.len); | |
| 88 #endif | |
| 89 chan->in_cbuf.waiting = false; | |
| 90 chan->in_cbuf.abort = false; | |
| 91 cyg_drv_mutex_init(&chan->in_cbuf.lock); | |
| 92 cyg_drv_cond_init(&chan->in_cbuf.wait, &chan->in_cbuf.lock); | |
| 93 } | |
| 94 chan->init = true; | |
| 95 } | |
| 96 | |
| 97 static Cyg_ErrNo | |
| 98 serial_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len) | |
| 99 { | |
| 100 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 101 serial_channel *chan = (serial_channel *)t->priv; | |
| 102 serial_funs *funs = chan->funs; | |
| 103 cyg_int32 size = *len; | |
| 104 cyg_uint8 *buf = (cyg_uint8 *)_buf; | |
| 105 int next; | |
| 106 cbuf_t *cbuf = &chan->out_cbuf; | |
| 107 Cyg_ErrNo res = ENOERR; | |
|
20
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
108 |
|
4
1d7f19c9e4d1
Merge from eCos master repository on 1999-05-11-21:11:10-BST
jlarmour
parents:
2
diff
changeset
|
109 cbuf->abort = false; |
| 2 | 110 cyg_drv_mutex_lock(&cbuf->lock); |
| 111 if (cbuf->len == 0) { | |
| 112 // Non interrupt driven (i.e. polled) operation | |
| 113 while (size-- > 0) { | |
| 114 while ((funs->putc)(chan, *buf) == false) ; // Ignore full, keep trying | |
| 115 buf++; | |
| 116 } | |
| 117 } else { | |
| 118 cyg_drv_dsr_lock(); // Avoid race condition testing pointers | |
| 119 while (size > 0) { | |
| 120 next = cbuf->put + 1; | |
| 121 if (next == cbuf->len) next = 0; | |
| 122 if (next == cbuf->get) { | |
| 123 cbuf->waiting = true; | |
| 124 // Buffer full - wait for space | |
| 125 (funs->start_xmit)(chan); // Make sure xmit is running | |
|
62
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
126 if (cbuf->waiting) { |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
127 // Note: 'start_xmit' may have obviated the need to wait :-) |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
128 cbuf->pending += size; // Have this much more to send [eventually] |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
129 cyg_drv_cond_wait(&cbuf->wait); |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
130 cbuf->pending -= size; |
|
7a6ac9edc838
Merge from eCos master repository on 2000-01-24-19:43:49-GMT
jlarmour
parents:
20
diff
changeset
|
131 } |
| 2 | 132 if (cbuf->abort) { |
| 133 // Give up! | |
| 134 cbuf->abort = false; | |
| 135 cbuf->waiting = false; | |
| 136 res = -EINTR; | |
| 137 break; | |
| 138 } | |
| 139 } else { | |
| 140 cbuf->data[cbuf->put++] = *buf++; | |
| 141 cbuf->put = next; | |
| 142 size--; // Only count if actually sent! | |
| 143 } | |
| 144 } | |
| 145 cyg_drv_dsr_unlock(); | |
| 146 (funs->start_xmit)(chan); // Start output as necessary | |
| 147 } | |
| 148 cyg_drv_mutex_unlock(&cbuf->lock); | |
| 149 return res; | |
| 150 } | |
| 151 | |
| 152 static Cyg_ErrNo | |
| 153 serial_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len) | |
| 154 { | |
| 155 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 156 serial_channel *chan = (serial_channel *)t->priv; | |
| 157 serial_funs *funs = chan->funs; | |
| 158 cyg_uint8 *buf = (cyg_uint8 *)_buf; | |
| 159 cyg_int32 size = 0; | |
| 160 cbuf_t *cbuf = &chan->in_cbuf; | |
| 161 Cyg_ErrNo res = ENOERR; | |
|
20
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
162 #ifdef XX_CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
163 extern int enable_diag_uart; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
164 int _enable = enable_diag_uart; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
165 int _time, _stime; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
166 externC cyg_tick_count_t cyg_current_time(void); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
167 #endif // CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
168 |
|
4
1d7f19c9e4d1
Merge from eCos master repository on 1999-05-11-21:11:10-BST
jlarmour
parents:
2
diff
changeset
|
169 cbuf->abort = false; |
| 2 | 170 cyg_drv_mutex_lock(&cbuf->lock); |
| 171 if (cbuf->len == 0) { | |
| 172 // Non interrupt driven (i.e. polled) operation | |
| 173 while (size++ < *len) { | |
| 174 *buf++ = (funs->getc)(chan); | |
| 175 } | |
| 176 } else { | |
| 177 cyg_drv_dsr_lock(); // Avoid races | |
| 178 while (size < *len) { | |
| 179 if (cbuf->get != cbuf->put) { | |
| 180 *buf++ = cbuf->data[cbuf->get]; | |
| 181 if (++cbuf->get == cbuf->len) cbuf->get = 0; | |
| 182 size++; | |
| 183 } else { | |
| 184 cbuf->waiting = true; | |
|
20
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
185 #ifdef XX_CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
186 enable_diag_uart = 0; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
187 HAL_CLOCK_READ(&_time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
188 _stime = (int)cyg_current_time(); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
189 diag_printf("READ wait - get: %d, put: %d, time: %x.%x\n", cbuf->get, cbuf->put, _stime, _time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
190 enable_diag_uart = _enable; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
191 #endif // CYGDBG_DIAG_BUF |
| 2 | 192 cyg_drv_cond_wait(&cbuf->wait); |
|
20
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
193 #ifdef XX_CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
194 enable_diag_uart = 0; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
195 HAL_CLOCK_READ(&_time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
196 _stime = (int)cyg_current_time(); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
197 diag_printf("READ continue - get: %d, put: %d, time: %x.%x\n", cbuf->get, cbuf->put, _stime, _time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
198 enable_diag_uart = _enable; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
199 #endif // CYGDBG_DIAG_BUF |
| 2 | 200 if (cbuf->abort) { |
| 201 // Give up! | |
| 202 cbuf->abort = false; | |
| 203 cbuf->waiting = false; | |
| 204 res = -EINTR; | |
| 205 break; | |
| 206 } | |
| 207 } | |
| 208 } | |
| 209 cyg_drv_dsr_unlock(); | |
| 210 } | |
|
20
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
211 cyg_drv_isr_lock(); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
212 #ifdef XX_CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
213 enable_diag_uart = 0; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
214 HAL_CLOCK_READ(&_time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
215 _stime = (int)cyg_current_time(); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
216 diag_printf("READ done - size: %d, len: %d, time: %x.%x\n", size, *len, _stime, _time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
217 enable_diag_uart = _enable; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
218 #endif // CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
219 cyg_drv_isr_unlock(); |
| 2 | 220 cyg_drv_mutex_unlock(&cbuf->lock); |
| 221 return res; | |
| 222 } | |
| 223 | |
| 224 static Cyg_ErrNo | |
| 225 serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf, cyg_uint32 *len) | |
| 226 { | |
| 227 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 228 serial_channel *chan = (serial_channel *)t->priv; | |
| 229 cyg_serial_info_t *buf = (cyg_serial_info_t *)xbuf; | |
| 230 Cyg_ErrNo res = ENOERR; | |
| 231 cbuf_t *cbuf = &chan->out_cbuf; | |
| 232 serial_funs *funs = chan->funs; | |
| 233 | |
| 234 switch (key) { | |
| 235 case CYG_IO_GET_CONFIG_SERIAL_INFO: | |
| 236 if (*len < sizeof(cyg_serial_info_t)) { | |
| 237 return -EINVAL; | |
| 238 } | |
| 239 *buf = chan->config; | |
| 240 *len = sizeof(chan->config); | |
| 241 break; | |
| 242 case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN: | |
| 243 // Wait for any pending output to complete | |
| 244 if (cbuf->len == 0) break; // Nothing to do if not buffered | |
| 245 cyg_drv_mutex_lock(&cbuf->lock); // Stop any further output processing | |
| 246 cyg_drv_dsr_lock(); | |
| 247 while (cbuf->pending || (cbuf->get != cbuf->put)) { | |
| 248 cbuf->waiting = true; | |
| 249 cyg_drv_cond_wait(&cbuf->wait); | |
| 250 } | |
| 251 cyg_drv_dsr_unlock(); | |
| 252 cyg_drv_mutex_unlock(&cbuf->lock); | |
| 253 break; | |
| 254 case CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH: | |
| 255 // Flush any buffered input | |
| 256 cbuf = &chan->in_cbuf; | |
| 257 if (cbuf->len == 0) break; // Nothing to do if not buffered | |
| 258 cyg_drv_mutex_lock(&cbuf->lock); // Stop any further input processing | |
| 259 cyg_drv_dsr_lock(); | |
| 260 if (cbuf->waiting) { | |
| 261 cbuf->abort = true; | |
| 262 cyg_drv_cond_signal(&cbuf->wait); | |
| 263 cbuf->waiting = false; | |
| 264 } | |
| 265 cbuf->get = cbuf->put; // Flush buffered input | |
| 266 cyg_drv_dsr_unlock(); | |
| 267 cyg_drv_mutex_unlock(&cbuf->lock); | |
| 268 break; | |
| 269 case CYG_IO_GET_CONFIG_SERIAL_ABORT: | |
| 270 // Abort any outstanding I/O, including blocked reads | |
| 271 // Caution - assumed to be called from 'timeout' (i.e. DSR) code | |
| 272 cbuf = &chan->in_cbuf; | |
| 273 if (cbuf->len != 0) { | |
| 274 cbuf->abort = true; | |
| 275 cyg_drv_cond_signal(&cbuf->wait); | |
| 276 } | |
| 277 cbuf = &chan->out_cbuf; | |
| 278 if (cbuf->len != 0) { | |
| 279 cbuf->abort = true; | |
| 280 cyg_drv_cond_signal(&cbuf->wait); | |
| 281 } | |
| 282 break; | |
| 283 case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH: | |
| 284 // Throw away any pending output | |
| 285 if (cbuf->len == 0) break; // Nothing to do if not buffered | |
| 286 cyg_drv_mutex_lock(&cbuf->lock); // Stop any further output processing | |
| 287 cyg_drv_dsr_lock(); | |
| 288 if (cbuf->get != cbuf->put) { | |
| 289 cbuf->get = cbuf->put; // Empties queue! | |
| 290 (funs->stop_xmit)(chan); // Done with transmit | |
| 291 } | |
| 292 if (cbuf->waiting) { | |
| 293 cbuf->abort = true; | |
| 294 cyg_drv_cond_signal(&cbuf->wait); | |
| 295 cbuf->waiting = false; | |
| 296 } | |
| 297 cyg_drv_dsr_unlock(); | |
| 298 cyg_drv_mutex_unlock(&cbuf->lock); | |
| 299 break; | |
| 300 default: | |
| 301 res = -EINVAL; | |
| 302 } | |
| 303 return res; | |
| 304 } | |
| 305 | |
| 306 static Cyg_ErrNo | |
| 307 serial_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) | |
| 308 { | |
| 309 Cyg_ErrNo res = ENOERR; | |
| 310 cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; | |
| 311 serial_channel *chan = (serial_channel *)t->priv; | |
| 312 serial_funs *funs = chan->funs; | |
| 313 cyg_serial_info_t *buf = (cyg_serial_info_t *)xbuf; | |
| 314 | |
| 315 switch (key) { | |
| 316 case CYG_IO_SET_CONFIG_SERIAL_INFO: | |
| 317 if (*len != sizeof(cyg_serial_info_t)) { | |
| 318 return -EINVAL; | |
| 319 } | |
| 320 if ((funs->set_config)(chan, buf) != true) { | |
| 321 // Device is not happy with paramters or they cannot be set | |
| 322 res = -EINVAL; | |
| 323 } | |
| 324 break; | |
| 325 default: | |
| 326 res = -EINVAL; | |
| 327 } | |
| 328 return res; | |
| 329 } | |
| 330 | |
| 331 static void | |
| 332 serial_xmt_char(serial_channel *chan) | |
| 333 { | |
| 334 cbuf_t *cbuf = &chan->out_cbuf; | |
| 335 serial_funs *funs = chan->funs; | |
| 336 unsigned char c; | |
| 337 int space; | |
| 338 | |
| 339 while (cbuf->get != cbuf->put) { | |
| 340 c = cbuf->data[cbuf->get]; | |
| 341 if ((funs->putc)(chan, c)) { | |
| 342 cbuf->get++; | |
| 343 if (cbuf->get == cbuf->len) cbuf->get = 0; | |
| 344 if (cbuf->waiting) { | |
| 345 // See if there is now enough room to restart writer | |
| 346 space = (cbuf->len + cbuf->get) - cbuf->put; | |
| 347 if (space > cbuf->len) space -= cbuf->len; | |
| 348 if (space >= cbuf->low_water) { | |
| 349 cbuf->waiting = false; | |
| 350 cyg_drv_cond_broadcast(&cbuf->wait); | |
| 351 } | |
| 352 } | |
| 353 } else { | |
| 354 return; // Need to wait for more space | |
| 355 } | |
| 356 } | |
| 357 (funs->stop_xmit)(chan); // Done with transmit | |
| 358 if (cbuf->waiting) { | |
| 359 cbuf->waiting = false; | |
| 360 cyg_drv_cond_signal(&cbuf->wait); | |
| 361 } | |
| 362 } | |
| 363 | |
| 364 static void | |
| 365 serial_rcv_char(serial_channel *chan, unsigned char c) | |
| 366 { | |
| 367 cbuf_t *cbuf = &chan->in_cbuf; | |
| 368 | |
| 369 cbuf->data[cbuf->put++] = c; | |
| 370 if (cbuf->put == cbuf->len) cbuf->put = 0; | |
| 371 if (cbuf->waiting) { | |
|
20
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
372 #ifdef XX_CYGDBG_DIAG_BUF |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
373 extern int enable_diag_uart; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
374 int _enable = enable_diag_uart; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
375 int _time, _stime; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
376 externC cyg_tick_count_t cyg_current_time(void); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
377 enable_diag_uart = 0; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
378 HAL_CLOCK_READ(&_time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
379 _stime = (int)cyg_current_time(); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
380 diag_printf("Signal reader - time: %x.%x\n", _stime, _time); |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
381 enable_diag_uart = _enable; |
|
5f5102441818
Merge from eCos master repository on 1999-07-02-23:17:07-BST
jlarmour
parents:
4
diff
changeset
|
382 #endif // CYGDBG_DIAG_BUF |
| 2 | 383 cbuf->waiting = false; |
| 384 cyg_drv_cond_signal(&cbuf->wait); | |
| 385 } | |
| 386 } | |
| 387 |
