Statistics
| Branch: | Revision:

root / vl.c @ a735aa31

History | View | Annotate | Download (96.8 kB)

1 0824d6fc bellard
/*
2 1df912cf bellard
 * QEMU PC System Emulator
3 0824d6fc bellard
 * 
4 1df912cf bellard
 * Copyright (c) 2003 Fabrice Bellard
5 0824d6fc bellard
 * 
6 1df912cf bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 1df912cf bellard
 * of this software and associated documentation files (the "Software"), to deal
8 1df912cf bellard
 * in the Software without restriction, including without limitation the rights
9 1df912cf bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 1df912cf bellard
 * copies of the Software, and to permit persons to whom the Software is
11 1df912cf bellard
 * furnished to do so, subject to the following conditions:
12 1df912cf bellard
 *
13 1df912cf bellard
 * The above copyright notice and this permission notice shall be included in
14 1df912cf bellard
 * all copies or substantial portions of the Software.
15 1df912cf bellard
 *
16 1df912cf bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 1df912cf bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 1df912cf bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 1df912cf bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 1df912cf bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 1df912cf bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 1df912cf bellard
 * THE SOFTWARE.
23 0824d6fc bellard
 */
24 0824d6fc bellard
#include <stdlib.h>
25 0824d6fc bellard
#include <stdio.h>
26 1df912cf bellard
#include <stdarg.h>
27 0824d6fc bellard
#include <string.h>
28 c45886db bellard
#include <ctype.h>
29 0824d6fc bellard
#include <getopt.h>
30 0824d6fc bellard
#include <inttypes.h>
31 0824d6fc bellard
#include <unistd.h>
32 0824d6fc bellard
#include <sys/mman.h>
33 0824d6fc bellard
#include <fcntl.h>
34 0824d6fc bellard
#include <signal.h>
35 0824d6fc bellard
#include <time.h>
36 0824d6fc bellard
#include <sys/time.h>
37 0824d6fc bellard
#include <malloc.h>
38 0824d6fc bellard
#include <termios.h>
39 0824d6fc bellard
#include <sys/poll.h>
40 0824d6fc bellard
#include <errno.h>
41 f1510b2c bellard
#include <sys/wait.h>
42 f1510b2c bellard
43 f1510b2c bellard
#include <sys/ioctl.h>
44 f1510b2c bellard
#include <sys/socket.h>
45 f1510b2c bellard
#include <linux/if.h>
46 f1510b2c bellard
#include <linux/if_tun.h>
47 0824d6fc bellard
48 0824d6fc bellard
#include "disas.h"
49 fc01f7e7 bellard
#include "thunk.h"
50 fc01f7e7 bellard
51 fc01f7e7 bellard
#include "vl.h"
52 0824d6fc bellard
53 5a67135a bellard
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
54 330d0414 bellard
#define BIOS_FILENAME "bios.bin"
55 330d0414 bellard
#define VGABIOS_FILENAME "vgabios.bin"
56 a735aa31 bellard
#define LINUX_BOOT_FILENAME "linux_boot.bin"
57 f1510b2c bellard
58 0824d6fc bellard
//#define DEBUG_UNUSED_IOPORT
59 330d0414 bellard
60 c9159e53 bellard
//#define DEBUG_IRQ_LATENCY
61 0824d6fc bellard
62 330d0414 bellard
/* output Bochs bios info messages */
63 330d0414 bellard
//#define DEBUG_BIOS
64 330d0414 bellard
65 7dea1da4 bellard
//#define DEBUG_CMOS
66 7dea1da4 bellard
67 330d0414 bellard
/* debug PIC */
68 330d0414 bellard
//#define DEBUG_PIC
69 330d0414 bellard
70 330d0414 bellard
/* debug NE2000 card */
71 330d0414 bellard
//#define DEBUG_NE2000
72 330d0414 bellard
73 330d0414 bellard
/* debug PC keyboard */
74 330d0414 bellard
//#define DEBUG_KBD
75 330d0414 bellard
76 313aa567 bellard
/* debug PC keyboard : only mouse */
77 313aa567 bellard
//#define DEBUG_MOUSE
78 313aa567 bellard
79 7dea1da4 bellard
//#define DEBUG_SERIAL
80 7dea1da4 bellard
81 bb551faa bellard
#if !defined(CONFIG_SOFTMMU)
82 7916e224 bellard
#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
83 bb551faa bellard
#else
84 bb551faa bellard
#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
85 bb551faa bellard
#endif
86 7916e224 bellard
87 c45886db bellard
#if defined (TARGET_I386)
88 0824d6fc bellard
#define KERNEL_LOAD_ADDR   0x00100000
89 c45886db bellard
#elif defined (TARGET_PPC)
90 c45886db bellard
//#define USE_OPEN_FIRMWARE
91 3f5dcc34 bellard
#if !defined (USE_OPEN_FIRMWARE)
92 c45886db bellard
#define KERNEL_LOAD_ADDR    0x01000000
93 c45886db bellard
#define KERNEL_STACK_ADDR   0x01200000
94 c45886db bellard
#else
95 c45886db bellard
#define KERNEL_LOAD_ADDR    0x00000000
96 c45886db bellard
#define KERNEL_STACK_ADDR   0x00400000
97 c45886db bellard
#endif
98 c45886db bellard
#endif
99 77fef8c1 bellard
#define INITRD_LOAD_ADDR     0x00400000
100 77fef8c1 bellard
#define KERNEL_PARAMS_ADDR   0x00090000
101 77fef8c1 bellard
#define KERNEL_CMDLINE_ADDR  0x00099000
102 0824d6fc bellard
103 313aa567 bellard
#define GUI_REFRESH_INTERVAL 30 
104 313aa567 bellard
105 7dea1da4 bellard
/* XXX: use a two level table to limit memory usage */
106 7dea1da4 bellard
#define MAX_IOPORTS 65536
107 0824d6fc bellard
108 5a67135a bellard
static const char *bios_dir = CONFIG_QEMU_SHAREDIR;
109 0824d6fc bellard
char phys_ram_file[1024];
110 c45886db bellard
CPUState *global_env;
111 c45886db bellard
CPUState *cpu_single_env;
112 fc01f7e7 bellard
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
113 fc01f7e7 bellard
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
114 c45886db bellard
BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
115 313aa567 bellard
int vga_ram_size;
116 313aa567 bellard
static DisplayState display_state;
117 a20dd508 bellard
int nographic;
118 313aa567 bellard
int term_inited;
119 313aa567 bellard
int64_t ticks_per_sec;
120 36b486bb bellard
int boot_device = 'c';
121 1ccde1cb bellard
static int ram_size;
122 0824d6fc bellard
123 0824d6fc bellard
/***********************************************************/
124 0824d6fc bellard
/* x86 io ports */
125 0824d6fc bellard
126 c45886db bellard
uint32_t default_ioport_readb(CPUState *env, uint32_t address)
127 0824d6fc bellard
{
128 0824d6fc bellard
#ifdef DEBUG_UNUSED_IOPORT
129 0824d6fc bellard
    fprintf(stderr, "inb: port=0x%04x\n", address);
130 0824d6fc bellard
#endif
131 fc01f7e7 bellard
    return 0xff;
132 0824d6fc bellard
}
133 0824d6fc bellard
134 c45886db bellard
void default_ioport_writeb(CPUState *env, uint32_t address, uint32_t data)
135 0824d6fc bellard
{
136 0824d6fc bellard
#ifdef DEBUG_UNUSED_IOPORT
137 0824d6fc bellard
    fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
138 0824d6fc bellard
#endif
139 0824d6fc bellard
}
140 0824d6fc bellard
141 0824d6fc bellard
/* default is to make two byte accesses */
142 c45886db bellard
uint32_t default_ioport_readw(CPUState *env, uint32_t address)
143 0824d6fc bellard
{
144 0824d6fc bellard
    uint32_t data;
145 330d0414 bellard
    data = ioport_read_table[0][address & (MAX_IOPORTS - 1)](env, address);
146 330d0414 bellard
    data |= ioport_read_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1) << 8;
147 0824d6fc bellard
    return data;
148 0824d6fc bellard
}
149 0824d6fc bellard
150 c45886db bellard
void default_ioport_writew(CPUState *env, uint32_t address, uint32_t data)
151 0824d6fc bellard
{
152 330d0414 bellard
    ioport_write_table[0][address & (MAX_IOPORTS - 1)](env, address, data & 0xff);
153 330d0414 bellard
    ioport_write_table[0][(address + 1) & (MAX_IOPORTS - 1)](env, address + 1, (data >> 8) & 0xff);
154 0824d6fc bellard
}
155 0824d6fc bellard
156 c45886db bellard
uint32_t default_ioport_readl(CPUState *env, uint32_t address)
157 0824d6fc bellard
{
158 fc01f7e7 bellard
#ifdef DEBUG_UNUSED_IOPORT
159 fc01f7e7 bellard
    fprintf(stderr, "inl: port=0x%04x\n", address);
160 fc01f7e7 bellard
#endif
161 fc01f7e7 bellard
    return 0xffffffff;
162 0824d6fc bellard
}
163 0824d6fc bellard
164 c45886db bellard
void default_ioport_writel(CPUState *env, uint32_t address, uint32_t data)
165 0824d6fc bellard
{
166 fc01f7e7 bellard
#ifdef DEBUG_UNUSED_IOPORT
167 fc01f7e7 bellard
    fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
168 fc01f7e7 bellard
#endif
169 0824d6fc bellard
}
170 0824d6fc bellard
171 fc01f7e7 bellard
void init_ioports(void)
172 0824d6fc bellard
{
173 0824d6fc bellard
    int i;
174 0824d6fc bellard
175 fc01f7e7 bellard
    for(i = 0; i < MAX_IOPORTS; i++) {
176 fc01f7e7 bellard
        ioport_read_table[0][i] = default_ioport_readb;
177 fc01f7e7 bellard
        ioport_write_table[0][i] = default_ioport_writeb;
178 fc01f7e7 bellard
        ioport_read_table[1][i] = default_ioport_readw;
179 fc01f7e7 bellard
        ioport_write_table[1][i] = default_ioport_writew;
180 fc01f7e7 bellard
        ioport_read_table[2][i] = default_ioport_readl;
181 fc01f7e7 bellard
        ioport_write_table[2][i] = default_ioport_writel;
182 fc01f7e7 bellard
    }
183 0824d6fc bellard
}
184 0824d6fc bellard
185 fc01f7e7 bellard
/* size is the word size in byte */
186 fc01f7e7 bellard
int register_ioport_read(int start, int length, IOPortReadFunc *func, int size)
187 f1510b2c bellard
{
188 fc01f7e7 bellard
    int i, bsize;
189 f1510b2c bellard
190 fc01f7e7 bellard
    if (size == 1)
191 fc01f7e7 bellard
        bsize = 0;
192 fc01f7e7 bellard
    else if (size == 2)
193 fc01f7e7 bellard
        bsize = 1;
194 fc01f7e7 bellard
    else if (size == 4)
195 fc01f7e7 bellard
        bsize = 2;
196 fc01f7e7 bellard
    else
197 fc01f7e7 bellard
        return -1;
198 fc01f7e7 bellard
    for(i = start; i < start + length; i += size)
199 fc01f7e7 bellard
        ioport_read_table[bsize][i] = func;
200 f1510b2c bellard
    return 0;
201 f1510b2c bellard
}
202 f1510b2c bellard
203 fc01f7e7 bellard
/* size is the word size in byte */
204 fc01f7e7 bellard
int register_ioport_write(int start, int length, IOPortWriteFunc *func, int size)
205 f1510b2c bellard
{
206 fc01f7e7 bellard
    int i, bsize;
207 f1510b2c bellard
208 fc01f7e7 bellard
    if (size == 1)
209 fc01f7e7 bellard
        bsize = 0;
210 fc01f7e7 bellard
    else if (size == 2)
211 fc01f7e7 bellard
        bsize = 1;
212 fc01f7e7 bellard
    else if (size == 4)
213 fc01f7e7 bellard
        bsize = 2;
214 fc01f7e7 bellard
    else
215 fc01f7e7 bellard
        return -1;
216 fc01f7e7 bellard
    for(i = start; i < start + length; i += size)
217 fc01f7e7 bellard
        ioport_write_table[bsize][i] = func;
218 f1510b2c bellard
    return 0;
219 f1510b2c bellard
}
220 f1510b2c bellard
221 0824d6fc bellard
void pstrcpy(char *buf, int buf_size, const char *str)
222 0824d6fc bellard
{
223 0824d6fc bellard
    int c;
224 0824d6fc bellard
    char *q = buf;
225 0824d6fc bellard
226 0824d6fc bellard
    if (buf_size <= 0)
227 0824d6fc bellard
        return;
228 0824d6fc bellard
229 0824d6fc bellard
    for(;;) {
230 0824d6fc bellard
        c = *str++;
231 0824d6fc bellard
        if (c == 0 || q >= buf + buf_size - 1)
232 0824d6fc bellard
            break;
233 0824d6fc bellard
        *q++ = c;
234 0824d6fc bellard
    }
235 0824d6fc bellard
    *q = '\0';
236 0824d6fc bellard
}
237 0824d6fc bellard
238 0824d6fc bellard
/* strcat and truncate. */
239 0824d6fc bellard
char *pstrcat(char *buf, int buf_size, const char *s)
240 0824d6fc bellard
{
241 0824d6fc bellard
    int len;
242 0824d6fc bellard
    len = strlen(buf);
243 0824d6fc bellard
    if (len < buf_size) 
244 0824d6fc bellard
        pstrcpy(buf + len, buf_size - len, s);
245 0824d6fc bellard
    return buf;
246 0824d6fc bellard
}
247 0824d6fc bellard
248 77fef8c1 bellard
#if defined (TARGET_I386)
249 77fef8c1 bellard
int load_kernel(const char *filename, uint8_t *addr, 
250 77fef8c1 bellard
                uint8_t *real_addr)
251 0824d6fc bellard
{
252 c45886db bellard
    int fd, size;
253 c45886db bellard
    int setup_sects;
254 0824d6fc bellard
255 0824d6fc bellard
    fd = open(filename, O_RDONLY);
256 0824d6fc bellard
    if (fd < 0)
257 0824d6fc bellard
        return -1;
258 77fef8c1 bellard
259 77fef8c1 bellard
    /* load 16 bit code */
260 77fef8c1 bellard
    if (read(fd, real_addr, 512) != 512)
261 0824d6fc bellard
        goto fail;
262 77fef8c1 bellard
    setup_sects = real_addr[0x1F1];
263 0824d6fc bellard
    if (!setup_sects)
264 0824d6fc bellard
        setup_sects = 4;
265 77fef8c1 bellard
    if (read(fd, real_addr + 512, setup_sects * 512) != 
266 77fef8c1 bellard
        setup_sects * 512)
267 77fef8c1 bellard
        goto fail;
268 77fef8c1 bellard
    
269 77fef8c1 bellard
    /* load 32 bit code */
270 0824d6fc bellard
    size = read(fd, addr, 16 * 1024 * 1024);
271 0824d6fc bellard
    if (size < 0)
272 0824d6fc bellard
        goto fail;
273 0824d6fc bellard
    close(fd);
274 0824d6fc bellard
    return size;
275 0824d6fc bellard
 fail:
276 0824d6fc bellard
    close(fd);
277 0824d6fc bellard
    return -1;
278 0824d6fc bellard
}
279 77fef8c1 bellard
#endif
280 0824d6fc bellard
281 0824d6fc bellard
/* return the size or -1 if error */
282 0824d6fc bellard
int load_image(const char *filename, uint8_t *addr)
283 0824d6fc bellard
{
284 0824d6fc bellard
    int fd, size;
285 0824d6fc bellard
    fd = open(filename, O_RDONLY);
286 0824d6fc bellard
    if (fd < 0)
287 0824d6fc bellard
        return -1;
288 0824d6fc bellard
    size = lseek(fd, 0, SEEK_END);
289 0824d6fc bellard
    lseek(fd, 0, SEEK_SET);
290 0824d6fc bellard
    if (read(fd, addr, size) != size) {
291 0824d6fc bellard
        close(fd);
292 0824d6fc bellard
        return -1;
293 0824d6fc bellard
    }
294 0824d6fc bellard
    close(fd);
295 0824d6fc bellard
    return size;
296 0824d6fc bellard
}
297 0824d6fc bellard
298 c45886db bellard
void cpu_outb(CPUState *env, int addr, int val)
299 0824d6fc bellard
{
300 fc01f7e7 bellard
    ioport_write_table[0][addr & (MAX_IOPORTS - 1)](env, addr, val);
301 0824d6fc bellard
}
302 0824d6fc bellard
303 c45886db bellard
void cpu_outw(CPUState *env, int addr, int val)
304 0824d6fc bellard
{
305 fc01f7e7 bellard
    ioport_write_table[1][addr & (MAX_IOPORTS - 1)](env, addr, val);
306 0824d6fc bellard
}
307 0824d6fc bellard
308 c45886db bellard
void cpu_outl(CPUState *env, int addr, int val)
309 0824d6fc bellard
{
310 fc01f7e7 bellard
    ioport_write_table[2][addr & (MAX_IOPORTS - 1)](env, addr, val);
311 0824d6fc bellard
}
312 0824d6fc bellard
313 c45886db bellard
int cpu_inb(CPUState *env, int addr)
314 0824d6fc bellard
{
315 fc01f7e7 bellard
    return ioport_read_table[0][addr & (MAX_IOPORTS - 1)](env, addr);
316 0824d6fc bellard
}
317 0824d6fc bellard
318 c45886db bellard
int cpu_inw(CPUState *env, int addr)
319 0824d6fc bellard
{
320 fc01f7e7 bellard
    return ioport_read_table[1][addr & (MAX_IOPORTS - 1)](env, addr);
321 0824d6fc bellard
}
322 0824d6fc bellard
323 c45886db bellard
int cpu_inl(CPUState *env, int addr)
324 0824d6fc bellard
{
325 fc01f7e7 bellard
    return ioport_read_table[2][addr & (MAX_IOPORTS - 1)](env, addr);
326 0824d6fc bellard
}
327 0824d6fc bellard
328 0824d6fc bellard
/***********************************************************/
329 c45886db bellard
void ioport80_write(CPUState *env, uint32_t addr, uint32_t data)
330 0824d6fc bellard
{
331 0824d6fc bellard
}
332 0824d6fc bellard
333 0824d6fc bellard
void hw_error(const char *fmt, ...)
334 0824d6fc bellard
{
335 0824d6fc bellard
    va_list ap;
336 0824d6fc bellard
337 0824d6fc bellard
    va_start(ap, fmt);
338 0824d6fc bellard
    fprintf(stderr, "qemu: hardware error: ");
339 0824d6fc bellard
    vfprintf(stderr, fmt, ap);
340 0824d6fc bellard
    fprintf(stderr, "\n");
341 0824d6fc bellard
#ifdef TARGET_I386
342 0824d6fc bellard
    cpu_x86_dump_state(global_env, stderr, X86_DUMP_FPU | X86_DUMP_CCOP);
343 c45886db bellard
#else
344 c45886db bellard
    cpu_dump_state(global_env, stderr, 0);
345 0824d6fc bellard
#endif
346 0824d6fc bellard
    va_end(ap);
347 0824d6fc bellard
    abort();
348 0824d6fc bellard
}
349 0824d6fc bellard
350 0824d6fc bellard
/***********************************************************/
351 0824d6fc bellard
/* cmos emulation */
352 0824d6fc bellard
353 c45886db bellard
#if defined (TARGET_I386)
354 0824d6fc bellard
#define RTC_SECONDS             0
355 0824d6fc bellard
#define RTC_SECONDS_ALARM       1
356 0824d6fc bellard
#define RTC_MINUTES             2
357 0824d6fc bellard
#define RTC_MINUTES_ALARM       3
358 0824d6fc bellard
#define RTC_HOURS               4
359 0824d6fc bellard
#define RTC_HOURS_ALARM         5
360 0824d6fc bellard
#define RTC_ALARM_DONT_CARE    0xC0
361 0824d6fc bellard
362 0824d6fc bellard
#define RTC_DAY_OF_WEEK         6
363 0824d6fc bellard
#define RTC_DAY_OF_MONTH        7
364 0824d6fc bellard
#define RTC_MONTH               8
365 0824d6fc bellard
#define RTC_YEAR                9
366 0824d6fc bellard
367 0824d6fc bellard
#define RTC_REG_A               10
368 0824d6fc bellard
#define RTC_REG_B               11
369 0824d6fc bellard
#define RTC_REG_C               12
370 0824d6fc bellard
#define RTC_REG_D               13
371 0824d6fc bellard
372 0824d6fc bellard
/* PC cmos mappings */
373 0824d6fc bellard
#define REG_EQUIPMENT_BYTE          0x14
374 dc887a4d bellard
#define REG_IBM_CENTURY_BYTE        0x32
375 77fef8c1 bellard
#define REG_IBM_PS2_CENTURY_BYTE    0x37
376 0824d6fc bellard
377 0824d6fc bellard
uint8_t cmos_data[128];
378 0824d6fc bellard
uint8_t cmos_index;
379 0824d6fc bellard
380 c45886db bellard
void cmos_ioport_write(CPUState *env, uint32_t addr, uint32_t data)
381 0824d6fc bellard
{
382 0824d6fc bellard
    if (addr == 0x70) {
383 0824d6fc bellard
        cmos_index = data & 0x7f;
384 7dea1da4 bellard
    } else {
385 7dea1da4 bellard
#ifdef DEBUG_CMOS
386 7dea1da4 bellard
        printf("cmos: write index=0x%02x val=0x%02x\n",
387 7dea1da4 bellard
               cmos_index, data);
388 7dea1da4 bellard
#endif        
389 7dea1da4 bellard
        switch(addr) {
390 7dea1da4 bellard
        case RTC_SECONDS_ALARM:
391 7dea1da4 bellard
        case RTC_MINUTES_ALARM:
392 7dea1da4 bellard
        case RTC_HOURS_ALARM:
393 7dea1da4 bellard
            /* XXX: not supported */
394 7dea1da4 bellard
            cmos_data[cmos_index] = data;
395 7dea1da4 bellard
            break;
396 7dea1da4 bellard
        case RTC_SECONDS:
397 7dea1da4 bellard
        case RTC_MINUTES:
398 7dea1da4 bellard
        case RTC_HOURS:
399 7dea1da4 bellard
        case RTC_DAY_OF_WEEK:
400 7dea1da4 bellard
        case RTC_DAY_OF_MONTH:
401 7dea1da4 bellard
        case RTC_MONTH:
402 7dea1da4 bellard
        case RTC_YEAR:
403 7dea1da4 bellard
            cmos_data[cmos_index] = data;
404 7dea1da4 bellard
            break;
405 7dea1da4 bellard
        case RTC_REG_A:
406 7dea1da4 bellard
        case RTC_REG_B:
407 7dea1da4 bellard
            cmos_data[cmos_index] = data;
408 7dea1da4 bellard
            break;
409 7dea1da4 bellard
        case RTC_REG_C:
410 7dea1da4 bellard
        case RTC_REG_D:
411 7dea1da4 bellard
            /* cannot write to them */
412 7dea1da4 bellard
            break;
413 7dea1da4 bellard
        default:
414 7dea1da4 bellard
            cmos_data[cmos_index] = data;
415 7dea1da4 bellard
            break;
416 7dea1da4 bellard
        }
417 0824d6fc bellard
    }
418 0824d6fc bellard
}
419 0824d6fc bellard
420 6e44ba7f bellard
static inline int to_bcd(int a)
421 6e44ba7f bellard
{
422 6e44ba7f bellard
    return ((a / 10) << 4) | (a % 10);
423 6e44ba7f bellard
}
424 6e44ba7f bellard
425 6e44ba7f bellard
static void cmos_update_time(void)
426 6e44ba7f bellard
{
427 6e44ba7f bellard
    struct tm *tm;
428 6e44ba7f bellard
    time_t ti;
429 6e44ba7f bellard
430 6e44ba7f bellard
    ti = time(NULL);
431 6e44ba7f bellard
    tm = gmtime(&ti);
432 6e44ba7f bellard
    cmos_data[RTC_SECONDS] = to_bcd(tm->tm_sec);
433 6e44ba7f bellard
    cmos_data[RTC_MINUTES] = to_bcd(tm->tm_min);
434 6e44ba7f bellard
    cmos_data[RTC_HOURS] = to_bcd(tm->tm_hour);
435 6e44ba7f bellard
    cmos_data[RTC_DAY_OF_WEEK] = to_bcd(tm->tm_wday);
436 6e44ba7f bellard
    cmos_data[RTC_DAY_OF_MONTH] = to_bcd(tm->tm_mday);
437 6e44ba7f bellard
    cmos_data[RTC_MONTH] = to_bcd(tm->tm_mon + 1);
438 6e44ba7f bellard
    cmos_data[RTC_YEAR] = to_bcd(tm->tm_year % 100);
439 6e44ba7f bellard
    cmos_data[REG_IBM_CENTURY_BYTE] = to_bcd((tm->tm_year / 100) + 19);
440 77fef8c1 bellard
    cmos_data[REG_IBM_PS2_CENTURY_BYTE] = cmos_data[REG_IBM_CENTURY_BYTE];
441 6e44ba7f bellard
}
442 6e44ba7f bellard
443 c45886db bellard
uint32_t cmos_ioport_read(CPUState *env, uint32_t addr)
444 0824d6fc bellard
{
445 0824d6fc bellard
    int ret;
446 0824d6fc bellard
447 0824d6fc bellard
    if (addr == 0x70) {
448 0824d6fc bellard
        return 0xff;
449 0824d6fc bellard
    } else {
450 7dea1da4 bellard
        switch(cmos_index) {
451 6e44ba7f bellard
        case RTC_SECONDS:
452 6e44ba7f bellard
        case RTC_MINUTES:
453 6e44ba7f bellard
        case RTC_HOURS:
454 6e44ba7f bellard
        case RTC_DAY_OF_WEEK:
455 6e44ba7f bellard
        case RTC_DAY_OF_MONTH:
456 6e44ba7f bellard
        case RTC_MONTH:
457 6e44ba7f bellard
        case RTC_YEAR:
458 6e44ba7f bellard
        case REG_IBM_CENTURY_BYTE:
459 77fef8c1 bellard
        case REG_IBM_PS2_CENTURY_BYTE:
460 6e44ba7f bellard
            cmos_update_time();
461 6e44ba7f bellard
            ret = cmos_data[cmos_index];
462 6e44ba7f bellard
            break;
463 7dea1da4 bellard
        case RTC_REG_A:
464 6e44ba7f bellard
            ret = cmos_data[cmos_index];
465 7dea1da4 bellard
            /* toggle update-in-progress bit for Linux (same hack as
466 7dea1da4 bellard
               plex86) */
467 0824d6fc bellard
            cmos_data[RTC_REG_A] ^= 0x80; 
468 7dea1da4 bellard
            break;
469 7dea1da4 bellard
        case RTC_REG_C:
470 6e44ba7f bellard
            ret = cmos_data[cmos_index];
471 7dea1da4 bellard
            pic_set_irq(8, 0);
472 0824d6fc bellard
            cmos_data[RTC_REG_C] = 0x00; 
473 7dea1da4 bellard
            break;
474 6e44ba7f bellard
        default:
475 6e44ba7f bellard
            ret = cmos_data[cmos_index];
476 6e44ba7f bellard
            break;
477 7dea1da4 bellard
        }
478 7dea1da4 bellard
#ifdef DEBUG_CMOS
479 7dea1da4 bellard
        printf("cmos: read index=0x%02x val=0x%02x\n",
480 7dea1da4 bellard
               cmos_index, ret);
481 7dea1da4 bellard
#endif
482 0824d6fc bellard
        return ret;
483 0824d6fc bellard
    }
484 0824d6fc bellard
}
485 0824d6fc bellard
486 0824d6fc bellard
void cmos_init(void)
487 0824d6fc bellard
{
488 330d0414 bellard
    int val;
489 0824d6fc bellard
490 6e44ba7f bellard
    cmos_update_time();
491 0824d6fc bellard
492 0824d6fc bellard
    cmos_data[RTC_REG_A] = 0x26;
493 0824d6fc bellard
    cmos_data[RTC_REG_B] = 0x02;
494 0824d6fc bellard
    cmos_data[RTC_REG_C] = 0x00;
495 0824d6fc bellard
    cmos_data[RTC_REG_D] = 0x80;
496 0824d6fc bellard
497 330d0414 bellard
    /* various important CMOS locations needed by PC/Bochs bios */
498 330d0414 bellard
499 0824d6fc bellard
    cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */
500 313aa567 bellard
    cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */
501 0824d6fc bellard
502 330d0414 bellard
    /* memory size */
503 1ccde1cb bellard
    val = (ram_size / 1024) - 1024;
504 330d0414 bellard
    if (val > 65535)
505 330d0414 bellard
        val = 65535;
506 330d0414 bellard
    cmos_data[0x17] = val;
507 330d0414 bellard
    cmos_data[0x18] = val >> 8;
508 330d0414 bellard
    cmos_data[0x30] = val;
509 330d0414 bellard
    cmos_data[0x31] = val >> 8;
510 330d0414 bellard
511 1ccde1cb bellard
    val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
512 330d0414 bellard
    if (val > 65535)
513 330d0414 bellard
        val = 65535;
514 330d0414 bellard
    cmos_data[0x34] = val;
515 330d0414 bellard
    cmos_data[0x35] = val >> 8;
516 330d0414 bellard
    
517 36b486bb bellard
    switch(boot_device) {
518 36b486bb bellard
    case 'a':
519 c45886db bellard
    case 'b':
520 36b486bb bellard
        cmos_data[0x3d] = 0x01; /* floppy boot */
521 36b486bb bellard
        break;
522 36b486bb bellard
    default:
523 36b486bb bellard
    case 'c':
524 36b486bb bellard
        cmos_data[0x3d] = 0x02; /* hard drive boot */
525 36b486bb bellard
        break;
526 36b486bb bellard
    case 'd':
527 36b486bb bellard
        cmos_data[0x3d] = 0x03; /* CD-ROM boot */
528 36b486bb bellard
        break;
529 36b486bb bellard
    }
530 36b486bb bellard
531 fc01f7e7 bellard
    register_ioport_write(0x70, 2, cmos_ioport_write, 1);
532 fc01f7e7 bellard
    register_ioport_read(0x70, 2, cmos_ioport_read, 1);
533 0824d6fc bellard
}
534 0824d6fc bellard
535 c45886db bellard
void cmos_register_fd (uint8_t fd0, uint8_t fd1)
536 c45886db bellard
{
537 c45886db bellard
    int nb = 0;
538 c45886db bellard
539 c45886db bellard
    cmos_data[0x10] = 0;
540 c45886db bellard
    switch (fd0) {
541 c45886db bellard
    case 0:
542 c45886db bellard
        /* 1.44 Mb 3"5 drive */
543 c45886db bellard
        cmos_data[0x10] |= 0x40;
544 c45886db bellard
        break;
545 c45886db bellard
    case 1:
546 c45886db bellard
        /* 2.88 Mb 3"5 drive */
547 c45886db bellard
        cmos_data[0x10] |= 0x60;
548 c45886db bellard
        break;
549 c45886db bellard
    case 2:
550 c45886db bellard
        /* 1.2 Mb 5"5 drive */
551 c45886db bellard
        cmos_data[0x10] |= 0x20;
552 c45886db bellard
        break;
553 c45886db bellard
    }
554 c45886db bellard
    switch (fd1) {
555 c45886db bellard
    case 0:
556 c45886db bellard
        /* 1.44 Mb 3"5 drive */
557 c45886db bellard
        cmos_data[0x10] |= 0x04;
558 c45886db bellard
        break;
559 c45886db bellard
    case 1:
560 c45886db bellard
        /* 2.88 Mb 3"5 drive */
561 c45886db bellard
        cmos_data[0x10] |= 0x06;
562 c45886db bellard
        break;
563 c45886db bellard
    case 2:
564 c45886db bellard
        /* 1.2 Mb 5"5 drive */
565 c45886db bellard
        cmos_data[0x10] |= 0x02;
566 c45886db bellard
        break;
567 c45886db bellard
    }
568 c45886db bellard
    if (fd0 < 3)
569 c45886db bellard
        nb++;
570 c45886db bellard
    if (fd1 < 3)
571 c45886db bellard
        nb++;
572 c45886db bellard
    switch (nb) {
573 c45886db bellard
    case 0:
574 c45886db bellard
        break;
575 c45886db bellard
    case 1:
576 c45886db bellard
        cmos_data[REG_EQUIPMENT_BYTE] |= 0x01; /* 1 drive, ready for boot */
577 c45886db bellard
        break;
578 c45886db bellard
    case 2:
579 c45886db bellard
        cmos_data[REG_EQUIPMENT_BYTE] |= 0x41; /* 2 drives, ready for boot */
580 c45886db bellard
        break;
581 c45886db bellard
    }
582 c45886db bellard
}
583 c45886db bellard
#endif /* TARGET_I386 */
584 c45886db bellard
585 0824d6fc bellard
/***********************************************************/
586 0824d6fc bellard
/* 8259 pic emulation */
587 0824d6fc bellard
588 0824d6fc bellard
typedef struct PicState {
589 0824d6fc bellard
    uint8_t last_irr; /* edge detection */
590 0824d6fc bellard
    uint8_t irr; /* interrupt request register */
591 0824d6fc bellard
    uint8_t imr; /* interrupt mask register */
592 0824d6fc bellard
    uint8_t isr; /* interrupt service register */
593 6e44ba7f bellard
    uint8_t priority_add; /* highest irq priority */
594 0824d6fc bellard
    uint8_t irq_base;
595 0824d6fc bellard
    uint8_t read_reg_select;
596 c45886db bellard
    uint8_t poll;
597 0824d6fc bellard
    uint8_t special_mask;
598 0824d6fc bellard
    uint8_t init_state;
599 0824d6fc bellard
    uint8_t auto_eoi;
600 6e44ba7f bellard
    uint8_t rotate_on_auto_eoi;
601 6e44ba7f bellard
    uint8_t special_fully_nested_mode;
602 0824d6fc bellard
    uint8_t init4; /* true if 4 byte init */
603 0824d6fc bellard
} PicState;
604 0824d6fc bellard
605 0824d6fc bellard
/* 0 is master pic, 1 is slave pic */
606 0824d6fc bellard
PicState pics[2];
607 0824d6fc bellard
int pic_irq_requested;
608 0824d6fc bellard
609 0824d6fc bellard
/* set irq level. If an edge is detected, then the IRR is set to 1 */
610 0824d6fc bellard
static inline void pic_set_irq1(PicState *s, int irq, int level)
611 0824d6fc bellard
{
612 0824d6fc bellard
    int mask;
613 0824d6fc bellard
    mask = 1 << irq;
614 0824d6fc bellard
    if (level) {
615 0824d6fc bellard
        if ((s->last_irr & mask) == 0)
616 0824d6fc bellard
            s->irr |= mask;
617 0824d6fc bellard
        s->last_irr |= mask;
618 0824d6fc bellard
    } else {
619 0824d6fc bellard
        s->last_irr &= ~mask;
620 0824d6fc bellard
    }
621 0824d6fc bellard
}
622 0824d6fc bellard
623 6e44ba7f bellard
/* return the highest priority found in mask (highest = smallest
624 6e44ba7f bellard
   number). Return 8 if no irq */
