Statistics
| Branch: | Revision:

root / monitor.c @ 9dc39cba

History | View | Annotate | Download (13.2 kB)

1 9dc39cba bellard
/*
2 9dc39cba bellard
 * QEMU monitor
3 9dc39cba bellard
 * 
4 9dc39cba bellard
 * Copyright (c) 2003-2004 Fabrice Bellard
5 9dc39cba bellard
 * 
6 9dc39cba bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 9dc39cba bellard
 * of this software and associated documentation files (the "Software"), to deal
8 9dc39cba bellard
 * in the Software without restriction, including without limitation the rights
9 9dc39cba bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 9dc39cba bellard
 * copies of the Software, and to permit persons to whom the Software is
11 9dc39cba bellard
 * furnished to do so, subject to the following conditions:
12 9dc39cba bellard
 *
13 9dc39cba bellard
 * The above copyright notice and this permission notice shall be included in
14 9dc39cba bellard
 * all copies or substantial portions of the Software.
15 9dc39cba bellard
 *
16 9dc39cba bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 9dc39cba bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 9dc39cba bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 9dc39cba bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 9dc39cba bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 9dc39cba bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 9dc39cba bellard
 * THE SOFTWARE.
23 9dc39cba bellard
 */
24 9dc39cba bellard
#include <stdlib.h>
25 9dc39cba bellard
#include <stdio.h>
26 9dc39cba bellard
#include <stdarg.h>
27 9dc39cba bellard
#include <string.h>
28 9dc39cba bellard
#include <getopt.h>
29 9dc39cba bellard
#include <inttypes.h>
30 9dc39cba bellard
#include <unistd.h>
31 9dc39cba bellard
#include <sys/mman.h>
32 9dc39cba bellard
#include <fcntl.h>
33 9dc39cba bellard
#include <signal.h>
34 9dc39cba bellard
#include <time.h>
35 9dc39cba bellard
#include <sys/time.h>
36 9dc39cba bellard
#include <malloc.h>
37 9dc39cba bellard
#include <termios.h>
38 9dc39cba bellard
#include <sys/poll.h>
39 9dc39cba bellard
#include <errno.h>
40 9dc39cba bellard
#include <ctype.h>
41 9dc39cba bellard
42 9dc39cba bellard
#include "cpu.h"
43 9dc39cba bellard
#include "vl.h"
44 9dc39cba bellard
45 9dc39cba bellard
//#define DEBUG
46 9dc39cba bellard
47 9dc39cba bellard
#define TERM_CMD_BUF_SIZE 4095
48 9dc39cba bellard
#define MAX_ARGS 64
49 9dc39cba bellard
50 9dc39cba bellard
#define IS_NORM 0
51 9dc39cba bellard
#define IS_ESC  1
52 9dc39cba bellard
#define IS_CSI  2
53 9dc39cba bellard
54 9dc39cba bellard
#define printf do_not_use_printf
55 9dc39cba bellard
56 9dc39cba bellard
static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
57 9dc39cba bellard
static int term_cmd_buf_index;
58 9dc39cba bellard
static int term_cmd_buf_size;
59 9dc39cba bellard
static int term_esc_state;
60 9dc39cba bellard
static int term_esc_param;
61 9dc39cba bellard
62 9dc39cba bellard
typedef struct term_cmd_t {
63 9dc39cba bellard
    const char *name;
64 9dc39cba bellard
    void (*handler)(int argc, const char **argv);
65 9dc39cba bellard
    const char *params;
66 9dc39cba bellard
    const char *help;
67 9dc39cba bellard
} term_cmd_t;
68 9dc39cba bellard
69 9dc39cba bellard
static term_cmd_t term_cmds[];
70 9dc39cba bellard
static term_cmd_t info_cmds[];
71 9dc39cba bellard
72 9dc39cba bellard
void term_printf(const char *fmt, ...)
73 9dc39cba bellard
{
74 9dc39cba bellard
    va_list ap;
75 9dc39cba bellard
    va_start(ap, fmt);
76 9dc39cba bellard
    vprintf(fmt, ap);
77 9dc39cba bellard
    va_end(ap);
78 9dc39cba bellard
}
79 9dc39cba bellard
80 9dc39cba bellard
void term_flush(void)
81 9dc39cba bellard
{
82 9dc39cba bellard
    fflush(stdout);
83 9dc39cba bellard
}
84 9dc39cba bellard
85 9dc39cba bellard
static int compare_cmd(const char *name, const char *list)
86 9dc39cba bellard
{
87 9dc39cba bellard
    const char *p, *pstart;
88 9dc39cba bellard
    int len;
89 9dc39cba bellard
    len = strlen(name);
90 9dc39cba bellard
    p = list;
91 9dc39cba bellard
    for(;;) {
92 9dc39cba bellard
        pstart = p;
93 9dc39cba bellard
        p = strchr(p, '|');
94 9dc39cba bellard
        if (!p)
95 9dc39cba bellard
            p = pstart + strlen(pstart);
96 9dc39cba bellard
        if ((p - pstart) == len && !memcmp(pstart, name, len))
97 9dc39cba bellard
            return 1;
98 9dc39cba bellard
        if (*p == '\0')
99 9dc39cba bellard
            break;
100 9dc39cba bellard
        p++;
101 9dc39cba bellard
    }
102 9dc39cba bellard
    return 0;
103 9dc39cba bellard
}
104 9dc39cba bellard
105 9dc39cba bellard
static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
106 9dc39cba bellard
{
107 9dc39cba bellard
    term_cmd_t *cmd;
108 9dc39cba bellard
109 9dc39cba bellard
    for(cmd = cmds; cmd->name != NULL; cmd++) {
110 9dc39cba bellard
        if (!name || !strcmp(name, cmd->name))
111 9dc39cba bellard
            term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
112 9dc39cba bellard
    }
113 9dc39cba bellard
}
114 9dc39cba bellard
115 9dc39cba bellard
static void help_cmd(const char *name)
116 9dc39cba bellard
{
117 9dc39cba bellard
    if (name && !strcmp(name, "info")) {
118 9dc39cba bellard
        help_cmd1(info_cmds, "info ", NULL);
119 9dc39cba bellard
    } else {
120 9dc39cba bellard
        help_cmd1(term_cmds, "", name);
121 9dc39cba bellard
    }
122 9dc39cba bellard
}
123 9dc39cba bellard
124 9dc39cba bellard
static void do_help(int argc, const char **argv)
125 9dc39cba bellard
{
126 9dc39cba bellard
    help_cmd(argv[1]);
127 9dc39cba bellard
}
128 9dc39cba bellard
129 9dc39cba bellard
static void do_commit(int argc, const char **argv)
130 9dc39cba bellard
{
131 9dc39cba bellard
    int i;
132 9dc39cba bellard
133 9dc39cba bellard
    for (i = 0; i < MAX_DISKS; i++) {
134 9dc39cba bellard
        if (bs_table[i])
135 9dc39cba bellard
            bdrv_commit(bs_table[i]);
136 9dc39cba bellard
    }
137 9dc39cba bellard
}
138 9dc39cba bellard
139 9dc39cba bellard
static void do_info(int argc, const char **argv)
140 9dc39cba bellard
{
141 9dc39cba bellard
    term_cmd_t *cmd;
142 9dc39cba bellard
    const char *item;
143 9dc39cba bellard
144 9dc39cba bellard
    if (argc < 2)
145 9dc39cba bellard
        goto help;
146 9dc39cba bellard
    item = argv[1];
147 9dc39cba bellard
    for(cmd = info_cmds; cmd->name != NULL; cmd++) {
148 9dc39cba bellard
        if (compare_cmd(argv[1], cmd->name)) 
149 9dc39cba bellard
            goto found;
150 9dc39cba bellard
    }
151 9dc39cba bellard
 help:
152 9dc39cba bellard
    help_cmd(argv[0]);
153 9dc39cba bellard
    return;
154 9dc39cba bellard
 found:
155 9dc39cba bellard
    cmd->handler(argc, argv);
156 9dc39cba bellard
}
157 9dc39cba bellard
158 9dc39cba bellard
static void do_info_network(int argc, const char **argv)
159 9dc39cba bellard
{
160 9dc39cba bellard
    int i, j;
161 9dc39cba bellard
    NetDriverState *nd;
162 9dc39cba bellard
    
163 9dc39cba bellard
    for(i = 0; i < nb_nics; i++) {
164 9dc39cba bellard
        nd = &nd_table[i];
165 9dc39cba bellard
        term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
166 9dc39cba bellard
        for(j = 0; j < 6; j++) {
167 9dc39cba bellard
            if (j > 0)
168 9dc39cba bellard
                term_printf(":");
169 9dc39cba bellard
            term_printf("%02x", nd->macaddr[j]);
170 9dc39cba bellard
        }
171 9dc39cba bellard
        term_printf("\n");
172 9dc39cba bellard
    }
173 9dc39cba bellard
}
174 9dc39cba bellard
 
