| 171 | | #define TELNET_IAC 0xFF // Interpret as command (escape) |
|---|
| 172 | | #define TELNET_IP 0xF4 // Interrupt process |
|---|
| 173 | | #define TELNET_WONT 0xFC // I Won't do it |
|---|
| 174 | | #define TELNET_DO 0xFD // Will you XXX |
|---|
| 175 | | #define TELNET_TM 0x06 // Time marker (special DO/WONT after IP) |
|---|
| 176 | | |
|---|
| 177 | | static cyg_bool |
|---|
| 178 | | _net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch) |
|---|
| 179 | | { |
|---|
| 180 | | if (in_buflen == 0) { |
|---|
| 181 | | __tcp_poll(); |
|---|
| 182 | | if (tcp_sock.state == _CLOSE_WAIT) { |
|---|
| 183 | | // This connection is breaking |
|---|
| 184 | | if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) { |
|---|
| 185 | | __tcp_close(&tcp_sock); |
|---|
| 186 | | return false; |
|---|
| 187 | | } |
|---|
| 188 | | } |
|---|
| 189 | | if (tcp_sock.state == _CLOSED) { |
|---|
| 190 | | // The connection is gone |
|---|
| 191 | | net_io_revert_console(); |
|---|
| 192 | | *ch = '\n'; |
|---|
| 193 | | return true; |
|---|
| 194 | | } |
|---|
| 195 | | in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf)); |
|---|
| 196 | | in_bufp = in_buf; |
|---|
| | 141 | #define TELNET_IAC 0xFF // Interpret as command (escape) |
|---|
| | 142 | #define TELNET_IP 0xF4 // Interrupt process |
|---|
| | 143 | #define TELNET_WONT 0xFC // I Won't do it |
|---|
| | 144 | #define TELNET_DO 0xFD // Will you XXX |
|---|
| | 145 | #define TELNET_TM 0x06 // Time marker (special DO/WONT after IP) |
|---|
| | 146 | |
|---|
| | 147 | static cyg_bool _net_io_getc_nonblock(void *__ch_data, cyg_uint8 * ch) |
|---|
| | 148 | { |
|---|
| | 149 | if (in_buflen == 0) { |
|---|
| | 150 | __tcp_poll(); |
|---|
| | 151 | if (tcp_sock.state == _CLOSE_WAIT) { |
|---|
| | 152 | // This connection is breaking |
|---|
| | 153 | if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) { |
|---|
| | 154 | __tcp_close(&tcp_sock); |
|---|
| | 155 | return false; |
|---|
| | 156 | } |
|---|
| | 157 | } |
|---|
| | 158 | if (tcp_sock.state == _CLOSED) { |
|---|
| | 159 | // The connection is gone |
|---|
| | 160 | net_io_revert_console(); |
|---|
| | 161 | *ch = '\n'; |
|---|
| | 162 | return true; |
|---|
| | 163 | } |
|---|
| | 164 | in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf)); |
|---|
| | 165 | in_bufp = in_buf; |
|---|
| 198 | | if (show_tcp && (in_buflen > 0)) { |
|---|
| 199 | | int old_console; |
|---|
| 200 | | old_console = start_console(); |
|---|
| 201 | | diag_printf("%s:%d\n", __FUNCTION__, __LINE__); |
|---|
| 202 | | diag_dump_buf(in_buf, in_buflen); |
|---|
| 203 | | end_console(old_console); |
|---|
| 204 | | } |
|---|
| 205 | | #endif // DEBUG_TCP |
|---|
| 206 | | } |
|---|
| 207 | | if (in_buflen) { |
|---|
| 208 | | *ch = *in_bufp++; |
|---|
| 209 | | in_buflen--; |
|---|
| 210 | | return true; |
|---|
| 211 | | } else { |
|---|
| 212 | | return false; |
|---|
| 213 | | } |
|---|
| 214 | | } |
|---|
| 215 | | |
|---|
| 216 | | static cyg_bool |
|---|
| 217 | | net_io_getc_nonblock(void* __ch_data, cyg_uint8* ch) |
|---|
| 218 | | { |
|---|
| 219 | | cyg_uint8 esc; |
|---|
| 220 | | |
|---|
| 221 | | if (!_net_io_getc_nonblock(__ch_data, ch)) |
|---|
| 222 | | return false; |
|---|
| 223 | | |
|---|
| 224 | | if (gdb_active || *ch != TELNET_IAC) |
|---|
| 225 | | return true; |
|---|
| 226 | | |
|---|
| 227 | | // Telnet escape - need to read/handle more |
|---|
| 228 | | while (!_net_io_getc_nonblock(__ch_data, &esc)) ; |
|---|
| 229 | | |
|---|
| 230 | | switch (esc) { |
|---|
| 231 | | case TELNET_IAC: |
|---|
| 232 | | // The other special case - escaped escape |
|---|
| 233 | | return true; |
|---|
| 234 | | case TELNET_IP: |
|---|
| 235 | | // Special case for ^C == Interrupt Process |
|---|
| 236 | | *ch = 0x03; |
|---|
| 237 | | // Just in case the other end needs synchronizing |
|---|
| 238 | | net_io_putc(__ch_data, TELNET_IAC); |
|---|
| 239 | | net_io_putc(__ch_data, TELNET_WONT); |
|---|
| 240 | | net_io_putc(__ch_data, TELNET_TM); |
|---|
| 241 | | net_io_flush(); |
|---|
| 242 | | return true; |
|---|
| 243 | | case TELNET_DO: |
|---|
| 244 | | // Telnet DO option |
|---|
| 245 | | while (!_net_io_getc_nonblock(__ch_data, &esc)) ; |
|---|
| 246 | | // Respond with WONT option |
|---|
| 247 | | net_io_putc(__ch_data, TELNET_IAC); |
|---|
| 248 | | net_io_putc(__ch_data, TELNET_WONT); |
|---|
| 249 | | net_io_putc(__ch_data, esc); |
|---|
| 250 | | return false; // Ignore this whole thing! |
|---|
| 251 | | default: |
|---|
| 252 | | return false; |
|---|
| 253 | | } |
|---|
| 254 | | } |
|---|
| 255 | | |
|---|
| 256 | | static cyg_uint8 |
|---|
| 257 | | net_io_getc(void* __ch_data) |
|---|
| 258 | | { |
|---|
| 259 | | cyg_uint8 ch; |
|---|
| 260 | | int idle_timeout = 10; // 10ms |
|---|
| 261 | | |
|---|
| 262 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 263 | | while (true) { |
|---|
| 264 | | if (net_io_getc_nonblock(__ch_data, &ch)) break; |
|---|
| 265 | | if (--idle_timeout == 0) { |
|---|
| 266 | | net_io_flush(); |
|---|
| 267 | | idle_timeout = 10; |
|---|
| 268 | | } |
|---|
| 269 | | } |
|---|
| 270 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 271 | | return ch; |
|---|
| | 167 | if (show_tcp && (in_buflen > 0)) { |
|---|
| | 168 | int old_console; |
|---|
| | 169 | old_console = start_console(); |
|---|
| | 170 | diag_printf("%s:%d\n", __FUNCTION__, __LINE__); |
|---|
| | 171 | diag_dump_buf(in_buf, in_buflen); |
|---|
| | 172 | end_console(old_console); |
|---|
| | 173 | } |
|---|
| | 174 | #endif // DEBUG_TCP |
|---|
| | 175 | } |
|---|
| | 176 | if (in_buflen) { |
|---|
| | 177 | *ch = *in_bufp++; |
|---|
| | 178 | in_buflen--; |
|---|
| | 179 | return true; |
|---|
| | 180 | } else { |
|---|
| | 181 | return false; |
|---|
| | 182 | } |
|---|
| | 183 | } |
|---|
| | 184 | |
|---|
| | 185 | static cyg_bool net_io_getc_nonblock(void *__ch_data, cyg_uint8 * ch) |
|---|
| | 186 | { |
|---|
| | 187 | cyg_uint8 esc; |
|---|
| | 188 | |
|---|
| | 189 | if (!_net_io_getc_nonblock(__ch_data, ch)) |
|---|
| | 190 | return false; |
|---|
| | 191 | |
|---|
| | 192 | if (gdb_active || *ch != TELNET_IAC) |
|---|
| | 193 | return true; |
|---|
| | 194 | |
|---|
| | 195 | // Telnet escape - need to read/handle more |
|---|
| | 196 | while (!_net_io_getc_nonblock(__ch_data, &esc)) ; |
|---|
| | 197 | |
|---|
| | 198 | switch (esc) { |
|---|
| | 199 | case TELNET_IAC: |
|---|
| | 200 | // The other special case - escaped escape |
|---|
| | 201 | return true; |
|---|
| | 202 | case TELNET_IP: |
|---|
| | 203 | // Special case for ^C == Interrupt Process |
|---|
| | 204 | *ch = 0x03; |
|---|
| | 205 | // Just in case the other end needs synchronizing |
|---|
| | 206 | net_io_putc(__ch_data, TELNET_IAC); |
|---|
| | 207 | net_io_putc(__ch_data, TELNET_WONT); |
|---|
| | 208 | net_io_putc(__ch_data, TELNET_TM); |
|---|
| | 209 | net_io_flush(); |
|---|
| | 210 | return true; |
|---|
| | 211 | case TELNET_DO: |
|---|
| | 212 | // Telnet DO option |
|---|
| | 213 | while (!_net_io_getc_nonblock(__ch_data, &esc)) ; |
|---|
| | 214 | // Respond with WONT option |
|---|
| | 215 | net_io_putc(__ch_data, TELNET_IAC); |
|---|
| | 216 | net_io_putc(__ch_data, TELNET_WONT); |
|---|
| | 217 | net_io_putc(__ch_data, esc); |
|---|
| | 218 | return false; // Ignore this whole thing! |
|---|
| | 219 | default: |
|---|
| | 220 | return false; |
|---|
| | 221 | } |
|---|
| | 222 | } |
|---|
| | 223 | |
|---|
| | 224 | static cyg_uint8 net_io_getc(void *__ch_data) |
|---|
| | 225 | { |
|---|
| | 226 | cyg_uint8 ch; |
|---|
| | 227 | int idle_timeout = 10; // 10ms |
|---|
| | 228 | |
|---|
| | 229 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 230 | while (true) { |
|---|
| | 231 | if (net_io_getc_nonblock(__ch_data, &ch)) |
|---|
| | 232 | break; |
|---|
| | 233 | if (--idle_timeout == 0) { |
|---|
| | 234 | net_io_flush(); |
|---|
| | 235 | idle_timeout = 10; |
|---|
| | 236 | } |
|---|
| | 237 | } |
|---|
| | 238 | CYGARC_HAL_RESTORE_GP(); |
|---|
| | 239 | return ch; |
|---|
| | 240 | } |
|---|
| | 241 | |
|---|
| | 242 | static void net_io_flush(void) |
|---|
| | 243 | { |
|---|
| | 244 | int n; |
|---|
| | 245 | char *bp = out_buf; |
|---|
| | 246 | |
|---|
| | 247 | #ifdef DEBUG_TCP |
|---|
| | 248 | if (show_tcp) { |
|---|
| | 249 | int old_console; |
|---|
| | 250 | old_console = start_console(); |
|---|
| | 251 | diag_printf("%s.%d\n", __FUNCTION__, __LINE__); |
|---|
| | 252 | diag_dump_buf(out_buf, out_buflen); |
|---|
| | 253 | end_console(old_console); |
|---|
| | 254 | } |
|---|
| | 255 | #endif // SHOW_TCP |
|---|
| | 256 | n = __tcp_write_block(&tcp_sock, bp, out_buflen); |
|---|
| | 257 | if (n < 0) { |
|---|
| | 258 | // The connection is gone! |
|---|
| | 259 | net_io_revert_console(); |
|---|
| | 260 | } else { |
|---|
| | 261 | out_buflen -= n; |
|---|
| | 262 | bp += n; |
|---|
| | 263 | } |
|---|
| | 264 | out_bufp = out_buf; |
|---|
| | 265 | out_buflen = 0; |
|---|
| | 266 | // Check interrupt flag |
|---|
| | 267 | if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { |
|---|
| | 268 | CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); |
|---|
| | 269 | cyg_hal_user_break(0); |
|---|
| | 270 | } |
|---|
| | 271 | } |
|---|
| | 272 | |
|---|
| | 273 | static void net_io_putc(void *__ch_data, cyg_uint8 c) |
|---|
| | 274 | { |
|---|
| | 275 | static bool have_dollar, have_hash; |
|---|
| | 276 | static int hash_count; |
|---|
| | 277 | |
|---|
| | 278 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 279 | *out_bufp++ = c; |
|---|
| | 280 | if (c == '$') |
|---|
| | 281 | have_dollar = true; |
|---|
| | 282 | if (have_dollar && (c == '#')) { |
|---|
| | 283 | have_hash = true; |
|---|
| | 284 | hash_count = 0; |
|---|
| | 285 | } |
|---|
| | 286 | if ((++out_buflen == sizeof(out_buf)) || |
|---|
| | 287 | (flush_output_lines && c == '\n') || |
|---|
| | 288 | (have_hash && (++hash_count == 3))) { |
|---|
| | 289 | net_io_flush(); |
|---|
| | 290 | have_dollar = false; |
|---|
| | 291 | } |
|---|
| | 292 | CYGARC_HAL_RESTORE_GP(); |
|---|
| 275 | | net_io_flush(void) |
|---|
| 276 | | { |
|---|
| 277 | | int n; |
|---|
| 278 | | char *bp = out_buf; |
|---|
| 279 | | |
|---|
| | 296 | net_io_write(void *__ch_data, const cyg_uint8 * __buf, cyg_uint32 __len) |
|---|
| | 297 | { |
|---|
| | 298 | int old_console; |
|---|
| | 299 | |
|---|
| | 300 | old_console = start_console(); |
|---|
| | 301 | diag_printf("%s.%d\n", __FUNCTION__, __LINE__); |
|---|
| | 302 | end_console(old_console); |
|---|
| | 303 | #if 0 |
|---|
| | 304 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 305 | |
|---|
| | 306 | while (__len-- > 0) |
|---|
| | 307 | net_io_putc(__ch_data, *__buf++); |
|---|
| | 308 | |
|---|
| | 309 | CYGARC_HAL_RESTORE_GP(); |
|---|
| | 310 | #endif |
|---|
| | 311 | } |
|---|
| | 312 | |
|---|
| | 313 | static void net_io_read(void *__ch_data, cyg_uint8 * __buf, cyg_uint32 __len) |
|---|
| | 314 | { |
|---|
| | 315 | int old_console; |
|---|
| | 316 | |
|---|
| | 317 | old_console = start_console(); |
|---|
| | 318 | diag_printf("%s.%d\n", __FUNCTION__, __LINE__); |
|---|
| | 319 | end_console(old_console); |
|---|
| | 320 | #if 0 |
|---|
| | 321 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 322 | |
|---|
| | 323 | while (__len-- > 0) |
|---|
| | 324 | *__buf++ = net_io_getc(__ch_data); |
|---|
| | 325 | |
|---|
| | 326 | CYGARC_HAL_RESTORE_GP(); |
|---|
| | 327 | #endif |
|---|
| | 328 | } |
|---|
| | 329 | |
|---|
| | 330 | static cyg_bool net_io_getc_timeout(void *__ch_data, cyg_uint8 * ch) |
|---|
| | 331 | { |
|---|
| | 332 | int delay_count; |
|---|
| | 333 | cyg_bool res; |
|---|
| | 334 | |
|---|
| | 335 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 336 | net_io_flush(); // Make sure any output has been sent |
|---|
| | 337 | delay_count = _timeout; |
|---|
| | 338 | |
|---|
| | 339 | for (;;) { |
|---|
| | 340 | res = net_io_getc_nonblock(__ch_data, ch); |
|---|
| | 341 | if (res || 0 == delay_count--) |
|---|
| | 342 | break; |
|---|
| | 343 | } |
|---|
| | 344 | |
|---|
| | 345 | CYGARC_HAL_RESTORE_GP(); |
|---|
| | 346 | |
|---|
| | 347 | return res; |
|---|
| | 348 | } |
|---|
| | 349 | |
|---|
| | 350 | static int net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...) |
|---|
| | 351 | { |
|---|
| | 352 | static int vector = 0; |
|---|
| | 353 | int ret = 0; |
|---|
| | 354 | static int irq_state = 0; |
|---|
| | 355 | |
|---|
| | 356 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 357 | |
|---|
| | 358 | switch (__func) { |
|---|
| | 359 | case __COMMCTL_IRQ_ENABLE: |
|---|
| | 360 | irq_state = 1; |
|---|
| | 361 | if (vector == 0) { |
|---|
| | 362 | vector = eth_drv_int_vector(); |
|---|
| | 363 | } |
|---|
| | 364 | HAL_INTERRUPT_UNMASK(vector); |
|---|
| | 365 | break; |
|---|
| | 366 | case __COMMCTL_IRQ_DISABLE: |
|---|
| | 367 | ret = irq_state; |
|---|
| | 368 | irq_state = 0; |
|---|
| | 369 | if (vector == 0) { |
|---|
| | 370 | vector = eth_drv_int_vector(); |
|---|
| | 371 | } |
|---|
| | 372 | HAL_INTERRUPT_MASK(vector); |
|---|
| | 373 | break; |
|---|
| | 374 | case __COMMCTL_DBG_ISR_VECTOR: |
|---|
| | 375 | ret = vector; |
|---|
| | 376 | break; |
|---|
| | 377 | case __COMMCTL_SET_TIMEOUT: |
|---|
| | 378 | { |
|---|
| | 379 | va_list ap; |
|---|
| | 380 | |
|---|
| | 381 | va_start(ap, __func); |
|---|
| | 382 | |
|---|
| | 383 | ret = _timeout; |
|---|
| | 384 | _timeout = va_arg(ap, cyg_uint32); |
|---|
| | 385 | |
|---|
| | 386 | va_end(ap); |
|---|
| | 387 | break; |
|---|
| | 388 | } |
|---|
| | 389 | case __COMMCTL_FLUSH_OUTPUT: |
|---|
| | 390 | net_io_flush(); |
|---|
| | 391 | break; |
|---|
| | 392 | case __COMMCTL_ENABLE_LINE_FLUSH: |
|---|
| | 393 | flush_output_lines = true; |
|---|
| | 394 | break; |
|---|
| | 395 | case __COMMCTL_DISABLE_LINE_FLUSH: |
|---|
| | 396 | flush_output_lines = false; |
|---|
| | 397 | break; |
|---|
| | 398 | default: |
|---|
| | 399 | break; |
|---|
| | 400 | } |
|---|
| | 401 | CYGARC_HAL_RESTORE_GP(); |
|---|
| | 402 | return ret; |
|---|
| | 403 | } |
|---|
| | 404 | |
|---|
| | 405 | static int |
|---|
| | 406 | net_io_isr(void *__ch_data, int *__ctrlc, |
|---|
| | 407 | CYG_ADDRWORD __vector, CYG_ADDRWORD __data) |
|---|
| | 408 | { |
|---|
| | 409 | char ch; |
|---|
| | 410 | |
|---|
| | 411 | CYGARC_HAL_SAVE_GP(); |
|---|
| | 412 | *__ctrlc = 0; |
|---|
| | 413 | if (net_io_getc_nonblock(__ch_data, &ch)) { |
|---|
| | 414 | if (ch == 0x03) { |
|---|
| | 415 | *__ctrlc = 1; |
|---|
| | 416 | } |
|---|
| | 417 | } |
|---|
| | 418 | CYGARC_HAL_RESTORE_GP(); |
|---|
| | 419 | return CYG_ISR_HANDLED; |
|---|
| | 420 | } |
|---|
| | 421 | |
|---|
| | 422 | // TEMP |
|---|
| | 423 | |
|---|
| | 424 | int start_console(void) |
|---|
| | 425 | { |
|---|
| | 426 | int cur_console = |
|---|
| | 427 | CYGACC_CALL_IF_SET_CONSOLE_COMM |
|---|
| | 428 | (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| | 429 | |
|---|
| | 430 | #ifdef CYGSEM_REDBOOT_FLASH_CONFIG |
|---|
| | 431 | int i = 0; |
|---|
| | 432 | if (flash_get_config("info_console_force", &i, CONFIG_BOOL)) |
|---|
| | 433 | if (i) |
|---|
| | 434 | if (!flash_get_config |
|---|
| | 435 | ("info_console_number", &i, CONFIG_INT)) |
|---|
| | 436 | i = 0; // the default, if that call failed. |
|---|
| | 437 | if (i) |
|---|
| | 438 | CYGACC_CALL_IF_SET_CONSOLE_COMM(i); |
|---|
| | 439 | else |
|---|
| | 440 | #endif |
|---|
| | 441 | CYGACC_CALL_IF_SET_CONSOLE_COMM(0); |
|---|
| | 442 | |
|---|
| | 443 | return cur_console; |
|---|
| | 444 | } |
|---|
| | 445 | |
|---|
| | 446 | void end_console(int old_console) |
|---|
| | 447 | { |
|---|
| | 448 | // Restore original console |
|---|
| | 449 | CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console); |
|---|
| | 450 | } |
|---|
| | 451 | |
|---|
| | 452 | // TEMP |
|---|
| | 453 | |
|---|
| | 454 | static void net_io_revert_console(void) |
|---|
| | 455 | { |
|---|
| | 456 | #ifdef CYGPKG_REDBOOT_ANY_CONSOLE |
|---|
| | 457 | console_selected = false; |
|---|
| | 458 | #endif |
|---|
| | 459 | CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console); |
|---|
| | 460 | CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug); |
|---|
| | 461 | console_echo = true; |
|---|
| | 462 | } |
|---|
| | 463 | |
|---|
| | 464 | static void net_io_assume_console(void) |
|---|
| | 465 | { |
|---|
| | 466 | #ifdef CYGPKG_REDBOOT_ANY_CONSOLE |
|---|
| | 467 | console_selected = true; |
|---|
| | 468 | #endif |
|---|
| | 469 | console_echo = false; |
|---|
| | 470 | orig_console = |
|---|
| | 471 | CYGACC_CALL_IF_SET_CONSOLE_COMM |
|---|
| | 472 | (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| | 473 | CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); |
|---|
| | 474 | orig_debug = |
|---|
| | 475 | CYGACC_CALL_IF_SET_DEBUG_COMM |
|---|
| | 476 | (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| | 477 | CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL); |
|---|
| | 478 | } |
|---|
| | 479 | |
|---|
| | 480 | static void net_io_init(void) |
|---|
| | 481 | { |
|---|
| | 482 | static int init = 0; |
|---|
| | 483 | if (!init) { |
|---|
| | 484 | hal_virtual_comm_table_t *comm; |
|---|
| | 485 | int cur = |
|---|
| | 486 | CYGACC_CALL_IF_SET_CONSOLE_COMM |
|---|
| | 487 | (CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| | 488 | |
|---|
| | 489 | // Setup procs in the vector table |
|---|
| | 490 | CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); |
|---|
| | 491 | comm = CYGACC_CALL_IF_CONSOLE_PROCS(); |
|---|
| | 492 | //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan); |
|---|
| | 493 | CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write); |
|---|
| | 494 | CYGACC_COMM_IF_READ_SET(*comm, net_io_read); |
|---|
| | 495 | CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc); |
|---|
| | 496 | CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc); |
|---|
| | 497 | CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control); |
|---|
| | 498 | CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr); |
|---|
| | 499 | CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout); |
|---|
| | 500 | |
|---|
| | 501 | // Disable interrupts via this interface to set static |
|---|
| | 502 | // state into correct state. |
|---|
| | 503 | net_io_control(comm, __COMMCTL_IRQ_DISABLE); |
|---|
| | 504 | |
|---|
| | 505 | // Restore original console |
|---|
| | 506 | CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); |
|---|
| | 507 | |
|---|
| | 508 | init = 1; |
|---|
| | 509 | gdb_active = false; |
|---|
| | 510 | } |
|---|
| | 511 | __tcp_listen(&tcp_sock, gdb_port); |
|---|
| | 512 | state = tcp_sock.state; |
|---|
| 281 | | if (show_tcp) { |
|---|
| 282 | | int old_console; |
|---|
| 283 | | old_console = start_console(); |
|---|
| 284 | | diag_printf("%s.%d\n", __FUNCTION__, __LINE__); |
|---|
| 285 | | diag_dump_buf(out_buf, out_buflen); |
|---|
| 286 | | end_console(old_console); |
|---|
| 287 | | } |
|---|
| 288 | | #endif // SHOW_TCP |
|---|
| 289 | | n = __tcp_write_block(&tcp_sock, bp, out_buflen); |
|---|
| 290 | | if (n < 0) { |
|---|
| 291 | | // The connection is gone! |
|---|
| 292 | | net_io_revert_console(); |
|---|
| 293 | | } else { |
|---|
| 294 | | out_buflen -= n; |
|---|
| 295 | | bp += n; |
|---|
| 296 | | } |
|---|
| 297 | | out_bufp = out_buf; out_buflen = 0; |
|---|
| 298 | | // Check interrupt flag |
|---|
| 299 | | if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { |
|---|
| 300 | | CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); |
|---|
| 301 | | cyg_hal_user_break(0); |
|---|
| 302 | | } |
|---|
| 303 | | } |
|---|
| 304 | | |
|---|
| 305 | | static void |
|---|
| 306 | | net_io_putc(void* __ch_data, cyg_uint8 c) |
|---|
| 307 | | { |
|---|
| 308 | | static bool have_dollar, have_hash; |
|---|
| 309 | | static int hash_count; |
|---|
| 310 | | |
|---|
| 311 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 312 | | *out_bufp++ = c; |
|---|
| 313 | | if (c == '$') have_dollar = true; |
|---|
| 314 | | if (have_dollar && (c == '#')) { |
|---|
| 315 | | have_hash = true; |
|---|
| 316 | | hash_count = 0; |
|---|
| 317 | | } |
|---|
| 318 | | if ((++out_buflen == sizeof(out_buf)) || |
|---|
| 319 | | (flush_output_lines && c == '\n') || |
|---|
| 320 | | (have_hash && (++hash_count == 3))) { |
|---|
| 321 | | net_io_flush(); |
|---|
| 322 | | have_dollar = false; |
|---|
| 323 | | } |
|---|
| 324 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 325 | | } |
|---|
| 326 | | |
|---|
| 327 | | static void |
|---|
| 328 | | net_io_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len) |
|---|
| 329 | | { |
|---|
| 330 | | int old_console; |
|---|
| 331 | | |
|---|
| 332 | | old_console = start_console(); |
|---|
| 333 | | diag_printf("%s.%d\n", __FUNCTION__, __LINE__); |
|---|
| 334 | | end_console(old_console); |
|---|
| 335 | | #if 0 |
|---|
| 336 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 337 | | |
|---|
| 338 | | while(__len-- > 0) |
|---|
| 339 | | net_io_putc(__ch_data, *__buf++); |
|---|
| 340 | | |
|---|
| 341 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 342 | | #endif |
|---|
| 343 | | } |
|---|
| 344 | | |
|---|
| 345 | | static void |
|---|
| 346 | | net_io_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) |
|---|
| 347 | | { |
|---|
| 348 | | int old_console; |
|---|
| 349 | | |
|---|
| 350 | | old_console = start_console(); |
|---|
| 351 | | diag_printf("%s.%d\n", __FUNCTION__, __LINE__); |
|---|
| 352 | | end_console(old_console); |
|---|
| 353 | | #if 0 |
|---|
| 354 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 355 | | |
|---|
| 356 | | while(__len-- > 0) |
|---|
| 357 | | *__buf++ = net_io_getc(__ch_data); |
|---|
| 358 | | |
|---|
| 359 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 360 | | #endif |
|---|
| 361 | | } |
|---|
| 362 | | |
|---|
| 363 | | static cyg_bool |
|---|
| 364 | | net_io_getc_timeout(void* __ch_data, cyg_uint8* ch) |
|---|
| 365 | | { |
|---|
| 366 | | int delay_count; |
|---|
| 367 | | cyg_bool res; |
|---|
| 368 | | |
|---|
| 369 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 370 | | net_io_flush(); // Make sure any output has been sent |
|---|
| 371 | | delay_count = _timeout; |
|---|
| 372 | | |
|---|
| 373 | | for(;;) { |
|---|
| 374 | | res = net_io_getc_nonblock(__ch_data, ch); |
|---|
| 375 | | if (res || 0 == delay_count--) |
|---|
| 376 | | break; |
|---|
| 377 | | } |
|---|
| 378 | | |
|---|
| 379 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 380 | | |
|---|
| 381 | | return res; |
|---|
| 382 | | } |
|---|
| 383 | | |
|---|
| 384 | | static int |
|---|
| 385 | | net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...) |
|---|
| 386 | | { |
|---|
| 387 | | static int vector = 0; |
|---|
| 388 | | int ret = 0; |
|---|
| 389 | | static int irq_state = 0; |
|---|
| 390 | | |
|---|
| 391 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 392 | | |
|---|
| 393 | | switch (__func) { |
|---|
| 394 | | case __COMMCTL_IRQ_ENABLE: |
|---|
| 395 | | irq_state = 1; |
|---|
| 396 | | if (vector == 0) { |
|---|
| 397 | | vector = eth_drv_int_vector(); |
|---|
| 398 | | } |
|---|
| 399 | | HAL_INTERRUPT_UNMASK(vector); |
|---|
| 400 | | break; |
|---|
| 401 | | case __COMMCTL_IRQ_DISABLE: |
|---|
| 402 | | ret = irq_state; |
|---|
| 403 | | irq_state = 0; |
|---|
| 404 | | if (vector == 0) { |
|---|
| 405 | | vector = eth_drv_int_vector(); |
|---|
| 406 | | } |
|---|
| 407 | | HAL_INTERRUPT_MASK(vector); |
|---|
| 408 | | break; |
|---|
| 409 | | case __COMMCTL_DBG_ISR_VECTOR: |
|---|
| 410 | | ret = vector; |
|---|
| 411 | | break; |
|---|
| 412 | | case __COMMCTL_SET_TIMEOUT: |
|---|
| 413 | | { |
|---|
| 414 | | va_list ap; |
|---|
| 415 | | |
|---|
| 416 | | va_start(ap, __func); |
|---|
| 417 | | |
|---|
| 418 | | ret = _timeout; |
|---|
| 419 | | _timeout = va_arg(ap, cyg_uint32); |
|---|
| 420 | | |
|---|
| 421 | | va_end(ap); |
|---|
| 422 | | break; |
|---|
| 423 | | } |
|---|
| 424 | | case __COMMCTL_FLUSH_OUTPUT: |
|---|
| 425 | | net_io_flush(); |
|---|
| 426 | | break; |
|---|
| 427 | | case __COMMCTL_ENABLE_LINE_FLUSH: |
|---|
| 428 | | flush_output_lines = true; |
|---|
| 429 | | break; |
|---|
| 430 | | case __COMMCTL_DISABLE_LINE_FLUSH: |
|---|
| 431 | | flush_output_lines = false; |
|---|
| 432 | | break; |
|---|
| 433 | | default: |
|---|
| 434 | | break; |
|---|
| 435 | | } |
|---|
| 436 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 437 | | return ret; |
|---|
| 438 | | } |
|---|
| 439 | | |
|---|
| 440 | | static int |
|---|
| 441 | | net_io_isr(void *__ch_data, int* __ctrlc, |
|---|
| 442 | | CYG_ADDRWORD __vector, CYG_ADDRWORD __data) |
|---|
| 443 | | { |
|---|
| 444 | | char ch; |
|---|
| 445 | | |
|---|
| 446 | | CYGARC_HAL_SAVE_GP(); |
|---|
| 447 | | *__ctrlc = 0; |
|---|
| 448 | | if (net_io_getc_nonblock(__ch_data, &ch)) { |
|---|
| 449 | | if (ch == 0x03) { |
|---|
| 450 | | *__ctrlc = 1; |
|---|
| 451 | | } |
|---|
| 452 | | } |
|---|
| 453 | | CYGARC_HAL_RESTORE_GP(); |
|---|
| 454 | | return CYG_ISR_HANDLED; |
|---|
| 455 | | } |
|---|
| 456 | | |
|---|
| 457 | | // TEMP |
|---|
| 458 | | |
|---|
| 459 | | int |
|---|
| 460 | | start_console(void) |
|---|
| 461 | | { |
|---|
| 462 | | int cur_console = |
|---|
| 463 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| 464 | | |
|---|
| 465 | | #ifdef CYGSEM_REDBOOT_FLASH_CONFIG |
|---|
| 466 | | int i = 0; |
|---|
| 467 | | if ( flash_get_config( "info_console_force", &i, CONFIG_BOOL) ) |
|---|
| 468 | | if ( i ) |
|---|
| 469 | | if ( ! flash_get_config( "info_console_number", &i, CONFIG_INT) ) |
|---|
| 470 | | i = 0; // the default, if that call failed. |
|---|
| 471 | | if ( i ) |
|---|
| 472 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(i); |
|---|
| 473 | | else |
|---|
| 474 | | #endif |
|---|
| 475 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(0); |
|---|
| 476 | | |
|---|
| 477 | | return cur_console; |
|---|
| 478 | | } |
|---|
| 479 | | |
|---|
| 480 | | void |
|---|
| 481 | | end_console(int old_console) |
|---|
| 482 | | { |
|---|
| 483 | | // Restore original console |
|---|
| 484 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console); |
|---|
| 485 | | } |
|---|
| 486 | | // TEMP |
|---|
| 487 | | |
|---|
| 488 | | static void |
|---|
| 489 | | net_io_revert_console(void) |
|---|
| 490 | | { |
|---|
| 491 | | #ifdef CYGPKG_REDBOOT_ANY_CONSOLE |
|---|
| 492 | | console_selected = false; |
|---|
| 493 | | #endif |
|---|
| 494 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console); |
|---|
| 495 | | CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug); |
|---|
| 496 | | console_echo = true; |
|---|
| 497 | | } |
|---|
| 498 | | |
|---|
| 499 | | static void |
|---|
| 500 | | net_io_assume_console(void) |
|---|
| 501 | | { |
|---|
| 502 | | #ifdef CYGPKG_REDBOOT_ANY_CONSOLE |
|---|
| 503 | | console_selected = true; |
|---|
| 504 | | #endif |
|---|
| 505 | | console_echo = false; |
|---|
| 506 | | orig_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| 507 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); |
|---|
| 508 | | orig_debug = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| 509 | | CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL); |
|---|
| 510 | | } |
|---|
| 511 | | |
|---|
| 512 | | static void |
|---|
| 513 | | net_io_init(void) |
|---|
| 514 | | { |
|---|
| 515 | | static int init = 0; |
|---|
| 516 | | if (!init) { |
|---|
| 517 | | hal_virtual_comm_table_t* comm; |
|---|
| 518 | | int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); |
|---|
| 519 | | |
|---|
| 520 | | // Setup procs in the vector table |
|---|
| 521 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL); |
|---|
| 522 | | comm = CYGACC_CALL_IF_CONSOLE_PROCS(); |
|---|
| 523 | | //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan); |
|---|
| 524 | | CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write); |
|---|
| 525 | | CYGACC_COMM_IF_READ_SET(*comm, net_io_read); |
|---|
| 526 | | CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc); |
|---|
| 527 | | CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc); |
|---|
| 528 | | CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control); |
|---|
| 529 | | CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr); |
|---|
| 530 | | CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout); |
|---|
| 531 | | |
|---|
| 532 | | // Disable interrupts via this interface to set static |
|---|
| 533 | | // state into correct state. |
|---|
| 534 | | net_io_control( comm, __COMMCTL_IRQ_DISABLE ); |
|---|
| 535 | | |
|---|
| 536 | | // Restore original console |
|---|
| 537 | | CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); |
|---|
| 538 | | |
|---|
| 539 | | init = 1; |
|---|
| 540 | | gdb_active = false; |
|---|
| 541 | | } |
|---|
| 542 | | __tcp_listen(&tcp_sock, gdb_port); |
|---|
| 543 | | state = tcp_sock.state; |
|---|
| 544 | | #ifdef DEBUG_TCP |
|---|
| 545 | | diag_printf("show tcp = %p\n", (void *)&show_tcp); |
|---|
| | 514 | diag_printf("show tcp = %p\n", (void *)&show_tcp); |
|---|
| 607 | | static void |
|---|
| 608 | | flash_get_IP(char *id, ip_addr_t *val) |
|---|
| 609 | | { |
|---|
| 610 | | ip_addr_t my_ip; |
|---|
| 611 | | int i; |
|---|
| 612 | | |
|---|
| 613 | | if (flash_get_config(id, &my_ip, CONFIG_IP)) { |
|---|
| 614 | | if (my_ip[0] != 0 || my_ip[1] != 0 || |
|---|
| 615 | | my_ip[2] != 0 || my_ip[3] != 0) { |
|---|
| 616 | | // 'id' is set to something so let it override any static IP |
|---|
| 617 | | for (i=0; i<4; i++) |
|---|
| 618 | | (*val)[i] = my_ip[i]; |
|---|
| 619 | | } |
|---|
| 620 | | } |
|---|
| 621 | | } |
|---|
| 622 | | #endif |
|---|
| 623 | | |
|---|
| 624 | | static cyg_netdevtab_entry_t * |
|---|
| 625 | | net_devtab_entry(unsigned index) |
|---|
| 626 | | { |
|---|
| 627 | | cyg_netdevtab_entry_t *t = &__NETDEVTAB__[index]; |
|---|
| 628 | | |
|---|
| 629 | | if (t < &__NETDEVTAB__[0] || t >= &__NETDEVTAB_END__) |
|---|
| | 580 | static void flash_get_IP(char *id, ip_addr_t * val) |
|---|
| | 581 | { |
|---|
| | 582 | ip_addr_t my_ip; |
|---|
| | 583 | int i; |
|---|
| | 584 | |
|---|
| | 585 | if (flash_get_config(id, &my_ip, CONFIG_IP)) { |
|---|
| | 586 | if (my_ip[0] != 0 || my_ip[1] != 0 || |
|---|
| | 587 | my_ip[2] != 0 || my_ip[3] != 0) { |
|---|
| | 588 | // 'id' is set to something so let it override any static IP |
|---|
| | 589 | for (i = 0; i < 4; i++) |
|---|
| | 590 | (*val)[i] = my_ip[i]; |
|---|
| | 591 | } |
|---|
| | 592 | } |
|---|
| | 593 | } |
|---|
| | 594 | #endif |
|---|
| | 595 | |
|---|
| | 596 | static cyg_netdevtab_entry_t *net_devtab_entry(unsigned index) |
|---|
| | 597 | { |
|---|
| | 598 | cyg_netdevtab_entry_t *t = &__NETDEVTAB__[index]; |
|---|
| | 599 | |
|---|
| | 600 | if (t < &__NETDEVTAB__[0] || t >= &__NETDEVTAB_END__) |
|---|
| | 601 | return NULL; |
|---|
| | 602 | |
|---|
| | 603 | return t; |
|---|
| | 604 | } |
|---|
| | 605 | |
|---|
| | 606 | const char *net_devname(unsigned index) |
|---|
| | 607 | { |
|---|
| | 608 | cyg_netdevtab_entry_t *t = net_devtab_entry(index); |
|---|
| | 609 | if (t) |
|---|
| | 610 | return t->name; |
|---|
| 856 | | char *slash_pos; |
|---|
| 857 | | /* see if the (optional) mask length was given */ |
|---|
| 858 | | if( (slash_pos = strchr(ip_addr, '/')) ) { |
|---|
| 859 | | int mask_len; |
|---|
| 860 | | unsigned long mask; |
|---|
| 861 | | *slash_pos = '\0'; |
|---|
| 862 | | slash_pos++; |
|---|
| 863 | | if( !parse_num(slash_pos, (unsigned long *)&mask_len, 0, 0) || |
|---|
| 864 | | mask_len <= 0 || mask_len > 32 ) { |
|---|
| 865 | | diag_printf("Invalid mask length: %s\n", slash_pos); |
|---|
| 866 | | return; |
|---|
| 867 | | } |
|---|
| 868 | | mask = htonl((0xffffffff << (32-mask_len))&0xffffffff); |
|---|
| 869 | | memcpy(&__local_ip_mask, &mask, 4); |
|---|
| 870 | | } |
|---|
| 871 | | #endif |
|---|
| 872 | | if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) { |
|---|
| 873 | | diag_printf("Invalid local IP address: %s\n", ip_addr); |
|---|
| 874 | | return; |
|---|
| 875 | | } |
|---|
| 876 | | // Of course, each address goes in its own place :-) |
|---|
| 877 | | memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr)); |
|---|
| 878 | | } |
|---|
| 879 | | if (host_addr_set) { |
|---|
| 880 | | if (!_gethostbyname(host_addr, (in_addr_t *)&host)) { |
|---|
| 881 | | diag_printf("Invalid server address: %s\n", host_addr); |
|---|
| 882 | | return; |
|---|
| 883 | | } |
|---|
| 884 | | my_bootp_info.bp_siaddr = host.sin_addr; |
|---|
| 885 | | } |
|---|
| | 822 | char *slash_pos; |
|---|
| | 823 | /* see if the (optional) mask length was given */ |
|---|
| | 824 | if ((slash_pos = strchr(ip_addr, '/'))) { |
|---|
| | 825 | int mask_len; |
|---|
| | 826 | unsigned long mask; |
|---|
| | 827 | *slash_pos = '\0'; |
|---|
| | 828 | slash_pos++; |
|---|
| | 829 | if (!parse_num |
|---|
| | 830 | (slash_pos, (unsigned long *)&mask_len, 0, 0) |
|---|
| | 831 | || mask_len <= 0 || mask_len > 32) { |
|---|
| | 832 | diag_printf("Invalid mask length: %s\n", |
|---|
| | 833 | slash_pos); |
|---|
| | 834 | return; |
|---|
| | 835 | } |
|---|
| | 836 | mask = |
|---|
| | 837 | htonl((0xffffffff << (32 - mask_len)) & 0xffffffff); |
|---|
| | 838 | memcpy(&__local_ip_mask, &mask, 4); |
|---|
| | 839 | } |
|---|
| | 840 | #endif |
|---|
| | 841 | if (!_gethostbyname(ip_addr, (in_addr_t *) & host)) { |
|---|
| | 842 | diag_printf("Invalid local IP address: %s\n", ip_addr); |
|---|
| | 843 | return; |
|---|
| | 844 | } |
|---|
| | 845 | // Of course, each address goes in its own place :-) |
|---|
| | 846 | memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr)); |
|---|
| | 847 | } |
|---|
| | 848 | if (host_addr_set) { |
|---|
| | 849 | if (!_gethostbyname(host_addr, (in_addr_t *) & host)) { |
|---|
| | 850 | diag_printf("Invalid server address: %s\n", host_addr); |
|---|
| | 851 | return; |
|---|
| | 852 | } |
|---|
| | 853 | my_bootp_info.bp_siaddr = host.sin_addr; |
|---|
| | 854 | } |
|---|