625 0824d6fc bellard
static inline int get_priority(PicState *s, int mask)
626 0824d6fc bellard
{
627 0824d6fc bellard
    int priority;
628 0824d6fc bellard
    if (mask == 0)
629 6e44ba7f bellard
        return 8;
630 6e44ba7f bellard
    priority = 0;
631 0824d6fc bellard
    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
632 6e44ba7f bellard
        priority++;
633 0824d6fc bellard
    return priority;
634 0824d6fc bellard
}
635 0824d6fc bellard
636 0824d6fc bellard
/* return the pic wanted interrupt. return -1 if none */
637 0824d6fc bellard
static int pic_get_irq(PicState *s)
638 0824d6fc bellard
{
639 0824d6fc bellard
    int mask, cur_priority, priority;
640 0824d6fc bellard
641 0824d6fc bellard
    mask = s->irr & ~s->imr;
642 0824d6fc bellard
    priority = get_priority(s, mask);
643 6e44ba7f bellard
    if (priority == 8)
644 0824d6fc bellard
        return -1;
645 6e44ba7f bellard
    /* compute current priority. If special fully nested mode on the
646 6e44ba7f bellard
       master, the IRQ coming from the slave is not taken into account
647 6e44ba7f bellard
       for the priority computation. */
648 6e44ba7f bellard
    mask = s->isr;
649 6e44ba7f bellard
    if (s->special_fully_nested_mode && s == &pics[0])
650 6e44ba7f bellard
        mask &= ~(1 << 2);
651 6e44ba7f bellard
    cur_priority = get_priority(s, mask);
652 6e44ba7f bellard
    if (priority < cur_priority) {
653 0824d6fc bellard
        /* higher priority found: an irq should be generated */
654 6e44ba7f bellard
        return (priority + s->priority_add) & 7;
655 0824d6fc bellard
    } else {
656 0824d6fc bellard
        return -1;
657 0824d6fc bellard
    }
658 0824d6fc bellard
}
659 0824d6fc bellard
660 c9159e53 bellard
/* raise irq to CPU if necessary. must be called every time the active
661 c9159e53 bellard
   irq may change */
