Commit c4b1fcc0f9594cae64d5bf172548a522db0c2545

Authored by bellard
1 parent 0f35920c

added I/O API - io port API change - added multiple network interface support - …

…redirect serial port to a pseudo terminal if using graphical mode


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@663 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 349 additions and 286 deletions
... ... @@ -39,6 +39,7 @@
39 39 #include <sys/poll.h>
40 40 #include <errno.h>
41 41 #include <sys/wait.h>
  42 +#include <pty.h>
42 43  
43 44 #include <sys/ioctl.h>
44 45 #include <sys/socket.h>
... ... @@ -81,6 +82,7 @@ const char *bios_dir = CONFIG_QEMU_SHAREDIR;
81 82 char phys_ram_file[1024];
82 83 CPUState *global_env;
83 84 CPUState *cpu_single_env;
  85 +void *ioport_opaque[MAX_IOPORTS];
84 86 IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
85 87 IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
86 88 BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
... ... @@ -93,11 +95,14 @@ int boot_device = &#39;c&#39;;
93 95 static int ram_size;
94 96 static char network_script[1024];
95 97 int pit_min_timer_count = 0;
  98 +int nb_nics;
  99 +NetDriverState nd_table[MAX_NICS];
  100 +SerialState *serial_console;
96 101  
97 102 /***********************************************************/
98 103 /* x86 io ports */
99 104  
100   -uint32_t default_ioport_readb(CPUState *env, uint32_t address)
  105 +uint32_t default_ioport_readb(void *opaque, uint32_t address)
101 106 {
102 107 #ifdef DEBUG_UNUSED_IOPORT
103 108 fprintf(stderr, "inb: port=0x%04x\n", address);
... ... @@ -105,7 +110,7 @@ uint32_t default_ioport_readb(CPUState *env, uint32_t address)
105 110 return 0xff;
106 111 }
107 112  
108   -void default_ioport_writeb(CPUState *env, uint32_t address, uint32_t data)
  113 +void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
109 114 {
110 115 #ifdef DEBUG_UNUSED_IOPORT
111 116 fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
... ... @@ -113,21 +118,21 @@ void default_ioport_writeb(CPUState *env, uint32_t address, uint32_t data)
113 118 }
114 119  
115 120 /* default is to make two byte accesses */
116   -uint32_t default_ioport_readw(CPUState *env, uint32_t address)
  121 +uint32_t default_ioport_readw(void *opaque, uint32_t address)
117 122 {
118 123 uint32_t data;
119   - data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](env, address);
120   - data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1) << 8;
  124 + data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](opaque, address);
  125 + data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](opaque, address + 1) << 8;
121 126 return data;
122 127 }
123 128  
124   -void default_ioport_writew(CPUState *env, uint32_t address, uint32_t data)
  129 +void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
125 130 {
126   - ioport_write_table[0][address & (MAX_IOPORTS - 1)](env, address, data & 0xff);
127   - ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1, (data >> 8) & 0xff);
  131 + ioport_write_table[0][address & (MAX_IOPORTS - 1)](opaque, address, data & 0xff);
  132 + ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](opaque, address + 1, (data >> 8) & 0xff);
128 133 }
129 134  
130   -uint32_t default_ioport_readl(CPUState *env, uint32_t address)
  135 +uint32_t default_ioport_readl(void *opaque, uint32_t address)
131 136 {
132 137 #ifdef DEBUG_UNUSED_IOPORT
133 138 fprintf(stderr, "inl: port=0x%04x\n", address);
... ... @@ -135,7 +140,7 @@ uint32_t default_ioport_readl(CPUState *env, uint32_t address)
135 140 return 0xffffffff;
136 141 }
137 142  
138   -void default_ioport_writel(CPUState *env, uint32_t address, uint32_t data)
  143 +void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
139 144 {
140 145 #ifdef DEBUG_UNUSED_IOPORT
141 146 fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
... ... @@ -157,38 +162,52 @@ void init_ioports(void)
157 162 }
158 163  
159 164 /* size is the word size in byte */
160   -int register_ioport_read(int start, int length, IOPortReadFunc *func, int size)
  165 +int register_ioport_read(int start, int length, int size,
  166 + IOPortReadFunc *func, void *opaque)
161 167 {
162 168 int i, bsize;
163 169  
164   - if (size == 1)
  170 + if (size == 1) {
165 171 bsize = 0;
166   - else if (size == 2)
  172 + } else if (size == 2) {
167 173 bsize = 1;
168   - else if (size == 4)
  174 + } else if (size == 4) {
169 175 bsize = 2;
170   - else
  176 + } else {
  177 + hw_error("register_ioport_read: invalid size");
171 178 return -1;
172   - for(i = start; i < start + length; i += size)
  179 + }
  180 + for(i = start; i < start + length; i += size) {
173 181 ioport_read_table[bsize][i] = func;
  182 + if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
  183 + hw_error("register_ioport_read: invalid opaque");
  184 + ioport_opaque[i] = opaque;
  185 + }
174 186 return 0;
175 187 }
176 188  
177 189 /* size is the word size in byte */
178   -int register_ioport_write(int start, int length, IOPortWriteFunc *func, int size)
  190 +int register_ioport_write(int start, int length, int size,
  191 + IOPortWriteFunc *func, void *opaque)