175 9dc39cba bellard
static void do_info_block(int argc, const char **argv)
176 9dc39cba bellard
{
177 9dc39cba bellard
    bdrv_info();
178 9dc39cba bellard
}
179 9dc39cba bellard
180 9dc39cba bellard
static void do_quit(int argc, const char **argv)
181 9dc39cba bellard
{
182 9dc39cba bellard
    exit(0);
183 9dc39cba bellard
}
184 9dc39cba bellard
185 9dc39cba bellard
static int eject_device(BlockDriverState *bs, int force)
186 9dc39cba bellard
{
187 9dc39cba bellard
    if (bdrv_is_inserted(bs)) {
188 9dc39cba bellard
        if (!force) {
189 9dc39cba bellard
            if (!bdrv_is_removable(bs)) {
190 9dc39cba bellard
                term_printf("device is not removable\n");
191 9dc39cba bellard
                return -1;
192 9dc39cba bellard
            }
193 9dc39cba bellard
            if (bdrv_is_locked(bs)) {
194 9dc39cba bellard
                term_printf("device is locked\n");
195 9dc39cba bellard
                return -1;
196 9dc39cba bellard
            }
197 9dc39cba bellard
        }
198 9dc39cba bellard
        bdrv_close(bs);
199 9dc39cba bellard
    }
200 9dc39cba bellard
    return 0;
201 9dc39cba bellard
}
202 9dc39cba bellard
203 9dc39cba bellard
static void do_eject(int argc, const char **argv)
204 9dc39cba bellard
{
205 9dc39cba bellard
    BlockDriverState *bs;
206 9dc39cba bellard
    const char **parg;
207 9dc39cba bellard
    int force;
208 9dc39cba bellard
209 9dc39cba bellard
    parg = argv + 1;
210 9dc39cba bellard
    if (!*parg) {
211 9dc39cba bellard
    fail:
212 9dc39cba bellard
        help_cmd(argv[0]);
213 9dc39cba bellard
        return;
214 9dc39cba bellard
    }
215 9dc39cba bellard
    force = 0;
216 9dc39cba bellard
    if (!strcmp(*parg, "-f")) {
217 9dc39cba bellard
        force = 1;
218 9dc39cba bellard
        parg++;
219 9dc39cba bellard
    }
220 9dc39cba bellard
    if (!*parg)
221 9dc39cba bellard
        goto fail;
222 9dc39cba bellard
    bs = bdrv_find(*parg);
223 9dc39cba bellard
    if (!bs) {
224 9dc39cba bellard
        term_printf("device not found\n");
225 9dc39cba bellard
        return;
226 9dc39cba bellard
    }
227 9dc39cba bellard
    eject_device(bs, force);
228 9dc39cba bellard
}
229 9dc39cba bellard
230 9dc39cba bellard
static void do_change(int argc, const char **argv)
231 9dc39cba bellard
{
232 9dc39cba bellard
    BlockDriverState *bs;
233 9dc39cba bellard
234 9dc39cba bellard
    if (argc != 3) {
235 9dc39cba bellard
        help_cmd(argv[0]);
236 9dc39cba bellard
        return;
237 9dc39cba bellard
    }
238 9dc39cba bellard
    bs = bdrv_find(argv[1]);
239 9dc39cba bellard
    if (!bs) {
240 9dc39cba bellard
        term_printf("device not found\n");
241 9dc39cba bellard
        return;
242 9dc39cba bellard
    }
243 9dc39cba bellard
    if (eject_device(bs, 0) < 0)
244 9dc39cba bellard
        return;
245 9dc39cba bellard
    bdrv_open(bs, argv[2], 0);
246 9dc39cba bellard
}
247 9dc39cba bellard
248 9dc39cba bellard
static term_cmd_t term_cmds[] = {
249 9dc39cba bellard
    { "help|?", do_help, 
250 9dc39cba bellard
      "[cmd]", "show the help" },
251 9dc39cba bellard
    { "commit", do_commit, 
252 9dc39cba bellard
      "", "commit changes to the disk images (if -snapshot is used)" },
253 9dc39cba bellard
    { "info", do_info,
254 9dc39cba bellard
      "subcommand", "show various information about the system state" },
255 9dc39cba bellard
    { "q|quit", do_quit,
256 9dc39cba bellard
      "", "quit the emulator" },
257 9dc39cba bellard
    { "eject", do_eject,
258 9dc39cba bellard
      "[-f] device", "eject a removable media (use -f to force it)" },
259 9dc39cba bellard
    { "change", do_change,
260 9dc39cba bellard
      "device filename", "change a removable media" },
261 9dc39cba bellard
    { NULL, NULL, },
262 9dc39cba bellard
};
263 9dc39cba bellard
264 9dc39cba bellard
static term_cmd_t info_cmds[] = {
265 9dc39cba bellard
    { "network", do_info_network,
266 9dc39cba bellard
      "", "show the network state" },
267 9dc39cba bellard
    { "block", do_info_block,
268 9dc39cba bellard
      "", "show the block devices" },
269 9dc39cba bellard
    { NULL, NULL, },
270 9dc39cba bellard
};
271 9dc39cba bellard
272 9dc39cba bellard
static void term_handle_command(char *cmdline)
273 9dc39cba bellard
{
274 9dc39cba bellard
    char *p, *pstart;
275 9dc39cba bellard
    int argc;
276 9dc39cba bellard
    const char *args[MAX_ARGS + 1];
277 9dc39cba bellard
    term_cmd_t *cmd;
278 9dc39cba bellard
279 9dc39cba bellard
#ifdef DEBUG
280 9dc39cba bellard
    term_printf("command='%s'\n", cmdline);
281 9dc39cba bellard
#endif
282 9dc39cba bellard
    
283 9dc39cba bellard
    /* split command in words */
284 9dc39cba bellard
    argc = 0;
285 9dc39cba bellard
    p = cmdline;
286 9dc39cba bellard
    for(;;) {
287 9dc39cba bellard
        while (isspace(*p))
288 9dc39cba bellard
            p++;
289 9dc39cba bellard
        if (*p == '\0')
290 9dc39cba bellard
            break;
291 9dc39cba bellard
        pstart = p;
292 9dc39cba bellard
        while (*p != '\0' && !isspace(*p))
293 9dc39cba bellard
            p++;
294 9dc39cba bellard
        args[argc] = pstart;
295 9dc39cba bellard
        argc++;
296 9dc39cba bellard
        if (argc >= MAX_ARGS)
297 9dc39cba bellard
            break;
298 9dc39cba bellard
        if (*p == '\0')
299 9dc39cba bellard
            break;
300 9dc39cba bellard
        *p++ = '\0';
301 9dc39cba bellard
    }
302 9dc39cba bellard
    args[argc] = NULL;
303 9dc39cba bellard
#ifdef DEBUG
304 9dc39cba bellard
    for(i=0;i<argc;i++) {
305 9dc39cba bellard
        term_printf(" '%s'", args[i]);
306 9dc39cba bellard
    }
307 9dc39cba bellard
    term_printf("\n");
308 9dc39cba bellard
#endif
309 9dc39cba bellard
    if (argc <= 0)
310 9dc39cba bellard
        return;
311 9dc39cba bellard
    for(cmd = term_cmds; cmd->name != NULL; cmd++) {
312 9dc39cba bellard
        if (compare_cmd(args[0], cmd->name)) 
313 9dc39cba bellard
            goto found;
314 9dc39cba bellard
    }
315 9dc39cba bellard
    term_printf("unknown command: '%s'\n", args[0]);
316 9dc39cba bellard
    return;
317 9dc39cba bellard
 found:
318 9dc39cba bellard
    cmd->handler(argc, args);
319 9dc39cba bellard
}
320 9dc39cba bellard
321 9dc39cba bellard
static void term_show_prompt(void)
322 9dc39cba bellard
{
323 9dc39cba bellard
    term_printf("(qemu) ");
324 9dc39cba bellard
    fflush(stdout);
325 9dc39cba bellard
    term_cmd_buf_index = 0;
326 9dc39cba bellard
    term_cmd_buf_size = 0;
327 9dc39cba bellard
    term_esc_state = IS_NORM;
328 9dc39cba bellard
}
329 9dc39cba bellard
330 9dc39cba bellard
static void term_insert_char(int ch)
331 9dc39cba bellard
{
332 9dc39cba bellard
    if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
333 9dc39cba bellard
        memmove(term_cmd_buf + term_cmd_buf_index + 1,
334 9dc39cba bellard
                term_cmd_buf + term_cmd_buf_index,
335 9dc39cba bellard
                term_cmd_buf_size - term_cmd_buf_index);
336 9dc39cba bellard
        term_cmd_buf[term_cmd_buf_index] = ch;
337 9dc39cba bellard
        term_cmd_buf_size++;
338 9dc39cba bellard
        term_printf("\033[@%c", ch);
339 9dc39cba bellard
        term_cmd_buf_index++;
340 9dc39cba bellard
        term_flush();
341 9dc39cba bellard
    }