662 c45886db bellard
void pic_update_irq(void)
663 0824d6fc bellard
{
664 0824d6fc bellard
    int irq2, irq;
665 0824d6fc bellard
666 0824d6fc bellard
    /* first look at slave pic */
667 0824d6fc bellard
    irq2 = pic_get_irq(&pics[1]);
668 0824d6fc bellard
    if (irq2 >= 0) {
669 0824d6fc bellard
        /* if irq request by slave pic, signal master PIC */
670 0824d6fc bellard
        pic_set_irq1(&pics[0], 2, 1);
671 0824d6fc bellard
        pic_set_irq1(&pics[0], 2, 0);
672 0824d6fc bellard
    }
673 0824d6fc bellard
    /* look at requested irq */
674 0824d6fc bellard
    irq = pic_get_irq(&pics[0]);
675 0824d6fc bellard
    if (irq >= 0) {
676 0824d6fc bellard
        if (irq == 2) {
677 0824d6fc bellard
            /* from slave pic */
678 0824d6fc bellard
            pic_irq_requested = 8 + irq2;
679 0824d6fc bellard
        } else {
680 0824d6fc bellard
            /* from master pic */
681 0824d6fc bellard
            pic_irq_requested = irq;
682 0824d6fc bellard
        }
683 6e44ba7f bellard
#if defined(DEBUG_PIC)
684 6e44ba7f bellard
        {
685 6e44ba7f bellard
            int i;
686 6e44ba7f bellard
            for(i = 0; i < 2; i++) {
687 6e44ba7f bellard
                printf("pic%d: imr=%x irr=%x padd=%d\n", 
688 6e44ba7f bellard
                       i, pics[i].imr, pics[i].irr, pics[i].priority_add);
689 6e44ba7f bellard
                
690 6e44ba7f bellard
            }
691 6e44ba7f bellard
        }
692 6e44ba7f bellard
        printf("pic: cpu_interrupt req=%d\n", pic_irq_requested);
693 6e44ba7f bellard
#endif
694 c45886db bellard
        cpu_interrupt(global_env, CPU_INTERRUPT_HARD);
695 0824d6fc bellard
    }
696 0824d6fc bellard
}
697 0824d6fc bellard
698 c9159e53 bellard
#ifdef DEBUG_IRQ_LATENCY
699 c9159e53 bellard
int64_t irq_time[16];
700 c9159e53 bellard
int64_t cpu_get_ticks(void);
701 c9159e53 bellard
#endif
702 313aa567 bellard
#if defined(DEBUG_PIC)
703 b118d61e bellard
int irq_level[16];
704 b118d61e bellard
#endif
705 c9159e53 bellard
706 c9159e53 bellard
void pic_set_irq(int irq, int level)
707 c9159e53 bellard
{
708 313aa567 bellard
#if defined(DEBUG_PIC)
709 b118d61e bellard
    if (level != irq_level[irq]) {
710 b118d61e bellard
        printf("pic_set_irq: irq=%d level=%d\n", irq, level);
711 b118d61e bellard
        irq_level[irq] = level;
712 b118d61e bellard
    }
713 b118d61e bellard
#endif
714 c9159e53 bellard
#ifdef DEBUG_IRQ_LATENCY
715 c9159e53 bellard
    if (level) {
716 c9159e53 bellard
        irq_time[irq] = cpu_get_ticks();
717 c9159e53 bellard
    }
718 c9159e53 bellard
#endif
719 c9159e53 bellard
    pic_set_irq1(&pics[irq >> 3], irq & 7, level);
720 c9159e53 bellard
    pic_update_irq();
721 c9159e53 bellard
}
722 c9159e53 bellard
723 6e44ba7f bellard
/* acknowledge interrupt 'irq' */
724 6e44ba7f bellard
static inline void pic_intack(PicState *s, int irq)
725 6e44ba7f bellard
{
726 6e44ba7f bellard
    if (s->auto_eoi) {
727 6e44ba7f bellard
        if (s->rotate_on_auto_eoi)
728 6e44ba7f bellard
            s->priority_add = (irq + 1) & 7;
729 6e44ba7f bellard
    } else {
730 6e44ba7f bellard
        s->isr |= (1 << irq);
731 6e44ba7f bellard
    }
732 6e44ba7f bellard
    s->irr &= ~(1 << irq);
733 6e44ba7f bellard
}
734 6e44ba7f bellard
735 c45886db bellard
int cpu_x86_get_pic_interrupt(CPUState *env)
736 0824d6fc bellard
{
737 0824d6fc bellard
    int irq, irq2, intno;
738 0824d6fc bellard
739 0824d6fc bellard
    /* signal the pic that the irq was acked by the CPU */
740 0824d6fc bellard
    irq = pic_irq_requested;
741 c9159e53 bellard
#ifdef DEBUG_IRQ_LATENCY
742 313aa567 bellard
    printf("IRQ%d latency=%0.3fus\n", 
743 313aa567 bellard
           irq, 
744 313aa567 bellard
           (double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec);
745 c9159e53 bellard
#endif
746 7dea1da4 bellard
#if defined(DEBUG_PIC)
747 b118d61e bellard
    printf("pic_interrupt: irq=%d\n", irq);
748 b118d61e bellard
#endif
749 c9159e53 bellard
750 0824d6fc bellard
    if (irq >= 8) {
751 0824d6fc bellard
        irq2 = irq & 7;
752 6e44ba7f bellard
        pic_intack(&pics[1], irq2);
753 0824d6fc bellard
        irq = 2;
754 0824d6fc bellard
        intno = pics[1].irq_base + irq2;
755 0824d6fc bellard
    } else {
756 0824d6fc bellard
        intno = pics[0].irq_base + irq;
757 0824d6fc bellard
    }
758 6e44ba7f bellard
    pic_intack(&pics[0], irq);
759 0824d6fc bellard
    return intno;
760 0824d6fc bellard
}
761 0824d6fc bellard
762 c45886db bellard
void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
763 0824d6fc bellard
{
764 0824d6fc bellard
    PicState *s;
765 6e44ba7f bellard
    int priority, cmd, irq;
766 0824d6fc bellard
767 b118d61e bellard
#ifdef DEBUG_PIC
768 b118d61e bellard
    printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
769 b118d61e bellard
#endif
770 0824d6fc bellard
    s = &pics[addr >> 7];
771 0824d6fc bellard
    addr &= 1;
772 0824d6fc bellard
    if (addr == 0) {
773 0824d6fc bellard
        if (val & 0x10) {
774 0824d6fc bellard
            /* init */
775 0824d6fc bellard
            memset(s, 0, sizeof(PicState));
776 0824d6fc bellard
            s->init_state = 1;
777 0824d6fc bellard
            s->init4 = val & 1;
778 0824d6fc bellard
            if (val & 0x02)
779 0824d6fc bellard
                hw_error("single mode not supported");
780 0824d6fc bellard
            if (val & 0x08)
781 0824d6fc bellard
                hw_error("level sensitive irq not supported");
782 0824d6fc bellard
        } else if (val & 0x08) {
783 6e44ba7f bellard
            if (val & 0x04)
784 c45886db bellard
                s->poll = 1;
785 0824d6fc bellard
            if (val & 0x02)
786 0824d6fc bellard
                s->read_reg_select = val & 1;
787 0824d6fc bellard
            if (val & 0x40)
788 0824d6fc bellard
                s->special_mask = (val >> 5) & 1;
789 0824d6fc bellard
        } else {
790 6e44ba7f bellard
            cmd = val >> 5;
791 6e44ba7f bellard
            switch(cmd) {
792 6e44ba7f bellard
            case 0:
793 6e44ba7f bellard
            case 4:
794 6e44ba7f bellard
                s->rotate_on_auto_eoi = cmd >> 2;
795 0824d6fc bellard
                break;
796 6e44ba7f bellard
            case 1: /* end of interrupt */
797 6e44ba7f bellard
            case 5:
798 0824d6fc bellard
                priority = get_priority(s, s->isr);
799 6e44ba7f bellard
                if (priority != 8) {
800 6e44ba7f bellard
                    irq = (priority + s->priority_add) & 7;
801 6e44ba7f bellard
                    s->isr &= ~(1 << irq);
802 6e44ba7f bellard
                    if (cmd == 5)
803 6e44ba7f bellard
                        s->priority_add = (irq + 1) & 7;
804 6e44ba7f bellard
                    pic_update_irq();
805 0824d6fc bellard
                }
806 0824d6fc bellard
                break;
807 6e44ba7f bellard
            case 3:
808 6e44ba7f bellard
                irq = val & 7;
809 6e44ba7f bellard
                s->isr &= ~(1 << irq);
810 313aa567 bellard
                pic_update_irq();
811 0824d6fc bellard
                break;
812 6e44ba7f bellard
            case 6:
813 0824d6fc bellard
                s->priority_add = (val + 1) & 7;
814 313aa567 bellard
                pic_update_irq();
815 0824d6fc bellard
                break;
816 6e44ba7f bellard
            case 7:
817 6e44ba7f bellard
                irq = val & 7;
818 6e44ba7f bellard
                s->isr &= ~(1 << irq);
819 6e44ba7f bellard
                s->priority_add = (irq + 1) & 7;
820 313aa567 bellard
                pic_update_irq();
821 0824d6fc bellard
                break;
822 6e44ba7f bellard
            default:
823 6e44ba7f bellard
                /* no operation */
824 6e44ba7f bellard
                break;
825 0824d6fc bellard
            }
826 0824d6fc bellard
        }
827 0824d6fc bellard
    } else {
828 0824d6fc bellard
        switch(s->init_state) {
829 0824d6fc bellard
        case 0:
830 0824d6fc bellard
            /* normal mode */
831 0824d6fc bellard
            s->imr = val;
832 c9159e53 bellard
            pic_update_irq();
833 0824d6fc bellard
            break;
834 0824d6fc bellard
        case 1:
835 0824d6fc bellard
            s->irq_base = val & 0xf8;
836 0824d6fc bellard
            s->init_state = 2;
837 0824d6fc bellard
            break;
838 0824d6fc bellard
        case 2:
839 0824d6fc bellard
            if (s->init4) {
840 0824d6fc bellard
                s->init_state = 3;
841 0824d6fc bellard
            } else {
842 0824d6fc bellard
                s->init_state = 0;
843 0824d6fc bellard
            }
844 0824d6fc bellard
            break;
845 0824d6fc bellard
        case 3:
846 6e44ba7f bellard
            s->special_fully_nested_mode = (val >> 4) & 1;
847 0824d6fc bellard
            s->auto_eoi = (val >> 1) & 1;
848 0824d6fc bellard
            s->init_state = 0;
849 0824d6fc bellard
            break;
850 0824d6fc bellard
        }
851 0824d6fc bellard
    }
852 0824d6fc bellard
}
853 0824d6fc bellard
854 c45886db bellard
static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
855 c45886db bellard
{
856 c45886db bellard
    int ret;
857 c45886db bellard
858 c45886db bellard
    ret = pic_get_irq(s);
859 c45886db bellard
    if (ret >= 0) {
860 c45886db bellard
        if (addr1 >> 7) {
861 c45886db bellard
            pics[0].isr &= ~(1 << 2);
862 c45886db bellard
            pics[0].irr &= ~(1 << 2);
863 c45886db bellard
        }
864 c45886db bellard
        s->irr &= ~(1 << ret);
865 c45886db bellard
        s->isr &= ~(1 << ret);
866 c45886db bellard
        if (addr1 >> 7 || ret != 2)
867 c45886db bellard
            pic_update_irq();
868 c45886db bellard
    } else {
869 c45886db bellard
        ret = 0x07;
870 c45886db bellard
        pic_update_irq();
871 c45886db bellard
    }
872 c45886db bellard
873 c45886db bellard
    return ret;
874 c45886db bellard
}
875 c45886db bellard
876 c45886db bellard
uint32_t pic_ioport_read(CPUState *env, uint32_t addr1)
877 0824d6fc bellard
{
878 0824d6fc bellard
    PicState *s;
879 b118d61e bellard
    unsigned int addr;
880 b118d61e bellard
    int ret;
881 b118d61e bellard
882 b118d61e bellard
    addr = addr1;
883 0824d6fc bellard
    s = &pics[addr >> 7];
884 0824d6fc bellard
    addr &= 1;
885 6e44ba7f bellard
    if (s->poll) {
886 c45886db bellard
        ret = pic_poll_read(s, addr1);
887 c45886db bellard
        s->poll = 0;
888 c45886db bellard
    } else {
889 6e44ba7f bellard
        if (addr == 0) {
890 6e44ba7f bellard
            if (s->read_reg_select)
891 6e44ba7f bellard
                ret = s->isr;
892 6e44ba7f bellard
            else
893 6e44ba7f bellard
                ret = s->irr;
894 6e44ba7f bellard
        } else {
895 6e44ba7f bellard
            ret = s->imr;
896 6e44ba7f bellard
        }
897 c45886db bellard
    }
898 b118d61e bellard
#ifdef DEBUG_PIC
899 b118d61e bellard
    printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
900 b118d61e bellard
#endif
901 b118d61e bellard
    return ret;
902 0824d6fc bellard
}
903 0824d6fc bellard
904 c45886db bellard
/* memory mapped interrupt status */
905 c45886db bellard
uint32_t pic_intack_read(CPUState *env)
906 c45886db bellard
{
907 c45886db bellard
    int ret;
908 c45886db bellard
909 c45886db bellard
    ret = pic_poll_read(&pics[0], 0x00);
910 c45886db bellard
    if (ret == 2)
911 c45886db bellard
        ret = pic_poll_read(&pics[1], 0x80) + 8;
912 c45886db bellard
    /* Prepare for ISR read */
913 c45886db bellard
    pics[0].read_reg_select = 1;
914 c45886db bellard
    
915 c45886db bellard
    return ret;
916 c45886db bellard
}
917 c45886db bellard
918 0824d6fc bellard
void pic_init(void)
919 0824d6fc bellard
{
920 c45886db bellard
#if defined (TARGET_I386) || defined (TARGET_PPC)
921 fc01f7e7 bellard
    register_ioport_write(0x20, 2, pic_ioport_write, 1);
922 fc01f7e7 bellard
    register_ioport_read(0x20, 2, pic_ioport_read, 1);
923 fc01f7e7 bellard
    register_ioport_write(0xa0, 2, pic_ioport_write, 1);
924 fc01f7e7 bellard
    register_ioport_read(0xa0, 2, pic_ioport_read, 1);
925 c45886db bellard
#endif
926 0824d6fc bellard
}
927 0824d6fc bellard
928 0824d6fc bellard
/***********************************************************/
929 0824d6fc bellard
/* 8253 PIT emulation */
930 0824d6fc bellard
931 0824d6fc bellard
#define PIT_FREQ 1193182
932 0824d6fc bellard
933 0824d6fc bellard
#define RW_STATE_LSB 0
934 0824d6fc bellard
#define RW_STATE_MSB 1
935 0824d6fc bellard
#define RW_STATE_WORD0 2
936 0824d6fc bellard
#define RW_STATE_WORD1 3
937 0824d6fc bellard
#define RW_STATE_LATCHED_WORD0 4
938 0824d6fc bellard
#define RW_STATE_LATCHED_WORD1 5
939 0824d6fc bellard
940 0824d6fc bellard
typedef struct PITChannelState {
941 87858c89 bellard
    int count; /* can be 65536 */
942 0824d6fc bellard
    uint16_t latched_count;
943 0824d6fc bellard
    uint8_t rw_state;
944 0824d6fc bellard
    uint8_t mode;
945 0824d6fc bellard
    uint8_t bcd; /* not supported */
946 0824d6fc bellard
    uint8_t gate; /* timer start */
947 0824d6fc bellard
    int64_t count_load_time;
948 87858c89 bellard
    int64_t count_last_edge_check_time;
949 0824d6fc bellard
} PITChannelState;
950 0824d6fc bellard
951 0824d6fc bellard
PITChannelState pit_channels[3];
952 0824d6fc bellard
int speaker_data_on;
953 61a2ad53 bellard
int dummy_refresh_clock;
954 87858c89 bellard
int pit_min_timer_count = 0;
955 0824d6fc bellard
956 34865134 bellard
957 34865134 bellard
#if defined(__powerpc__)
958 34865134 bellard
959 34865134 bellard
static inline uint32_t get_tbl(void) 
960 0824d6fc bellard
{
961 34865134 bellard
    uint32_t tbl;
962 34865134 bellard
    asm volatile("mftb %0" : "=r" (tbl));
963 34865134 bellard
    return tbl;
964 0824d6fc bellard
}
965 0824d6fc bellard
966 34865134 bellard
static inline uint32_t get_tbu(void) 
967 34865134 bellard
{
968 34865134 bellard
        uint32_t tbl;
969 34865134 bellard
        asm volatile("mftbu %0" : "=r" (tbl));
970 34865134 bellard
        return tbl;
971 34865134 bellard
}
972 34865134 bellard
973 34865134 bellard
int64_t cpu_get_real_ticks(void)
974 34865134 bellard
{
975 34865134 bellard
    uint32_t l, h, h1;
976 34865134 bellard
    /* NOTE: we test if wrapping has occurred */
977 34865134 bellard
    do {
978 34865134 bellard
        h = get_tbu();
979 34865134 bellard
        l = get_tbl();
980 34865134 bellard
        h1 = get_tbu();
981 34865134 bellard
    } while (h != h1);
982 34865134 bellard
    return ((int64_t)h << 32) | l;
983 34865134 bellard
}
984 34865134 bellard
985 34865134 bellard
#elif defined(__i386__)
986 34865134 bellard
987 34865134 bellard
int64_t cpu_get_real_ticks(void)
988 0824d6fc bellard
{
989 0824d6fc bellard
    int64_t val;
990 0824d6fc bellard
    asm("rdtsc" : "=A" (val));
991 0824d6fc bellard
    return val;
992 0824d6fc bellard
}
993 0824d6fc bellard
994 34865134 bellard
#else
995 34865134 bellard
#error unsupported CPU
996 34865134 bellard
#endif
997 34865134 bellard
998 34865134 bellard
static int64_t cpu_ticks_offset;
999 34865134 bellard
static int64_t cpu_ticks_last;
1000 34865134 bellard
1001 34865134 bellard
int64_t cpu_get_ticks(void)
1002 34865134 bellard
{
1003 34865134 bellard
    return cpu_get_real_ticks() + cpu_ticks_offset;
1004 34865134 bellard
}
1005 34865134 bellard
1006 34865134 bellard
/* enable cpu_get_ticks() */
1007 34865134 bellard
void cpu_enable_ticks(void)
1008 34865134 bellard
{
1009 34865134 bellard
    cpu_ticks_offset = cpu_ticks_last - cpu_get_real_ticks();
1010 34865134 bellard
}
1011 34865134 bellard
1012 34865134 bellard
/* disable cpu_get_ticks() : the clock is stopped. You must not call
1013 34865134 bellard
   cpu_get_ticks() after that.  */
1014 34865134 bellard
void cpu_disable_ticks(void)
1015 34865134 bellard
{
1016 34865134 bellard
    cpu_ticks_last = cpu_get_ticks();
1017 34865134 bellard
}
1018 34865134 bellard
1019 34865134 bellard
int64_t get_clock(void)
1020 34865134 bellard
{
1021 34865134 bellard
    struct timeval tv;
1022 34865134 bellard
    gettimeofday(&tv, NULL);
1023 34865134 bellard
    return tv.tv_sec * 1000000LL + tv.tv_usec;
1024 34865134 bellard
}
1025 34865134 bellard
1026 0824d6fc bellard
void cpu_calibrate_ticks(void)
1027 0824d6fc bellard
{
1028 0824d6fc bellard
    int64_t usec, ticks;
1029 0824d6fc bellard
1030 0824d6fc bellard
    usec = get_clock();
1031 0824d6fc bellard
    ticks = cpu_get_ticks();
1032 0824d6fc bellard
    usleep(50 * 1000);
1033 0824d6fc bellard
    usec = get_clock() - usec;
1034 0824d6fc bellard
    ticks = cpu_get_ticks() - ticks;
1035 0824d6fc bellard
    ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
1036 0824d6fc bellard
}
1037 0824d6fc bellard
1038 87858c89 bellard
/* compute with 96 bit intermediate result: (a*b)/c */
1039 87858c89 bellard
static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
1040 87858c89 bellard
{
1041 87858c89 bellard
    union {
1042 87858c89 bellard
        uint64_t ll;
1043 87858c89 bellard
        struct {
1044 87858c89 bellard
#ifdef WORDS_BIGENDIAN
1045 87858c89 bellard
            uint32_t high, low;
1046 87858c89 bellard
#else
1047 87858c89 bellard
            uint32_t low, high;
1048 87858c89 bellard
#endif            
1049 87858c89 bellard
        } l;
1050 87858c89 bellard
    } u, res;
1051 87858c89 bellard
    uint64_t rl, rh;
1052 87858c89 bellard
1053 87858c89 bellard
    u.ll = a;
1054 87858c89 bellard
    rl = (uint64_t)u.l.low * (uint64_t)b;
1055 87858c89 bellard
    rh = (uint64_t)u.l.high * (uint64_t)b;
1056 87858c89 bellard
    rh += (rl >> 32);
1057 87858c89 bellard
    res.l.high = rh / c;
1058 87858c89 bellard
    res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
1059 87858c89 bellard
    return res.ll;
1060 87858c89 bellard
}
1061 87858c89 bellard
1062 0824d6fc bellard
static int pit_get_count(PITChannelState *s)
1063 0824d6fc bellard
{
1064 87858c89 bellard
    uint64_t d;
1065 0824d6fc bellard
    int counter;
1066 0824d6fc bellard
1067 87858c89 bellard
    d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
1068 0824d6fc bellard
    switch(s->mode) {
1069 0824d6fc bellard
    case 0:
1070 0824d6fc bellard
    case 1:
1071 0824d6fc bellard
    case 4:
1072 0824d6fc bellard
    case 5:
1073 0824d6fc bellard
        counter = (s->count - d) & 0xffff;
1074 0824d6fc bellard
        break;
1075 c2655080 bellard
    case 3:
1076 c2655080 bellard
        /* XXX: may be incorrect for odd counts */
1077 c2655080 bellard
        counter = s->count - ((2 * d) % s->count);
1078 c2655080 bellard
        break;
1079 0824d6fc bellard
    default:
1080 0824d6fc bellard
        counter = s->count - (d % s->count);
1081 0824d6fc bellard
        break;
1082 0824d6fc bellard
    }
1083 0824d6fc bellard
    return counter;
1084 0824d6fc bellard
}
1085 0824d6fc bellard
1086 0824d6fc bellard
/* get pit output bit */
1087 0824d6fc bellard
static int pit_get_out(PITChannelState *s)
1088 0824d6fc bellard
{
1089 87858c89 bellard
    uint64_t d;
1090 0824d6fc bellard
    int out;
1091 0824d6fc bellard
1092 87858c89 bellard
    d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
1093 0824d6fc bellard
    switch(s->mode) {
1094 0824d6fc bellard
    default:
1095 0824d6fc bellard
    case 0:
1096 0824d6fc bellard
        out = (d >= s->count);
1097 0824d6fc bellard
        break;
1098 0824d6fc bellard
    case 1:
1099 0824d6fc bellard
        out = (d < s->count);
1100 0824d6fc bellard
        break;
1101 0824d6fc bellard
    case 2:
1102 0824d6fc bellard
        if ((d % s->count) == 0 && d != 0)
1103 0824d6fc bellard
            out = 1;
1104 0824d6fc bellard
        else
1105 0824d6fc bellard
            out = 0;
1106 0824d6fc bellard
        break;
1107 0824d6fc bellard
    case 3:
1108 c2655080 bellard
        out = (d % s->count) < ((s->count + 1) >> 1);
1109 0824d6fc bellard
        break;
1110 0824d6fc bellard
    case 4:
1111 0824d6fc bellard
    case 5:
1112 0824d6fc bellard
        out = (d == s->count);
1113 0824d6fc bellard
        break;
1114 0824d6fc bellard
    }
1115 0824d6fc bellard
    return out;
1116 0824d6fc bellard
}
1117 0824d6fc bellard
1118 87858c89 bellard
/* get the number of 0 to 1 transitions we had since we call this
1119 87858c89 bellard
   function */
1120 87858c89 bellard
/* XXX: maybe better to use ticks precision to avoid getting edges
1121 87858c89 bellard
   twice if checks are done at very small intervals */
1122 87858c89 bellard
static int pit_get_out_edges(PITChannelState *s)
1123 87858c89 bellard
{
1124 87858c89 bellard
    uint64_t d1, d2;
1125 87858c89 bellard
    int64_t ticks;
1126 87858c89 bellard
    int ret, v;
1127 87858c89 bellard
1128 87858c89 bellard
    ticks = cpu_get_ticks();
1129 87858c89 bellard
    d1 = muldiv64(s->count_last_edge_check_time - s->count_load_time, 
1130 87858c89 bellard
                 PIT_FREQ, ticks_per_sec);
1131 87858c89 bellard
    d2 = muldiv64(ticks - s->count_load_time, 
1132 87858c89 bellard
                  PIT_FREQ, ticks_per_sec);
1133 87858c89 bellard
    s->count_last_edge_check_time = ticks;
1134 87858c89 bellard
    switch(s->mode) {
1135 87858c89 bellard
    default:
1136 87858c89 bellard
    case 0:
1137 87858c89 bellard
        if (d1 < s->count && d2 >= s->count)
1138 87858c89 bellard
            ret = 1;
1139 87858c89 bellard
        else
1140 87858c89 bellard
            ret = 0;
1141 87858c89 bellard
        break;
1142 87858c89 bellard
    case 1:
1143 87858c89 bellard
        ret = 0;
1144 87858c89 bellard
        break;
1145 87858c89 bellard
    case 2:
1146 87858c89 bellard
        d1 /= s->count;
1147 87858c89 bellard
        d2 /= s->count;
1148 87858c89 bellard
        ret = d2 - d1;
1149 87858c89 bellard
        break;
1150 87858c89 bellard
    case 3:
1151 c2655080 bellard
        v = s->count - ((s->count + 1) >> 1);
1152 87858c89 bellard
        d1 = (d1 + v) / s->count;
1153 87858c89 bellard
        d2 = (d2 + v) / s->count;
1154 87858c89 bellard
        ret = d2 - d1;
1155 87858c89 bellard
        break;
1156 87858c89 bellard
    case 4:
1157 87858c89 bellard
    case 5:
1158 87858c89 bellard
        if (d1 < s->count && d2 >= s->count)
1159 87858c89 bellard
            ret = 1;
1160 87858c89 bellard
        else
1161 87858c89 bellard
            ret = 0;
1162 87858c89 bellard
        break;
1163 87858c89 bellard
    }
1164 87858c89 bellard
    return ret;
1165 87858c89 bellard
}
1166 87858c89 bellard
1167 c2655080 bellard
/* val must be 0 or 1 */
1168 c2655080 bellard
static inline void pit_set_gate(PITChannelState *s, int val)
1169 c2655080 bellard
{
1170 c2655080 bellard
    switch(s->mode) {
1171 c2655080 bellard
    default:
1172 c2655080 bellard
    case 0:
1173 c2655080 bellard
    case 4:
1174 c2655080 bellard
        /* XXX: just disable/enable counting */
1175 c2655080 bellard
        break;
1176 c2655080 bellard
    case 1:
1177 c2655080 bellard
    case 5:
1178 c2655080 bellard
        if (s->gate < val) {
1179 c2655080 bellard
            /* restart counting on rising edge */
1180 c2655080 bellard
            s->count_load_time = cpu_get_ticks();
1181 c2655080 bellard
            s->count_last_edge_check_time = s->count_load_time;
1182 c2655080 bellard
        }
1183 c2655080 bellard
        break;
1184 c2655080 bellard
    case 2:
1185 c2655080 bellard
    case 3:
1186 c2655080 bellard
        if (s->gate < val) {
1187 c2655080 bellard
            /* restart counting on rising edge */
1188 c2655080 bellard
            s->count_load_time = cpu_get_ticks();
1189 c2655080 bellard
            s->count_last_edge_check_time = s->count_load_time;
1190 c2655080 bellard
        }
1191 c2655080 bellard
        /* XXX: disable/enable counting */
1192 c2655080 bellard
        break;
1193 c2655080 bellard
    }
1194 c2655080 bellard
    s->gate = val;
1195 c2655080 bellard
}
1196 c2655080 bellard
1197 87858c89 bellard
static inline void pit_load_count(PITChannelState *s, int val)
1198 87858c89 bellard
{
1199 87858c89 bellard
    if (val == 0)
1200 87858c89 bellard
        val = 0x10000;
1201 87858c89 bellard
    s->count_load_time = cpu_get_ticks();
1202 87858c89 bellard
    s->count_last_edge_check_time = s->count_load_time;
1203 87858c89 bellard
    s->count = val;
1204 87858c89 bellard
    if (s == &pit_channels[0] && val <= pit_min_timer_count) {
1205 87858c89 bellard
        fprintf(stderr, 
1206 bb551faa bellard
                "\nWARNING: qemu: on your system, accurate timer emulation is impossible if its frequency is more than %d Hz. If using a 2.6 guest Linux kernel, you must patch asm/param.h to change HZ from 1000 to 100.\n\n", 
1207 87858c89 bellard
                PIT_FREQ / pit_min_timer_count);
1208 87858c89 bellard
    }
1209 87858c89 bellard
}
1210 87858c89 bellard
1211 c45886db bellard
void pit_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
1212 0824d6fc bellard
{
1213 0824d6fc bellard
    int channel, access;
1214 0824d6fc bellard
    PITChannelState *s;
1215 87858c89 bellard
1216 0824d6fc bellard
    addr &= 3;
1217 0824d6fc bellard
    if (addr == 3) {
1218 0824d6fc bellard
        channel = val >> 6;
1219 0824d6fc bellard
        if (channel == 3)
1220 0824d6fc bellard
            return;
1221 0824d6fc bellard
        s = &pit_channels[channel];
1222 0824d6fc bellard
        access = (val >> 4) & 3;
1223 0824d6fc bellard
        switch(access) {
1224 0824d6fc bellard
        case 0:
1225 0824d6fc bellard
            s->latched_count = pit_get_count(s);
1226 0824d6fc bellard
            s->rw_state = RW_STATE_LATCHED_WORD0;
1227 0824d6fc bellard
            break;
1228 0824d6fc bellard
        default:
1229 87858c89 bellard
            s->mode = (val >> 1) & 7;
1230 87858c89 bellard
            s->bcd = val & 1;
1231 0824d6fc bellard
            s->rw_state = access - 1 +  RW_STATE_LSB;
1232 0824d6fc bellard
            break;
1233 0824d6fc bellard
        }
1234 0824d6fc bellard
    } else {
1235 0824d6fc bellard
        s = &pit_channels[addr];
1236 0824d6fc bellard
        switch(s->rw_state) {
1237 0824d6fc bellard
        case RW_STATE_LSB:
1238 87858c89 bellard
            pit_load_count(s, val);
1239 0824d6fc bellard
            break;
1240 0824d6fc bellard
        case RW_STATE_MSB:
1241 87858c89 bellard
            pit_load_count(s, val << 8);
1242 0824d6fc bellard
            break;
1243 0824d6fc bellard
        case RW_STATE_WORD0:
1244 0824d6fc bellard
        case RW_STATE_WORD1:
1245 0824d6fc bellard
            if (s->rw_state & 1) {
1246 87858c89 bellard
                pit_load_count(s, (s->latched_count & 0xff) | (val << 8));
1247 0824d6fc bellard
            } else {
1248 0824d6fc bellard
                s->latched_count = val;
1249 0824d6fc bellard
            }
1250 0824d6fc bellard
            s->rw_state ^= 1;
1251 0824d6fc bellard
            break;
1252 0824d6fc bellard
        }
1253 0824d6fc bellard
    }
1254 0824d6fc bellard
}
1255 0824d6fc bellard
1256 c45886db bellard
uint32_t pit_ioport_read(CPUState *env, uint32_t addr)
1257 0824d6fc bellard
{
1258 0824d6fc bellard
    int ret, count;
1259 0824d6fc bellard
    PITChannelState *s;
1260 0824d6fc bellard
    
1261 0824d6fc bellard
    addr &= 3;
1262 0824d6fc bellard
    s = &pit_channels[addr];
1263 0824d6fc bellard
    switch(s->rw_state) {
1264 0824d6fc bellard
    case RW_STATE_LSB:
1265 0824d6fc bellard
    case RW_STATE_MSB:
1266 0824d6fc bellard
    case RW_STATE_WORD0:
1267 0824d6fc bellard
    case RW_STATE_WORD1:
1268 0824d6fc bellard
        count = pit_get_count(s);
1269 0824d6fc bellard
        if (s->rw_state & 1)
1270 0824d6fc bellard
            ret = (count >> 8) & 0xff;
1271 0824d6fc bellard
        else
1272 0824d6fc bellard
            ret = count & 0xff;
1273 0824d6fc bellard
        if (s->rw_state & 2)
1274 0824d6fc bellard
            s->rw_state ^= 1;
1275 0824d6fc bellard
        break;
1276 0824d6fc bellard
    default:
1277 0824d6fc bellard
    case RW_STATE_LATCHED_WORD0:
1278 0824d6fc bellard
    case RW_STATE_LATCHED_WORD1:
1279 0824d6fc bellard
        if (s->rw_state & 1)
1280 0824d6fc bellard
            ret = s->latched_count >> 8;
1281 0824d6fc bellard
        else
1282 0824d6fc bellard
            ret = s->latched_count & 0xff;
1283 0824d6fc bellard
        s->rw_state ^= 1;
1284 0824d6fc bellard
        break;
1285 0824d6fc bellard
    }
1286 0824d6fc bellard
    return ret;
1287 0824d6fc bellard
}
1288 0824d6fc bellard
1289 c45886db bellard
#if defined (TARGET_I386)
1290 c45886db bellard
void speaker_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
1291 0824d6fc bellard
{
1292 0824d6fc bellard
    speaker_data_on = (val >> 1) & 1;
1293 c2655080 bellard
    pit_set_gate(&pit_channels[2], val & 1);
1294 0824d6fc bellard
}
1295 0824d6fc bellard
1296 c45886db bellard
uint32_t speaker_ioport_read(CPUState *env, uint32_t addr)
1297 0824d6fc bellard
{
1298 0824d6fc bellard
    int out;
1299 0824d6fc bellard
    out = pit_get_out(&pit_channels[2]);
1300 61a2ad53 bellard
    dummy_refresh_clock ^= 1;
1301 61a2ad53 bellard
    return (speaker_data_on << 1) | pit_channels[2].gate | (out << 5) |
1302 61a2ad53 bellard
      (dummy_refresh_clock << 4);
1303 0824d6fc bellard
}
1304 c45886db bellard
#endif
1305 0824d6fc bellard
1306 0824d6fc bellard
void pit_init(void)
1307 0824d6fc bellard
{
1308 87858c89 bellard
    PITChannelState *s;
1309 87858c89 bellard
    int i;
1310 87858c89 bellard
1311 87858c89 bellard
    cpu_calibrate_ticks();
1312 87858c89 bellard
1313 87858c89 bellard
    for(i = 0;i < 3; i++) {
1314 87858c89 bellard
        s = &pit_channels[i];
1315 87858c89 bellard
        s->mode = 3;
1316 87858c89 bellard
        s->gate = (i != 2);
1317 87858c89 bellard
        pit_load_count(s, 0);
1318 87858c89 bellard
    }
1319 87858c89 bellard
1320 fc01f7e7 bellard
    register_ioport_write(0x40, 4, pit_ioport_write, 1);
1321 fc01f7e7 bellard
    register_ioport_read(0x40, 3, pit_ioport_read, 1);
1322 0824d6fc bellard
1323 c45886db bellard
#if defined (TARGET_I386)
1324 fc01f7e7 bellard
    register_ioport_read(0x61, 1, speaker_ioport_read, 1);
1325 fc01f7e7 bellard
    register_ioport_write(0x61, 1, speaker_ioport_write, 1);
1326 c45886db bellard
#endif
1327 0824d6fc bellard
}
1328 0824d6fc bellard
1329 0824d6fc bellard
/***********************************************************/
1330 0824d6fc bellard
/* serial port emulation */
1331 0824d6fc bellard
1332 0824d6fc bellard
#define UART_IRQ        4
1333 0824d6fc bellard
1334 0824d6fc bellard
#define UART_LCR_DLAB        0x80        /* Divisor latch access bit */
1335 0824d6fc bellard
1336 0824d6fc bellard
#define UART_IER_MSI        0x08        /* Enable Modem status interrupt */
1337 0824d6fc bellard
#define UART_IER_RLSI        0x04        /* Enable receiver line status interrupt */
1338 0824d6fc bellard
#define UART_IER_THRI        0x02        /* Enable Transmitter holding register int. */
1339 0824d6fc bellard
#define UART_IER_RDI        0x01        /* Enable receiver data interrupt */
1340 0824d6fc bellard
1341 0824d6fc bellard
#define UART_IIR_NO_INT        0x01        /* No interrupts pending */
1342 0824d6fc bellard
#define UART_IIR_ID        0x06        /* Mask for the interrupt ID */
1343 0824d6fc bellard
1344 0824d6fc bellard
#define UART_IIR_MSI        0x00        /* Modem status interrupt */
1345 0824d6fc bellard
#define UART_IIR_THRI        0x02        /* Transmitter holding register empty */
1346 0824d6fc bellard
#define UART_IIR_RDI        0x04        /* Receiver data interrupt */
1347 0824d6fc bellard
#define UART_IIR_RLSI        0x06        /* Receiver line status interrupt */
1348 0824d6fc bellard
1349 7dea1da4 bellard
/*
1350 7dea1da4 bellard
 * These are the definitions for the Modem Control Register
1351 7dea1da4 bellard
 */
1352 7dea1da4 bellard
#define UART_MCR_LOOP        0x10        /* Enable loopback test mode */
1353 7dea1da4 bellard
#define UART_MCR_OUT2        0x08        /* Out2 complement */
1354 7dea1da4 bellard
#define UART_MCR_OUT1        0x04        /* Out1 complement */
1355 7dea1da4 bellard
#define UART_MCR_RTS        0x02        /* RTS complement */
1356 7dea1da4 bellard
#define UART_MCR_DTR        0x01        /* DTR complement */
1357 7dea1da4 bellard
1358 7dea1da4 bellard
/*
1359 7dea1da4 bellard
 * These are the definitions for the Modem Status Register
1360 7dea1da4 bellard
 */
1361 7dea1da4 bellard
#define UART_MSR_DCD        0x80        /* Data Carrier Detect */
1362 7dea1da4 bellard
#define UART_MSR_RI        0x40        /* Ring Indicator */
1363 7dea1da4 bellard
#define UART_MSR_DSR        0x20        /* Data Set Ready */
1364 7dea1da4 bellard
#define UART_MSR_CTS        0x10        /* Clear to Send */
1365 7dea1da4 bellard
#define UART_MSR_DDCD        0x08        /* Delta DCD */
1366 7dea1da4 bellard
#define UART_MSR_TERI        0x04        /* Trailing edge ring indicator */
1367 7dea1da4 bellard
#define UART_MSR_DDSR        0x02        /* Delta DSR */
1368 7dea1da4 bellard
#define UART_MSR_DCTS        0x01        /* Delta CTS */
1369 7dea1da4 bellard
#define UART_MSR_ANY_DELTA 0x0F        /* Any of the delta bits! */
1370 7dea1da4 bellard
1371 0824d6fc bellard
#define UART_LSR_TEMT        0x40        /* Transmitter empty */
1372 0824d6fc bellard
#define UART_LSR_THRE        0x20        /* Transmit-hold-register empty */
1373 0824d6fc bellard
#define UART_LSR_BI        0x10        /* Break interrupt indicator */
1374 0824d6fc bellard
#define UART_LSR_FE        0x08        /* Frame error indicator */
1375 0824d6fc bellard
#define UART_LSR_PE        0x04        /* Parity error indicator */
1376 0824d6fc bellard
#define UART_LSR_OE        0x02        /* Overrun error indicator */
1377 0824d6fc bellard
#define UART_LSR_DR        0x01        /* Receiver data ready */
1378 0824d6fc bellard
1379 0824d6fc bellard
typedef struct SerialState {
1380 0824d6fc bellard
    uint8_t divider;
1381 0824d6fc bellard
    uint8_t rbr; /* receive register */
1382 0824d6fc bellard
    uint8_t ier;
1383 0824d6fc bellard
    uint8_t iir; /* read only */
1384 0824d6fc bellard
    uint8_t lcr;
1385 0824d6fc bellard
    uint8_t mcr;
1386 0824d6fc bellard
    uint8_t lsr; /* read only */
1387 0824d6fc bellard
    uint8_t msr;
1388 0824d6fc bellard
    uint8_t scr;
1389 7dea1da4 bellard
    /* NOTE: this hidden state is necessary for tx irq generation as
1390 7dea1da4 bellard
       it can be reset while reading iir */
1391 7dea1da4 bellard
    int thr_ipending;
1392 0824d6fc bellard
} SerialState;
1393 0824d6fc bellard
1394 0824d6fc bellard
SerialState serial_ports[1];
1395 0824d6fc bellard
1396 0824d6fc bellard
void serial_update_irq(void)
1397 0824d6fc bellard
{
1398 0824d6fc bellard
    SerialState *s = &serial_ports[0];
1399 0824d6fc bellard
1400 0824d6fc bellard
    if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
1401 0824d6fc bellard
        s->iir = UART_IIR_RDI;
1402 7dea1da4 bellard
    } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
1403 0824d6fc bellard
        s->iir = UART_IIR_THRI;
1404 0824d6fc bellard
    } else {
1405 0824d6fc bellard
        s->iir = UART_IIR_NO_INT;
1406 0824d6fc bellard
    }
1407 0824d6fc bellard
    if (s->iir != UART_IIR_NO_INT) {
1408 0824d6fc bellard
        pic_set_irq(UART_IRQ, 1);
1409 0824d6fc bellard
    } else {
1410 0824d6fc bellard
        pic_set_irq(UART_IRQ, 0);
1411 0824d6fc bellard
    }