179 192 {
180 193 int i, bsize;
181 194  
182   - if (size == 1)
  195 + if (size == 1) {
183 196 bsize = 0;
184   - else if (size == 2)
  197 + } else if (size == 2) {
185 198 bsize = 1;
186   - else if (size == 4)
  199 + } else if (size == 4) {
187 200 bsize = 2;
188   - else
  201 + } else {
  202 + hw_error("register_ioport_write: invalid size");
189 203 return -1;
190   - for(i = start; i < start + length; i += size)
  204 + }
  205 + for(i = start; i < start + length; i += size) {
191 206 ioport_write_table[bsize][i] = func;
  207 + if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
  208 + hw_error("register_ioport_read: invalid opaque");
  209 + ioport_opaque[i] = opaque;
  210 + }
192 211 return 0;
193 212 }
194 213  
... ... @@ -238,32 +257,38 @@ int load_image(const char *filename, uint8_t *addr)
238 257  
239 258 void cpu_outb(CPUState *env, int addr, int val)
240 259 {
241   - ioport_write_table[0][addr & (MAX_IOPORTS - 1)](env, addr, val);
  260 + addr &= (MAX_IOPORTS - 1);
  261 + ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
242 262 }
243 263  
244 264 void cpu_outw(CPUState *env, int addr, int val)
245 265 {
246   - ioport_write_table[1][addr & (MAX_IOPORTS - 1)](env, addr, val);
  266 + addr &= (MAX_IOPORTS - 1);
  267 + ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
247 268 }
248 269  
249 270 void cpu_outl(CPUState *env, int addr, int val)
250 271 {
251   - ioport_write_table[2][addr & (MAX_IOPORTS - 1)](env, addr, val);
  272 + addr &= (MAX_IOPORTS - 1);
  273 + ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
252 274 }
253 275  
254 276 int cpu_inb(CPUState *env, int addr)
255 277 {
256   - return ioport_read_table[0][addr & (MAX_IOPORTS - 1)](env, addr);
  278 + addr &= (MAX_IOPORTS - 1);
  279 + return ioport_read_table[0][addr](ioport_opaque[addr], addr);
257 280 }
258 281  
259 282 int cpu_inw(CPUState *env, int addr)
260 283 {
261   - return ioport_read_table[1][addr & (MAX_IOPORTS - 1)](env, addr);
  284 + addr &= (MAX_IOPORTS - 1);
  285 + return ioport_read_table[1][addr](ioport_opaque[addr], addr);
262 286 }
263 287  
264 288 int cpu_inl(CPUState *env, int addr)
265 289 {
266   - return ioport_read_table[2][addr & (MAX_IOPORTS - 1)](env, addr);
  290 + addr &= (MAX_IOPORTS - 1);
  291 + return ioport_read_table[2][addr](ioport_opaque[addr], addr);
267 292 }
268 293  
269 294 /***********************************************************/
... ... @@ -389,171 +414,34 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
389 414 return res.ll;
390 415 }
391 416  
392   -#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
393   -static int term_got_escape, term_command;
394   -static unsigned char term_cmd_buf[128];
395   -
396   -typedef struct term_cmd_t {
397   - const unsigned char *name;
398   - void (*handler)(unsigned char *params);
399   -} term_cmd_t;
400   -
401   -static void do_change_cdrom (unsigned char *params);
402   -static void do_change_fd0 (unsigned char *params);
403   -static void do_change_fd1 (unsigned char *params);
404   -
405   -static term_cmd_t term_cmds[] = {
406   - { "changecd", &do_change_cdrom, },
407   - { "changefd0", &do_change_fd0, },
408   - { "changefd1", &do_change_fd1, },
409   - { NULL, NULL, },
410   -};
411   -
412   -void term_print_help(void)
413   -{
414   - printf("\n"
415   - "C-a h print this help\n"
416   - "C-a x exit emulatior\n"
417   - "C-a d switch on/off debug log\n"
418   - "C-a s save disk data back to file (if -snapshot)\n"
419   - "C-a b send break (magic sysrq)\n"
420   - "C-a c send qemu internal command\n"
421   - "C-a C-a send C-a\n"
422   - );
423   -}
424   -
425   -static void do_change_cdrom (unsigned char *params)
426   -{
427   - /* Dunno how to do it... */
428   -}
429   -
430   -static void do_change_fd (int fd, unsigned char *params)
431   -{
432   - unsigned char *name_start, *name_end, *ros;
433   - int ro;
434   -
435   - for (name_start = params;
436   - isspace(*name_start); name_start++)
437   - continue;
438   - if (*name_start == '\0')
439   - return;
440   - for (name_end = name_start;
441   - !isspace(*name_end) && *name_end != '\0'; name_end++)
442   - continue;
443   - for (ros = name_end + 1; isspace(*ros); ros++)
444   - continue;
445   - if (ros[0] == 'r' && ros[1] == 'o')
446   - ro = 1;
447   - else
448   - ro = 0;
449   - *name_end = '\0';
450   - printf("Change fd %d to %s (%s)\n", fd, name_start, params);
451   - fdctrl_disk_change(fd, name_start, ro);
452   -}
453   -
454   -static void do_change_fd0 (unsigned char *params)
455   -{
456   - do_change_fd(0, params);
457   -}
458   -
459   -static void do_change_fd1 (unsigned char *params)
460   -{
461   - do_change_fd(1, params);
462   -}
  417 +/***********************************************************/
  418 +/* serial device */
