1 /* Serial console layer, layered on top of sercomm HDLC */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
23 #include <asm/system.h>
28 #include <osmocom/core/msgb.h>
29 #include <comm/sercomm.h>
30 #include <comm/sercomm_cons.h>
36 static void raw_puts(const char *s
)
39 int uart_id
= sercomm_get_uart();
41 uart_putchar_wait(uart_id
, *s
++);
45 #define raw_putd(x) raw_puts(x)
50 int sercomm_puts(const char *s
)
53 const int len
= strlen(s
);
54 unsigned int bytes_left
= len
;
56 if (!sercomm_initialized()) {
57 raw_putd("sercomm not initialized: ");
62 /* This function is called from any context: Supervisor, IRQ, FIQ, ...
63 * as such, we need to ensure re-entrant calls are either supported or
65 local_irq_save(flags
);
68 while (bytes_left
> 0) {
69 unsigned int write_num
, space_left
, flush
;
73 scons
.cur_msg
= sercomm_alloc_msgb(SERCOMM_CONS_ALLOC
);
76 raw_putd("cannot allocate sercomm msgb: ");
81 /* space left in the current msgb */
82 space_left
= msgb_tailroom(scons
.cur_msg
);
84 if (space_left
<= bytes_left
) {
85 write_num
= space_left
;
86 /* flush buffer when it is full */
89 write_num
= bytes_left
;
93 /* obtain pointer where to copy the data */
94 data
= msgb_put(scons
.cur_msg
, write_num
);
96 /* copy data while looking for \n line termination */
99 for (i
= 0; i
< write_num
; i
++) {
100 /* flush buffer at end of line, but skip
101 * flushing if we have a backlog in order to
102 * increase efficiency of msgb filling */
104 sercomm_tx_queue_depth(SC_DLCI_CONSOLE
) < 4)
109 bytes_left
-= write_num
;
112 sercomm_sendmsg(SC_DLCI_CONSOLE
, scons
.cur_msg
);
113 /* reset scons.cur_msg pointer to ensure we allocate
114 * a new one next round */
115 scons
.cur_msg
= NULL
;
119 local_irq_restore(flags
);
124 int sercomm_putchar(int c
)
132 rc
= sercomm_puts(s
);