1412 0824d6fc bellard
}
1413 0824d6fc bellard
1414 c45886db bellard
void serial_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
1415 0824d6fc bellard
{
1416 0824d6fc bellard
    SerialState *s = &serial_ports[0];
1417 0824d6fc bellard
    unsigned char ch;
1418 0824d6fc bellard
    int ret;
1419 0824d6fc bellard
    
1420 0824d6fc bellard
    addr &= 7;
1421 7dea1da4 bellard
#ifdef DEBUG_SERIAL
1422 7dea1da4 bellard
    printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
1423 7dea1da4 bellard
#endif
1424 0824d6fc bellard
    switch(addr) {
1425 0824d6fc bellard
    default:
1426 0824d6fc bellard
    case 0:
1427 0824d6fc bellard
        if (s->lcr & UART_LCR_DLAB) {
1428 0824d6fc bellard
            s->divider = (s->divider & 0xff00) | val;
1429 0824d6fc bellard
        } else {
1430 7dea1da4 bellard
            s->thr_ipending = 0;
1431 0824d6fc bellard
            s->lsr &= ~UART_LSR_THRE;
1432 0824d6fc bellard
            serial_update_irq();
1433 0824d6fc bellard
1434 0824d6fc bellard
            ch = val;
1435 0824d6fc bellard
            do {
1436 0824d6fc bellard
                ret = write(1, &ch, 1);
1437 0824d6fc bellard
            } while (ret != 1);
1438 7dea1da4 bellard
            s->thr_ipending = 1;
1439 0824d6fc bellard
            s->lsr |= UART_LSR_THRE;
1440 0824d6fc bellard
            s->lsr |= UART_LSR_TEMT;
1441 0824d6fc bellard
            serial_update_irq();
1442 0824d6fc bellard
        }
1443 0824d6fc bellard
        break;
1444 0824d6fc bellard
    case 1:
1445 0824d6fc bellard
        if (s->lcr & UART_LCR_DLAB) {
1446 0824d6fc bellard
            s->divider = (s->divider & 0x00ff) | (val << 8);
1447 0824d6fc bellard
        } else {
1448 0824d6fc bellard
            s->ier = val;
1449 0824d6fc bellard
            serial_update_irq();
1450 0824d6fc bellard
        }
1451 0824d6fc bellard
        break;
1452 0824d6fc bellard
    case 2:
1453 0824d6fc bellard
        break;
1454 0824d6fc bellard
    case 3:
1455 0824d6fc bellard
        s->lcr = val;
1456 0824d6fc bellard
        break;
1457 0824d6fc bellard
    case 4:
1458 0824d6fc bellard
        s->mcr = val;
1459 0824d6fc bellard
        break;
1460 0824d6fc bellard
    case 5:
1461 0824d6fc bellard
        break;
1462 0824d6fc bellard
    case 6:
1463 0824d6fc bellard
        s->msr = val;
1464 0824d6fc bellard
        break;
1465 0824d6fc bellard
    case 7:
1466 0824d6fc bellard
        s->scr = val;
1467 0824d6fc bellard
        break;
1468 0824d6fc bellard
    }
1469 0824d6fc bellard
}
1470 0824d6fc bellard
1471 c45886db bellard
uint32_t serial_ioport_read(CPUState *env, uint32_t addr)
1472 0824d6fc bellard
{
1473 0824d6fc bellard
    SerialState *s = &serial_ports[0];
1474 0824d6fc bellard
    uint32_t ret;
1475 0824d6fc bellard
1476 0824d6fc bellard
    addr &= 7;
1477 0824d6fc bellard
    switch(addr) {
1478 0824d6fc bellard
    default:
1479 0824d6fc bellard
    case 0:
1480 0824d6fc bellard
        if (s->lcr & UART_LCR_DLAB) {
1481 0824d6fc bellard
            ret = s->divider & 0xff; 
1482 0824d6fc bellard
        } else {
1483 0824d6fc bellard
            ret = s->rbr;
1484 0824d6fc bellard
            s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
1485 0824d6fc bellard
            serial_update_irq();
1486 0824d6fc bellard
        }
1487 0824d6fc bellard
        break;
1488 0824d6fc bellard
    case 1:
1489 0824d6fc bellard
        if (s->lcr & UART_LCR_DLAB) {
1490 0824d6fc bellard
            ret = (s->divider >> 8) & 0xff;
1491 0824d6fc bellard
        } else {
1492 0824d6fc bellard
            ret = s->ier;
1493 0824d6fc bellard
        }
1494 0824d6fc bellard
        break;
1495 0824d6fc bellard
    case 2:
1496 0824d6fc bellard
        ret = s->iir;
1497 7dea1da4 bellard
        /* reset THR pending bit */
1498 7dea1da4 bellard
        if ((ret & 0x7) == UART_IIR_THRI)
1499 7dea1da4 bellard
            s->thr_ipending = 0;
1500 7dea1da4 bellard
        serial_update_irq();
1501 0824d6fc bellard
        break;
1502 0824d6fc bellard
    case 3:
1503 0824d6fc bellard
        ret = s->lcr;
1504 0824d6fc bellard
        break;
1505 0824d6fc bellard
    case 4:
1506 0824d6fc bellard
        ret = s->mcr;
1507 0824d6fc bellard
        break;
1508 0824d6fc bellard
    case 5:
1509 0824d6fc bellard
        ret = s->lsr;
1510 0824d6fc bellard
        break;
1511 0824d6fc bellard
    case 6:
1512 7dea1da4 bellard
        if (s->mcr & UART_MCR_LOOP) {
1513 7dea1da4 bellard
            /* in loopback, the modem output pins are connected to the
1514 7dea1da4 bellard
               inputs */
1515 7dea1da4 bellard
            ret = (s->mcr & 0x0c) << 4;
1516 7dea1da4 bellard
            ret |= (s->mcr & 0x02) << 3;
1517 7dea1da4 bellard
            ret |= (s->mcr & 0x01) << 5;
1518 7dea1da4 bellard
        } else {
1519 7dea1da4 bellard
            ret = s->msr;
1520 7dea1da4 bellard
        }
1521 0824d6fc bellard
        break;
1522 0824d6fc bellard
    case 7:
1523 0824d6fc bellard
        ret = s->scr;
1524 0824d6fc bellard
        break;
1525 0824d6fc bellard
    }
1526 7dea1da4 bellard
#ifdef DEBUG_SERIAL
1527 7dea1da4 bellard
    printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
1528 7dea1da4 bellard
#endif
1529 0824d6fc bellard
    return ret;
1530 0824d6fc bellard
}
1531 0824d6fc bellard
1532 0824d6fc bellard
#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
1533 c45886db bellard
static int term_got_escape, term_command;
1534 c45886db bellard
static unsigned char term_cmd_buf[128];
1535 c45886db bellard
1536 c45886db bellard
typedef struct term_cmd_t {
1537 c45886db bellard
    const unsigned char *name;
1538 c45886db bellard
    void (*handler)(unsigned char *params);
1539 c45886db bellard
} term_cmd_t;
1540 c45886db bellard
1541 c45886db bellard
static void do_change_cdrom (unsigned char *params);
1542 c45886db bellard
static void do_change_fd0 (unsigned char *params);
1543 c45886db bellard
static void do_change_fd1 (unsigned char *params);
1544 c45886db bellard
1545 c45886db bellard
static term_cmd_t term_cmds[] = {
1546 c45886db bellard
    { "changecd", &do_change_cdrom, },
1547 c45886db bellard
    { "changefd0", &do_change_fd0, },
1548 c45886db bellard
    { "changefd1", &do_change_fd1, },
1549 c45886db bellard
    { NULL, NULL, },
1550 c45886db bellard
};
1551 0824d6fc bellard
1552 0824d6fc bellard
void term_print_help(void)
1553 0824d6fc bellard
{
1554 0824d6fc bellard
    printf("\n"
1555 0824d6fc bellard
           "C-a h    print this help\n"
1556 0824d6fc bellard
           "C-a x    exit emulatior\n"
1557 c45886db bellard
           "C-a d    switch on/off debug log\n"
1558 33e3963e bellard
           "C-a s    save disk data back to file (if -snapshot)\n"
1559 0824d6fc bellard
           "C-a b    send break (magic sysrq)\n"
1560 c45886db bellard
           "C-a c    send qemu internal command\n"
1561 0824d6fc bellard
           "C-a C-a  send C-a\n"
1562 0824d6fc bellard
           );
1563 0824d6fc bellard
}
1564 0824d6fc bellard
1565 c45886db bellard
static void do_change_cdrom (unsigned char *params)
1566 c45886db bellard
{
1567 c45886db bellard
    /* Dunno how to do it... */
1568 c45886db bellard
}
1569 c45886db bellard
1570 c45886db bellard
static void do_change_fd (int fd, unsigned char *params)
1571 c45886db bellard
{
1572 c45886db bellard
    unsigned char *name_start, *name_end, *ros;
1573 c45886db bellard
    int ro;
1574 c45886db bellard
1575 c45886db bellard
    for (name_start = params;
1576 c45886db bellard
         isspace(*name_start); name_start++)
1577 c45886db bellard
        continue;
1578 c45886db bellard
    if (*name_start == '\0')
1579 c45886db bellard
        return;
1580 c45886db bellard
    for (name_end = name_start;
1581 c45886db bellard
         !isspace(*name_end) && *name_end != '\0'; name_end++)
1582 c45886db bellard
        continue;
1583 c45886db bellard
    for (ros = name_end + 1; isspace(*ros); ros++)
1584 c45886db bellard
        continue;
1585 c45886db bellard
    if (ros[0] == 'r' && ros[1] == 'o')
1586 c45886db bellard
        ro = 1;
1587 c45886db bellard
    else
1588 c45886db bellard
        ro = 0;
1589 c45886db bellard
    *name_end = '\0';
1590 c45886db bellard
    printf("Change fd %d to %s (%s)\n", fd, name_start, params);
1591 c45886db bellard
    fdctrl_disk_change(fd, name_start, ro);
1592 c45886db bellard
}
1593 c45886db bellard
1594 c45886db bellard
static void do_change_fd0 (unsigned char *params)
1595 c45886db bellard
{
1596 c45886db bellard
    do_change_fd(0, params);
1597 c45886db bellard
}
1598 c45886db bellard
1599 c45886db bellard
static void do_change_fd1 (unsigned char *params)
1600 c45886db bellard
{
1601 c45886db bellard
    do_change_fd(1, params);
1602 c45886db bellard
}
1603 c45886db bellard
1604 c45886db bellard
static void serial_treat_command ()
1605 c45886db bellard
{
1606 c45886db bellard
    unsigned char *cmd_start, *cmd_end;
1607 c45886db bellard
    int i;
1608 c45886db bellard
1609 c45886db bellard
    for (cmd_start = term_cmd_buf; isspace(*cmd_start); cmd_start++)
1610 c45886db bellard
        continue;
1611 c45886db bellard
    for (cmd_end = cmd_start;
1612 c45886db bellard
         !isspace(*cmd_end) && *cmd_end != '\0'; cmd_end++)
1613 c45886db bellard
        continue;
1614 c45886db bellard
    for (i = 0; term_cmds[i].name != NULL; i++) {
1615 c45886db bellard
        if (strlen(term_cmds[i].name) == (cmd_end - cmd_start) &&
1616 c45886db bellard
            memcmp(term_cmds[i].name, cmd_start, cmd_end - cmd_start) == 0) {
1617 c45886db bellard
            (*term_cmds[i].handler)(cmd_end + 1);
1618 c45886db bellard
            return;
1619 c45886db bellard
        }
1620 c45886db bellard
    }
1621 c45886db bellard
    *cmd_end = '\0';
1622 c45886db bellard
    printf("Unknown term command: %s\n", cmd_start);
1623 c45886db bellard
}
1624 c45886db bellard
1625 c45886db bellard
extern FILE *logfile;
1626 c45886db bellard
1627 0824d6fc bellard
/* called when a char is received */
1628 0824d6fc bellard
void serial_received_byte(SerialState *s, int ch)
1629 0824d6fc bellard
{
1630 c45886db bellard
    if (term_command) {
1631 c45886db bellard
        if (ch == '\n' || ch == '\r' || term_command == 127) {
1632 c45886db bellard
            printf("\n");
1633 c45886db bellard
            serial_treat_command();
1634 c45886db bellard
            term_command = 0;
1635 c45886db bellard
        } else {
1636 c45886db bellard
            if (ch == 0x7F || ch == 0x08) {
1637 c45886db bellard
                if (term_command > 1) {
1638 c45886db bellard
                    term_cmd_buf[--term_command - 1] = '\0';
1639 c45886db bellard
                    printf("\r                                               "
1640 c45886db bellard
                           "                               ");
1641 c45886db bellard
                    printf("\r> %s", term_cmd_buf);
1642 c45886db bellard
                }
1643 c45886db bellard
            } else if (ch > 0x1f) {
1644 c45886db bellard
                term_cmd_buf[term_command++ - 1] = ch;
1645 c45886db bellard
                term_cmd_buf[term_command - 1] = '\0';
1646 c45886db bellard
                printf("\r> %s", term_cmd_buf);
1647 c45886db bellard
            }
1648 c45886db bellard
            fflush(stdout);
1649 c45886db bellard
        }
1650 c45886db bellard
    } else if (term_got_escape) {
1651 0824d6fc bellard
        term_got_escape = 0;
1652 0824d6fc bellard
        switch(ch) {
1653 0824d6fc bellard
        case 'h':
1654 0824d6fc bellard
            term_print_help();
1655 0824d6fc bellard
            break;
1656 0824d6fc bellard
        case 'x':
1657 0824d6fc bellard
            exit(0);
1658 0824d6fc bellard
            break;
1659 33e3963e bellard
        case 's': 
1660 33e3963e bellard
            {
1661 33e3963e bellard
                int i;
1662 33e3963e bellard
                for (i = 0; i < MAX_DISKS; i++) {
1663 33e3963e bellard
                    if (bs_table[i])
1664 33e3963e bellard
                        bdrv_commit(bs_table[i]);
1665 33e3963e bellard
                }
1666 33e3963e bellard
            }
1667 33e3963e bellard
            break;
1668 0824d6fc bellard
        case 'b':
1669 0824d6fc bellard
            /* send break */
1670 0824d6fc bellard
            s->rbr = 0;
1671 0824d6fc bellard
            s->lsr |= UART_LSR_BI | UART_LSR_DR;
1672 0824d6fc bellard
            serial_update_irq();
1673 0824d6fc bellard
            break;
1674 c45886db bellard
        case 'c':
1675 c45886db bellard
            printf("> ");
1676 c45886db bellard
            fflush(stdout);
1677 c45886db bellard
            term_command = 1;
1678 07ad1b93 bellard
            break;
1679 6e44ba7f bellard
        case 'd':
1680 6e44ba7f bellard
            cpu_set_log(CPU_LOG_ALL);
1681 6e44ba7f bellard
            break;
1682 0824d6fc bellard
        case TERM_ESCAPE:
1683 0824d6fc bellard
            goto send_char;
1684 0824d6fc bellard
        }
1685 0824d6fc bellard
    } else if (ch == TERM_ESCAPE) {
1686 0824d6fc bellard
        term_got_escape = 1;
1687 0824d6fc bellard
    } else {
1688 0824d6fc bellard
    send_char:
1689 0824d6fc bellard
        s->rbr = ch;
1690 0824d6fc bellard
        s->lsr |= UART_LSR_DR;
1691 0824d6fc bellard
        serial_update_irq();
1692 0824d6fc bellard
    }
1693 0824d6fc bellard
}
1694 0824d6fc bellard
1695 0824d6fc bellard
void serial_init(void)
1696 0824d6fc bellard
{
1697 0824d6fc bellard
    SerialState *s = &serial_ports[0];
1698 0824d6fc bellard
1699 0824d6fc bellard
    s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
1700 7dea1da4 bellard
    s->iir = UART_IIR_NO_INT;
1701 7dea1da4 bellard
    
1702 c45886db bellard
#if defined(TARGET_I386) || defined (TARGET_PPC)
1703 fc01f7e7 bellard
    register_ioport_write(0x3f8, 8, serial_ioport_write, 1);
1704 fc01f7e7 bellard
    register_ioport_read(0x3f8, 8, serial_ioport_read, 1);
1705 c45886db bellard
#endif
1706 0824d6fc bellard
}
1707 0824d6fc bellard
1708 f1510b2c bellard
/***********************************************************/
1709 f1510b2c bellard
/* ne2000 emulation */
1710 f1510b2c bellard
1711 c45886db bellard
#if defined (TARGET_I386)
1712 f1510b2c bellard
#define NE2000_IOPORT   0x300
1713 f1510b2c bellard
#define NE2000_IRQ      9
1714 f1510b2c bellard
1715 f1510b2c bellard
#define MAX_ETH_FRAME_SIZE 1514
1716 f1510b2c bellard
1717 f1510b2c bellard
#define E8390_CMD        0x00  /* The command register (for all pages) */
1718 f1510b2c bellard
/* Page 0 register offsets. */
1719 f1510b2c bellard
#define EN0_CLDALO        0x01        /* Low byte of current local dma addr  RD */
1720 f1510b2c bellard
#define EN0_STARTPG        0x01        /* Starting page of ring bfr WR */
1721 f1510b2c bellard
#define EN0_CLDAHI        0x02        /* High byte of current local dma addr  RD */
1722 f1510b2c bellard
#define EN0_STOPPG        0x02        /* Ending page +1 of ring bfr WR */
1723 f1510b2c bellard
#define EN0_BOUNDARY        0x03        /* Boundary page of ring bfr RD WR */
1724 f1510b2c bellard
#define EN0_TSR                0x04        /* Transmit status reg RD */
1725 f1510b2c bellard
#define EN0_TPSR        0x04        /* Transmit starting page WR */
1726 f1510b2c bellard
#define EN0_NCR                0x05        /* Number of collision reg RD */
1727 f1510b2c bellard
#define EN0_TCNTLO        0x05        /* Low  byte of tx byte count WR */
1728 f1510b2c bellard
#define EN0_FIFO        0x06        /* FIFO RD */
1729 f1510b2c bellard
#define EN0_TCNTHI        0x06        /* High byte of tx byte count WR */
1730 f1510b2c bellard
#define EN0_ISR                0x07        /* Interrupt status reg RD WR */
1731 f1510b2c bellard
#define EN0_CRDALO        0x08        /* low byte of current remote dma address RD */
1732 f1510b2c bellard
#define EN0_RSARLO        0x08        /* Remote start address reg 0 */
1733 f1510b2c bellard
#define EN0_CRDAHI        0x09        /* high byte, current remote dma address RD */
1734 f1510b2c bellard
#define EN0_RSARHI        0x09        /* Remote start address reg 1 */
1735 f1510b2c bellard
#define EN0_RCNTLO        0x0a        /* Remote byte count reg WR */
1736 f1510b2c bellard
#define EN0_RCNTHI        0x0b        /* Remote byte count reg WR */
1737 f1510b2c bellard
#define EN0_RSR                0x0c        /* rx status reg RD */
1738 f1510b2c bellard
#define EN0_RXCR        0x0c        /* RX configuration reg WR */
1739 f1510b2c bellard
#define EN0_TXCR        0x0d        /* TX configuration reg WR */
1740 f1510b2c bellard
#define EN0_COUNTER0        0x0d        /* Rcv alignment error counter RD */
1741 f1510b2c bellard
#define EN0_DCFG        0x0e        /* Data configuration reg WR */
1742 f1510b2c bellard
#define EN0_COUNTER1        0x0e        /* Rcv CRC error counter RD */
1743 f1510b2c bellard
#define EN0_IMR                0x0f        /* Interrupt mask reg WR */
1744 f1510b2c bellard
#define EN0_COUNTER2        0x0f        /* Rcv missed frame error counter RD */
1745 f1510b2c bellard
1746 f1510b2c bellard
#define EN1_PHYS        0x11
1747 f1510b2c bellard
#define EN1_CURPAG      0x17
1748 f1510b2c bellard
#define EN1_MULT        0x18
1749 f1510b2c bellard
1750 f1510b2c bellard
/*  Register accessed at EN_CMD, the 8390 base addr.  */
1751 f1510b2c bellard
#define E8390_STOP        0x01        /* Stop and reset the chip */
1752 f1510b2c bellard
#define E8390_START        0x02        /* Start the chip, clear reset */
1753 f1510b2c bellard
#define E8390_TRANS        0x04        /* Transmit a frame */
1754 f1510b2c bellard
#define E8390_RREAD        0x08        /* Remote read */
1755 f1510b2c bellard
#define E8390_RWRITE        0x10        /* Remote write  */
1756 f1510b2c bellard
#define E8390_NODMA        0x20        /* Remote DMA */
1757 f1510b2c bellard
#define E8390_PAGE0        0x00        /* Select page chip registers */
1758 f1510b2c bellard
#define E8390_PAGE1        0x40        /* using the two high-order bits */
1759 f1510b2c bellard
#define E8390_PAGE2        0x80        /* Page 3 is invalid. */
1760 f1510b2c bellard
1761 f1510b2c bellard
/* Bits in EN0_ISR - Interrupt status register */
1762 f1510b2c bellard
#define ENISR_RX        0x01        /* Receiver, no error */
1763 f1510b2c bellard
#define ENISR_TX        0x02        /* Transmitter, no error */
1764 f1510b2c bellard
#define ENISR_RX_ERR        0x04        /* Receiver, with error */
1765 f1510b2c bellard
#define ENISR_TX_ERR        0x08        /* Transmitter, with error */
1766 f1510b2c bellard
#define ENISR_OVER        0x10        /* Receiver overwrote the ring */
1767 f1510b2c bellard
#define ENISR_COUNTERS        0x20        /* Counters need emptying */
1768 f1510b2c bellard
#define ENISR_RDC        0x40        /* remote dma complete */
1769 f1510b2c bellard
#define ENISR_RESET        0x80        /* Reset completed */
1770 f1510b2c bellard
#define ENISR_ALL        0x3f        /* Interrupts we will enable */
1771 f1510b2c bellard
1772 f1510b2c bellard
/* Bits in received packet status byte and EN0_RSR*/
1773 f1510b2c bellard
#define ENRSR_RXOK        0x01        /* Received a good packet */
1774 f1510b2c bellard
#define ENRSR_CRC        0x02        /* CRC error */
1775 f1510b2c bellard
#define ENRSR_FAE        0x04        /* frame alignment error */
1776 f1510b2c bellard
#define ENRSR_FO        0x08        /* FIFO overrun */
1777 f1510b2c bellard
#define ENRSR_MPA        0x10        /* missed pkt */
1778 f1510b2c bellard
#define ENRSR_PHY        0x20        /* physical/multicast address */
1779 f1510b2c bellard
#define ENRSR_DIS        0x40        /* receiver disable. set in monitor mode */
1780 f1510b2c bellard
#define ENRSR_DEF        0x80        /* deferring */
1781 f1510b2c bellard
1782 f1510b2c bellard
/* Transmitted packet status, EN0_TSR. */
1783 f1510b2c bellard
#define ENTSR_PTX 0x01        /* Packet transmitted without error */
1784 f1510b2c bellard
#define ENTSR_ND  0x02        /* The transmit wasn't deferred. */
1785 f1510b2c bellard
#define ENTSR_COL 0x04        /* The transmit collided at least once. */
1786 f1510b2c bellard
#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
1787 f1510b2c bellard
#define ENTSR_CRS 0x10        /* The carrier sense was lost. */
1788 f1510b2c bellard
#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
1789 f1510b2c bellard
#define ENTSR_CDH 0x40        /* The collision detect "heartbeat" signal was lost. */
1790 f1510b2c bellard
#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
1791 f1510b2c bellard
1792 f1510b2c bellard
#define NE2000_MEM_SIZE 32768
1793 f1510b2c bellard
1794 f1510b2c bellard
typedef struct NE2000State {
1795 f1510b2c bellard
    uint8_t cmd;
1796 f1510b2c bellard
    uint32_t start;
1797 f1510b2c bellard
    uint32_t stop;
1798 f1510b2c bellard
    uint8_t boundary;
1799 f1510b2c bellard
    uint8_t tsr;
1800 f1510b2c bellard
    uint8_t tpsr;
1801 f1510b2c bellard
    uint16_t tcnt;
1802 f1510b2c bellard
    uint16_t rcnt;
1803 f1510b2c bellard
    uint32_t rsar;
1804 f1510b2c bellard
    uint8_t isr;
1805 f1510b2c bellard
    uint8_t dcfg;
1806 f1510b2c bellard
    uint8_t imr;
1807 f1510b2c bellard
    uint8_t phys[6]; /* mac address */
1808 f1510b2c bellard
    uint8_t curpag;
1809 f1510b2c bellard
    uint8_t mult[8]; /* multicast mask array */
1810 f1510b2c bellard
    uint8_t mem[NE2000_MEM_SIZE];
1811 f1510b2c bellard
} NE2000State;
1812 f1510b2c bellard
1813 f1510b2c bellard
NE2000State ne2000_state;
1814 f1510b2c bellard
int net_fd = -1;
1815 f1510b2c bellard
char network_script[1024];
1816 f1510b2c bellard
1817 f1510b2c bellard
void ne2000_reset(void)
1818 f1510b2c bellard
{
1819 f1510b2c bellard
    NE2000State *s = &ne2000_state;
1820 f1510b2c bellard
    int i;
1821 f1510b2c bellard
1822 f1510b2c bellard
    s->isr = ENISR_RESET;
1823 f1510b2c bellard
    s->mem[0] = 0x52;
1824 f1510b2c bellard
    s->mem[1] = 0x54;
1825 f1510b2c bellard
    s->mem[2] = 0x00;
1826 f1510b2c bellard
    s->mem[3] = 0x12;
1827 f1510b2c bellard
    s->mem[4] = 0x34;
1828 f1510b2c bellard
    s->mem[5] = 0x56;
1829 f1510b2c bellard
    s->mem[14] = 0x57;
1830 f1510b2c bellard
    s->mem[15] = 0x57;
1831 f1510b2c bellard
1832 f1510b2c bellard
    /* duplicate prom data */
1833 f1510b2c bellard
    for(i = 15;i >= 0; i--) {
1834 f1510b2c bellard
        s->mem[2 * i] = s->mem[i];
1835 f1510b2c bellard
        s->mem[2 * i + 1] = s->mem[i];
1836 f1510b2c bellard
    }
1837 f1510b2c bellard
}
1838 f1510b2c bellard
1839 f1510b2c bellard
void ne2000_update_irq(NE2000State *s)
1840 f1510b2c bellard
{
1841 f1510b2c bellard
    int isr;
1842 f1510b2c bellard
    isr = s->isr & s->imr;
1843 f1510b2c bellard
    if (isr)
1844 f1510b2c bellard
        pic_set_irq(NE2000_IRQ, 1);
1845 f1510b2c bellard
    else
1846 f1510b2c bellard
        pic_set_irq(NE2000_IRQ, 0);
1847 f1510b2c bellard
}
1848 f1510b2c bellard
1849 f1510b2c bellard
int net_init(void)
1850 f1510b2c bellard
{
1851 f1510b2c bellard
    struct ifreq ifr;
1852 f1510b2c bellard
    int fd, ret, pid, status;
1853 f1510b2c bellard
    
1854 f1510b2c bellard
    fd = open("/dev/net/tun", O_RDWR);
1855 f1510b2c bellard
    if (fd < 0) {
1856 f1510b2c bellard
        fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
1857 f1510b2c bellard
        return -1;
1858 f1510b2c bellard
    }
1859 f1510b2c bellard
    memset(&ifr, 0, sizeof(ifr));
1860 f1510b2c bellard
    ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
1861 f1510b2c bellard
    pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
1862 f1510b2c bellard
    ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
1863 f1510b2c bellard
    if (ret != 0) {
1864 f1510b2c bellard
        fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
1865 f1510b2c bellard
        close(fd);
1866 f1510b2c bellard
        return -1;
1867 f1510b2c bellard
    }
1868 fc01f7e7 bellard
    printf("Connected to host network interface: %s\n", ifr.ifr_name);
1869 f1510b2c bellard
    fcntl(fd, F_SETFL, O_NONBLOCK);
1870 f1510b2c bellard
    net_fd = fd;
1871 f1510b2c bellard
1872 f1510b2c bellard
    /* try to launch network init script */
1873 f1510b2c bellard
    pid = fork();
1874 f1510b2c bellard
    if (pid >= 0) {
1875 f1510b2c bellard
        if (pid == 0) {
1876 f1510b2c bellard
            execl(network_script, network_script, ifr.ifr_name, NULL);
1877 f1510b2c bellard
            exit(1);
1878 f1510b2c bellard
        }
1879 f1510b2c bellard
        while (waitpid(pid, &status, 0) != pid);
1880 f1510b2c bellard
        if (!WIFEXITED(status) ||
1881 f1510b2c bellard
            WEXITSTATUS(status) != 0) {
1882 f1510b2c bellard
            fprintf(stderr, "%s: could not launch network script for '%s'\n",
1883 f1510b2c bellard
                    network_script, ifr.ifr_name);
1884 f1510b2c bellard
        }
1885 f1510b2c bellard
    }
1886 f1510b2c bellard
    return 0;
1887 f1510b2c bellard
}
1888 f1510b2c bellard
1889 f1510b2c bellard
void net_send_packet(NE2000State *s, const uint8_t *buf, int size)
1890 f1510b2c bellard
{
1891 f1510b2c bellard
#ifdef DEBUG_NE2000
1892 f1510b2c bellard
    printf("NE2000: sending packet size=%d\n", size);
1893 f1510b2c bellard
#endif
1894 f1510b2c bellard
    write(net_fd, buf, size);
1895 f1510b2c bellard
}
1896 f1510b2c bellard
1897 f1510b2c bellard
/* return true if the NE2000 can receive more data */
1898 f1510b2c bellard
int ne2000_can_receive(NE2000State *s)
1899 f1510b2c bellard
{
1900 f1510b2c bellard
    int avail, index, boundary;
1901 f1510b2c bellard
    
1902 f1510b2c bellard
    if (s->cmd & E8390_STOP)
1903 f1510b2c bellard
        return 0;
1904 f1510b2c bellard
    index = s->curpag << 8;
1905 f1510b2c bellard
    boundary = s->boundary << 8;
1906 f1510b2c bellard
    if (index < boundary)
1907 f1510b2c bellard
        avail = boundary - index;
1908 f1510b2c bellard
    else
1909 f1510b2c bellard
        avail = (s->stop - s->start) - (index - boundary);
1910 f1510b2c bellard
    if (avail < (MAX_ETH_FRAME_SIZE + 4))
1911 f1510b2c bellard
        return 0;
1912 f1510b2c bellard
    return 1;
1913 f1510b2c bellard
}
1914 f1510b2c bellard
1915 f1510b2c bellard
void ne2000_receive(NE2000State *s, uint8_t *buf, int size)
1916 f1510b2c bellard
{
1917 f1510b2c bellard
    uint8_t *p;
1918 f1510b2c bellard
    int total_len, next, avail, len, index;
1919 f1510b2c bellard
1920 f1510b2c bellard
#if defined(DEBUG_NE2000)
1921 f1510b2c bellard
    printf("NE2000: received len=%d\n", size);
1922 f1510b2c bellard
#endif
1923 f1510b2c bellard
1924 f1510b2c bellard
    index = s->curpag << 8;
1925 f1510b2c bellard
    /* 4 bytes for header */
1926 f1510b2c bellard
    total_len = size + 4;
1927 f1510b2c bellard
    /* address for next packet (4 bytes for CRC) */
1928 f1510b2c bellard
    next = index + ((total_len + 4 + 255) & ~0xff);
1929 f1510b2c bellard
    if (next >= s->stop)
1930 f1510b2c bellard
        next -= (s->stop - s->start);
1931 f1510b2c bellard
    /* prepare packet header */
1932 f1510b2c bellard
    p = s->mem + index;
1933 f1510b2c bellard
    p[0] = ENRSR_RXOK; /* receive status */
1934 f1510b2c bellard
    p[1] = next >> 8;
1935 f1510b2c bellard
    p[2] = total_len;
1936 f1510b2c bellard
    p[3] = total_len >> 8;
1937 f1510b2c bellard
    index += 4;
1938 f1510b2c bellard
1939 f1510b2c bellard
    /* write packet data */
1940 f1510b2c bellard
    while (size > 0) {
1941 f1510b2c bellard
        avail = s->stop - index;
1942 f1510b2c bellard
        len = size;
1943 f1510b2c bellard
        if (len > avail)
1944 f1510b2c bellard
            len = avail;
1945 f1510b2c bellard
        memcpy(s->mem + index, buf, len);
1946 f1510b2c bellard
        buf += len;
1947 f1510b2c bellard
        index += len;
1948 f1510b2c bellard
        if (index == s->stop)
1949 f1510b2c bellard
            index = s->start;
1950 f1510b2c bellard
        size -= len;
1951 f1510b2c bellard
    }
1952 f1510b2c bellard
    s->curpag = next >> 8;
1953 f1510b2c bellard
    
1954 f1510b2c bellard
    /* now we can signal we have receive something */
1955 f1510b2c bellard
    s->isr |= ENISR_RX;
1956 f1510b2c bellard
    ne2000_update_irq(s);
1957 f1510b2c bellard
}
1958 f1510b2c bellard
1959 c45886db bellard
void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
1960 f1510b2c bellard
{
1961 f1510b2c bellard
    NE2000State *s = &ne2000_state;
1962 f1510b2c bellard
    int offset, page;
1963 f1510b2c bellard
1964 f1510b2c bellard
    addr &= 0xf;
1965 f1510b2c bellard
#ifdef DEBUG_NE2000
1966 f1510b2c bellard
    printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
1967 f1510b2c bellard
#endif
1968 f1510b2c bellard
    if (addr == E8390_CMD) {
1969 f1510b2c bellard
        /* control register */
1970 f1510b2c bellard
        s->cmd = val;
1971 f1510b2c bellard
        if (val & E8390_START) {
1972 f1510b2c bellard
            /* test specific case: zero length transfert */
1973 f1510b2c bellard
            if ((val & (E8390_RREAD | E8390_RWRITE)) &&
1974 f1510b2c bellard
                s->rcnt == 0) {
1975 f1510b2c bellard
                s->isr |= ENISR_RDC;
1976 f1510b2c bellard
                ne2000_update_irq(s);
1977 f1510b2c bellard
            }
1978 f1510b2c bellard
            if (val & E8390_TRANS) {
1979 f1510b2c bellard
                net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
1980 f1510b2c bellard
                /* signal end of transfert */
1981 f1510b2c bellard
                s->tsr = ENTSR_PTX;
1982 f1510b2c bellard
                s->isr |= ENISR_TX;
1983 f1510b2c bellard
                ne2000_update_irq(s);
1984 f1510b2c bellard
            }
1985 f1510b2c bellard
        }
1986 f1510b2c bellard
    } else {
1987 f1510b2c bellard
        page = s->cmd >> 6;
1988 f1510b2c bellard
        offset = addr | (page << 4);
1989 f1510b2c bellard
        switch(offset) {
1990 f1510b2c bellard
        case EN0_STARTPG:
1991 f1510b2c bellard
            s->start = val << 8;
1992 f1510b2c bellard
            break;
1993 f1510b2c bellard
        case EN0_STOPPG:
1994 f1510b2c bellard
            s->stop = val << 8;
1995 f1510b2c bellard
            break;
1996 f1510b2c bellard
        case EN0_BOUNDARY:
1997 f1510b2c bellard
            s->boundary = val;
1998 f1510b2c bellard
            break;
1999 f1510b2c bellard
        case EN0_IMR:
2000 f1510b2c bellard
            s->imr = val;
2001 f1510b2c bellard
            ne2000_update_irq(s);
2002 f1510b2c bellard
            break;
2003 f1510b2c bellard
        case EN0_TPSR:
2004 f1510b2c bellard
            s->tpsr = val;
2005 f1510b2c bellard
            break;
2006 f1510b2c bellard
        case EN0_TCNTLO:
2007 f1510b2c bellard
            s->tcnt = (s->tcnt & 0xff00) | val;
2008 f1510b2c bellard
            break;
2009 f1510b2c bellard
        case EN0_TCNTHI:
2010 f1510b2c bellard
            s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
2011 f1510b2c bellard
            break;
2012 f1510b2c bellard
        case EN0_RSARLO:
2013 f1510b2c bellard
            s->rsar = (s->rsar & 0xff00) | val;
2014 f1510b2c bellard
            break;
2015 f1510b2c bellard
        case EN0_RSARHI:
2016 f1510b2c bellard
            s->rsar = (s->rsar & 0x00ff) | (val << 8);
2017 f1510b2c bellard
            break;
2018 f1510b2c bellard
        case EN0_RCNTLO:
2019 f1510b2c bellard
            s->rcnt = (s->rcnt & 0xff00) | val;
2020 f1510b2c bellard
            break;
2021 f1510b2c bellard
        case EN0_RCNTHI:
2022 f1510b2c bellard
            s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
2023 f1510b2c bellard
            break;
2024 f1510b2c bellard
        case EN0_DCFG:
2025 f1510b2c bellard
            s->dcfg = val;
2026 f1510b2c bellard
            break;
2027 f1510b2c bellard
        case EN0_ISR:
2028 f1510b2c bellard
            s->isr &= ~val;
2029 f1510b2c bellard
            ne2000_update_irq(s);
2030 f1510b2c bellard
            break;
2031 f1510b2c bellard
        case EN1_PHYS ... EN1_PHYS + 5:
2032 f1510b2c bellard
            s->phys[offset - EN1_PHYS] = val;
2033 f1510b2c bellard
            break;
2034 f1510b2c bellard
        case EN1_CURPAG:
2035 f1510b2c bellard
            s->curpag = val;
2036 f1510b2c bellard
            break;
2037 f1510b2c bellard
        case EN1_MULT ... EN1_MULT + 7:
2038 f1510b2c bellard
            s->mult[offset - EN1_MULT] = val;
2039 f1510b2c bellard
            break;
2040 f1510b2c bellard
        }
2041 f1510b2c bellard
    }
2042 f1510b2c bellard
}
2043 f1510b2c bellard
2044 c45886db bellard
uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr)
2045 f1510b2c bellard
{
2046 f1510b2c bellard
    NE2000State *s = &ne2000_state;
2047 f1510b2c bellard
    int offset, page, ret;
2048 f1510b2c bellard
2049 f1510b2c bellard
    addr &= 0xf;
2050 f1510b2c bellard
    if (addr == E8390_CMD) {
2051 f1510b2c bellard
        ret = s->cmd;
2052 f1510b2c bellard
    } else {
2053 f1510b2c bellard
        page = s->cmd >> 6;
2054 f1510b2c bellard
        offset = addr | (page << 4);
2055 f1510b2c bellard
        switch(offset) {
2056 f1510b2c bellard
        case EN0_TSR:
2057 f1510b2c bellard
            ret = s->tsr;
2058 f1510b2c bellard
            break;
2059 f1510b2c bellard
        case EN0_BOUNDARY:
2060 f1510b2c bellard
            ret = s->boundary;
2061 f1510b2c bellard
            break;
2062 f1510b2c bellard
        case EN0_ISR:
2063 f1510b2c bellard
            ret = s->isr;
2064 f1510b2c bellard
            break;
2065 f1510b2c bellard
        case EN1_PHYS ... EN1_PHYS + 5:
2066 f1510b2c bellard
            ret = s->phys[offset - EN1_PHYS];
2067 f1510b2c bellard
            break;
2068 f1510b2c bellard
        case EN1_CURPAG:
2069 f1510b2c bellard
            ret = s->curpag;
2070 f1510b2c bellard
            break;
2071 f1510b2c bellard
        case EN1_MULT ... EN1_MULT + 7:
2072 f1510b2c bellard
            ret = s->mult[offset - EN1_MULT];
2073 f1510b2c bellard
            break;
2074 f1510b2c bellard
        default:
2075 f1510b2c bellard
            ret = 0x00;
2076 f1510b2c bellard
            break;
2077 f1510b2c bellard
        }
2078 f1510b2c bellard
    }
2079 f1510b2c bellard
#ifdef DEBUG_NE2000
2080 f1510b2c bellard
    printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
2081 f1510b2c bellard
#endif
2082 f1510b2c bellard
    return ret;
2083 f1510b2c bellard
}
2084 f1510b2c bellard
2085 c45886db bellard
void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
2086 f1510b2c bellard
{
2087 f1510b2c bellard
    NE2000State *s = &ne2000_state;
2088 f1510b2c bellard
    uint8_t *p;
2089 f1510b2c bellard
2090 f1510b2c bellard
#ifdef DEBUG_NE2000
2091 f1510b2c bellard
    printf("NE2000: asic write val=0x%04x\n", val);
2092 f1510b2c bellard
#endif
2093 f1510b2c bellard
    p = s->mem + s->rsar;
2094 f1510b2c bellard
    if (s->dcfg & 0x01) {
2095 f1510b2c bellard
        /* 16 bit access */
2096 f1510b2c bellard
        p[0] = val;
2097 f1510b2c bellard
        p[1] = val >> 8;
2098 f1510b2c bellard
        s->rsar += 2;
2099 f1510b2c bellard
        s->rcnt -= 2;
2100 f1510b2c bellard
    } else {
2101 f1510b2c bellard
        /* 8 bit access */
2102 f1510b2c bellard
        p[0] = val;
2103 f1510b2c bellard
        s->rsar++;
2104 f1510b2c bellard
        s->rcnt--;
2105 f1510b2c bellard
    }
2106 f1510b2c bellard
    /* wrap */
2107 f1510b2c bellard
    if (s->rsar == s->stop)
2108 f1510b2c bellard
        s->rsar = s->start;
2109 f1510b2c bellard
    if (s->rcnt == 0) {
2110 f1510b2c bellard
        /* signal end of transfert */
2111 f1510b2c bellard
        s->isr |= ENISR_RDC;
2112 f1510b2c bellard
        ne2000_update_irq(s);
2113 f1510b2c bellard
    }
2114 f1510b2c bellard
}
2115 f1510b2c bellard
2116 c45886db bellard
uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr)
2117 f1510b2c bellard
{
2118 f1510b2c bellard
    NE2000State *s = &ne2000_state;
2119 f1510b2c bellard
    uint8_t *p;
2120 f1510b2c bellard
    int ret;
2121 f1510b2c bellard
2122 f1510b2c bellard
    p = s->mem + s->rsar;
2123 f1510b2c bellard
    if (s->dcfg & 0x01) {
2124 f1510b2c bellard
        /* 16 bit access */
2125 f1510b2c bellard
        ret = p[0] | (p[1] << 8);
2126 f1510b2c bellard
        s->rsar += 2;
2127 f1510b2c bellard
        s->rcnt -= 2;
2128 f1510b2c bellard
    } else {
2129 f1510b2c bellard
        /* 8 bit access */
2130 f1510b2c bellard
        ret = p[0];
2131 f1510b2c bellard
        s->rsar++;
2132 f1510b2c bellard
        s->rcnt--;
2133 f1510b2c bellard
    }
2134 f1510b2c bellard
    /* wrap */
2135 f1510b2c bellard
    if (s->rsar == s->stop)
2136 f1510b2c bellard
        s->rsar = s->start;
2137 f1510b2c bellard
    if (s->rcnt == 0) {
2138 f1510b2c bellard
        /* signal end of transfert */
2139 f1510b2c bellard
        s->isr |= ENISR_RDC;
2140 f1510b2c bellard
        ne2000_update_irq(s);
2141 f1510b2c bellard
    }
2142 f1510b2c bellard
#ifdef DEBUG_NE2000
2143 f1510b2c bellard
    printf("NE2000: asic read val=0x%04x\n", ret);
2144 f1510b2c bellard
#endif
2145 f1510b2c bellard
    return ret;
2146 f1510b2c bellard
}
2147 f1510b2c bellard
2148 c45886db bellard
void ne2000_reset_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
2149 f1510b2c bellard
{
2150 f1510b2c bellard
    /* nothing to do (end of reset pulse) */
2151 f1510b2c bellard
}
2152 f1510b2c bellard
2153 c45886db bellard
uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr)
2154 f1510b2c bellard
{
2155 f1510b2c bellard
    ne2000_reset();
2156 f1510b2c bellard
    return 0;
2157 f1510b2c bellard
}
2158 f1510b2c bellard
2159 f1510b2c bellard
void ne2000_init(void)
2160 f1510b2c bellard
{
2161 fc01f7e7 bellard
    register_ioport_write(NE2000_IOPORT, 16, ne2000_ioport_write, 1);
2162 fc01f7e7 bellard
    register_ioport_read(NE2000_IOPORT, 16, ne2000_ioport_read, 1);
2163 f1510b2c bellard
2164 fc01f7e7 bellard
    register_ioport_write(NE2000_IOPORT + 0x10, 1, ne2000_asic_ioport_write, 1);
2165 fc01f7e7 bellard
    register_ioport_read(NE2000_IOPORT + 0x10, 1, ne2000_asic_ioport_read, 1);
2166 fc01f7e7 bellard
    register_ioport_write(NE2000_IOPORT + 0x10, 2, ne2000_asic_ioport_write, 2);
2167 fc01f7e7 bellard
    register_ioport_read(NE2000_IOPORT + 0x10, 2, ne2000_asic_ioport_read, 2);
2168 f1510b2c bellard
2169 fc01f7e7 bellard
    register_ioport_write(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_write, 1);
2170 fc01f7e7 bellard
    register_ioport_read(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_read, 1);
2171 f1510b2c bellard
    ne2000_reset();
2172 f1510b2c bellard
}
2173 c45886db bellard
#endif
2174 c45886db bellard
2175 c45886db bellard
/***********************************************************/
2176 c45886db bellard
/* PC floppy disk controler emulation glue */
2177 c45886db bellard
#define PC_FDC_DMA  0x2
2178 c45886db bellard
#define PC_FDC_IRQ  0x6
2179 c45886db bellard
#define PC_FDC_BASE 0x3F0
2180 c45886db bellard
2181 c45886db bellard
static void fdctrl_register (unsigned char **disknames, int ro,
2182 c45886db bellard
                             char boot_device)