463 419  
464   -static void term_treat_command(void)
  420 +int serial_open_device(void)
465 421 {
466   - unsigned char *cmd_start, *cmd_end;
467   - int i;
  422 + char slave_name[1024];
  423 + int master_fd, slave_fd;
468 424  
469   - for (cmd_start = term_cmd_buf; isspace(*cmd_start); cmd_start++)
470   - continue;
471   - for (cmd_end = cmd_start;
472   - !isspace(*cmd_end) && *cmd_end != '\0'; cmd_end++)
473   - continue;
474   - for (i = 0; term_cmds[i].name != NULL; i++) {
475   - if (strlen(term_cmds[i].name) == (cmd_end - cmd_start) &&
476   - memcmp(term_cmds[i].name, cmd_start, cmd_end - cmd_start) == 0) {
477   - (*term_cmds[i].handler)(cmd_end + 1);
478   - return;
479   - }
480   - }
481   - *cmd_end = '\0';
482   - printf("Unknown term command: %s\n", cmd_start);
483   -}
484   -
485   -extern FILE *logfile;
486   -
487   -/* called when a char is received */
488   -void term_received_byte(int ch)
489   -{
490   - if (term_command) {
491   - if (ch == '\n' || ch == '\r' || term_command == 127) {
492   - printf("\n");
493   - term_treat_command();
494   - term_command = 0;
495   - } else {
496   - if (ch == 0x7F || ch == 0x08) {
497   - if (term_command > 1) {
498   - term_cmd_buf[--term_command - 1] = '\0';
499   - printf("\r "
500   - " ");
501   - printf("\r> %s", term_cmd_buf);
502   - }
503   - } else if (ch > 0x1f) {
504   - term_cmd_buf[term_command++ - 1] = ch;
505   - term_cmd_buf[term_command - 1] = '\0';
506   - printf("\r> %s", term_cmd_buf);
507   - }
508   - fflush(stdout);
509   - }
510   - } else if (term_got_escape) {
511   - term_got_escape = 0;
512   - switch(ch) {
513   - case 'h':
514   - term_print_help();
515   - break;
516   - case 'x':
517   - exit(0);
518   - break;
519   - case 's':
520   - {
521   - int i;
522   - for (i = 0; i < MAX_DISKS; i++) {
523   - if (bs_table[i])
524   - bdrv_commit(bs_table[i]);
525   - }
526   - }
527   - break;
528   - case 'b':
529   - serial_receive_break();
530   - break;
531   - case 'c':
532   - printf("> ");
533   - fflush(stdout);
534   - term_command = 1;
535   - break;
536   - case 'd':
537   - cpu_set_log(CPU_LOG_ALL);
538   - break;
539   - case TERM_ESCAPE:
540   - goto send_char;
541   - }
542   - } else if (ch == TERM_ESCAPE) {
543   - term_got_escape = 1;
  425 + if (serial_console == NULL && nographic) {
  426 + /* use console for serial port */
  427 + return 0;
544 428 } else {
545   - send_char:
546   - serial_receive_byte(ch);
  429 + if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
  430 + fprintf(stderr, "warning: could not create pseudo terminal for serial port\n");
  431 + return -1;
  432 + }
  433 + fprintf(stderr, "Serial port redirected to %s\n", slave_name);
  434 + return master_fd;
547 435 }
548 436 }
549 437  
550 438 /***********************************************************/
551 439 /* Linux network device redirector */
552 440  
553   -int net_init(void)
  441 +static int tun_open(char *ifname, int ifname_size)
554 442 {
555 443 struct ifreq ifr;
556   - int fd, ret, pid, status;
  444 + int fd, ret;
557 445  
558 446 fd = open("/dev/net/tun", O_RDWR);
559 447 if (fd < 0) {
... ... @@ -570,32 +458,62 @@ int net_init(void)
570 458 return -1;
571 459 }
572 460 printf("Connected to host network interface: %s\n", ifr.ifr_name);
  461 + pstrcpy(ifname, ifname_size, ifr.ifr_name);
573 462 fcntl(fd, F_SETFL, O_NONBLOCK);
574   - net_fd = fd;
  463 + return fd;
  464 +}
