Commit 82c643ff50dfdd82b89e9c5361fd132c79e0872c
1 parent
457831f4
char device support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1023 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
408 additions
and
76 deletions
hw/pc.c
... | ... | @@ -324,7 +324,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, |
324 | 324 | const char *initrd_filename) |
325 | 325 | { |
326 | 326 | char buf[1024]; |
327 | - int ret, linux_boot, initrd_size, i, nb_nics1, fd; | |
327 | + int ret, linux_boot, initrd_size, i, nb_nics1; | |
328 | 328 | unsigned long bios_offset, vga_bios_offset; |
329 | 329 | int bios_size, isa_bios_size; |
330 | 330 | PCIBus *pci_bus; |
... | ... | @@ -471,8 +471,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, |
471 | 471 | pic_init(); |
472 | 472 | pit = pit_init(0x40, 0); |
473 | 473 | |
474 | - fd = serial_open_device(); | |
475 | - serial_init(0x3f8, 4, fd); | |
474 | + serial_init(0x3f8, 4, serial_hd); | |
476 | 475 | |
477 | 476 | if (pci_enabled) { |
478 | 477 | for(i = 0; i < nb_nics; i++) { | ... | ... |
hw/ppc_chrp.c
... | ... | @@ -126,7 +126,7 @@ void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device, |
126 | 126 | openpic_t *openpic; |
127 | 127 | m48t59_t *nvram; |
128 | 128 | int PPC_io_memory; |
129 | - int ret, linux_boot, i, fd; | |
129 | + int ret, linux_boot, i; | |
130 | 130 | unsigned long bios_offset; |
131 | 131 | uint32_t kernel_base, kernel_size, initrd_base, initrd_size; |
132 | 132 | PCIBus *pci_bus; |
... | ... | @@ -200,8 +200,7 @@ void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device, |
200 | 200 | pic_init(); |
201 | 201 | |
202 | 202 | /* XXX: use Mac Serial port */ |
203 | - fd = serial_open_device(); | |
204 | - serial_init(0x3f8, 4, fd); | |
203 | + serial_init(0x3f8, 4, serial_hd); | |
205 | 204 | |
206 | 205 | for(i = 0; i < nb_nics; i++) { |
207 | 206 | pci_ne2000_init(pci_bus, &nd_table[i]); | ... | ... |
hw/ppc_prep.c
... | ... | @@ -415,7 +415,7 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device, |
415 | 415 | char buf[1024]; |
416 | 416 | m48t59_t *nvram; |
417 | 417 | int PPC_io_memory; |
418 | - int ret, linux_boot, i, nb_nics1, fd; | |
418 | + int ret, linux_boot, i, nb_nics1; | |
419 | 419 | unsigned long bios_offset; |
420 | 420 | uint32_t kernel_base, kernel_size, initrd_base, initrd_size; |
421 | 421 | PCIBus *pci_bus; |
... | ... | @@ -492,8 +492,7 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device, |
492 | 492 | pic_init(); |
493 | 493 | // pit = pit_init(0x40, 0); |
494 | 494 | |
495 | - fd = serial_open_device(); | |
496 | - serial_init(0x3f8, 4, fd); | |
495 | + serial_init(0x3f8, 4, serial_hd); | |
497 | 496 | nb_nics1 = nb_nics; |
498 | 497 | if (nb_nics1 > NE2000_NB_MAX) |
499 | 498 | nb_nics1 = NE2000_NB_MAX; | ... | ... |
hw/serial.c
... | ... | @@ -84,7 +84,7 @@ struct SerialState { |
84 | 84 | it can be reset while reading iir */ |
85 | 85 | int thr_ipending; |
86 | 86 | int irq; |
87 | - int out_fd; | |
87 | + CharDriverState *chr; | |
88 | 88 | }; |
89 | 89 | |
90 | 90 | static void serial_update_irq(SerialState *s) |
... | ... | @@ -107,7 +107,6 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
107 | 107 | { |
108 | 108 | SerialState *s = opaque; |
109 | 109 | unsigned char ch; |
110 | - int ret; | |
111 | 110 | |
112 | 111 | addr &= 7; |
113 | 112 | #ifdef DEBUG_SERIAL |
... | ... | @@ -122,13 +121,8 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
122 | 121 | s->thr_ipending = 0; |
123 | 122 | s->lsr &= ~UART_LSR_THRE; |
124 | 123 | serial_update_irq(s); |
125 | - | |
126 | - if (s->out_fd >= 0) { | |
127 | - ch = val; | |
128 | - do { | |
129 | - ret = write(s->out_fd, &ch, 1); | |
130 | - } while (ret != 1); | |
131 | - } | |
124 | + ch = val; | |
125 | + qemu_chr_write(s->chr, &ch, 1); | |
132 | 126 | s->thr_ipending = 1; |
133 | 127 | s->lsr |= UART_LSR_THRE; |
134 | 128 | s->lsr |= UART_LSR_TEMT; |
... | ... | @@ -223,19 +217,19 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr) |
223 | 217 | return ret; |
224 | 218 | } |
225 | 219 | |
226 | -int serial_can_receive(SerialState *s) | |
220 | +static int serial_can_receive(SerialState *s) | |
227 | 221 | { |
228 | 222 | return !(s->lsr & UART_LSR_DR); |
229 | 223 | } |
230 | 224 | |
231 | -void serial_receive_byte(SerialState *s, int ch) | |
225 | +static void serial_receive_byte(SerialState *s, int ch) | |
232 | 226 | { |
233 | 227 | s->rbr = ch; |
234 | 228 | s->lsr |= UART_LSR_DR; |
235 | 229 | serial_update_irq(s); |
236 | 230 | } |
237 | 231 | |
238 | -void serial_receive_break(SerialState *s) | |
232 | +static void serial_receive_break(SerialState *s) | |
239 | 233 | { |
240 | 234 | s->rbr = 0; |
241 | 235 | s->lsr |= UART_LSR_BI | UART_LSR_DR; |
... | ... | @@ -254,8 +248,15 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size) |
254 | 248 | serial_receive_byte(s, buf[0]); |
255 | 249 | } |
256 | 250 | |
251 | +static void serial_event(void *opaque, int event) | |
252 | +{ | |
253 | + SerialState *s = opaque; | |
254 | + if (event == CHR_EVENT_BREAK) | |
255 | + serial_receive_break(s); | |
256 | +} | |
257 | + | |
257 | 258 | /* If fd is zero, it means that the serial device uses the console */ |
258 | -SerialState *serial_init(int base, int irq, int fd) | |
259 | +SerialState *serial_init(int base, int irq, CharDriverState *chr) | |
259 | 260 | { |
260 | 261 | SerialState *s; |
261 | 262 | |
... | ... | @@ -268,16 +269,8 @@ SerialState *serial_init(int base, int irq, int fd) |
268 | 269 | |
269 | 270 | register_ioport_write(base, 8, 1, serial_ioport_write, s); |
270 | 271 | register_ioport_read(base, 8, 1, serial_ioport_read, s); |
271 | - | |
272 | - if (fd < 0) { | |
273 | - /* no associated device */ | |
274 | - s->out_fd = -1; | |
275 | - } else if (fd != 0) { | |
276 | - qemu_add_fd_read_handler(fd, serial_can_receive1, serial_receive1, s); | |
277 | - s->out_fd = fd; | |
278 | - } else { | |
279 | - serial_console = s; | |
280 | - s->out_fd = 1; | |
281 | - } | |
272 | + s->chr = chr; | |
273 | + qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s); | |
274 | + qemu_chr_add_event_handler(chr, serial_event); | |
282 | 275 | return s; |
283 | 276 | } | ... | ... |
vl.c
... | ... | @@ -128,7 +128,6 @@ static char network_script[1024]; |
128 | 128 | int pit_min_timer_count = 0; |
129 | 129 | int nb_nics; |
130 | 130 | NetDriverState nd_table[MAX_NICS]; |
131 | -SerialState *serial_console; | |
132 | 131 | QEMUTimer *gui_timer; |
133 | 132 | int vm_running; |
134 | 133 | int audio_enabled = 0; |
... | ... | @@ -139,6 +138,7 @@ int cirrus_vga_enabled = 1; |
139 | 138 | int graphic_width = 800; |
140 | 139 | int graphic_height = 600; |
141 | 140 | int graphic_depth = 15; |
141 | +TextConsole *vga_console; | |
142 | 142 | |
143 | 143 | /***********************************************************/ |
144 | 144 | /* x86 ISA bus support */ |
... | ... | @@ -298,6 +298,22 @@ char *pstrcat(char *buf, int buf_size, const char *s) |
298 | 298 | return buf; |
299 | 299 | } |
300 | 300 | |
301 | +int strstart(const char *str, const char *val, const char **ptr) | |
302 | +{ | |
303 | + const char *p, *q; | |
304 | + p = str; | |
305 | + q = val; | |
306 | + while (*q != '\0') { | |
307 | + if (*p != *q) | |
308 | + return 0; | |
309 | + p++; | |
310 | + q++; | |
311 | + } | |
312 | + if (ptr) | |
313 | + *ptr = p; | |
314 | + return 1; | |
315 | +} | |
316 | + | |
301 | 317 | /* return the size or -1 if error */ |
302 | 318 | int get_image_size(const char *filename) |
303 | 319 | { |
... | ... | @@ -949,42 +965,273 @@ void quit_timers(void) |
949 | 965 | } |
950 | 966 | |
951 | 967 | /***********************************************************/ |
952 | -/* serial device */ | |
968 | +/* character device */ | |
953 | 969 | |
954 | -#ifdef _WIN32 | |
970 | +int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) | |
971 | +{ | |
972 | + return s->chr_write(s, buf, len); | |
973 | +} | |
955 | 974 | |
956 | -int serial_open_device(void) | |
975 | +void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) | |
957 | 976 | { |
958 | - return -1; | |
977 | + char buf[4096]; | |
978 | + va_list ap; | |
979 | + va_start(ap, fmt); | |
980 | + vsnprintf(buf, sizeof(buf), fmt, ap); | |
981 | + qemu_chr_write(s, buf, strlen(buf)); | |
982 | + va_end(ap); | |
959 | 983 | } |
960 | 984 | |
961 | -#else | |
985 | +void qemu_chr_add_read_handler(CharDriverState *s, | |
986 | + IOCanRWHandler *fd_can_read, | |
987 | + IOReadHandler *fd_read, void *opaque) | |
988 | +{ | |
989 | + s->chr_add_read_handler(s, fd_can_read, fd_read, opaque); | |
990 | +} | |
991 | + | |
992 | +void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event) | |
993 | +{ | |
994 | + s->chr_event = chr_event; | |
995 | +} | |
962 | 996 | |
963 | -int serial_open_device(void) | |
997 | +static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |
964 | 998 | { |
965 | - if (serial_console == NULL && nographic) { | |
966 | - /* use console for serial port */ | |
967 | - return 0; | |
999 | + return len; | |
1000 | +} | |
1001 | + | |
1002 | +static void null_chr_add_read_handler(CharDriverState *chr, | |
1003 | + IOCanRWHandler *fd_can_read, | |
1004 | + IOReadHandler *fd_read, void *opaque) | |
1005 | +{ | |
1006 | +} | |
1007 | + | |
1008 | +CharDriverState *qemu_chr_open_null(void) | |
1009 | +{ | |
1010 | + CharDriverState *chr; | |
1011 | + | |
1012 | + chr = qemu_mallocz(sizeof(CharDriverState)); | |
1013 | + if (!chr) | |
1014 | + return NULL; | |
1015 | + chr->chr_write = null_chr_write; | |
1016 | + chr->chr_add_read_handler = null_chr_add_read_handler; | |
1017 | + return chr; | |
1018 | +} | |
1019 | + | |
1020 | +#ifndef _WIN32 | |
1021 | + | |
1022 | +typedef struct { | |
1023 | + int fd_in, fd_out; | |
1024 | + /* for nographic stdio only */ | |
1025 | + IOCanRWHandler *fd_can_read; | |
1026 | + IOReadHandler *fd_read; | |
1027 | + void *fd_opaque; | |
1028 | +} FDCharDriver; | |
1029 | + | |
1030 | +#define STDIO_MAX_CLIENTS 2 | |
1031 | + | |
1032 | +static int stdio_nb_clients; | |
1033 | +static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS]; | |
1034 | + | |
1035 | +static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | |
1036 | +{ | |
1037 | + FDCharDriver *s = chr->opaque; | |
1038 | + return write(s->fd_out, buf, len); | |
1039 | +} | |
1040 | + | |
1041 | +static void fd_chr_add_read_handler(CharDriverState *chr, | |
1042 | + IOCanRWHandler *fd_can_read, | |
1043 | + IOReadHandler *fd_read, void *opaque) | |
1044 | +{ | |
1045 | + FDCharDriver *s = chr->opaque; | |
1046 | + | |
1047 | + if (nographic && s->fd_in == 0) { | |
1048 | + s->fd_can_read = fd_can_read; | |
1049 | + s->fd_read = fd_read; | |
1050 | + s->fd_opaque = opaque; | |
968 | 1051 | } else { |
969 | -#if 0 | |
970 | - char slave_name[1024]; | |
971 | - int master_fd, slave_fd; | |
972 | - | |
973 | - /* Not satisfying */ | |
974 | - if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) { | |
975 | - fprintf(stderr, "warning: could not create pseudo terminal for serial port\n"); | |
976 | - return -1; | |
1052 | + qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque); | |
1053 | + } | |
1054 | +} | |
1055 | + | |
1056 | +/* open a character device to a unix fd */ | |
1057 | +CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) | |
1058 | +{ | |
1059 | + CharDriverState *chr; | |
1060 | + FDCharDriver *s; | |
1061 | + | |
1062 | + chr = qemu_mallocz(sizeof(CharDriverState)); | |
1063 | + if (!chr) | |
1064 | + return NULL; | |
1065 | + s = qemu_mallocz(sizeof(FDCharDriver)); | |
1066 | + if (!s) { | |
1067 | + free(chr); | |
1068 | + return NULL; | |
1069 | + } | |
1070 | + s->fd_in = fd_in; | |
1071 | + s->fd_out = fd_out; | |
1072 | + chr->opaque = s; | |
1073 | + chr->chr_write = fd_chr_write; | |
1074 | + chr->chr_add_read_handler = fd_chr_add_read_handler; | |
1075 | + return chr; | |
1076 | +} | |
1077 | + | |
1078 | +/* for STDIO, we handle the case where several clients use it | |
1079 | + (nographic mode) */ | |
1080 | + | |
1081 | +#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */ | |
1082 | + | |
1083 | +static int term_got_escape, client_index; | |
1084 | + | |
1085 | +void term_print_help(void) | |
1086 | +{ | |
1087 | + printf("\n" | |
1088 | + "C-a h print this help\n" | |
1089 | + "C-a x exit emulator\n" | |
1090 | + "C-a s save disk data back to file (if -snapshot)\n" | |
1091 | + "C-a b send break (magic sysrq)\n" | |
1092 | + "C-a c switch between console and monitor\n" | |
1093 | + "C-a C-a send C-a\n" | |
1094 | + ); | |
1095 | +} | |
1096 | + | |
1097 | +/* called when a char is received */ | |
1098 | +static void stdio_received_byte(int ch) | |
1099 | +{ | |
1100 | + if (term_got_escape) { | |
1101 | + term_got_escape = 0; | |
1102 | + switch(ch) { | |
1103 | + case 'h': | |
1104 | + term_print_help(); | |
1105 | + break; | |
1106 | + case 'x': | |
1107 | + exit(0); | |
1108 | + break; | |
1109 | + case 's': | |
1110 | + { | |
1111 | + int i; | |
1112 | + for (i = 0; i < MAX_DISKS; i++) { | |
1113 | + if (bs_table[i]) | |
1114 | + bdrv_commit(bs_table[i]); | |
1115 | + } | |
1116 | + } | |
1117 | + break; | |
1118 | + case 'b': | |
1119 | + if (client_index < stdio_nb_clients) { | |
1120 | + CharDriverState *chr; | |
1121 | + FDCharDriver *s; | |
1122 | + | |
1123 | + chr = stdio_clients[client_index]; | |
1124 | + s = chr->opaque; | |
1125 | + chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK); | |
1126 | + } | |
1127 | + break; | |
1128 | + case 'c': | |
1129 | + client_index++; | |
1130 | + if (client_index >= stdio_nb_clients) | |
1131 | + client_index = 0; | |
1132 | + if (client_index == 0) { | |
1133 | + /* send a new line in the monitor to get the prompt */ | |
1134 | + ch = '\r'; | |
1135 | + goto send_char; | |
1136 | + } | |
1137 | + break; | |
1138 | + case TERM_ESCAPE: | |
1139 | + goto send_char; | |
1140 | + } | |
1141 | + } else if (ch == TERM_ESCAPE) { | |
1142 | + term_got_escape = 1; | |
1143 | + } else { | |
1144 | + send_char: | |
1145 | + if (client_index < stdio_nb_clients) { | |
1146 | + uint8_t buf[1]; | |
1147 | + CharDriverState *chr; | |
1148 | + FDCharDriver *s; | |
1149 | + | |
1150 | + chr = stdio_clients[client_index]; | |
1151 | + s = chr->opaque; | |
1152 | + buf[0] = ch; | |
1153 | + /* XXX: should queue the char if the device is not | |
1154 | + ready */ | |
1155 | + if (s->fd_can_read(s->fd_opaque) > 0) | |
1156 | + s->fd_read(s->fd_opaque, buf, 1); | |
977 | 1157 | } |
978 | - fprintf(stderr, "Serial port redirected to %s\n", slave_name); | |
979 | - return master_fd; | |
980 | -#else | |
981 | - return -1; | |
982 | -#endif | |
983 | 1158 | } |
984 | 1159 | } |
985 | 1160 | |
1161 | +static int stdio_can_read(void *opaque) | |
1162 | +{ | |
1163 | + /* XXX: not strictly correct */ | |
1164 | + return 1; | |
1165 | +} | |
1166 | + | |
1167 | +static void stdio_read(void *opaque, const uint8_t *buf, int size) | |
1168 | +{ | |
1169 | + int i; | |
1170 | + for(i = 0; i < size; i++) | |
1171 | + stdio_received_byte(buf[i]); | |
1172 | +} | |
1173 | + | |
1174 | +CharDriverState *qemu_chr_open_stdio(void) | |
1175 | +{ | |
1176 | + CharDriverState *chr; | |
1177 | + | |
1178 | + if (nographic) { | |
1179 | + if (stdio_nb_clients >= STDIO_MAX_CLIENTS) | |
1180 | + return NULL; | |
1181 | + chr = qemu_chr_open_fd(0, 1); | |
1182 | + if (stdio_nb_clients == 0) | |
1183 | + qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL); | |
1184 | + client_index = stdio_nb_clients; | |
1185 | + } else { | |
1186 | + if (stdio_nb_clients != 0) | |
1187 | + return NULL; | |
1188 | + chr = qemu_chr_open_fd(0, 1); | |
1189 | + } | |
1190 | + stdio_clients[stdio_nb_clients++] = chr; | |
1191 | + return chr; | |
1192 | +} | |
1193 | + | |
1194 | +#if defined(__linux__) | |
1195 | +CharDriverState *qemu_chr_open_pty(void) | |
1196 | +{ | |
1197 | + char slave_name[1024]; | |
1198 | + int master_fd, slave_fd; | |
1199 | + | |
1200 | + /* Not satisfying */ | |
1201 | + if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) { | |
1202 | + return NULL; | |
1203 | + } | |
1204 | + fprintf(stderr, "char device redirected to %s\n", slave_name); | |
1205 | + return qemu_chr_open_fd(master_fd, master_fd); | |
1206 | +} | |
1207 | +#else | |
1208 | +CharDriverState *qemu_chr_open_pty(void) | |
1209 | +{ | |
1210 | + return NULL; | |
1211 | +} | |
986 | 1212 | #endif |
987 | 1213 | |
1214 | +#endif /* !defined(_WIN32) */ | |
1215 | + | |
1216 | +CharDriverState *qemu_chr_open(const char *filename) | |
1217 | +{ | |
1218 | + if (!strcmp(filename, "vc")) { | |
1219 | + return text_console_init(&display_state); | |
1220 | + } else if (!strcmp(filename, "null")) { | |
1221 | + return qemu_chr_open_null(); | |
1222 | + } else | |
1223 | +#ifndef _WIN32 | |
1224 | + if (!strcmp(filename, "pty")) { | |
1225 | + return qemu_chr_open_pty(); | |
1226 | + } else if (!strcmp(filename, "stdio")) { | |
1227 | + return qemu_chr_open_stdio(); | |
1228 | + } else | |
1229 | +#endif | |
1230 | + { | |
1231 | + return NULL; | |
1232 | + } | |
1233 | +} | |
1234 | + | |
988 | 1235 | /***********************************************************/ |
989 | 1236 | /* Linux network device redirectors */ |
990 | 1237 | |
... | ... | @@ -2106,6 +2353,8 @@ void help(void) |
2106 | 2353 | "-initrd file use 'file' as initial ram disk\n" |
2107 | 2354 | "\n" |
2108 | 2355 | "Debug/Expert options:\n" |
2356 | + "-monitor dev redirect the monitor to char device 'dev'\n" | |
2357 | + "-serial dev redirect the serial port to char device 'dev'\n" | |
2109 | 2358 | "-S freeze CPU at startup (use 'c' to start execution)\n" |
2110 | 2359 | "-s wait gdb connection to port %d\n" |
2111 | 2360 | "-p port change gdb connection port\n" |
... | ... | @@ -2121,7 +2370,13 @@ void help(void) |
2121 | 2370 | " (default is CL-GD5446 PCI VGA)\n" |
2122 | 2371 | #endif |
2123 | 2372 | "\n" |
2124 | - "During emulation, use C-a h to get terminal commands:\n", | |
2373 | + "During emulation, the following keys are useful:\n" | |
2374 | + "ctrl-shift-f toggle full screen\n" | |
2375 | + "ctrl-shift-Fn switch to virtual console 'n'\n" | |
2376 | + "ctrl-shift toggle mouse and keyboard grab\n" | |
2377 | + "\n" | |
2378 | + "When using -nographic, press 'ctrl-a h' to get some help.\n" | |
2379 | + , | |
2125 | 2380 | #ifdef CONFIG_SOFTMMU |
2126 | 2381 | "qemu", |
2127 | 2382 | #else |
... | ... | @@ -2131,7 +2386,6 @@ void help(void) |
2131 | 2386 | DEFAULT_NETWORK_SCRIPT, |
2132 | 2387 | DEFAULT_GDBSTUB_PORT, |
2133 | 2388 | "/tmp/qemu.log"); |
2134 | - term_print_help(); | |
2135 | 2389 | #ifndef CONFIG_SOFTMMU |
2136 | 2390 | printf("\n" |
2137 | 2391 | "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n" |
... | ... | @@ -2184,6 +2438,8 @@ enum { |
2184 | 2438 | QEMU_OPTION_cirrusvga, |
2185 | 2439 | QEMU_OPTION_g, |
2186 | 2440 | QEMU_OPTION_std_vga, |
2441 | + QEMU_OPTION_monitor, | |
2442 | + QEMU_OPTION_serial, | |
2187 | 2443 | }; |
2188 | 2444 | |
2189 | 2445 | typedef struct QEMUOption { |
... | ... | @@ -2235,7 +2491,9 @@ const QEMUOption qemu_options[] = { |
2235 | 2491 | { "localtime", 0, QEMU_OPTION_localtime }, |
2236 | 2492 | { "isa", 0, QEMU_OPTION_isa }, |
2237 | 2493 | { "std-vga", 0, QEMU_OPTION_std_vga }, |
2238 | - | |
2494 | + { "monitor", 1, QEMU_OPTION_monitor }, | |
2495 | + { "serial", 1, QEMU_OPTION_serial }, | |
2496 | + | |
2239 | 2497 | /* temporary options */ |
2240 | 2498 | { "pci", 0, QEMU_OPTION_pci }, |
2241 | 2499 | { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, |
... | ... | @@ -2273,6 +2531,9 @@ int main(int argc, char **argv) |
2273 | 2531 | int net_if_type, nb_tun_fds, tun_fds[MAX_NICS]; |
2274 | 2532 | int optind; |
2275 | 2533 | const char *r, *optarg; |
2534 | + CharDriverState *monitor_hd; | |
2535 | + char monitor_device[128]; | |
2536 | + char serial_device[128]; | |
2276 | 2537 | |
2277 | 2538 | #if !defined(CONFIG_SOFTMMU) |
2278 | 2539 | /* we never want that malloc() uses mmap() */ |
... | ... | @@ -2297,6 +2558,8 @@ int main(int argc, char **argv) |
2297 | 2558 | kernel_cmdline = ""; |
2298 | 2559 | has_cdrom = 1; |
2299 | 2560 | cyls = heads = secs = 0; |
2561 | + pstrcpy(monitor_device, sizeof(monitor_device), "vc"); | |
2562 | + pstrcpy(serial_device, sizeof(serial_device), "vc"); | |
2300 | 2563 | |
2301 | 2564 | nb_tun_fds = 0; |
2302 | 2565 | net_if_type = -1; |
... | ... | @@ -2308,7 +2571,7 @@ int main(int argc, char **argv) |
2308 | 2571 | macaddr[3] = 0x12; |
2309 | 2572 | macaddr[4] = 0x34; |
2310 | 2573 | macaddr[5] = 0x56; |
2311 | - | |
2574 | + | |
2312 | 2575 | optind = 1; |
2313 | 2576 | for(;;) { |
2314 | 2577 | if (optind >= argc) |
... | ... | @@ -2375,6 +2638,8 @@ int main(int argc, char **argv) |
2375 | 2638 | } |
2376 | 2639 | break; |
2377 | 2640 | case QEMU_OPTION_nographic: |
2641 | + pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); | |
2642 | + pstrcpy(serial_device, sizeof(serial_device), "stdio"); | |
2378 | 2643 | nographic = 1; |
2379 | 2644 | break; |
2380 | 2645 | case QEMU_OPTION_kernel: |
... | ... | @@ -2561,6 +2826,12 @@ int main(int argc, char **argv) |
2561 | 2826 | graphic_depth = depth; |
2562 | 2827 | } |
2563 | 2828 | break; |
2829 | + case QEMU_OPTION_monitor: | |
2830 | + pstrcpy(monitor_device, sizeof(monitor_device), optarg); | |
2831 | + break; | |
2832 | + case QEMU_OPTION_serial: | |
2833 | + pstrcpy(serial_device, sizeof(serial_device), optarg); | |
2834 | + break; | |
2564 | 2835 | } |
2565 | 2836 | } |
2566 | 2837 | } |
... | ... | @@ -2750,6 +3021,24 @@ int main(int argc, char **argv) |
2750 | 3021 | #endif |
2751 | 3022 | } |
2752 | 3023 | |
3024 | + vga_console = graphic_console_init(ds); | |
3025 | + | |
3026 | + monitor_hd = qemu_chr_open(monitor_device); | |
3027 | + if (!monitor_hd) { | |
3028 | + fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); | |
3029 | + exit(1); | |
3030 | + } | |
3031 | + monitor_init(monitor_hd, !nographic); | |
3032 | + | |
3033 | + serial_hd = qemu_chr_open(serial_device); | |
3034 | + if (!serial_hd) { | |
3035 | + fprintf(stderr, "qemu: could not open serial device '%s'\n", serial_device); | |
3036 | + exit(1); | |
3037 | + } | |
3038 | + if (!strcmp(serial_device, "vc")) | |
3039 | + qemu_chr_printf(serial_hd, "serial0 console\n"); | |
3040 | + | |
3041 | + | |
2753 | 3042 | /* setup cpu signal handlers for MMU / self modifying code handling */ |
2754 | 3043 | #if !defined(CONFIG_SOFTMMU) |
2755 | 3044 | |
... | ... | @@ -2805,10 +3094,6 @@ int main(int argc, char **argv) |
2805 | 3094 | kernel_filename, kernel_cmdline, initrd_filename); |
2806 | 3095 | #endif |
2807 | 3096 | |
2808 | - /* launched after the device init so that it can display or not a | |
2809 | - banner */ | |
2810 | - monitor_init(); | |
2811 | - | |
2812 | 3097 | gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); |
2813 | 3098 | qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); |
2814 | 3099 | ... | ... |
vl.h
... | ... | @@ -215,8 +215,7 @@ extern const char *bios_dir; |
215 | 215 | |
216 | 216 | void pstrcpy(char *buf, int buf_size, const char *str); |
217 | 217 | char *pstrcat(char *buf, int buf_size, const char *s); |
218 | - | |
219 | -int serial_open_device(void); | |
218 | +int strstart(const char *str, const char *val, const char **ptr); | |
220 | 219 | |
221 | 220 | extern int vm_running; |
222 | 221 | |
... | ... | @@ -265,6 +264,31 @@ void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque); |
265 | 264 | void kbd_put_keycode(int keycode); |
266 | 265 | void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); |
267 | 266 | |
267 | +/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx | |
268 | + constants) */ | |
269 | +#define QEMU_KEY_ESC1(c) ((c) | 0xe100) | |
270 | +#define QEMU_KEY_BACKSPACE 0x007f | |
271 | +#define QEMU_KEY_UP QEMU_KEY_ESC1('A') | |
272 | +#define QEMU_KEY_DOWN QEMU_KEY_ESC1('B') | |
273 | +#define QEMU_KEY_RIGHT QEMU_KEY_ESC1('C') | |
274 | +#define QEMU_KEY_LEFT QEMU_KEY_ESC1('D') | |
275 | +#define QEMU_KEY_HOME QEMU_KEY_ESC1(1) | |
276 | +#define QEMU_KEY_END QEMU_KEY_ESC1(4) | |
277 | +#define QEMU_KEY_PAGEUP QEMU_KEY_ESC1(5) | |
278 | +#define QEMU_KEY_PAGEDOWN QEMU_KEY_ESC1(6) | |
279 | +#define QEMU_KEY_DELETE QEMU_KEY_ESC1(3) | |
280 | + | |
281 | +#define QEMU_KEY_CTRL_UP 0xe400 | |
282 | +#define QEMU_KEY_CTRL_DOWN 0xe401 | |
283 | +#define QEMU_KEY_CTRL_LEFT 0xe402 | |
284 | +#define QEMU_KEY_CTRL_RIGHT 0xe403 | |
285 | +#define QEMU_KEY_CTRL_HOME 0xe404 | |
286 | +#define QEMU_KEY_CTRL_END 0xe405 | |
287 | +#define QEMU_KEY_CTRL_PAGEUP 0xe406 | |
288 | +#define QEMU_KEY_CTRL_PAGEDOWN 0xe407 | |
289 | + | |
290 | +void kbd_put_keysym(int keysym); | |
291 | + | |
268 | 292 | /* async I/O support */ |
269 | 293 | |
270 | 294 | typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); |
... | ... | @@ -274,6 +298,42 @@ int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, |
274 | 298 | IOReadHandler *fd_read, void *opaque); |
275 | 299 | void qemu_del_fd_read_handler(int fd); |
276 | 300 | |
301 | +/* character device */ | |
302 | + | |
303 | +#define CHR_EVENT_BREAK 0 /* serial break char */ | |
304 | + | |
305 | +typedef void IOEventHandler(void *opaque, int event); | |
306 | + | |
307 | +typedef struct CharDriverState { | |
308 | + int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); | |
309 | + void (*chr_add_read_handler)(struct CharDriverState *s, | |
310 | + IOCanRWHandler *fd_can_read, | |
311 | + IOReadHandler *fd_read, void *opaque); | |
312 | + IOEventHandler *chr_event; | |
313 | + void *opaque; | |
314 | +} CharDriverState; | |
315 | + | |
316 | +void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); | |
317 | +int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); | |
318 | +void qemu_chr_add_read_handler(CharDriverState *s, | |
319 | + IOCanRWHandler *fd_can_read, | |
320 | + IOReadHandler *fd_read, void *opaque); | |
321 | +void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event); | |
322 | + | |
323 | +CharDriverState *serial_hd; | |
324 | + | |
325 | +/* consoles */ | |
326 | + | |
327 | +typedef struct DisplayState DisplayState; | |
328 | +typedef struct TextConsole TextConsole; | |
329 | + | |
330 | +extern TextConsole *vga_console; | |
331 | + | |
332 | +TextConsole *graphic_console_init(DisplayState *ds); | |
333 | +int is_active_console(TextConsole *s); | |
334 | +CharDriverState *text_console_init(DisplayState *ds); | |
335 | +void console_select(unsigned int index); | |
336 | + | |
277 | 337 | /* network redirectors support */ |
278 | 338 | |
279 | 339 | #define MAX_NICS 8 |
... | ... | @@ -437,6 +497,7 @@ void bdrv_set_change_cb(BlockDriverState *bs, |
437 | 497 | |
438 | 498 | void bdrv_info(void); |
439 | 499 | BlockDriverState *bdrv_find(const char *name); |
500 | +void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque); | |
440 | 501 | |
441 | 502 | /* ISA bus */ |
442 | 503 | |
... | ... | @@ -534,14 +595,16 @@ openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus); |
534 | 595 | |
535 | 596 | #define VGA_RAM_SIZE (4096 * 1024) |
536 | 597 | |
537 | -typedef struct DisplayState { | |
598 | +struct DisplayState { | |
538 | 599 | uint8_t *data; |
539 | 600 | int linesize; |
540 | 601 | int depth; |
602 | + int width; | |
603 | + int height; | |
541 | 604 | void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); |
542 | 605 | void (*dpy_resize)(struct DisplayState *s, int w, int h); |
543 | 606 | void (*dpy_refresh)(struct DisplayState *s); |
544 | -} DisplayState; | |
607 | +}; | |
545 | 608 | |
546 | 609 | static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) |
547 | 610 | { |
... | ... | @@ -644,13 +707,7 @@ void rtc_set_date(RTCState *s, const struct tm *tm); |
644 | 707 | /* serial.c */ |
645 | 708 | |
646 | 709 | typedef struct SerialState SerialState; |
647 | - | |
648 | -extern SerialState *serial_console; | |
649 | - | |
650 | -SerialState *serial_init(int base, int irq, int fd); | |
651 | -int serial_can_receive(SerialState *s); | |
652 | -void serial_receive_byte(SerialState *s, int ch); | |
653 | -void serial_receive_break(SerialState *s); | |
710 | +SerialState *serial_init(int base, int irq, CharDriverState *chr); | |
654 | 711 | |
655 | 712 | /* i8259.c */ |
656 | 713 | |
... | ... | @@ -767,7 +824,7 @@ extern ADBBusState adb_bus; |
767 | 824 | int cuda_init(openpic_t *openpic, int irq); |
768 | 825 | |
769 | 826 | /* monitor.c */ |
770 | -void monitor_init(void); | |
827 | +void monitor_init(CharDriverState *hd, int show_banner); | |
771 | 828 | void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); |
772 | 829 | void term_flush(void); |
773 | 830 | void term_print_help(void); | ... | ... |