2183 c45886db bellard
{
2184 c45886db bellard
    int i;
2185 c45886db bellard
2186 c45886db bellard
    fdctrl_init(PC_FDC_IRQ, PC_FDC_DMA, 0, PC_FDC_BASE, boot_device);
2187 c45886db bellard
    for (i = 0; i < MAX_FD; i++) {
2188 c45886db bellard
        if (disknames[i] != NULL)
2189 c45886db bellard
            fdctrl_disk_change(i, disknames[i], ro);
2190 c45886db bellard
    }
2191 c45886db bellard
}
2192 f1510b2c bellard
2193 f1510b2c bellard
/***********************************************************/
2194 330d0414 bellard
/* keyboard emulation */
2195 330d0414 bellard
2196 330d0414 bellard
/*        Keyboard Controller Commands */
2197 330d0414 bellard
#define KBD_CCMD_READ_MODE        0x20        /* Read mode bits */
2198 330d0414 bellard
#define KBD_CCMD_WRITE_MODE        0x60        /* Write mode bits */
2199 330d0414 bellard
#define KBD_CCMD_GET_VERSION        0xA1        /* Get controller version */
2200 330d0414 bellard
#define KBD_CCMD_MOUSE_DISABLE        0xA7        /* Disable mouse interface */
2201 330d0414 bellard
#define KBD_CCMD_MOUSE_ENABLE        0xA8        /* Enable mouse interface */
2202 330d0414 bellard
#define KBD_CCMD_TEST_MOUSE        0xA9        /* Mouse interface test */
2203 330d0414 bellard
#define KBD_CCMD_SELF_TEST        0xAA        /* Controller self test */
2204 330d0414 bellard
#define KBD_CCMD_KBD_TEST        0xAB        /* Keyboard interface test */
2205 330d0414 bellard
#define KBD_CCMD_KBD_DISABLE        0xAD        /* Keyboard interface disable */
2206 330d0414 bellard
#define KBD_CCMD_KBD_ENABLE        0xAE        /* Keyboard interface enable */
2207 330d0414 bellard
#define KBD_CCMD_READ_INPORT    0xC0    /* read input port */
2208 330d0414 bellard
#define KBD_CCMD_READ_OUTPORT        0xD0    /* read output port */
2209 330d0414 bellard
#define KBD_CCMD_WRITE_OUTPORT        0xD1    /* write output port */
2210 330d0414 bellard
#define KBD_CCMD_WRITE_OBUF        0xD2
2211 330d0414 bellard
#define KBD_CCMD_WRITE_AUX_OBUF        0xD3    /* Write to output buffer as if
2212 330d0414 bellard
                                           initiated by the auxiliary device */
2213 330d0414 bellard
#define KBD_CCMD_WRITE_MOUSE        0xD4        /* Write the following byte to the mouse */
2214 1f5476fc bellard
#define KBD_CCMD_DISABLE_A20    0xDD    /* HP vectra only ? */
2215 1f5476fc bellard
#define KBD_CCMD_ENABLE_A20     0xDF    /* HP vectra only ? */
2216 330d0414 bellard
#define KBD_CCMD_RESET                0xFE
2217 330d0414 bellard
2218 330d0414 bellard
/* Keyboard Commands */
2219 330d0414 bellard
#define KBD_CMD_SET_LEDS        0xED        /* Set keyboard leds */
2220 330d0414 bellard
#define KBD_CMD_ECHO             0xEE
2221 07ad1b93 bellard
#define KBD_CMD_GET_ID                 0xF2        /* get keyboard ID */
2222 330d0414 bellard
#define KBD_CMD_SET_RATE        0xF3        /* Set typematic rate */
2223 330d0414 bellard
#define KBD_CMD_ENABLE                0xF4        /* Enable scanning */
2224 330d0414 bellard
#define KBD_CMD_RESET_DISABLE        0xF5        /* reset and disable scanning */
2225 330d0414 bellard
#define KBD_CMD_RESET_ENABLE           0xF6    /* reset and enable scanning */
2226 330d0414 bellard
#define KBD_CMD_RESET                0xFF        /* Reset */
2227 330d0414 bellard
2228 330d0414 bellard
/* Keyboard Replies */
2229 330d0414 bellard
#define KBD_REPLY_POR                0xAA        /* Power on reset */
2230 330d0414 bellard
#define KBD_REPLY_ACK                0xFA        /* Command ACK */
2231 330d0414 bellard
#define KBD_REPLY_RESEND        0xFE        /* Command NACK, send the cmd again */
2232 330d0414 bellard
2233 330d0414 bellard
/* Status Register Bits */
2234 330d0414 bellard
#define KBD_STAT_OBF                 0x01        /* Keyboard output buffer full */
2235 330d0414 bellard
#define KBD_STAT_IBF                 0x02        /* Keyboard input buffer full */
2236 330d0414 bellard
#define KBD_STAT_SELFTEST        0x04        /* Self test successful */
2237 330d0414 bellard
#define KBD_STAT_CMD                0x08        /* Last write was a command write (0=data) */
2238 330d0414 bellard
#define KBD_STAT_UNLOCKED        0x10        /* Zero if keyboard locked */
2239 330d0414 bellard
#define KBD_STAT_MOUSE_OBF        0x20        /* Mouse output buffer full */
2240 330d0414 bellard
#define KBD_STAT_GTO                 0x40        /* General receive/xmit timeout */
2241 330d0414 bellard
#define KBD_STAT_PERR                 0x80        /* Parity error */
2242 330d0414 bellard
2243 330d0414 bellard
/* Controller Mode Register Bits */
2244 330d0414 bellard
#define KBD_MODE_KBD_INT        0x01        /* Keyboard data generate IRQ1 */
2245 330d0414 bellard
#define KBD_MODE_MOUSE_INT        0x02        /* Mouse data generate IRQ12 */
2246 330d0414 bellard
#define KBD_MODE_SYS                 0x04        /* The system flag (?) */
2247 330d0414 bellard
#define KBD_MODE_NO_KEYLOCK        0x08        /* The keylock doesn't affect the keyboard if set */
2248 330d0414 bellard
#define KBD_MODE_DISABLE_KBD        0x10        /* Disable keyboard interface */
2249 330d0414 bellard
#define KBD_MODE_DISABLE_MOUSE        0x20        /* Disable mouse interface */
2250 330d0414 bellard
#define KBD_MODE_KCC                 0x40        /* Scan code conversion to PC format */
2251 330d0414 bellard
#define KBD_MODE_RFU                0x80
2252 330d0414 bellard
2253 330d0414 bellard
/* Mouse Commands */
2254 330d0414 bellard
#define AUX_SET_SCALE11                0xE6        /* Set 1:1 scaling */
2255 330d0414 bellard
#define AUX_SET_SCALE21                0xE7        /* Set 2:1 scaling */
2256 313aa567 bellard
#define AUX_SET_RES                0xE8        /* Set resolution */
2257 330d0414 bellard
#define AUX_GET_SCALE                0xE9        /* Get scaling factor */
2258 330d0414 bellard
#define AUX_SET_STREAM                0xEA        /* Set stream mode */
2259 313aa567 bellard
#define AUX_POLL                0xEB        /* Poll */
2260 313aa567 bellard
#define AUX_RESET_WRAP                0xEC        /* Reset wrap mode */
2261 313aa567 bellard
#define AUX_SET_WRAP                0xEE        /* Set wrap mode */
2262 313aa567 bellard
#define AUX_SET_REMOTE                0xF0        /* Set remote mode */
2263 313aa567 bellard
#define AUX_GET_TYPE                0xF2        /* Get type */
2264 330d0414 bellard
#define AUX_SET_SAMPLE                0xF3        /* Set sample rate */
2265 330d0414 bellard
#define AUX_ENABLE_DEV                0xF4        /* Enable aux device */
2266 330d0414 bellard
#define AUX_DISABLE_DEV                0xF5        /* Disable aux device */
2267 313aa567 bellard
#define AUX_SET_DEFAULT                0xF6
2268 330d0414 bellard
#define AUX_RESET                0xFF        /* Reset aux device */
2269 330d0414 bellard
#define AUX_ACK                        0xFA        /* Command byte ACK. */
2270 330d0414 bellard
2271 313aa567 bellard
#define MOUSE_STATUS_REMOTE     0x40
2272 313aa567 bellard
#define MOUSE_STATUS_ENABLED    0x20
2273 313aa567 bellard
#define MOUSE_STATUS_SCALE21    0x10
2274 313aa567 bellard
2275 313aa567 bellard
#define KBD_QUEUE_SIZE 256
2276 330d0414 bellard
2277 330d0414 bellard
typedef struct {
2278 330d0414 bellard
    uint8_t data[KBD_QUEUE_SIZE];
2279 330d0414 bellard
    int rptr, wptr, count;
2280 330d0414 bellard
} KBDQueue;
2281 330d0414 bellard
2282 330d0414 bellard
typedef struct KBDState {
2283 330d0414 bellard
    KBDQueue queues[2];
2284 330d0414 bellard
    uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
2285 330d0414 bellard
    uint8_t status;
2286 330d0414 bellard
    uint8_t mode;
2287 313aa567 bellard
    /* keyboard state */
2288 330d0414 bellard
    int kbd_write_cmd;
2289 330d0414 bellard
    int scan_enabled;
2290 313aa567 bellard
    /* mouse state */
2291 313aa567 bellard
    int mouse_write_cmd;
2292 313aa567 bellard
    uint8_t mouse_status;
2293 313aa567 bellard
    uint8_t mouse_resolution;
2294 313aa567 bellard
    uint8_t mouse_sample_rate;
2295 313aa567 bellard
    uint8_t mouse_wrap;
2296 313aa567 bellard
    uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
2297 313aa567 bellard
    uint8_t mouse_detect_state;
2298 313aa567 bellard
    int mouse_dx; /* current values, needed for 'poll' mode */
2299 313aa567 bellard
    int mouse_dy;
2300 313aa567 bellard
    int mouse_dz;
2301 313aa567 bellard
    uint8_t mouse_buttons;
2302 330d0414 bellard
} KBDState;
2303 330d0414 bellard
2304 330d0414 bellard
KBDState kbd_state;
2305 cd4c3e88 bellard
int reset_requested;
2306 330d0414 bellard
2307 313aa567 bellard
/* update irq and KBD_STAT_[MOUSE_]OBF */
2308 07ad1b93 bellard
/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
2309 07ad1b93 bellard
   incorrect, but it avoids having to simulate exact delays */