575 465  
576   - /* try to launch network init script */
577   - pid = fork();
578   - if (pid >= 0) {
579   - if (pid == 0) {
580   - execl(network_script, network_script, ifr.ifr_name, NULL);
581   - exit(1);
  466 +static int net_init(void)
  467 +{
  468 + int pid, status, launch_script, i;
  469 + NetDriverState *nd;
  470 + char *args[MAX_NICS + 2];
  471 + char **parg;
  472 +
  473 + launch_script = 0;
  474 + for(i = 0; i < nb_nics; i++) {
  475 + nd = &nd_table[i];
  476 + if (nd->fd < 0) {
  477 + nd->fd = tun_open(nd->ifname, sizeof(nd->ifname));
  478 + if (nd->fd >= 0)
  479 + launch_script = 1;
582 480 }
583   - while (waitpid(pid, &status, 0) != pid);
584   - if (!WIFEXITED(status) ||
585   - WEXITSTATUS(status) != 0) {
586   - fprintf(stderr, "%s: could not launch network script for '%s'\n",
587   - network_script, ifr.ifr_name);
  481 + }
  482 +
  483 + if (launch_script) {
  484 + /* try to launch network init script */
  485 + pid = fork();
  486 + if (pid >= 0) {
  487 + if (pid == 0) {
  488 + parg = args;
  489 + *parg++ = network_script;
  490 + for(i = 0; i < nb_nics; i++) {
  491 + nd = &nd_table[i];
  492 + if (nd->fd >= 0) {
  493 + *parg++ = nd->ifname;
  494 + }
  495 + }
  496 + *parg++ = NULL;
  497 + execv(network_script, args);
  498 + exit(1);
  499 + }
  500 + while (waitpid(pid, &status, 0) != pid);
  501 + if (!WIFEXITED(status) ||
  502 + WEXITSTATUS(status) != 0) {
  503 + fprintf(stderr, "%s: could not launch network script\n",
  504 + network_script);
  505 + }
588 506 }
589 507 }
590 508 return 0;
591 509 }
592 510  
593   -void net_send_packet(int net_fd, const uint8_t *buf, int size)
  511 +void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
594 512 {
595 513 #ifdef DEBUG_NE2000
596 514 printf("NE2000: sending packet size=%d\n", size);
597 515 #endif
598   - write(net_fd, buf, size);
  516 + write(nd->fd, buf, size);
599 517 }
600 518  
601 519 /***********************************************************/
... ... @@ -702,6 +620,37 @@ static void host_alarm_handler(int host_signum, siginfo_t *info,
702 620 }
703 621 }
704 622  
  623 +#define MAX_IO_HANDLERS 64
  624 +
  625 +typedef struct IOHandlerRecord {
  626 + int fd;
  627 + IOCanRWHandler *fd_can_read;
  628 + IOReadHandler *fd_read;
  629 + void *opaque;
  630 + /* temporary data */
  631 + struct pollfd *ufd;
  632 + int max_size;
  633 +} IOHandlerRecord;
  634 +
  635 +static IOHandlerRecord io_handlers[MAX_IO_HANDLERS];
  636 +static int nb_io_handlers = 0;
  637 +
  638 +int add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
  639 + IOReadHandler *fd_read, void *opaque)
  640 +{
  641 + IOHandlerRecord *ioh;
  642 +
  643 + if (nb_io_handlers >= MAX_IO_HANDLERS)
  644 + return -1;
  645 + ioh = &io_handlers[nb_io_handlers];
  646 + ioh->fd = fd;
  647 + ioh->fd_can_read = fd_can_read;
  648 + ioh->fd_read = fd_read;
  649 + ioh->opaque = opaque;
  650 + nb_io_handlers++;
  651 + return 0;
  652 +}
  653 +
705 654 /* main execution loop */
706 655  
707 656 CPUState *cpu_gdbstub_get_env(void *opaque)
... ... @@ -711,12 +660,10 @@ CPUState *cpu_gdbstub_get_env(void *opaque)
711 660  
712 661 int main_loop(void *opaque)
713 662 {
714   - struct pollfd ufds[3], *pf, *serial_ufd, *gdb_ufd;
715   -#if defined (TARGET_I386)
716   - struct pollfd *net_ufd;
717   -#endif
718   - int ret, n, timeout, serial_ok;
719   - uint8_t ch;
  663 + struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf, *gdb_ufd;
  664 + int ret, n, timeout, serial_ok, max_size, i;
  665 + uint8_t buf[4096];
  666 + IOHandlerRecord *ioh;
720 667 CPUState *env = global_env;
721 668  
722 669 if (!term_inited) {
... ... @@ -747,24 +694,26 @@ int main_loop(void *opaque)
747 694 timeout = 10;
748 695 else
749 696 timeout = 0;
  697 +
750 698 /* poll any events */
751   - serial_ufd = NULL;
752 699 pf = ufds;
753   - if (serial_ok && serial_can_receive()) {
754   - serial_ufd = pf;
755   - pf->fd = 0;
756   - pf->events = POLLIN;
757   - pf++;
758   - }
759   -#if defined (TARGET_I386)
760   - net_ufd = NULL;
761   - if (net_fd > 0 && ne2000_can_receive()) {
762   - net_ufd = pf;
763   - pf->fd = net_fd;
764   - pf->events = POLLIN;
765   - pf++;
  700 + ioh = io_handlers;
  701 + for(i = 0; i < nb_io_handlers; i++) {
  702 + max_size = ioh->fd_can_read(ioh->opaque);
  703 + if (max_size > 0) {
  704 + if (max_size > sizeof(buf))
  705 + max_size = sizeof(buf);
  706 + pf->fd = ioh->fd;
  707 + pf->events = POLLIN;
  708 + ioh->ufd = pf;
  709 + pf++;
  710 + } else {
  711 + ioh->ufd = NULL;
  712 + }
  713 + ioh->max_size = max_size;
  714 + ioh++;
766 715 }
767   -#endif
  716 +
768 717 gdb_ufd = NULL;
769 718 if (gdbstub_fd > 0) {
770 719 gdb_ufd = pf;
... ... @@ -775,29 +724,17 @@ int main_loop(void *opaque)
775 724  
776 725 ret = poll(ufds, pf - ufds, timeout);
777 726 if (ret > 0) {
778   - if (serial_ufd && (serial_ufd->revents & POLLIN)) {
779   - n = read(0, &ch, 1);
780   - if (n == 1) {
781   - term_received_byte(ch);
782   - } else {
783   - /* Closed, stop polling. */
784   - serial_ok = 0;
785   - }
786   - }
787   -#if defined (TARGET_I386)
788   - if (net_ufd && (net_ufd->revents & POLLIN)) {
789   - uint8_t buf[MAX_ETH_FRAME_SIZE];
790   -
791   - n = read(net_fd, buf, MAX_ETH_FRAME_SIZE);
792   - if (n > 0) {
793   - if (n < 60) {
794   - memset(buf + n, 0, 60 - n);
795   - n = 60;
  727 + ioh = io_handlers;
  728 + for(i = 0; i < nb_io_handlers; i++) {
  729 + pf = ioh->ufd;
  730 + if (pf) {
  731 + n = read(ioh->fd, buf, ioh->max_size);
  732 + if (n > 0) {
  733 + ioh->fd_read(ioh->opaque, buf, n);
796 734 }
797   - ne2000_receive(buf, n);
798 735 }
  736 + ioh++;
799 737 }
800   -#endif
801 738 if (gdb_ufd && (gdb_ufd->revents & POLLIN)) {
802 739 uint8_t buf[1];
803 740 /* stop emulation if requested by gdb */
... ... @@ -845,15 +782,18 @@ void help(void)
845 782 "-fda/-fdb file use 'file' as floppy disk 0/1 image\n"
846 783 "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
847 784 "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
848   - "-cdrom file use 'file' as IDE cdrom 2 image\n"
  785 + "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
849 786 "-boot [a|b|c|d] boot on floppy (a, b), hard disk (c) or CD-ROM (d)\n"
850 787 "-snapshot write to temporary files instead of disk image files\n"
851 788 "-m megs set virtual RAM size to megs MB\n"
  789 + "-nographic disable graphical output and redirect serial I/Os to console\n"
  790 + "\n"
  791 + "Network options:\n"
852 792 "-n script set network init script [default=%s]\n"
853   - "-tun-fd fd this fd talks to tap/tun, use it.\n"
854   - "-nographic disable graphical output\n"
  793 + "-nics n simulate 'n' network interfaces [default=1]\n"
  794 + "-tun-fd fd0[,...] use these fds as already opened tap/tun interfaces\n"
855 795 "\n"
856   - "Linux boot specific (does not require PC BIOS):\n"
  796 + "Linux boot specific:\n"
857 797 "-kernel bzImage use 'bzImage' as kernel image\n"
858 798 "-append cmdline use 'cmdline' as kernel command line\n"
859 799 "-initrd file use 'file' as initial ram disk\n"
... ... @@ -904,7 +844,8 @@ struct option long_options[] = {
904 844 { "boot", 1, NULL, 0, },
905 845 { "fda", 1, NULL, 0, },
906 846 { "fdb", 1, NULL, 0, },
907   - { "no-code-copy", 0, NULL, 0},
  847 + { "no-code-copy", 0, NULL, 0 },
  848 + { "nics", 1, NULL, 0 },
908 849 { NULL, 0, NULL, 0 },
909 850 };
910 851  
... ... @@ -931,7 +872,7 @@ static uint8_t *signal_stack;
931 872  
932 873 int main(int argc, char **argv)
933 874 {
934   - int c, i, use_gdbstub, gdbstub_port, long_index;
  875 + int c, i, use_gdbstub, gdbstub_port, long_index, has_cdrom;
935 876 int snapshot, linux_boot;
936 877 struct sigaction act;
937 878 struct itimerval itv;
... ... @@ -940,6 +881,7 @@ int main(int argc, char **argv)
940 881 const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
941 882 const char *kernel_filename, *kernel_cmdline;
942 883 DisplayState *ds = &display_state;
  884 + int cyls, heads, secs;
943 885  
944 886 /* we never want that malloc() uses mmap() */
945 887 mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
... ... @@ -950,15 +892,29 @@ int main(int argc, char **argv)
950 892 hd_filename[i] = NULL;
951 893 ram_size = 32 * 1024 * 1024;
952 894 vga_ram_size = VGA_RAM_SIZE;
953   -#if defined (TARGET_I386)
954 895 pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
955   -#endif
956 896 use_gdbstub = 0;
957 897 gdbstub_port = DEFAULT_GDBSTUB_PORT;
958 898 snapshot = 0;
959 899 nographic = 0;
960 900 kernel_filename = NULL;
961 901 kernel_cmdline = "";
  902 + has_cdrom = 1;
  903 + cyls = heads = secs = 0;
  904 +
  905 + nb_nics = 1;
  906 + for(i = 0; i < MAX_NICS; i++) {
  907 + NetDriverState *nd = &nd_table[i];
  908 + nd->fd = -1;
  909 + /* init virtual mac address */
  910 + nd->macaddr[0] = 0x52;
  911 + nd->macaddr[1] = 0x54;
  912 + nd->macaddr[2] = 0x00;
  913 + nd->macaddr[3] = 0x12;
  914 + nd->macaddr[4] = 0x34;
  915 + nd->macaddr[5] = 0x56 + i;
  916 + }
  917 +
962 918 for(;;) {
963 919 c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index);
964 920 if (c == -1)
... ... @@ -980,7 +936,6 @@ int main(int argc, char **argv)
980 936 break;
981 937 case 4:
982 938 {
983   - int cyls, heads, secs;
984 939 const char *p;
985 940 p = optarg;
986 941 cyls = strtol(p, (char **)&p, 0);
... ... @@ -992,10 +947,10 @@ int main(int argc, char **argv)
992 947 goto chs_fail;
993 948 p++;
994 949 secs = strtol(p, (char **)&p, 0);
995   - if (*p != '\0')
996   - goto chs_fail;
997   - ide_set_geometry(0, cyls, heads, secs);
998   - chs_fail: ;
  950 + if (*p != '\0') {
  951 + chs_fail:
  952 + cyls = 0;
  953 + }
999 954 }
1000 955 break;
1001 956 case 5:
... ... @@ -1007,20 +962,38 @@ int main(int argc, char **argv)
1007 962 case 7:
1008 963 kernel_cmdline = optarg;
1009 964 break;
1010   -#if defined (TARGET_I386)
1011 965 case 8:
1012   - net_fd = atoi(optarg);
  966 + {
  967 + const char *p;
  968 + int fd;
  969 + p = optarg;
  970 + nb_nics = 0;
  971 + for(;;) {
  972 + fd = strtol(p, (char **)&p, 0);
  973 + nd_table[nb_nics].fd = fd;
  974 + snprintf(nd_table[nb_nics].ifname,
  975 + sizeof(nd_table[nb_nics].ifname),
  976 + "fd%d", nb_nics);
  977 + nb_nics++;
  978 + if (*p == ',') {
  979 + p++;
  980 + } else if (*p != '\0') {
  981 + fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_nics);
  982 + exit(1);
  983 + }
  984 + }
  985 + }
1013 986 break;
1014   -#endif
1015 987 case 9:
1016 988 hd_filename[2] = optarg;
  989 + has_cdrom = 0;
1017 990 break;
1018 991 case 10:
1019 992 hd_filename[3] = optarg;
1020 993 break;
1021 994 case 11:
1022 995 hd_filename[2] = optarg;
1023   - ide_set_cdrom(2, 1);
  996 + has_cdrom = 1;
1024 997 break;
1025 998 case 12:
1026 999 boot_device = optarg[0];
... ... @@ -1039,6 +1012,13 @@ int main(int argc, char **argv)
1039 1012 case 15:
1040 1013 code_copy_enabled = 0;
1041 1014 break;
  1015 + case 16:
  1016 + nb_nics = atoi(optarg);
  1017 + if (nb_nics < 1 || nb_nics > MAX_NICS) {
  1018 + fprintf(stderr, "qemu: invalid number of network interfaces\n");
  1019 + exit(1);
  1020 + }
  1021 + break;
1042 1022 }
1043 1023 break;
1044 1024 case 'h':
... ... @@ -1057,11 +1037,9 @@ int main(int argc, char **argv)
1057 1037 case 'd':
1058 1038 cpu_set_log(CPU_LOG_ALL);
1059 1039 break;
1060   -#if defined (TARGET_I386)
1061 1040 case 'n':
1062 1041 pstrcpy(network_script, sizeof(network_script), optarg);
1063 1042 break;
1064   -#endif
1065 1043 case 's':
1066 1044 use_gdbstub = 1;
1067 1045 break;
... ... @@ -1102,11 +1080,8 @@ int main(int argc, char **argv)
1102 1080 setvbuf(stdout, NULL, _IOLBF, 0);
1103 1081 #endif
1104 1082  
1105   - /* init network tun interface */
1106   -#if defined (TARGET_I386)
1107   - if (net_fd < 0)
1108   - net_init();
1109   -#endif
  1083 + /* init host network redirectors */
  1084 + net_init();
1110 1085  
1111 1086 /* init the memory */
1112 1087 phys_ram_size = ram_size + vga_ram_size;
... ... @@ -1151,15 +1126,49 @@ int main(int argc, char **argv)
1151 1126 }
1152 1127 #endif
1153 1128  
  1129 + /* we always create the cdrom drive, even if no disk is there */
  1130 + if (has_cdrom) {
  1131 + bs_table[2] = bdrv_new("cdrom");
  1132 + bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
  1133 + }
  1134 +
1154 1135 /* open the virtual block devices */
1155 1136 for(i = 0; i < MAX_DISKS; i++) {
1156 1137 if (hd_filename[i]) {
1157   - bs_table[i] = bdrv_open(hd_filename[i], snapshot);
1158 1138 if (!bs_table[i]) {
  1139 + char buf[64];
  1140 + snprintf(buf, sizeof(buf), "hd%c", i + 'a');
  1141 + bs_table[i] = bdrv_new(buf);
  1142 + }
  1143 + if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
1159 1144 fprintf(stderr, "qemu: could not open hard disk image '%s\n",
1160 1145 hd_filename[i]);
1161 1146 exit(1);
1162 1147 }
  1148 + if (i == 0 && cyls != 0)
  1149 + bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
  1150 + }
  1151 + }
  1152 +
  1153 + /* we always create at least one floppy disk */
  1154 + fd_table[0] = bdrv_new("fda");
  1155 + bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY);
  1156 +
  1157 + for(i = 0; i < MAX_FD; i++) {
  1158 + if (fd_filename[i]) {
  1159 + if (!fd_table[i]) {
  1160 + char buf[64];
  1161 + snprintf(buf, sizeof(buf), "fd%c", i + 'a');
  1162 + fd_table[i] = bdrv_new(buf);
  1163 + bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
  1164 + }
  1165 + if (fd_filename[i] != '\0') {
  1166 + if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
  1167 + fprintf(stderr, "qemu: could not open floppy disk image '%s\n",
  1168 + fd_filename[i]);
  1169 + exit(1);
  1170 + }
  1171 + }
1163 1172 }
1164 1173 }
1165 1174  
... ... @@ -1190,6 +1199,10 @@ int main(int argc, char **argv)
1190 1199 ppc_init();
1191 1200 #endif
1192 1201  
  1202 + /* launched after the device init so that it can display or not a
  1203 + banner */
  1204 + monitor_init();
  1205 +
1193 1206 /* setup cpu signal handlers for MMU / self modifying code handling */
1194 1207 #if !defined(CONFIG_SOFTMMU)
1195 1208  
... ...
... ... @@ -31,16 +31,16 @@ extern int reset_requested;
31 31 extern int64_t ticks_per_sec;
32 32 extern int pit_min_timer_count;
33 33  
34   -typedef void (IOPortWriteFunc)(struct CPUState *env, uint32_t address, uint32_t data);
35   -typedef uint32_t (IOPortReadFunc)(struct CPUState *env, uint32_t address);
  34 +typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
  35 +typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
36 36  
37   -int register_ioport_read(int start, int length, IOPortReadFunc *func, int size);
38   -int register_ioport_write(int start, int length, IOPortWriteFunc *func, int size);
  37 +int register_ioport_read(int start, int length, int size,
  38 + IOPortReadFunc *func, void *opaque);
  39 +int register_ioport_write(int start, int length, int size,
  40 + IOPortWriteFunc *func, void *opaque);
39 41 int64_t cpu_get_ticks(void);
40 42 uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
41 43  
42   -void net_send_packet(int net_fd, const uint8_t *buf, int size);
43   -
44 44 void hw_error(const char *fmt, ...);
45 45  
46 46 int load_image(const char *filename, uint8_t *addr);
... ... @@ -49,10 +49,37 @@ extern const char *bios_dir;
49 49 void pstrcpy(char *buf, int buf_size, const char *str);
50 50 char *pstrcat(char *buf, int buf_size, const char *s);
51 51  
  52 +int serial_open_device(void);
  53 +
  54 +/* network redirectors support */
  55 +
  56 +#define MAX_NICS 8
  57 +
  58 +typedef struct NetDriverState {
  59 + int fd;
  60 + uint8_t macaddr[6];
  61 + char ifname[16];
  62 +} NetDriverState;
  63 +
  64 +extern int nb_nics;
  65 +extern NetDriverState nd_table[MAX_NICS];
  66 +
  67 +void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size);
  68 +
  69 +/* async I/O support */
  70 +
  71 +typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
  72 +typedef int IOCanRWHandler(void *opaque);
  73 +
  74 +int add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
  75 + IOReadHandler *fd_read, void *opaque);
  76 +
52 77 /* block.c */
53 78 typedef struct BlockDriverState BlockDriverState;
54 79  
55   -BlockDriverState *bdrv_open(const char *filename, int snapshot);
  80 +BlockDriverState *bdrv_new(const char *device_name);
  81 +void bdrv_delete(BlockDriverState *bs);
  82 +int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot);
56 83 void bdrv_close(BlockDriverState *bs);
57 84 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
58 85 uint8_t *buf, int nb_sectors);
... ... @@ -62,6 +89,27 @@ void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
62 89 int bdrv_commit(BlockDriverState *bs);
63 90 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
64 91  
  92 +#define BDRV_TYPE_HD 0
  93 +#define BDRV_TYPE_CDROM 1
  94 +#define BDRV_TYPE_FLOPPY 2
  95 +
  96 +void bdrv_set_geometry_hint(BlockDriverState *bs,
  97 + int cyls, int heads, int secs);
  98 +void bdrv_set_type_hint(BlockDriverState *bs, int type);
  99 +void bdrv_get_geometry_hint(BlockDriverState *bs,
  100 + int *pcyls, int *pheads, int *psecs);
  101 +int bdrv_get_type_hint(BlockDriverState *bs);
  102 +int bdrv_is_removable(BlockDriverState *bs);
  103 +int bdrv_is_read_only(BlockDriverState *bs);
  104 +int bdrv_is_inserted(BlockDriverState *bs);
  105 +int bdrv_is_locked(BlockDriverState *bs);
  106 +void bdrv_set_locked(BlockDriverState *bs, int locked);
  107 +void bdrv_set_change_cb(BlockDriverState *bs,
  108 + void (*change_cb)(void *opaque), void *opaque);
  109 +
  110 +void bdrv_info(void);
  111 +BlockDriverState *bdrv_find(const char *name);
  112 +
65 113 /* vga.c */
66 114  
67 115 #define VGA_RAM_SIZE (4096 * 1024)
... ... @@ -97,9 +145,8 @@ void sdl_display_init(DisplayState *ds);
97 145  
98 146 extern BlockDriverState *bs_table[MAX_DISKS];
99 147  
100   -void ide_init(void);
101   -void ide_set_geometry(int n, int cyls, int heads, int secs);
102   -void ide_set_cdrom(int n, int is_cdrom);
  148 +void ide_init(int iobase, int iobase2, int irq,
  149 + BlockDriverState *hd0, BlockDriverState *hd1);
103 150  
104 151 /* oss.c */
105 152 typedef enum {
... ... @@ -138,20 +185,13 @@ void SB16_init (void);
138 185 #define MAX_FD 2
139 186 extern BlockDriverState *fd_table[MAX_FD];
140 187  
141   -void cmos_register_fd (uint8_t fd0, uint8_t fd1);
142 188 void fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, uint32_t base,
143   - char boot_device);
144   -int fdctrl_disk_change (int idx, const unsigned char *filename, int ro);
  189 + BlockDriverState **fds);
  190 +int fdctrl_get_drive_type(int drive_num);
