Statistics
| Branch: | Revision:

root / vl.c @ 8dc75d75

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