2310 330d0414 bellard
static void kbd_update_irq(KBDState *s)
2311 330d0414 bellard
{
2312 313aa567 bellard
    int irq12_level, irq1_level;
2313 313aa567 bellard
2314 313aa567 bellard
    irq1_level = 0;    
2315 313aa567 bellard
    irq12_level = 0;    
2316 313aa567 bellard
    s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
2317 313aa567 bellard
    if (s->queues[0].count != 0 ||
2318 313aa567 bellard
        s->queues[1].count != 0) {
2319 313aa567 bellard
        s->status |= KBD_STAT_OBF;
2320 313aa567 bellard
        if (s->queues[1].count != 0) {
2321 313aa567 bellard
            s->status |= KBD_STAT_MOUSE_OBF;
2322 313aa567 bellard
            if (s->mode & KBD_MODE_MOUSE_INT)
2323 313aa567 bellard
                irq12_level = 1;
2324 313aa567 bellard
        } else {
2325 07ad1b93 bellard
            if ((s->mode & KBD_MODE_KBD_INT) && 
2326 07ad1b93 bellard
                !(s->mode & KBD_MODE_DISABLE_KBD))
2327 313aa567 bellard
                irq1_level = 1;
2328 313aa567 bellard
        }
2329 313aa567 bellard
    }
2330 313aa567 bellard
    pic_set_irq(1, irq1_level);
2331 313aa567 bellard
    pic_set_irq(12, irq12_level);
2332 330d0414 bellard
}
2333 330d0414 bellard
2334 330d0414 bellard
static void kbd_queue(KBDState *s, int b, int aux)
2335 330d0414 bellard
{
2336 330d0414 bellard
    KBDQueue *q = &kbd_state.queues[aux];
2337 330d0414 bellard
2338 313aa567 bellard
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
2339 313aa567 bellard
    if (aux)
2340 313aa567 bellard
        printf("mouse event: 0x%02x\n", b);
2341 313aa567 bellard
#ifdef DEBUG_KBD
2342 313aa567 bellard
    else
2343 313aa567 bellard
        printf("kbd event: 0x%02x\n", b);
2344 313aa567 bellard
#endif
2345 313aa567 bellard
#endif
2346 330d0414 bellard
    if (q->count >= KBD_QUEUE_SIZE)
2347 330d0414 bellard
        return;
2348 330d0414 bellard
    q->data[q->wptr] = b;
2349 330d0414 bellard
    if (++q->wptr == KBD_QUEUE_SIZE)
2350 330d0414 bellard
        q->wptr = 0;
2351 330d0414 bellard
    q->count++;
2352 330d0414 bellard
    kbd_update_irq(s);
2353 330d0414 bellard
}
2354 cd4c3e88 bellard
2355 313aa567 bellard
void kbd_put_keycode(int keycode)
2356 313aa567 bellard
{
2357 313aa567 bellard
    KBDState *s = &kbd_state;
2358 313aa567 bellard
    kbd_queue(s, keycode, 0);
2359 313aa567 bellard
}
2360 313aa567 bellard
2361 c45886db bellard
uint32_t kbd_read_status(CPUState *env, uint32_t addr)
2362 cd4c3e88 bellard
{
2363 330d0414 bellard
    KBDState *s = &kbd_state;
2364 330d0414 bellard
    int val;
2365 330d0414 bellard
    val = s->status;
2366 c45886db bellard
#if defined(DEBUG_KBD)
2367 330d0414 bellard
    printf("kbd: read status=0x%02x\n", val);
2368 330d0414 bellard
#endif
2369 330d0414 bellard
    return val;
2370 cd4c3e88 bellard
}
2371 cd4c3e88 bellard
2372 c45886db bellard
void kbd_write_command(CPUState *env, uint32_t addr, uint32_t val)
2373 cd4c3e88 bellard
{
2374 330d0414 bellard
    KBDState *s = &kbd_state;
2375 330d0414 bellard
2376 330d0414 bellard
#ifdef DEBUG_KBD
2377 330d0414 bellard
    printf("kbd: write cmd=0x%02x\n", val);
2378 330d0414 bellard
#endif
2379 cd4c3e88 bellard
    switch(val) {
2380 330d0414 bellard
    case KBD_CCMD_READ_MODE:
2381 330d0414 bellard
        kbd_queue(s, s->mode, 0);
2382 330d0414 bellard
        break;
2383 330d0414 bellard
    case KBD_CCMD_WRITE_MODE:
2384 330d0414 bellard
    case KBD_CCMD_WRITE_OBUF:
2385 330d0414 bellard
    case KBD_CCMD_WRITE_AUX_OBUF:
2386 330d0414 bellard
    case KBD_CCMD_WRITE_MOUSE:
2387 330d0414 bellard
    case KBD_CCMD_WRITE_OUTPORT:
2388 330d0414 bellard
        s->write_cmd = val;
2389 330d0414 bellard
        break;
2390 330d0414 bellard
    case KBD_CCMD_MOUSE_DISABLE:
2391 330d0414 bellard
        s->mode |= KBD_MODE_DISABLE_MOUSE;
2392 330d0414 bellard
        break;
2393 330d0414 bellard
    case KBD_CCMD_MOUSE_ENABLE:
2394 330d0414 bellard
        s->mode &= ~KBD_MODE_DISABLE_MOUSE;
2395 330d0414 bellard
        break;
2396 330d0414 bellard
    case KBD_CCMD_TEST_MOUSE:
2397 330d0414 bellard
        kbd_queue(s, 0x00, 0);
2398 330d0414 bellard
        break;
2399 330d0414 bellard
    case KBD_CCMD_SELF_TEST:
2400 330d0414 bellard
        s->status |= KBD_STAT_SELFTEST;
2401 330d0414 bellard
        kbd_queue(s, 0x55, 0);
2402 330d0414 bellard
        break;
2403 330d0414 bellard
    case KBD_CCMD_KBD_TEST:
2404 330d0414 bellard
        kbd_queue(s, 0x00, 0);
2405 330d0414 bellard
        break;
2406 330d0414 bellard
    case KBD_CCMD_KBD_DISABLE:
2407 330d0414 bellard
        s->mode |= KBD_MODE_DISABLE_KBD;
2408 07ad1b93 bellard
        kbd_update_irq(s);
2409 330d0414 bellard
        break;
2410 330d0414 bellard
    case KBD_CCMD_KBD_ENABLE:
2411 330d0414 bellard
        s->mode &= ~KBD_MODE_DISABLE_KBD;
2412 07ad1b93 bellard
        kbd_update_irq(s);
2413 330d0414 bellard
        break;
2414 330d0414 bellard
    case KBD_CCMD_READ_INPORT:
2415 330d0414 bellard
        kbd_queue(s, 0x00, 0);
2416 330d0414 bellard
        break;
2417 330d0414 bellard
    case KBD_CCMD_READ_OUTPORT:
2418 330d0414 bellard
        /* XXX: check that */
2419 c45886db bellard
#ifdef TARGET_I386
2420 415e561f bellard
        val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1);
2421 c45886db bellard
#else
2422 c45886db bellard
        val = 0x01;
2423 c45886db bellard
#endif
2424 330d0414 bellard
        if (s->status & KBD_STAT_OBF)
2425 330d0414 bellard
            val |= 0x10;
2426 330d0414 bellard
        if (s->status & KBD_STAT_MOUSE_OBF)
2427 330d0414 bellard
            val |= 0x20;
2428 330d0414 bellard
        kbd_queue(s, val, 0);
2429 330d0414 bellard
        break;
2430 c45886db bellard
#ifdef TARGET_I386
2431 330d0414 bellard
    case KBD_CCMD_ENABLE_A20:
2432 1f5476fc bellard
        cpu_x86_set_a20(env, 1);
2433 330d0414 bellard
        break;
2434 330d0414 bellard
    case KBD_CCMD_DISABLE_A20:
2435 1f5476fc bellard
        cpu_x86_set_a20(env, 0);
2436 330d0414 bellard
        break;
2437 c45886db bellard
#endif
2438 330d0414 bellard
    case KBD_CCMD_RESET:
2439 cd4c3e88 bellard
        reset_requested = 1;
2440 c45886db bellard
        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
2441 cd4c3e88 bellard
        break;
2442 27503323 bellard
    case 0xff:
2443 27503323 bellard
        /* ignore that - I don't know what is its use */
2444 27503323 bellard
        break;
2445 cd4c3e88 bellard
    default:
2446 36b486bb bellard
        fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
2447 330d0414 bellard
        break;
2448 330d0414 bellard
    }
2449 330d0414 bellard
}
2450 330d0414 bellard
2451 c45886db bellard
uint32_t kbd_read_data(CPUState *env, uint32_t addr)
2452 330d0414 bellard
{
2453 330d0414 bellard
    KBDState *s = &kbd_state;
2454 330d0414 bellard
    KBDQueue *q;
2455 7dea1da4 bellard
    int val, index;
2456 330d0414 bellard
    
2457 313aa567 bellard
    q = &s->queues[0]; /* first check KBD data */
2458 330d0414 bellard
    if (q->count == 0)
2459 313aa567 bellard
        q = &s->queues[1]; /* then check AUX data */
2460 330d0414 bellard
    if (q->count == 0) {
2461 7dea1da4 bellard
        /* NOTE: if no data left, we return the last keyboard one
2462 7dea1da4 bellard
           (needed for EMM386) */
2463 7dea1da4 bellard
        /* XXX: need a timer to do things correctly */
2464 7dea1da4 bellard
        q = &s->queues[0];
2465 7dea1da4 bellard
        index = q->rptr - 1;
2466 7dea1da4 bellard
        if (index < 0)
2467 7dea1da4 bellard
            index = KBD_QUEUE_SIZE - 1;
2468 7dea1da4 bellard
        val = q->data[index];
2469 330d0414 bellard
    } else {
2470 330d0414 bellard
        val = q->data[q->rptr];
2471 330d0414 bellard
        if (++q->rptr == KBD_QUEUE_SIZE)
2472 330d0414 bellard
            q->rptr = 0;
2473 330d0414 bellard
        q->count--;
2474 313aa567 bellard
        /* reading deasserts IRQ */
2475 313aa567 bellard
        if (q == &s->queues[0])
2476 313aa567 bellard
            pic_set_irq(1, 0);
2477 313aa567 bellard
        else
2478 313aa567 bellard
            pic_set_irq(12, 0);
2479 330d0414 bellard
    }
2480 313aa567 bellard
    /* reassert IRQs if data left */
2481 313aa567 bellard
    kbd_update_irq(s);
2482 330d0414 bellard
#ifdef DEBUG_KBD
2483 330d0414 bellard
    printf("kbd: read data=0x%02x\n", val);
2484 330d0414 bellard
#endif
2485 330d0414 bellard
    return val;
2486 330d0414 bellard
}
2487 330d0414 bellard
2488 330d0414 bellard
static void kbd_reset_keyboard(KBDState *s)
2489 330d0414 bellard
{
2490 330d0414 bellard
    s->scan_enabled = 1;
2491 330d0414 bellard
}
2492 330d0414 bellard
2493 330d0414 bellard
static void kbd_write_keyboard(KBDState *s, int val)
2494 330d0414 bellard
{
2495 330d0414 bellard
    switch(s->kbd_write_cmd) {
2496 330d0414 bellard
    default:
2497 330d0414 bellard
    case -1:
2498 330d0414 bellard
        switch(val) {
2499 330d0414 bellard
        case 0x00:
2500 330d0414 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2501 330d0414 bellard
            break;
2502 330d0414 bellard
        case 0x05:
2503 330d0414 bellard
            kbd_queue(s, KBD_REPLY_RESEND, 0);
2504 330d0414 bellard
            break;
2505 07ad1b93 bellard
        case KBD_CMD_GET_ID:
2506 07ad1b93 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2507 07ad1b93 bellard
            kbd_queue(s, 0xab, 0);
2508 07ad1b93 bellard
            kbd_queue(s, 0x83, 0);
2509 07ad1b93 bellard
            break;
2510 330d0414 bellard
        case KBD_CMD_ECHO:
2511 330d0414 bellard
            kbd_queue(s, KBD_CMD_ECHO, 0);
2512 330d0414 bellard
            break;
2513 330d0414 bellard
        case KBD_CMD_ENABLE:
2514 330d0414 bellard
            s->scan_enabled = 1;
2515 330d0414 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2516 330d0414 bellard
            break;
2517 330d0414 bellard
        case KBD_CMD_SET_LEDS:
2518 330d0414 bellard
        case KBD_CMD_SET_RATE:
2519 330d0414 bellard
            s->kbd_write_cmd = val;
2520 1f5476fc bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2521 330d0414 bellard
            break;
2522 330d0414 bellard
        case KBD_CMD_RESET_DISABLE:
2523 330d0414 bellard
            kbd_reset_keyboard(s);
2524 330d0414 bellard
            s->scan_enabled = 0;
2525 330d0414 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2526 330d0414 bellard
            break;
2527 330d0414 bellard
        case KBD_CMD_RESET_ENABLE:
2528 330d0414 bellard
            kbd_reset_keyboard(s);
2529 330d0414 bellard
            s->scan_enabled = 1;
2530 330d0414 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2531 330d0414 bellard
            break;
2532 330d0414 bellard
        case KBD_CMD_RESET:
2533 330d0414 bellard
            kbd_reset_keyboard(s);
2534 330d0414 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2535 330d0414 bellard
            kbd_queue(s, KBD_REPLY_POR, 0);
2536 330d0414 bellard
            break;
2537 330d0414 bellard
        default:
2538 330d0414 bellard
            kbd_queue(s, KBD_REPLY_ACK, 0);
2539 330d0414 bellard
            break;
2540 330d0414 bellard
        }
2541 330d0414 bellard
        break;
2542 330d0414 bellard
    case KBD_CMD_SET_LEDS:
2543 330d0414 bellard
        kbd_queue(s, KBD_REPLY_ACK, 0);
2544 313aa567 bellard
        s->kbd_write_cmd = -1;
2545 330d0414 bellard
        break;
2546 330d0414 bellard
    case KBD_CMD_SET_RATE:
2547 330d0414 bellard
        kbd_queue(s, KBD_REPLY_ACK, 0);
2548 313aa567 bellard
        s->kbd_write_cmd = -1;
2549 313aa567 bellard
        break;
2550 313aa567 bellard
    }
2551 313aa567 bellard
}
2552 313aa567 bellard
2553 313aa567 bellard
static void kbd_mouse_send_packet(KBDState *s)
2554 313aa567 bellard
{
2555 313aa567 bellard
    unsigned int b;
2556 313aa567 bellard
    int dx1, dy1, dz1;
2557 313aa567 bellard
2558 313aa567 bellard
    dx1 = s->mouse_dx;
2559 313aa567 bellard
    dy1 = s->mouse_dy;
2560 313aa567 bellard
    dz1 = s->mouse_dz;
2561 313aa567 bellard
    /* XXX: increase range to 8 bits ? */
2562 313aa567 bellard
    if (dx1 > 127)
2563 313aa567 bellard
        dx1 = 127;
2564 313aa567 bellard
    else if (dx1 < -127)
2565 313aa567 bellard
        dx1 = -127;
2566 313aa567 bellard
    if (dy1 > 127)
2567 313aa567 bellard
        dy1 = 127;
2568 313aa567 bellard
    else if (dy1 < -127)
2569 313aa567 bellard
        dy1 = -127;
2570 313aa567 bellard
    b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
2571 313aa567 bellard
    kbd_queue(s, b, 1);
2572 313aa567 bellard
    kbd_queue(s, dx1 & 0xff, 1);
2573 313aa567 bellard
    kbd_queue(s, dy1 & 0xff, 1);
2574 313aa567 bellard
    /* extra byte for IMPS/2 or IMEX */
2575 313aa567 bellard
    switch(s->mouse_type) {
2576 313aa567 bellard
    default:
2577 313aa567 bellard
        break;
2578 313aa567 bellard
    case 3:
2579 313aa567 bellard
        if (dz1 > 127)
2580 313aa567 bellard
            dz1 = 127;
2581 313aa567 bellard
        else if (dz1 < -127)
2582 313aa567 bellard
                dz1 = -127;
2583 313aa567 bellard
        kbd_queue(s, dz1 & 0xff, 1);
2584 313aa567 bellard
        break;
2585 313aa567 bellard
    case 4:
2586 313aa567 bellard
        if (dz1 > 7)
2587 313aa567 bellard
            dz1 = 7;
2588 313aa567 bellard
        else if (dz1 < -7)
2589 313aa567 bellard
            dz1 = -7;
2590 313aa567 bellard
        b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
2591 313aa567 bellard
        kbd_queue(s, b, 1);
2592 313aa567 bellard
        break;
2593 313aa567 bellard
    }
2594 313aa567 bellard
2595 313aa567 bellard
    /* update deltas */
2596 313aa567 bellard
    s->mouse_dx -= dx1;
2597 313aa567 bellard
    s->mouse_dy -= dy1;
2598 313aa567 bellard
    s->mouse_dz -= dz1;
2599 313aa567 bellard
}
2600 313aa567 bellard
2601 313aa567 bellard
void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
2602 313aa567 bellard
{
2603 313aa567 bellard
    KBDState *s = &kbd_state;
2604 313aa567 bellard
2605 313aa567 bellard
    /* check if deltas are recorded when disabled */
2606 313aa567 bellard
    if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
2607 313aa567 bellard
        return;
2608 313aa567 bellard
2609 313aa567 bellard
    s->mouse_dx += dx;
2610 313aa567 bellard
    s->mouse_dy -= dy;
2611 313aa567 bellard
    s->mouse_dz += dz;
2612 313aa567 bellard
    s->mouse_buttons = buttons_state;
2613 313aa567 bellard
    
2614 313aa567 bellard
    if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
2615 313aa567 bellard
        (s->queues[1].count < (KBD_QUEUE_SIZE - 16))) {
2616 313aa567 bellard
        for(;;) {
2617 313aa567 bellard
            /* if not remote, send event. Multiple events are sent if
2618 313aa567 bellard
               too big deltas */
2619 313aa567 bellard
            kbd_mouse_send_packet(s);
2620 313aa567 bellard
            if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
2621 313aa567 bellard
                break;
2622 313aa567 bellard
        }
2623 313aa567 bellard
    }