145 191  
146 192 /* ne2000.c */
147 193  
148   -#define MAX_ETH_FRAME_SIZE 1514
149   -
150   -void ne2000_init(int base, int irq);
151   -int ne2000_can_receive(void);
152   -void ne2000_receive(uint8_t *buf, int size);
153   -
154   -extern int net_fd;
  194 +void ne2000_init(int base, int irq, NetDriverState *nd);
155 195  
156 196 /* pckbd.c */
157 197  
... ... @@ -179,10 +219,14 @@ void rtc_timer(void);
179 219  
180 220 /* serial.c */
181 221  
182   -void serial_init(int base, int irq);
183   -int serial_can_receive(void);
184   -void serial_receive_byte(int ch);
185   -void serial_receive_break(void);
  222 +typedef struct SerialState SerialState;
  223 +
  224 +extern SerialState *serial_console;
  225 +
  226 +SerialState *serial_init(int base, int irq, int fd);
  227 +int serial_can_receive(SerialState *s);
  228 +void serial_receive_byte(SerialState *s, int ch);
  229 +void serial_receive_break(SerialState *s);
186 230  
187 231 /* i8259.c */
188 232  
... ... @@ -206,7 +250,7 @@ typedef struct PITChannelState {
206 250  
207 251 extern PITChannelState pit_channels[3];
208 252  
209   -void pit_init(void);
  253 +void pit_init(int base);
210 254 void pit_set_gate(PITChannelState *s, int val);
211 255 int pit_get_out(PITChannelState *s);
212 256 int pit_get_out_edges(PITChannelState *s);
... ... @@ -217,4 +261,10 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
217 261 const char *kernel_filename, const char *kernel_cmdline,
218 262 const char *initrd_filename);
219 263  
  264 +/* monitor.c */
  265 +void monitor_init(void);
  266 +void term_printf(const char *fmt, ...);
  267 +void term_flush(void);
  268 +void term_print_help(void);
  269 +
220 270 #endif /* VL_H */
... ...