342 9dc39cba bellard
}
343 9dc39cba bellard
344 9dc39cba bellard
static void term_backward_char(void)
345 9dc39cba bellard
{
346 9dc39cba bellard
    if (term_cmd_buf_index > 0) {
347 9dc39cba bellard
        term_cmd_buf_index--;
348 9dc39cba bellard
        term_printf("\033[D");
349 9dc39cba bellard
        term_flush();
350 9dc39cba bellard
    }
351 9dc39cba bellard
}
352 9dc39cba bellard
353 9dc39cba bellard
static void term_forward_char(void)
354 9dc39cba bellard
{
355 9dc39cba bellard
    if (term_cmd_buf_index < term_cmd_buf_size) {
356 9dc39cba bellard
        term_cmd_buf_index++;
357 9dc39cba bellard
        term_printf("\033[C");
358 9dc39cba bellard
        term_flush();
359 9dc39cba bellard
    }
360 9dc39cba bellard
}
361 9dc39cba bellard
362 9dc39cba bellard
static void term_delete_char(void)
363 9dc39cba bellard
{
364 9dc39cba bellard
    if (term_cmd_buf_index < term_cmd_buf_size) {
365 9dc39cba bellard
        memmove(term_cmd_buf + term_cmd_buf_index,
366 9dc39cba bellard
                term_cmd_buf + term_cmd_buf_index + 1,
367 9dc39cba bellard
                term_cmd_buf_size - term_cmd_buf_index - 1);
368 9dc39cba bellard
        term_printf("\033[P");
369 9dc39cba bellard
        term_cmd_buf_size--;
370 9dc39cba bellard
        term_flush();
371 9dc39cba bellard
    }
372 9dc39cba bellard
}
373 9dc39cba bellard
374 9dc39cba bellard
static void term_backspace(void)
375 9dc39cba bellard
{
376 9dc39cba bellard
    if (term_cmd_buf_index > 0) {
377 9dc39cba bellard
        term_backward_char();
378 9dc39cba bellard
        term_delete_char();
379 9dc39cba bellard
    }
380 9dc39cba bellard
}
381 9dc39cba bellard
382 9dc39cba bellard
static void term_bol(void)
383 9dc39cba bellard
{
384 9dc39cba bellard
    while (term_cmd_buf_index > 0)
385 9dc39cba bellard
        term_backward_char();
386 9dc39cba bellard
}
387 9dc39cba bellard
388 9dc39cba bellard
static void term_eol(void)
389 9dc39cba bellard
{
390 9dc39cba bellard
    while (term_cmd_buf_index < term_cmd_buf_size)
391 9dc39cba bellard
        term_forward_char();
392 9dc39cba bellard
}
393 9dc39cba bellard
394 9dc39cba bellard
/* return true if command handled */
395 9dc39cba bellard
static void term_handle_byte(int ch)
396 9dc39cba bellard
{
397 9dc39cba bellard
    switch(term_esc_state) {
398 9dc39cba bellard
    case IS_NORM:
399 9dc39cba bellard
        switch(ch) {
400 9dc39cba bellard
        case 1:
401 9dc39cba bellard
            term_bol();
402 9dc39cba bellard
            break;
403 9dc39cba bellard
        case 5:
404 9dc39cba bellard
            term_eol();
405 9dc39cba bellard
            break;
406 9dc39cba bellard
        case 10:
407 9dc39cba bellard
        case 13:
408 9dc39cba bellard
            term_cmd_buf[term_cmd_buf_size] = '\0';
409 9dc39cba bellard
            term_printf("\n");
410 9dc39cba bellard
            term_handle_command(term_cmd_buf);
411 9dc39cba bellard
            term_show_prompt();
412 9dc39cba bellard
            break;
413 9dc39cba bellard
        case 27:
414 9dc39cba bellard
            term_esc_state = IS_ESC;
415 9dc39cba bellard
            break;
416 9dc39cba bellard
        case 127:
417 9dc39cba bellard
        case 8:
418 9dc39cba bellard
            term_backspace();
419 9dc39cba bellard
            break;
420 9dc39cba bellard
        default:
421 9dc39cba bellard
            if (ch >= 32) {
422 9dc39cba bellard
                term_insert_char(ch);
423 9dc39cba bellard
            }
424 9dc39cba bellard
            break;
425 9dc39cba bellard
        }
426 9dc39cba bellard
        break;
427 9dc39cba bellard
    case IS_ESC:
428 9dc39cba bellard
        if (ch == '[') {
429 9dc39cba bellard
            term_esc_state = IS_CSI;
430 9dc39cba bellard
            term_esc_param = 0;
431 9dc39cba bellard
        } else {
432 9dc39cba bellard
            term_esc_state = IS_NORM;
433 9dc39cba bellard
        }
434 9dc39cba bellard
        break;
435 9dc39cba bellard
    case IS_CSI:
436 9dc39cba bellard
        switch(ch) {
437 9dc39cba bellard
        case 'D':
438 9dc39cba bellard
            term_backward_char();
439 9dc39cba bellard
            break;
440 9dc39cba bellard
        case 'C':
441 9dc39cba bellard
            term_forward_char();
442 9dc39cba bellard
            break;
443 9dc39cba bellard
        case '0' ... '9':
444 9dc39cba bellard
            term_esc_param = term_esc_param * 10 + (ch - '0');
445 9dc39cba bellard
            goto the_end;
446 9dc39cba bellard
        case '~':
447 9dc39cba bellard
            switch(term_esc_param) {
448 9dc39cba bellard
            case 1:
449 9dc39cba bellard
                term_bol();
450 9dc39cba bellard
                break;
451 9dc39cba bellard
            case 3:
452 9dc39cba bellard
                term_delete_char();
453 9dc39cba bellard
                break;
454 9dc39cba bellard
            case 4:
455 9dc39cba bellard
                term_eol();
456 9dc39cba bellard
                break;
457 9dc39cba bellard
            }
458 9dc39cba bellard
            break;
459 9dc39cba bellard
        default:
460 9dc39cba bellard
            break;
461 9dc39cba bellard
        }
462 9dc39cba bellard
        term_esc_state = IS_NORM;
463 9dc39cba bellard
    the_end:
464 9dc39cba bellard
        break;
465 9dc39cba bellard
    }
466 9dc39cba bellard
}
467 9dc39cba bellard
468 9dc39cba bellard
/*************************************************************/
469 9dc39cba bellard
/* serial console support */
470 9dc39cba bellard
471 9dc39cba bellard
#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
472 9dc39cba bellard
473 9dc39cba bellard
static int term_got_escape, term_command;
474 9dc39cba bellard
475 9dc39cba bellard
void term_print_help(void)
476 9dc39cba bellard
{
477 9dc39cba bellard
    term_printf("\n"
478 9dc39cba bellard
                "C-a h    print this help\n"
479 9dc39cba bellard
                "C-a x    exit emulatior\n"
480 9dc39cba bellard
                "C-a d    switch on/off debug log\n"
481 9dc39cba bellard
                "C-a s    save disk data back to file (if -snapshot)\n"
482 9dc39cba bellard
                "C-a b    send break (magic sysrq)\n"
483 9dc39cba bellard
                "C-a c    switch between console and monitor\n"
484 9dc39cba bellard
                "C-a C-a  send C-a\n"
485 9dc39cba bellard
                );
486 9dc39cba bellard
}
487 9dc39cba bellard
488 9dc39cba bellard
/* called when a char is received */
489 9dc39cba bellard
static void term_received_byte(int ch)
490 9dc39cba bellard
{
491 9dc39cba bellard
    if (!serial_console) {
492 9dc39cba bellard
        /* if no serial console, handle every command */
493 9dc39cba bellard
        term_handle_byte(ch);
494 9dc39cba bellard
    } else {
495 9dc39cba bellard
        if (term_got_escape) {
496 9dc39cba bellard
            term_got_escape = 0;
497 9dc39cba bellard
            switch(ch) {
498 9dc39cba bellard
            case 'h':
499 9dc39cba bellard
                term_print_help();
500 9dc39cba bellard
                break;
501 9dc39cba bellard
            case 'x':
502 9dc39cba bellard
                exit(0);
503 9dc39cba bellard
                break;
504 9dc39cba bellard
            case 's': 
505 9dc39cba bellard
                {
506 9dc39cba bellard
                    int i;
507 9dc39cba bellard
                    for (i = 0; i < MAX_DISKS; i++) {
508 9dc39cba bellard
                        if (bs_table[i])
509 9dc39cba bellard
                            bdrv_commit(bs_table[i]);
510 9dc39cba bellard
                    }
511 9dc39cba bellard
                }
512 9dc39cba bellard
                break;
513 9dc39cba bellard
            case 'b':
514 9dc39cba bellard
                if (serial_console)
515 9dc39cba bellard
                    serial_receive_break(serial_console);
516 9dc39cba bellard
                break;
517 9dc39cba bellard
            case 'c':
518 9dc39cba bellard
                if (!term_command) {
519 9dc39cba bellard
                    term_show_prompt();
520 9dc39cba bellard
                    term_command = 1;
521 9dc39cba bellard
                } else {
522 9dc39cba bellard
                    term_command = 0;
523 9dc39cba bellard
                }
524 9dc39cba bellard
                break;
525 9dc39cba bellard
            case 'd':
526 9dc39cba bellard
                cpu_set_log(CPU_LOG_ALL);
527 9dc39cba bellard
                break;
528 9dc39cba bellard
            case TERM_ESCAPE:
529 9dc39cba bellard
                goto send_char;
530 9dc39cba bellard
            }
531 9dc39cba bellard
        } else if (ch == TERM_ESCAPE) {
532 9dc39cba bellard
            term_got_escape = 1;
533 9dc39cba bellard
        } else {
534 9dc39cba bellard
        send_char:
535 9dc39cba bellard
            if (term_command) {
536 9dc39cba bellard
                term_handle_byte(ch);
537 9dc39cba bellard
            } else {
538 9dc39cba bellard
                if (serial_console)
539 9dc39cba bellard
                    serial_receive_byte(serial_console, ch);
540 9dc39cba bellard
            }
541 9dc39cba bellard
        }
542 9dc39cba bellard
    }
543 9dc39cba bellard
}
544 9dc39cba bellard
545 9dc39cba bellard
static int term_can_read(void *opaque)
546 9dc39cba bellard
{
547 9dc39cba bellard
    if (serial_console) {
548 9dc39cba bellard
        return serial_can_receive(serial_console);
549 9dc39cba bellard
    } else {
550 9dc39cba bellard
        return 1;
551 9dc39cba bellard
    }
552 9dc39cba bellard
}
553 9dc39cba bellard
554 9dc39cba bellard
static void term_read(void *opaque, const uint8_t *buf, int size)
555 9dc39cba bellard
{
556 9dc39cba bellard
    int i;
557 9dc39cba bellard
    for(i = 0; i < size; i++)
558 9dc39cba bellard
        term_received_byte(buf[i]);
559 9dc39cba bellard
}
560 9dc39cba bellard
561 9dc39cba bellard
void monitor_init(void)
562 9dc39cba bellard
{
563 9dc39cba bellard
    if (!serial_console) {
564 9dc39cba bellard
        term_printf("QEMU %s monitor - type 'help' for more information\n",
565 9dc39cba bellard
                    QEMU_VERSION);
566 9dc39cba bellard
        term_show_prompt();
567 9dc39cba bellard
    }
568 9dc39cba bellard
    add_fd_read_handler(0, term_can_read, term_read, NULL);
569 9dc39cba bellard
}