2624 313aa567 bellard
}
2625 313aa567 bellard
2626 313aa567 bellard
static void kbd_write_mouse(KBDState *s, int val)
2627 313aa567 bellard
{
2628 313aa567 bellard
#ifdef DEBUG_MOUSE
2629 313aa567 bellard
    printf("kbd: write mouse 0x%02x\n", val);
2630 313aa567 bellard
#endif
2631 313aa567 bellard
    switch(s->mouse_write_cmd) {
2632 313aa567 bellard
    default:
2633 313aa567 bellard
    case -1:
2634 313aa567 bellard
        /* mouse command */
2635 313aa567 bellard
        if (s->mouse_wrap) {
2636 313aa567 bellard
            if (val == AUX_RESET_WRAP) {
2637 313aa567 bellard
                s->mouse_wrap = 0;
2638 313aa567 bellard
                kbd_queue(s, AUX_ACK, 1);
2639 313aa567 bellard
                return;
2640 313aa567 bellard
            } else if (val != AUX_RESET) {
2641 313aa567 bellard
                kbd_queue(s, val, 1);
2642 313aa567 bellard
                return;
2643 313aa567 bellard
            }
2644 313aa567 bellard
        }
2645 313aa567 bellard
        switch(val) {
2646 313aa567 bellard
        case AUX_SET_SCALE11:
2647 313aa567 bellard
            s->mouse_status &= ~MOUSE_STATUS_SCALE21;
2648 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2649 313aa567 bellard
            break;
2650 313aa567 bellard
        case AUX_SET_SCALE21:
2651 313aa567 bellard
            s->mouse_status |= MOUSE_STATUS_SCALE21;
2652 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2653 313aa567 bellard
            break;
2654 313aa567 bellard
        case AUX_SET_STREAM:
2655 313aa567 bellard
            s->mouse_status &= ~MOUSE_STATUS_REMOTE;
2656 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2657 313aa567 bellard
            break;
2658 313aa567 bellard
        case AUX_SET_WRAP:
2659 313aa567 bellard
            s->mouse_wrap = 1;
2660 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2661 313aa567 bellard
            break;
2662 313aa567 bellard
        case AUX_SET_REMOTE:
2663 313aa567 bellard
            s->mouse_status |= MOUSE_STATUS_REMOTE;
2664 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2665 313aa567 bellard
            break;
2666 313aa567 bellard
        case AUX_GET_TYPE:
2667 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2668 313aa567 bellard
            kbd_queue(s, s->mouse_type, 1);
2669 313aa567 bellard
            break;
2670 313aa567 bellard
        case AUX_SET_RES:
2671 313aa567 bellard
        case AUX_SET_SAMPLE:
2672 313aa567 bellard
            s->mouse_write_cmd = val;
2673 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2674 313aa567 bellard
            break;
2675 313aa567 bellard
        case AUX_GET_SCALE:
2676 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2677 313aa567 bellard
            kbd_queue(s, s->mouse_status, 1);
2678 313aa567 bellard
            kbd_queue(s, s->mouse_resolution, 1);
2679 313aa567 bellard
            kbd_queue(s, s->mouse_sample_rate, 1);
2680 313aa567 bellard
            break;
2681 313aa567 bellard
        case AUX_POLL:
2682 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2683 313aa567 bellard
            kbd_mouse_send_packet(s);
2684 313aa567 bellard
            break;
2685 313aa567 bellard
        case AUX_ENABLE_DEV:
2686 313aa567 bellard
            s->mouse_status |= MOUSE_STATUS_ENABLED;
2687 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2688 313aa567 bellard
            break;
2689 313aa567 bellard
        case AUX_DISABLE_DEV:
2690 313aa567 bellard
            s->mouse_status &= ~MOUSE_STATUS_ENABLED;
2691 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2692 313aa567 bellard
            break;
2693 313aa567 bellard
        case AUX_SET_DEFAULT:
2694 313aa567 bellard
            s->mouse_sample_rate = 100;
2695 313aa567 bellard
            s->mouse_resolution = 2;
2696 313aa567 bellard
            s->mouse_status = 0;
2697 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2698 313aa567 bellard
            break;
2699 313aa567 bellard
        case AUX_RESET:
2700 313aa567 bellard
            s->mouse_sample_rate = 100;
2701 313aa567 bellard
            s->mouse_resolution = 2;
2702 313aa567 bellard
            s->mouse_status = 0;
2703 313aa567 bellard
            kbd_queue(s, AUX_ACK, 1);
2704 313aa567 bellard
            kbd_queue(s, 0xaa, 1);
2705 313aa567 bellard
            kbd_queue(s, s->mouse_type, 1);
2706 313aa567 bellard
            break;
2707 313aa567 bellard
        default:
2708 313aa567 bellard
            break;
2709 313aa567 bellard
        }
2710 313aa567 bellard
        break;
2711 313aa567 bellard
    case AUX_SET_SAMPLE:
2712 313aa567 bellard
        s->mouse_sample_rate = val;
2713 313aa567 bellard
#if 0
2714 313aa567 bellard
        /* detect IMPS/2 or IMEX */
2715 313aa567 bellard
        switch(s->mouse_detect_state) {
2716 313aa567 bellard
        default:
2717 313aa567 bellard
        case 0:
2718 313aa567 bellard
            if (val == 200)
2719 313aa567 bellard
                s->mouse_detect_state = 1;
2720 313aa567 bellard
            break;
2721 313aa567 bellard
        case 1:
2722 313aa567 bellard
            if (val == 100)
2723 313aa567 bellard
                s->mouse_detect_state = 2;
2724 313aa567 bellard
            else if (val == 200)
2725 313aa567 bellard
                s->mouse_detect_state = 3;
2726 313aa567 bellard
            else
2727 313aa567 bellard
                s->mouse_detect_state = 0;
2728 313aa567 bellard
            break;
2729 313aa567 bellard
        case 2:
2730 313aa567 bellard
            if (val == 80) 
2731 313aa567 bellard
                s->mouse_type = 3; /* IMPS/2 */
2732 313aa567 bellard
            s->mouse_detect_state = 0;
2733 313aa567 bellard
            break;
2734 313aa567 bellard
        case 3:
2735 313aa567 bellard
            if (val == 80) 
2736 313aa567 bellard
                s->mouse_type = 4; /* IMEX */
2737 313aa567 bellard
            s->mouse_detect_state = 0;
2738 313aa567 bellard
            break;
2739 313aa567 bellard
        }
2740 313aa567 bellard
#endif
2741 313aa567 bellard
        kbd_queue(s, AUX_ACK, 1);
2742 313aa567 bellard
        s->mouse_write_cmd = -1;
2743 313aa567 bellard
        break;
2744 313aa567 bellard
    case AUX_SET_RES:
2745 313aa567 bellard
        s->mouse_resolution = val;
2746 313aa567 bellard
        kbd_queue(s, AUX_ACK, 1);
2747 313aa567 bellard
        s->mouse_write_cmd = -1;
2748 330d0414 bellard
        break;
2749 330d0414 bellard
    }
2750 330d0414 bellard
}
2751 330d0414 bellard
2752 c45886db bellard
void kbd_write_data(CPUState *env, uint32_t addr, uint32_t val)
2753 330d0414 bellard
{
2754 330d0414 bellard
    KBDState *s = &kbd_state;
2755 330d0414 bellard
2756 330d0414 bellard
#ifdef DEBUG_KBD
2757 330d0414 bellard
    printf("kbd: write data=0x%02x\n", val);
2758 330d0414 bellard
#endif
2759 330d0414 bellard
2760 330d0414 bellard
    switch(s->write_cmd) {
2761 330d0414 bellard
    case 0:
2762 330d0414 bellard
        kbd_write_keyboard(s, val);
2763 330d0414 bellard
        break;
2764 330d0414 bellard
    case KBD_CCMD_WRITE_MODE:
2765 330d0414 bellard
        s->mode = val;
2766 330d0414 bellard
        kbd_update_irq(s);
2767 330d0414 bellard
        break;
2768 330d0414 bellard
    case KBD_CCMD_WRITE_OBUF:
2769 330d0414 bellard
        kbd_queue(s, val, 0);
2770 330d0414 bellard
        break;
2771 330d0414 bellard
    case KBD_CCMD_WRITE_AUX_OBUF:
2772 330d0414 bellard
        kbd_queue(s, val, 1);
2773 330d0414 bellard
        break;
2774 330d0414 bellard
    case KBD_CCMD_WRITE_OUTPORT:
2775 c45886db bellard
#ifdef TARGET_I386
2776 1f5476fc bellard
        cpu_x86_set_a20(env, (val >> 1) & 1);
2777 c45886db bellard
#endif
2778 330d0414 bellard
        if (!(val & 1)) {
2779 330d0414 bellard
            reset_requested = 1;
2780 c45886db bellard
            cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
2781 330d0414 bellard
        }
2782 330d0414 bellard
        break;
2783 313aa567 bellard
    case KBD_CCMD_WRITE_MOUSE:
2784 313aa567 bellard
        kbd_write_mouse(s, val);
2785 313aa567 bellard
        break;
2786 330d0414 bellard
    default:
2787 cd4c3e88 bellard
        break;
2788 cd4c3e88 bellard
    }
2789 330d0414 bellard
    s->write_cmd = 0;
2790 330d0414 bellard
}
2791 330d0414 bellard
2792 330d0414 bellard
void kbd_reset(KBDState *s)
2793 330d0414 bellard
{
2794 330d0414 bellard
    KBDQueue *q;
2795 330d0414 bellard
    int i;
2796 330d0414 bellard
2797 330d0414 bellard
    s->kbd_write_cmd = -1;
2798 313aa567 bellard
    s->mouse_write_cmd = -1;
2799 330d0414 bellard
    s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
2800 313aa567 bellard
    s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
2801 330d0414 bellard
    for(i = 0; i < 2; i++) {
2802 330d0414 bellard
        q = &s->queues[i];
2803 330d0414 bellard
        q->rptr = 0;
2804 330d0414 bellard
        q->wptr = 0;
2805 330d0414 bellard
        q->count = 0;
2806 330d0414 bellard
    }
2807 cd4c3e88 bellard
}
2808 cd4c3e88 bellard
2809 cd4c3e88 bellard
void kbd_init(void)
2810 cd4c3e88 bellard
{
2811 330d0414 bellard
    kbd_reset(&kbd_state);
2812 c45886db bellard
#if defined (TARGET_I386) || defined (TARGET_PPC)
2813 330d0414 bellard
    register_ioport_read(0x60, 1, kbd_read_data, 1);
2814 330d0414 bellard
    register_ioport_write(0x60, 1, kbd_write_data, 1);
2815 cd4c3e88 bellard
    register_ioport_read(0x64, 1, kbd_read_status, 1);
2816 cd4c3e88 bellard
    register_ioport_write(0x64, 1, kbd_write_command, 1);
2817 c45886db bellard
#endif
2818 cd4c3e88 bellard
}
2819 cd4c3e88 bellard
2820 cd4c3e88 bellard
/***********************************************************/
2821 330d0414 bellard
/* Bochs BIOS debug ports */
2822 c45886db bellard
#ifdef TARGET_I386
2823 330d0414 bellard
void bochs_bios_write(CPUX86State *env, uint32_t addr, uint32_t val)
2824 330d0414 bellard
{
2825 330d0414 bellard
    switch(addr) {
2826 330d0414 bellard
        /* Bochs BIOS messages */
2827 330d0414 bellard
    case 0x400:
2828 330d0414 bellard
    case 0x401:
2829 330d0414 bellard
        fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
2830 330d0414 bellard
        exit(1);
2831 330d0414 bellard
    case 0x402:
2832 330d0414 bellard
    case 0x403:
2833 330d0414 bellard
#ifdef DEBUG_BIOS
2834 330d0414 bellard
        fprintf(stderr, "%c", val);
2835 330d0414 bellard
#endif
2836 330d0414 bellard
        break;
2837 330d0414 bellard
2838 330d0414 bellard
        /* LGPL'ed VGA BIOS messages */
2839 330d0414 bellard
    case 0x501:
2840 330d0414 bellard
    case 0x502:
2841 330d0414 bellard
        fprintf(stderr, "VGA BIOS panic, line %d\n", val);
2842 330d0414 bellard
        exit(1);
2843 330d0414 bellard
    case 0x500:
2844 330d0414 bellard
    case 0x503:
2845 330d0414 bellard
#ifdef DEBUG_BIOS
2846 330d0414 bellard
        fprintf(stderr, "%c", val);
2847 330d0414 bellard
#endif
2848 330d0414 bellard
        break;
2849 330d0414 bellard
    }
2850 330d0414 bellard
}
2851 330d0414 bellard
2852 330d0414 bellard
void bochs_bios_init(void)
2853 330d0414 bellard
{
2854 330d0414 bellard
    register_ioport_write(0x400, 1, bochs_bios_write, 2);
2855 330d0414 bellard
    register_ioport_write(0x401, 1, bochs_bios_write, 2);
2856 330d0414 bellard
    register_ioport_write(0x402, 1, bochs_bios_write, 1);
2857 330d0414 bellard
    register_ioport_write(0x403, 1, bochs_bios_write, 1);
2858 330d0414 bellard
2859 330d0414 bellard
    register_ioport_write(0x501, 1, bochs_bios_write, 2);
2860 330d0414 bellard
    register_ioport_write(0x502, 1, bochs_bios_write, 2);
2861 330d0414 bellard
    register_ioport_write(0x500, 1, bochs_bios_write, 1);
2862 330d0414 bellard
    register_ioport_write(0x503, 1, bochs_bios_write, 1);
2863 330d0414 bellard
}
2864 c45886db bellard
#endif
2865 330d0414 bellard
2866 330d0414 bellard
/***********************************************************/
2867 313aa567 bellard
/* dumb display */
2868 313aa567 bellard
2869 313aa567 bellard
/* init terminal so that we can grab keys */
2870 313aa567 bellard
static struct termios oldtty;
2871 313aa567 bellard
2872 313aa567 bellard
static void term_exit(void)
2873 313aa567 bellard
{
2874 313aa567 bellard
    tcsetattr (0, TCSANOW, &oldtty);
2875 313aa567 bellard
}
2876 313aa567 bellard
2877 313aa567 bellard
static void term_init(void)
2878 313aa567 bellard
{
2879 313aa567 bellard
    struct termios tty;
2880 313aa567 bellard
2881 313aa567 bellard
    tcgetattr (0, &tty);
2882 313aa567 bellard
    oldtty = tty;
2883 313aa567 bellard
2884 313aa567 bellard
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
2885 313aa567 bellard
                          |INLCR|IGNCR|ICRNL|IXON);
2886 313aa567 bellard
    tty.c_oflag |= OPOST;
2887 a20dd508 bellard
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
2888 a20dd508 bellard
    /* if graphical mode, we allow Ctrl-C handling */
2889 a20dd508 bellard
    if (nographic)
2890 a20dd508 bellard
        tty.c_lflag &= ~ISIG;
2891 313aa567 bellard
    tty.c_cflag &= ~(CSIZE|PARENB);
2892 313aa567 bellard
    tty.c_cflag |= CS8;
2893 313aa567 bellard
    tty.c_cc[VMIN] = 1;
2894 313aa567 bellard
    tty.c_cc[VTIME] = 0;
2895 313aa567 bellard
    
2896 313aa567 bellard
    tcsetattr (0, TCSANOW, &tty);
2897 313aa567 bellard
2898 313aa567 bellard
    atexit(term_exit);
2899 313aa567 bellard
2900 313aa567 bellard
    fcntl(0, F_SETFL, O_NONBLOCK);
2901 313aa567 bellard
}
2902 313aa567 bellard
2903 313aa567 bellard
static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
2904 313aa567 bellard
{
2905 313aa567 bellard
}
2906 313aa567 bellard
2907 313aa567 bellard
static void dumb_resize(DisplayState *ds, int w, int h)
2908 313aa567 bellard
{
2909 313aa567 bellard
}
2910 313aa567 bellard
2911 313aa567 bellard
static void dumb_refresh(DisplayState *ds)
2912 313aa567 bellard
{
2913 313aa567 bellard
    vga_update_display();
2914 313aa567 bellard
}
2915 313aa567 bellard
2916 313aa567 bellard
void dumb_display_init(DisplayState *ds)
2917 313aa567 bellard
{
2918 313aa567 bellard
    ds->data = NULL;
2919 313aa567 bellard
    ds->linesize = 0;
2920 313aa567 bellard
    ds->depth = 0;
2921 313aa567 bellard
    ds->dpy_update = dumb_update;
2922 313aa567 bellard
    ds->dpy_resize = dumb_resize;
2923 313aa567 bellard
    ds->dpy_refresh = dumb_refresh;
2924 313aa567 bellard
}
2925 313aa567 bellard
2926 3a51dee6 bellard
#if !defined(CONFIG_SOFTMMU)
2927 313aa567 bellard
/***********************************************************/
2928 0824d6fc bellard
/* cpu signal handler */
2929 0824d6fc bellard
static void host_segv_handler(int host_signum, siginfo_t *info, 
2930 0824d6fc bellard
                              void *puc)
2931 0824d6fc bellard
{
2932 0824d6fc bellard
    if (cpu_signal_handler(host_signum, info, puc))
2933 0824d6fc bellard
        return;
2934 0824d6fc bellard
    term_exit();
2935 0824d6fc bellard
    abort();
2936 0824d6fc bellard
}
2937 3a51dee6 bellard
#endif
2938 0824d6fc bellard
2939 0824d6fc bellard
static int timer_irq_pending;
2940 87858c89 bellard
static int timer_irq_count;
2941 0824d6fc bellard
2942 313aa567 bellard
static int timer_ms;
2943 313aa567 bellard
static int gui_refresh_pending, gui_refresh_count;
2944 313aa567 bellard
2945 0824d6fc bellard
static void host_alarm_handler(int host_signum, siginfo_t *info, 
2946 0824d6fc bellard
                               void *puc)
2947 0824d6fc bellard
{
2948 87858c89 bellard
    /* NOTE: since usually the OS asks a 100 Hz clock, there can be
2949 87858c89 bellard
       some drift between cpu_get_ticks() and the interrupt time. So
2950 87858c89 bellard
       we queue some interrupts to avoid missing some */
2951 87858c89 bellard
    timer_irq_count += pit_get_out_edges(&pit_channels[0]);
2952 87858c89 bellard
    if (timer_irq_count) {
2953 87858c89 bellard
        if (timer_irq_count > 2)
2954 87858c89 bellard
            timer_irq_count = 2;
2955 87858c89 bellard
        timer_irq_count--;
2956 313aa567 bellard
        timer_irq_pending = 1;
2957 313aa567 bellard
    }
2958 313aa567 bellard
    gui_refresh_count += timer_ms;
2959 313aa567 bellard
    if (gui_refresh_count >= GUI_REFRESH_INTERVAL) {
2960 313aa567 bellard
        gui_refresh_count = 0;
2961 313aa567 bellard
        gui_refresh_pending = 1;
2962 313aa567 bellard
    }
2963 313aa567 bellard
2964 313aa567 bellard
    if (gui_refresh_pending || timer_irq_pending) {
2965 87858c89 bellard
        /* just exit from the cpu to have a chance to handle timers */
2966 c45886db bellard
        cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
2967 87858c89 bellard
    }
2968 0824d6fc bellard
}
2969 0824d6fc bellard
2970 b4608c04 bellard
/* main execution loop */
2971 b4608c04 bellard
2972 b4608c04 bellard
CPUState *cpu_gdbstub_get_env(void *opaque)
2973 b4608c04 bellard
{
2974 b4608c04 bellard
    return global_env;
2975 b4608c04 bellard
}
2976 b4608c04 bellard
2977 4c3a88a2 bellard
int main_loop(void *opaque)
2978 b4608c04 bellard
{
2979 c45886db bellard
    struct pollfd ufds[3], *pf, *serial_ufd, *gdb_ufd;
2980 c45886db bellard
#if defined (TARGET_I386)
2981 c45886db bellard
    struct pollfd *net_ufd;
2982 c45886db bellard
#endif
2983 27c3f2cb bellard
    int ret, n, timeout, serial_ok;
2984 b4608c04 bellard
    uint8_t ch;
2985 b4608c04 bellard
    CPUState *env = global_env;
2986 b4608c04 bellard
2987 a20dd508 bellard
    if (!term_inited) {
2988 313aa567 bellard
        /* initialize terminal only there so that the user has a
2989 313aa567 bellard
           chance to stop QEMU with Ctrl-C before the gdb connection
2990 313aa567 bellard
           is launched */
2991 313aa567 bellard
        term_inited = 1;
2992 313aa567 bellard
        term_init();
2993 313aa567 bellard
    }
2994 313aa567 bellard
2995 27c3f2cb bellard
    serial_ok = 1;
2996 34865134 bellard
    cpu_enable_ticks();
2997 b4608c04 bellard
    for(;;) {
2998 c45886db bellard
#if defined (DO_TB_FLUSH)
2999 c45886db bellard
        tb_flush();
3000 c45886db bellard
#endif
3001 c45886db bellard
        ret = cpu_exec(env);
3002 34865134 bellard
        if (reset_requested) {
3003 34865134 bellard
            ret = EXCP_INTERRUPT; 
3004 cd4c3e88 bellard
            break;
3005 34865134 bellard
        }
3006 34865134 bellard
        if (ret == EXCP_DEBUG) {
3007 34865134 bellard
            ret = EXCP_DEBUG;
3008 34865134 bellard
            break;
3009 34865134 bellard
        }
3010 b4608c04 bellard
        /* if hlt instruction, we wait until the next IRQ */
3011 b4608c04 bellard
        if (ret == EXCP_HLT) 
3012 b4608c04 bellard
            timeout = 10;
3013 b4608c04 bellard
        else
3014 b4608c04 bellard
            timeout = 0;
3015 b4608c04 bellard
        /* poll any events */
3016 b4608c04 bellard
        serial_ufd = NULL;
3017 b4608c04 bellard
        pf = ufds;
3018 27c3f2cb bellard
        if (serial_ok && !(serial_ports[0].lsr & UART_LSR_DR)) {
3019 b4608c04 bellard
            serial_ufd = pf;
3020 b4608c04 bellard
            pf->fd = 0;
3021 b4608c04 bellard
            pf->events = POLLIN;
3022 b4608c04 bellard
            pf++;
3023 b4608c04 bellard
        }
3024 c45886db bellard
#if defined (TARGET_I386)
3025 b4608c04 bellard
        net_ufd = NULL;
3026 b4608c04 bellard
        if (net_fd > 0 && ne2000_can_receive(&ne2000_state)) {
3027 b4608c04 bellard
            net_ufd = pf;
3028 b4608c04 bellard
            pf->fd = net_fd;
3029 b4608c04 bellard
            pf->events = POLLIN;
3030 b4608c04 bellard
            pf++;
3031 b4608c04 bellard
        }
3032 c45886db bellard
#endif
3033 b4608c04 bellard
        gdb_ufd = NULL;
3034 b4608c04 bellard
        if (gdbstub_fd > 0) {
3035 b4608c04 bellard
            gdb_ufd = pf;
3036 b4608c04 bellard
            pf->fd = gdbstub_fd;
3037 b4608c04 bellard
            pf->events = POLLIN;
3038 b4608c04 bellard
            pf++;
3039 b4608c04 bellard
        }
3040 b4608c04 bellard
3041 b4608c04 bellard
        ret = poll(ufds, pf - ufds, timeout);
3042 b4608c04 bellard
        if (ret > 0) {
3043 b4608c04 bellard
            if (serial_ufd && (serial_ufd->revents & POLLIN)) {
3044 b4608c04 bellard
                n = read(0, &ch, 1);
3045 b4608c04 bellard
                if (n == 1) {
3046 b4608c04 bellard
                    serial_received_byte(&serial_ports[0], ch);
3047 27c3f2cb bellard
                } else {
3048 27c3f2cb bellard
                    /* Closed, stop polling. */
3049 27c3f2cb bellard
                    serial_ok = 0;
3050 b4608c04 bellard
                }
3051 b4608c04 bellard
            }
3052 c45886db bellard
#if defined (TARGET_I386)
3053 b4608c04 bellard
            if (net_ufd && (net_ufd->revents & POLLIN)) {
3054 b4608c04 bellard
                uint8_t buf[MAX_ETH_FRAME_SIZE];
3055 b4608c04 bellard
3056 b4608c04 bellard
                n = read(net_fd, buf, MAX_ETH_FRAME_SIZE);
3057 b4608c04 bellard
                if (n > 0) {
3058 b4608c04 bellard
                    if (n < 60) {
3059 b4608c04 bellard
                        memset(buf + n, 0, 60 - n);
3060 b4608c04 bellard
                        n = 60;
3061 b4608c04 bellard
                    }
3062 b4608c04 bellard
                    ne2000_receive(&ne2000_state, buf, n);
3063 b4608c04 bellard
                }
3064 b4608c04 bellard
            }
3065 c45886db bellard
#endif
3066 b4608c04 bellard
            if (gdb_ufd && (gdb_ufd->revents & POLLIN)) {
3067 b4608c04 bellard
                uint8_t buf[1];
3068 b4608c04 bellard
                /* stop emulation if requested by gdb */
3069 b4608c04 bellard
                n = read(gdbstub_fd, buf, 1);
3070 34865134 bellard
                if (n == 1) {
3071 34865134 bellard
                    ret = EXCP_INTERRUPT; 
3072 b4608c04 bellard
                    break;
3073 34865134 bellard
                }
3074 b4608c04 bellard
            }
3075 b4608c04 bellard
        }
3076 b4608c04 bellard
3077 b4608c04 bellard
        /* timer IRQ */
3078 b4608c04 bellard
        if (timer_irq_pending) {
3079 c45886db bellard
#if defined (TARGET_I386)
3080 b4608c04 bellard
            pic_set_irq(0, 1);
3081 b4608c04 bellard
            pic_set_irq(0, 0);
3082 b4608c04 bellard
            timer_irq_pending = 0;
3083 7dea1da4 bellard
            /* XXX: RTC test */
3084 8f2b1fb0 bellard
            if (cmos_data[RTC_REG_B] & 0x50) {
3085 7dea1da4 bellard
                pic_set_irq(8, 1);
3086 7dea1da4 bellard
            }
3087 c45886db bellard
#endif
3088 b4608c04 bellard
        }
3089 8dc75d75 bellard
        /* XXX: add explicit timer */
3090 8dc75d75 bellard
        SB16_run();
3091 8dc75d75 bellard
3092 8dc75d75 bellard
        /* run dma transfers, if any */
3093 8dc75d75 bellard
        DMA_run();
3094 313aa567 bellard
3095 313aa567 bellard
        /* VGA */
3096 313aa567 bellard
        if (gui_refresh_pending) {
3097 313aa567 bellard
            display_state.dpy_refresh(&display_state);
3098 313aa567 bellard
            gui_refresh_pending = 0;
3099 313aa567 bellard
        }
3100 b4608c04 bellard
    }
3101 34865134 bellard
    cpu_disable_ticks();
3102 34865134 bellard
    return ret;
3103 b4608c04 bellard
}
3104 b4608c04 bellard
3105 0824d6fc bellard
void help(void)
3106 0824d6fc bellard
{
3107 a20dd508 bellard
    printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
3108 0db63474 bellard
           "usage: %s [options] [disk_image]\n"
3109 0824d6fc bellard
           "\n"
3110 a20dd508 bellard
           "'disk_image' is a raw hard image image for IDE hard disk 0\n"
3111 fc01f7e7 bellard
           "\n"
3112 a20dd508 bellard
           "Standard options:\n"
3113 c45886db bellard
           "-fda/-fdb file  use 'file' as floppy disk 0/1 image\n"
3114 36b486bb bellard
           "-hda/-hdb file  use 'file' as IDE hard disk 0/1 image\n"
3115 36b486bb bellard
           "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
3116 36b486bb bellard
           "-cdrom file     use 'file' as IDE cdrom 2 image\n"
3117 6e44ba7f bellard
           "-boot [a|b|c|d] boot on floppy (a, b), hard disk (c) or CD-ROM (d)\n"
3118 a20dd508 bellard
           "-snapshot       write to temporary files instead of disk image files\n"
3119 a20dd508 bellard
           "-m megs         set virtual RAM size to megs MB\n"
3120 a20dd508 bellard
           "-n script       set network init script [default=%s]\n"
3121 42f1e0e4 bellard
           "-tun-fd fd      this fd talks to tap/tun, use it.\n"
3122 a20dd508 bellard
           "-nographic      disable graphical output\n"
3123 a20dd508 bellard
           "\n"
3124 a20dd508 bellard
           "Linux boot specific (does not require PC BIOS):\n"
3125 a20dd508 bellard
           "-kernel bzImage use 'bzImage' as kernel image\n"
3126 a20dd508 bellard
           "-append cmdline use 'cmdline' as kernel command line\n"
3127 a20dd508 bellard
           "-initrd file    use 'file' as initial ram disk\n"
3128 fc01f7e7 bellard
           "\n"
3129 330d0414 bellard
           "Debug/Expert options:\n"
3130 a20dd508 bellard
           "-s              wait gdb connection to port %d\n"
3131 a20dd508 bellard
           "-p port         change gdb connection port\n"
3132 6e44ba7f bellard
           "-d              output log to %s\n"
3133 a20dd508 bellard
           "-hdachs c,h,s   force hard disk 0 geometry (usually qemu can guess it)\n"
3134 a20dd508 bellard
           "-L path         set the directory for the BIOS and VGA BIOS\n"
3135 77fef8c1 bellard
#ifdef USE_CODE_COPY
3136 77fef8c1 bellard
           "-no-code-copy   disable code copy acceleration\n"
3137 77fef8c1 bellard
#endif
3138 77fef8c1 bellard
3139 0824d6fc bellard
           "\n"
3140 f1510b2c bellard
           "During emulation, use C-a h to get terminal commands:\n",
3141 0db63474 bellard
#ifdef CONFIG_SOFTMMU
3142 0db63474 bellard
           "qemu",
3143 0db63474 bellard
#else
3144 0db63474 bellard
           "qemu-fast",
3145 0db63474 bellard
#endif
3146 0db63474 bellard
           DEFAULT_NETWORK_SCRIPT, 
3147 6e44ba7f bellard
           DEFAULT_GDBSTUB_PORT,
3148 6e44ba7f bellard
           "/tmp/qemu.log");
3149 0824d6fc bellard
    term_print_help();
3150 0db63474 bellard
#ifndef CONFIG_SOFTMMU
3151 0db63474 bellard
    printf("\n"
3152 0db63474 bellard
           "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"
3153 0db63474 bellard
           "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"
3154 0db63474 bellard
           "PC emulation.\n");
3155 0db63474 bellard
#endif
3156 0824d6fc bellard
    exit(1);
3157 0824d6fc bellard
}
3158 0824d6fc bellard
3159 fc01f7e7 bellard
struct option long_options[] = {
3160 fc01f7e7 bellard
    { "initrd", 1, NULL, 0, },
3161 fc01f7e7 bellard
    { "hda", 1, NULL, 0, },
3162 fc01f7e7 bellard
    { "hdb", 1, NULL, 0, },
3163 33e3963e bellard
    { "snapshot", 0, NULL, 0, },
3164 330d0414 bellard
    { "hdachs", 1, NULL, 0, },
3165 a20dd508 bellard
    { "nographic", 0, NULL, 0, },
3166 a20dd508 bellard
    { "kernel", 1, NULL, 0, },
3167 a20dd508 bellard
    { "append", 1, NULL, 0, },
3168 42f1e0e4 bellard
    { "tun-fd", 1, NULL, 0, },
3169 36b486bb bellard
    { "hdc", 1, NULL, 0, },
3170 36b486bb bellard
    { "hdd", 1, NULL, 0, },
3171 36b486bb bellard
    { "cdrom", 1, NULL, 0, },
3172 36b486bb bellard
    { "boot", 1, NULL, 0, },
3173 c45886db bellard
    { "fda", 1, NULL, 0, },
3174 c45886db bellard
    { "fdb", 1, NULL, 0, },
3175 77fef8c1 bellard
    { "no-code-copy", 0, NULL, 0},
3176 fc01f7e7 bellard
    { NULL, 0, NULL, 0 },
3177 fc01f7e7 bellard
};
3178 fc01f7e7 bellard
3179 a20dd508 bellard
#ifdef CONFIG_SDL
3180 a20dd508 bellard
/* SDL use the pthreads and they modify sigaction. We don't
3181 a20dd508 bellard
   want that. */
3182 dc887a4d bellard
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
3183 a20dd508 bellard
extern void __libc_sigaction();
3184 a20dd508 bellard
#define sigaction(sig, act, oact) __libc_sigaction(sig, act, oact)
3185 a20dd508 bellard
#else
3186 a20dd508 bellard
extern void __sigaction();
3187 a20dd508 bellard
#define sigaction(sig, act, oact) __sigaction(sig, act, oact)
3188 a20dd508 bellard
#endif
3189 a20dd508 bellard
#endif /* CONFIG_SDL */
3190 a20dd508 bellard
3191 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3192 77fef8c1 bellard
3193 77fef8c1 bellard
/* this stack is only used during signal handling */
3194 77fef8c1 bellard
#define SIGNAL_STACK_SIZE 32768
3195 77fef8c1 bellard
3196 77fef8c1 bellard
static uint8_t *signal_stack;
3197 77fef8c1 bellard
3198 77fef8c1 bellard
#endif
3199 77fef8c1 bellard
3200 0824d6fc bellard
int main(int argc, char **argv)
3201 0824d6fc bellard
{
3202 fc01f7e7 bellard
    int c, ret, initrd_size, i, use_gdbstub, gdbstub_port, long_index;
3203 1ccde1cb bellard
    int snapshot, linux_boot;
3204 0824d6fc bellard
    struct sigaction act;
3205 0824d6fc bellard
    struct itimerval itv;
3206 c45886db bellard
    CPUState *env;
3207 7f7f9873 bellard
    const char *initrd_filename;
3208 c45886db bellard
    const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
3209 a20dd508 bellard
    const char *kernel_filename, *kernel_cmdline;
3210 77fef8c1 bellard
    char buf[1024];
3211 313aa567 bellard
    DisplayState *ds = &display_state;
3212 313aa567 bellard
3213 0824d6fc bellard
    /* we never want that malloc() uses mmap() */
3214 0824d6fc bellard
    mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
3215 fc01f7e7 bellard
    initrd_filename = NULL;
3216 c45886db bellard
    for(i = 0; i < MAX_FD; i++)
3217 c45886db bellard
        fd_filename[i] = NULL;
3218 fc01f7e7 bellard
    for(i = 0; i < MAX_DISKS; i++)
3219 fc01f7e7 bellard
        hd_filename[i] = NULL;
3220 1ccde1cb bellard
    ram_size = 32 * 1024 * 1024;
3221 313aa567 bellard
    vga_ram_size = VGA_RAM_SIZE;
3222 c45886db bellard
#if defined (TARGET_I386)
3223 f1510b2c bellard
    pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
3224 c45886db bellard
#endif
3225 b4608c04 bellard
    use_gdbstub = 0;
3226 b4608c04 bellard
    gdbstub_port = DEFAULT_GDBSTUB_PORT;
3227 33e3963e bellard
    snapshot = 0;
3228 a20dd508 bellard
    nographic = 0;
3229 a20dd508 bellard
    kernel_filename = NULL;
3230 a20dd508 bellard
    kernel_cmdline = "";
3231 0824d6fc bellard
    for(;;) {
3232 330d0414 bellard
        c = getopt_long_only(argc, argv, "hm:dn:sp:L:", long_options, &long_index);
3233 0824d6fc bellard
        if (c == -1)
3234 0824d6fc bellard
            break;
3235 0824d6fc bellard
        switch(c) {
3236 fc01f7e7 bellard
        case 0:
3237 fc01f7e7 bellard
            switch(long_index) {
3238 fc01f7e7 bellard
            case 0:
3239 fc01f7e7 bellard
                initrd_filename = optarg;
3240 fc01f7e7 bellard
                break;
3241 fc01f7e7 bellard
            case 1:
3242 fc01f7e7 bellard
                hd_filename[0] = optarg;
3243 fc01f7e7 bellard
                break;
3244 fc01f7e7 bellard
            case 2:
3245 fc01f7e7 bellard
                hd_filename[1] = optarg;
3246 fc01f7e7 bellard
                break;
3247 33e3963e bellard
            case 3:
3248 33e3963e bellard
                snapshot = 1;
3249 33e3963e bellard
                break;
3250 330d0414 bellard
            case 4:
3251 330d0414 bellard
                {
3252 330d0414 bellard
                    int cyls, heads, secs;
3253 330d0414 bellard
                    const char *p;
3254 330d0414 bellard
                    p = optarg;
3255 330d0414 bellard
                    cyls = strtol(p, (char **)&p, 0);
3256 330d0414 bellard
                    if (*p != ',')
3257 330d0414 bellard
                        goto chs_fail;
3258 330d0414 bellard
                    p++;
3259 330d0414 bellard
                    heads = strtol(p, (char **)&p, 0);
3260 330d0414 bellard
                    if (*p != ',')
3261 330d0414 bellard
                        goto chs_fail;
3262 330d0414 bellard
                    p++;
3263 330d0414 bellard
                    secs = strtol(p, (char **)&p, 0);
3264 330d0414 bellard
                    if (*p != '\0')
3265 330d0414 bellard
                        goto chs_fail;
3266 5391d806 bellard
                    ide_set_geometry(0, cyls, heads, secs);
3267 330d0414 bellard
                chs_fail: ;
3268 330d0414 bellard
                }
3269 330d0414 bellard
                break;
3270 313aa567 bellard
            case 5:
3271 a20dd508 bellard
                nographic = 1;
3272 a20dd508 bellard
                break;
3273 a20dd508 bellard
            case 6:
3274 a20dd508 bellard
                kernel_filename = optarg;
3275 a20dd508 bellard
                break;
3276 a20dd508 bellard
            case 7:
3277 a20dd508 bellard
                kernel_cmdline = optarg;
3278 313aa567 bellard
                break;
3279 c45886db bellard
#if defined (TARGET_I386)
3280 42f1e0e4 bellard
            case 8:
3281 42f1e0e4 bellard
                net_fd = atoi(optarg);
3282 42f1e0e4 bellard
                break;
3283 c45886db bellard
#endif
3284 36b486bb bellard
            case 9:
3285 36b486bb bellard
                hd_filename[2] = optarg;
3286 36b486bb bellard
                break;
3287 36b486bb bellard
            case 10:
3288 36b486bb bellard
                hd_filename[3] = optarg;
3289 36b486bb bellard
                break;
3290 36b486bb bellard
            case 11:
3291 36b486bb bellard
                hd_filename[2] = optarg;
3292 5391d806 bellard
                ide_set_cdrom(2, 1);
3293 36b486bb bellard
                break;
3294 36b486bb bellard
            case 12:
3295 36b486bb bellard
                boot_device = optarg[0];
3296 c45886db bellard
                if (boot_device != 'a' && boot_device != 'b' &&
3297 c45886db bellard
                    boot_device != 'c' && boot_device != 'd') {
3298 36b486bb bellard
                    fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
3299 36b486bb bellard
                    exit(1);
3300 36b486bb bellard
                }
3301 36b486bb bellard
                break;
3302 c45886db bellard
            case 13:
3303 c45886db bellard
                fd_filename[0] = optarg;
3304 c45886db bellard
                break;
3305 c45886db bellard
            case 14:
3306 c45886db bellard
                fd_filename[1] = optarg;
3307 c45886db bellard
                break;
3308 77fef8c1 bellard
            case 15:
3309 77fef8c1 bellard
                code_copy_enabled = 0;
3310 77fef8c1 bellard
                break;
3311 fc01f7e7 bellard
            }
3312 fc01f7e7 bellard
            break;
3313 0824d6fc bellard
        case 'h':
3314 0824d6fc bellard
            help();
3315 0824d6fc bellard
            break;
3316 0824d6fc bellard
        case 'm':
3317 1ccde1cb bellard
            ram_size = atoi(optarg) * 1024 * 1024;
3318 1ccde1cb bellard
            if (ram_size <= 0)
3319 0824d6fc bellard
                help();
3320 1ccde1cb bellard
            if (ram_size > PHYS_RAM_MAX_SIZE) {
3321 36b486bb bellard
                fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n",
3322 7916e224 bellard
                        PHYS_RAM_MAX_SIZE / (1024 * 1024));
3323 7916e224 bellard
                exit(1);
3324 7916e224 bellard
            }
3325 0824d6fc bellard
            break;
3326 0824d6fc bellard
        case 'd':
3327 34865134 bellard
            cpu_set_log(CPU_LOG_ALL);
3328 0824d6fc bellard
            break;
3329 c45886db bellard
#if defined (TARGET_I386)
3330 f1510b2c bellard
        case 'n':
3331 f1510b2c bellard
            pstrcpy(network_script, sizeof(network_script), optarg);
3332 f1510b2c bellard
            break;
3333 c45886db bellard
#endif
3334 b4608c04 bellard
        case 's':
3335 b4608c04 bellard
            use_gdbstub = 1;
3336 b4608c04 bellard
            break;
3337 b4608c04 bellard
        case 'p':
3338 b4608c04 bellard
            gdbstub_port = atoi(optarg);
3339 b4608c04 bellard
            break;
3340 330d0414 bellard
        case 'L':
3341 5a67135a bellard
            bios_dir = optarg;
3342 330d0414 bellard
            break;
3343 0824d6fc bellard
        }
3344 0824d6fc bellard
    }
3345 330d0414 bellard
3346 a20dd508 bellard
    if (optind < argc) {
3347 a20dd508 bellard
        hd_filename[0] = argv[optind++];
3348 a20dd508 bellard
    }
3349 a20dd508 bellard
3350 a20dd508 bellard
    linux_boot = (kernel_filename != NULL);
3351 330d0414 bellard
        
3352 c45886db bellard
    if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
3353 c45886db bellard
        fd_filename[0] == '\0')
3354 0824d6fc bellard
        help();
3355 8f2b1fb0 bellard
    
3356 8f2b1fb0 bellard
    /* boot to cd by default if no hard disk */
3357 d0309311 bellard
    if (hd_filename[0] == '\0' && boot_device == 'c') {
3358 d0309311 bellard
        if (fd_filename[0] != '\0')
3359 d0309311 bellard
            boot_device = 'a';
3360 d0309311 bellard
        else
3361 d0309311 bellard
            boot_device = 'd';
3362 d0309311 bellard
    }
3363 0824d6fc bellard
3364 dc887a4d bellard
#if !defined(CONFIG_SOFTMMU)
3365 dc887a4d bellard
    /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
3366 dc887a4d bellard
    {
3367 dc887a4d bellard
        static uint8_t stdout_buf[4096];
3368 dc887a4d bellard
        setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));
3369 dc887a4d bellard
    }
3370 dc887a4d bellard
#else
3371 b118d61e bellard
    setvbuf(stdout, NULL, _IOLBF, 0);
3372 dc887a4d bellard
#endif
3373 0824d6fc bellard
3374 f1510b2c bellard
    /* init network tun interface */
3375 c45886db bellard
#if defined (TARGET_I386)
3376 42f1e0e4 bellard
    if (net_fd < 0)
3377 42f1e0e4 bellard
        net_init();
3378 c45886db bellard
#endif
3379 f1510b2c bellard
3380 0824d6fc bellard
    /* init the memory */
3381 1ccde1cb bellard
    phys_ram_size = ram_size + vga_ram_size;
3382 7f7f9873 bellard
3383 7f7f9873 bellard
#ifdef CONFIG_SOFTMMU
3384 1ccde1cb bellard
    phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size);
3385 7f7f9873 bellard
    if (!phys_ram_base) {
3386 7f7f9873 bellard
        fprintf(stderr, "Could not allocate physical memory\n");
3387 0824d6fc bellard
        exit(1);
3388 0824d6fc bellard
    }
3389 7f7f9873 bellard
#else
3390 7f7f9873 bellard
    /* as we must map the same page at several addresses, we must use
3391 7f7f9873 bellard
       a fd */
3392 7f7f9873 bellard
    {
3393 7f7f9873 bellard
        const char *tmpdir;
3394 7f7f9873 bellard
3395 7f7f9873 bellard
        tmpdir = getenv("QEMU_TMPDIR");
3396 7f7f9873 bellard
        if (!tmpdir)
3397 7f7f9873 bellard
            tmpdir = "/tmp";
3398 7f7f9873 bellard
        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);
3399 7f7f9873 bellard
        if (mkstemp(phys_ram_file) < 0) {
3400 7f7f9873 bellard
            fprintf(stderr, "Could not create temporary memory file '%s'\n", 
3401 7f7f9873 bellard
                    phys_ram_file);
3402 7f7f9873 bellard
            exit(1);
3403 7f7f9873 bellard
        }
3404 7f7f9873 bellard
        phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
3405 7f7f9873 bellard
        if (phys_ram_fd < 0) {
3406 7f7f9873 bellard
            fprintf(stderr, "Could not open temporary memory file '%s'\n", 
3407 7f7f9873 bellard
                    phys_ram_file);
3408 7f7f9873 bellard
            exit(1);
3409 7f7f9873 bellard
        }
3410 1ccde1cb bellard
        ftruncate(phys_ram_fd, phys_ram_size);
3411 7f7f9873 bellard
        unlink(phys_ram_file);
3412 1ccde1cb bellard
        phys_ram_base = mmap(get_mmap_addr(phys_ram_size), 
3413 1ccde1cb bellard
                             phys_ram_size, 
3414 7f7f9873 bellard
                             PROT_WRITE | PROT_READ, MAP_SHARED | MAP_FIXED, 
3415 7f7f9873 bellard
                             phys_ram_fd, 0);
3416 7f7f9873 bellard
        if (phys_ram_base == MAP_FAILED) {
3417 7f7f9873 bellard
            fprintf(stderr, "Could not map physical memory\n");
3418 7f7f9873 bellard
            exit(1);
3419 7f7f9873 bellard
        }
3420 7f7f9873 bellard
    }
3421 7f7f9873 bellard
#endif
3422 0824d6fc bellard
3423 33e3963e bellard
    /* open the virtual block devices */
3424 33e3963e bellard
    for(i = 0; i < MAX_DISKS; i++) {
3425 33e3963e bellard
        if (hd_filename[i]) {
3426 33e3963e bellard
            bs_table[i] = bdrv_open(hd_filename[i], snapshot);
3427 33e3963e bellard
            if (!bs_table[i]) {
3428 36b486bb bellard
                fprintf(stderr, "qemu: could not open hard disk image '%s\n",
3429 33e3963e bellard
                        hd_filename[i]);
3430 33e3963e bellard
                exit(1);
3431 33e3963e bellard
            }
3432 33e3963e bellard
        }
3433 33e3963e bellard
    }
3434 33e3963e bellard
3435 330d0414 bellard
    /* init CPU state */
3436 330d0414 bellard
    env = cpu_init();
3437 330d0414 bellard
    global_env = env;
3438 330d0414 bellard
    cpu_single_env = env;
3439 330d0414 bellard
3440 330d0414 bellard
    init_ioports();
3441 0824d6fc bellard
3442 313aa567 bellard
    /* allocate RAM */
3443 1ccde1cb bellard
    cpu_register_physical_memory(0, ram_size, 0);
3444 313aa567 bellard
3445 77fef8c1 bellard
#if defined(TARGET_I386)
3446 77fef8c1 bellard
    /* RAW PC boot */
3447 77fef8c1 bellard
3448 77fef8c1 bellard
    /* BIOS load */
3449 77fef8c1 bellard
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
3450 77fef8c1 bellard
    ret = load_image(buf, phys_ram_base + 0x000f0000);
3451 77fef8c1 bellard
    if (ret != 0x10000) {
3452 77fef8c1 bellard
        fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
3453 77fef8c1 bellard
        exit(1);
3454 77fef8c1 bellard
    }
3455 77fef8c1 bellard
    
3456 77fef8c1 bellard
    /* VGA BIOS load */
3457 77fef8c1 bellard
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
3458 77fef8c1 bellard
    ret = load_image(buf, phys_ram_base + 0x000c0000);
3459 77fef8c1 bellard
    
3460 77fef8c1 bellard
    /* setup basic memory access */
3461 77fef8c1 bellard
    cpu_register_physical_memory(0xc0000, 0x10000, 0xc0000 | IO_MEM_ROM);
3462 77fef8c1 bellard
    cpu_register_physical_memory(0xf0000, 0x10000, 0xf0000 | IO_MEM_ROM);
3463 77fef8c1 bellard
    
3464 77fef8c1 bellard
    bochs_bios_init();
3465 77fef8c1 bellard
3466 330d0414 bellard
    if (linux_boot) {
3467 a735aa31 bellard
        uint8_t bootsect[512];
3468 77fef8c1 bellard
3469 77fef8c1 bellard
        if (bs_table[0] == NULL) {
3470 77fef8c1 bellard
            fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
3471 77fef8c1 bellard
            exit(1);
3472 77fef8c1 bellard
        }
3473 a735aa31 bellard
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
3474 a735aa31 bellard
        ret = load_image(buf, bootsect);
3475 a735aa31 bellard
        if (ret != sizeof(bootsect)) {
3476 a735aa31 bellard
            fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
3477 a735aa31 bellard
                    buf);
3478 a735aa31 bellard
            exit(1);
3479 a735aa31 bellard
        }
3480 a735aa31 bellard
3481 a735aa31 bellard
        bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
3482 77fef8c1 bellard
3483 330d0414 bellard
        /* now we can load the kernel */
3484 77fef8c1 bellard
        ret = load_kernel(kernel_filename, 
3485 77fef8c1 bellard
                          phys_ram_base + KERNEL_LOAD_ADDR,
3486 77fef8c1 bellard
                          phys_ram_base + KERNEL_PARAMS_ADDR);
3487 330d0414 bellard
        if (ret < 0) {
3488 36b486bb bellard
            fprintf(stderr, "qemu: could not load kernel '%s'\n", 
3489 a20dd508 bellard
                    kernel_filename);
3490 fc01f7e7 bellard
            exit(1);
3491 fc01f7e7 bellard
        }
3492 330d0414 bellard
        
3493 330d0414 bellard
        /* load initrd */
3494 330d0414 bellard
        initrd_size = 0;
3495 330d0414 bellard
        if (initrd_filename) {
3496 330d0414 bellard
            initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
3497 330d0414 bellard
            if (initrd_size < 0) {
3498 36b486bb bellard
                fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 
3499 330d0414 bellard
                        initrd_filename);
3500 330d0414 bellard
                exit(1);
3501 330d0414 bellard
            }
3502 330d0414 bellard
        }
3503 330d0414 bellard
        if (initrd_size > 0) {
3504 77fef8c1 bellard
            stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
3505 77fef8c1 bellard
            stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
3506 330d0414 bellard
        }
3507 77fef8c1 bellard
        pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
3508 77fef8c1 bellard
                kernel_cmdline);
3509 77fef8c1 bellard
        stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
3510 77fef8c1 bellard
        stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
3511 77fef8c1 bellard
                KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
3512 77fef8c1 bellard
        /* loader type */
3513 77fef8c1 bellard
        stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
3514 77fef8c1 bellard
    }
3515 c45886db bellard
#elif defined(TARGET_PPC)
3516 77fef8c1 bellard
    /* allocate ROM */
3517 77fef8c1 bellard
    //        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
3518 77fef8c1 bellard
    snprintf(buf, sizeof(buf), "%s", BIOS_FILENAME);
3519 77fef8c1 bellard
    printf("load BIOS at %p\n", phys_ram_base + 0x000f0000);
3520 77fef8c1 bellard
    ret = load_image(buf, phys_ram_base + 0x000f0000);
3521 77fef8c1 bellard
    if (ret != 0x10000) {
3522 77fef8c1 bellard
        fprintf(stderr, "qemu: could not load PPC bios '%s' (%d)\n%m\n",
3523 77fef8c1 bellard
                buf, ret);
3524 77fef8c1 bellard
        exit(1);
3525 0824d6fc bellard
    }
3526 77fef8c1 bellard
#endif
3527 0824d6fc bellard
3528 313aa567 bellard
    /* terminal init */
3529 a20dd508 bellard
    if (nographic) {
3530 313aa567 bellard
        dumb_display_init(ds);
3531 313aa567 bellard
    } else {
3532 313aa567 bellard
#ifdef CONFIG_SDL
3533 313aa567 bellard
        sdl_display_init(ds);
3534 313aa567 bellard
#else
3535 313aa567 bellard
        dumb_display_init(ds);
3536 313aa567 bellard
#endif
3537 313aa567 bellard
    }
3538 0824d6fc bellard
    /* init basic PC hardware */
3539 fc01f7e7 bellard
    register_ioport_write(0x80, 1, ioport80_write, 1);
3540 0824d6fc bellard
3541 1ccde1cb bellard
    vga_initialize(ds, phys_ram_base + ram_size, ram_size, 
3542 313aa567 bellard
             vga_ram_size);
3543 c45886db bellard
#if defined (TARGET_I386)
3544 0824d6fc bellard
    cmos_init();
3545 c45886db bellard
#endif
3546 0824d6fc bellard
    pic_init();
3547 0824d6fc bellard
    pit_init();
3548 0824d6fc bellard
    serial_init();
3549 c45886db bellard
#if defined (TARGET_I386)
3550 f1510b2c bellard
    ne2000_init();
3551 c45886db bellard
#endif
3552 fc01f7e7 bellard
    ide_init();
3553 cd4c3e88 bellard
    kbd_init();
3554 27503323 bellard
    AUD_init();
3555 27503323 bellard
    DMA_init();
3556 c45886db bellard
#if defined (TARGET_I386)
3557 27503323 bellard
    SB16_init();
3558 c45886db bellard
#endif
3559 c45886db bellard
#if defined (TARGET_PPC)
3560 c45886db bellard
    PPC_end_init();
3561 c45886db bellard
#endif
3562 c45886db bellard
    fdctrl_register((unsigned char **)fd_filename, snapshot, boot_device);
3563 77fef8c1 bellard
3564 0824d6fc bellard
    /* setup cpu signal handlers for MMU / self modifying code handling */
3565 77fef8c1 bellard
#if !defined(CONFIG_SOFTMMU)
3566 77fef8c1 bellard
3567 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3568 77fef8c1 bellard
    {
3569 77fef8c1 bellard
        stack_t stk;
3570 77fef8c1 bellard
        signal_stack = malloc(SIGNAL_STACK_SIZE);
3571 77fef8c1 bellard
        stk.ss_sp = signal_stack;
3572 77fef8c1 bellard
        stk.ss_size = SIGNAL_STACK_SIZE;
3573 77fef8c1 bellard
        stk.ss_flags = 0;
3574 77fef8c1 bellard
3575 77fef8c1 bellard
        if (sigaltstack(&stk, NULL) < 0) {
3576 77fef8c1 bellard
            perror("sigaltstack");
3577 77fef8c1 bellard
            exit(1);
3578 77fef8c1 bellard
        }
3579 77fef8c1 bellard
    }
3580 77fef8c1 bellard
#endif
3581 77fef8c1 bellard
        
3582 0824d6fc bellard
    sigfillset(&act.sa_mask);
3583 0824d6fc bellard
    act.sa_flags = SA_SIGINFO;
3584 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3585 77fef8c1 bellard
    act.sa_flags |= SA_ONSTACK;
3586 77fef8c1 bellard
#endif
3587 0824d6fc bellard
    act.sa_sigaction = host_segv_handler;
3588 0824d6fc bellard
    sigaction(SIGSEGV, &act, NULL);
3589 0824d6fc bellard
    sigaction(SIGBUS, &act, NULL);
3590 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3591 77fef8c1 bellard
    sigaction(SIGFPE, &act, NULL);
3592 77fef8c1 bellard
#endif
3593 3a51dee6 bellard
#endif
3594 0824d6fc bellard
3595 77fef8c1 bellard
    /* timer signal */
3596 77fef8c1 bellard
    sigfillset(&act.sa_mask);
3597 77fef8c1 bellard
    act.sa_flags = SA_SIGINFO;
3598 77fef8c1 bellard
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
3599 77fef8c1 bellard
    act.sa_flags |= SA_ONSTACK;
3600 77fef8c1 bellard
#endif
3601 0824d6fc bellard
    act.sa_sigaction = host_alarm_handler;
3602 0824d6fc bellard
    sigaction(SIGALRM, &act, NULL);
3603 0824d6fc bellard
3604 0824d6fc bellard
    itv.it_interval.tv_sec = 0;
3605 87858c89 bellard
    itv.it_interval.tv_usec = 1000;
3606 0824d6fc bellard
    itv.it_value.tv_sec = 0;
3607 0824d6fc bellard
    itv.it_value.tv_usec = 10 * 1000;
3608 0824d6fc bellard
    setitimer(ITIMER_REAL, &itv, NULL);
3609 87858c89 bellard
    /* we probe the tick duration of the kernel to inform the user if
3610 87858c89 bellard
       the emulated kernel requested a too high timer frequency */
3611 87858c89 bellard
    getitimer(ITIMER_REAL, &itv);
3612 313aa567 bellard
    timer_ms = itv.it_interval.tv_usec / 1000;
3613 87858c89 bellard
    pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / 
3614 87858c89 bellard
        1000000;
3615 7f7f9873 bellard
3616 b4608c04 bellard
    if (use_gdbstub) {
3617 b4608c04 bellard
        cpu_gdbstub(NULL, main_loop, gdbstub_port);
3618 b4608c04 bellard
    } else {
3619 b4608c04 bellard
        main_loop(NULL);
3620 0824d6fc bellard
    }
3621 0824d6fc bellard
    return 0;
3622 0824d6fc bellard
}