Revision 80cabfad

b/Makefile.target
1 1
include config.mak
2 2

  
3 3
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
4
VPATH=$(SRC_PATH):$(TARGET_PATH)
4
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw
5 5
CFLAGS=-Wall -O2 -g
6 6
LDFLAGS=-g
7 7
LIBS=
......
204 204
endif
205 205

  
206 206
# must use static linking to avoid leaving stuff in virtual address space
207
VL_OBJS=vl.o block.o ide.o vga.o sb16.o dma.o oss.o fdc.o osdep.o
207
VL_OBJS=vl.o osdep.o block.o ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o \
208
        fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
208 209
ifeq ($(TARGET_ARCH), ppc)
209 210
VL_OBJS+= hw.o
210 211
endif
b/hw/i8254.c
1
/*
2
 * QEMU 8253/8254 interval timer emulation
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

  
43
#include "cpu.h"
44
#include "vl.h"
45

  
46
#define RW_STATE_LSB 0
47
#define RW_STATE_MSB 1
48
#define RW_STATE_WORD0 2
49
#define RW_STATE_WORD1 3
50
#define RW_STATE_LATCHED_WORD0 4
51
#define RW_STATE_LATCHED_WORD1 5
52

  
53
PITChannelState pit_channels[3];
54

  
55
static int pit_get_count(PITChannelState *s)
56
{
57
    uint64_t d;
58
    int counter;
59

  
60
    d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
61
    switch(s->mode) {
62
    case 0:
63
    case 1:
64
    case 4:
65
    case 5:
66
        counter = (s->count - d) & 0xffff;
67
        break;
68
    case 3:
69
        /* XXX: may be incorrect for odd counts */
70
        counter = s->count - ((2 * d) % s->count);
71
        break;
72
    default:
73
        counter = s->count - (d % s->count);
74
        break;
75
    }
76
    return counter;
77
}
78

  
79
/* get pit output bit */
80
int pit_get_out(PITChannelState *s)
81
{
82
    uint64_t d;
83
    int out;
84

  
85
    d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
86
    switch(s->mode) {
87
    default:
88
    case 0:
89
        out = (d >= s->count);
90
        break;
91
    case 1:
92
        out = (d < s->count);
93
        break;
94
    case 2:
95
        if ((d % s->count) == 0 && d != 0)
96
            out = 1;
97
        else
98
            out = 0;
99
        break;
100
    case 3:
101
        out = (d % s->count) < ((s->count + 1) >> 1);
102
        break;
103
    case 4:
104
    case 5:
105
        out = (d == s->count);
106
        break;
107
    }
108
    return out;
109
}
110

  
111
/* get the number of 0 to 1 transitions we had since we call this
112
   function */
113
/* XXX: maybe better to use ticks precision to avoid getting edges
114
   twice if checks are done at very small intervals */
115
int pit_get_out_edges(PITChannelState *s)
116
{
117
    uint64_t d1, d2;
118
    int64_t ticks;
119
    int ret, v;
120

  
121
    ticks = cpu_get_ticks();
122
    d1 = muldiv64(s->count_last_edge_check_time - s->count_load_time, 
123
                 PIT_FREQ, ticks_per_sec);
124
    d2 = muldiv64(ticks - s->count_load_time, 
125
                  PIT_FREQ, ticks_per_sec);
126
    s->count_last_edge_check_time = ticks;
127
    switch(s->mode) {
128
    default:
129
    case 0:
130
        if (d1 < s->count && d2 >= s->count)
131
            ret = 1;
132
        else
133
            ret = 0;
134
        break;
135
    case 1:
136
        ret = 0;
137
        break;
138
    case 2:
139
        d1 /= s->count;
140
        d2 /= s->count;
141
        ret = d2 - d1;
142
        break;
143
    case 3:
144
        v = s->count - ((s->count + 1) >> 1);
145
        d1 = (d1 + v) / s->count;
146
        d2 = (d2 + v) / s->count;
147
        ret = d2 - d1;
148
        break;
149
    case 4:
150
    case 5:
151
        if (d1 < s->count && d2 >= s->count)
152
            ret = 1;
153
        else
154
            ret = 0;
155
        break;
156
    }
157
    return ret;
158
}
159

  
160
/* val must be 0 or 1 */
161
void pit_set_gate(PITChannelState *s, int val)
162
{
163
    switch(s->mode) {
164
    default:
165
    case 0:
166
    case 4:
167
        /* XXX: just disable/enable counting */
168
        break;
169
    case 1:
170
    case 5:
171
        if (s->gate < val) {
172
            /* restart counting on rising edge */
173
            s->count_load_time = cpu_get_ticks();
174
            s->count_last_edge_check_time = s->count_load_time;
175
        }
176
        break;
177
    case 2:
178
    case 3:
179
        if (s->gate < val) {
180
            /* restart counting on rising edge */
181
            s->count_load_time = cpu_get_ticks();
182
            s->count_last_edge_check_time = s->count_load_time;
183
        }
184
        /* XXX: disable/enable counting */
185
        break;
186
    }
187
    s->gate = val;
188
}
189

  
190
static inline void pit_load_count(PITChannelState *s, int val)
191
{
192
    if (val == 0)
193
        val = 0x10000;
194
    s->count_load_time = cpu_get_ticks();
195
    s->count_last_edge_check_time = s->count_load_time;
196
    s->count = val;
197
    if (s == &pit_channels[0] && val <= pit_min_timer_count) {
198
        fprintf(stderr, 
199
                "\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", 
200
                PIT_FREQ / pit_min_timer_count);
201
    }
202
}
203

  
204
void pit_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
205
{
206
    int channel, access;
207
    PITChannelState *s;
208

  
209
    addr &= 3;
210
    if (addr == 3) {
211
        channel = val >> 6;
212
        if (channel == 3)
213
            return;
214
        s = &pit_channels[channel];
215
        access = (val >> 4) & 3;
216
        switch(access) {
217
        case 0:
218
            s->latched_count = pit_get_count(s);
219
            s->rw_state = RW_STATE_LATCHED_WORD0;
220
            break;
221
        default:
222
            s->mode = (val >> 1) & 7;
223
            s->bcd = val & 1;
224
            s->rw_state = access - 1 +  RW_STATE_LSB;
225
            break;
226
        }
227
    } else {
228
        s = &pit_channels[addr];
229
        switch(s->rw_state) {
230
        case RW_STATE_LSB:
231
            pit_load_count(s, val);
232
            break;
233
        case RW_STATE_MSB:
234
            pit_load_count(s, val << 8);
235
            break;
236
        case RW_STATE_WORD0:
237
        case RW_STATE_WORD1:
238
            if (s->rw_state & 1) {
239
                pit_load_count(s, (s->latched_count & 0xff) | (val << 8));
240
            } else {
241
                s->latched_count = val;
242
            }
243
            s->rw_state ^= 1;
244
            break;
245
        }
246
    }
247
}
248

  
249
uint32_t pit_ioport_read(CPUState *env, uint32_t addr)
250
{
251
    int ret, count;
252
    PITChannelState *s;
253
    
254
    addr &= 3;
255
    s = &pit_channels[addr];
256
    switch(s->rw_state) {
257
    case RW_STATE_LSB:
258
    case RW_STATE_MSB:
259
    case RW_STATE_WORD0:
260
    case RW_STATE_WORD1:
261
        count = pit_get_count(s);
262
        if (s->rw_state & 1)
263
            ret = (count >> 8) & 0xff;
264
        else
265
            ret = count & 0xff;
266
        if (s->rw_state & 2)
267
            s->rw_state ^= 1;
268
        break;
269
    default:
270
    case RW_STATE_LATCHED_WORD0:
271
    case RW_STATE_LATCHED_WORD1:
272
        if (s->rw_state & 1)
273
            ret = s->latched_count >> 8;
274
        else
275
            ret = s->latched_count & 0xff;
276
        s->rw_state ^= 1;
277
        break;
278
    }
279
    return ret;
280
}
281

  
282
void pit_init(void)
283
{
284
    PITChannelState *s;
285
    int i;
286

  
287
    for(i = 0;i < 3; i++) {
288
        s = &pit_channels[i];
289
        s->mode = 3;
290
        s->gate = (i != 2);
291
        pit_load_count(s, 0);
292
    }
293

  
294
    register_ioport_write(0x40, 4, pit_ioport_write, 1);
295
    register_ioport_read(0x40, 3, pit_ioport_read, 1);
296
}
297

  
b/hw/i8259.c
1
/*
2
 * QEMU 8259 interrupt controller emulation
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

  
43
#include "cpu.h"
44
#include "vl.h"
45

  
46
/* debug PIC */
47
//#define DEBUG_PIC
48

  
49
typedef struct PicState {
50
    uint8_t last_irr; /* edge detection */
51
    uint8_t irr; /* interrupt request register */
52
    uint8_t imr; /* interrupt mask register */
53
    uint8_t isr; /* interrupt service register */
54
    uint8_t priority_add; /* highest irq priority */
55
    uint8_t irq_base;
56
    uint8_t read_reg_select;
57
    uint8_t poll;
58
    uint8_t special_mask;
59
    uint8_t init_state;
60
    uint8_t auto_eoi;
61
    uint8_t rotate_on_auto_eoi;
62
    uint8_t special_fully_nested_mode;
63
    uint8_t init4; /* true if 4 byte init */
64
} PicState;
65

  
66
/* 0 is master pic, 1 is slave pic */
67
PicState pics[2];
68
int pic_irq_requested;
69

  
70
/* set irq level. If an edge is detected, then the IRR is set to 1 */
71
static inline void pic_set_irq1(PicState *s, int irq, int level)
72
{
73
    int mask;
74
    mask = 1 << irq;
75
    if (level) {
76
        if ((s->last_irr & mask) == 0)
77
            s->irr |= mask;
78
        s->last_irr |= mask;
79
    } else {
80
        s->last_irr &= ~mask;
81
    }
82
}
83

  
84
/* return the highest priority found in mask (highest = smallest
85
   number). Return 8 if no irq */
86
static inline int get_priority(PicState *s, int mask)
87
{
88
    int priority;
89
    if (mask == 0)
90
        return 8;
91
    priority = 0;
92
    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
93
        priority++;
94
    return priority;
95
}
96

  
97
/* return the pic wanted interrupt. return -1 if none */
98
static int pic_get_irq(PicState *s)
99
{
100
    int mask, cur_priority, priority;
101

  
102
    mask = s->irr & ~s->imr;
103
    priority = get_priority(s, mask);
104
    if (priority == 8)
105
        return -1;
106
    /* compute current priority. If special fully nested mode on the
107
       master, the IRQ coming from the slave is not taken into account
108
       for the priority computation. */
109
    mask = s->isr;
110
    if (s->special_fully_nested_mode && s == &pics[0])
111
        mask &= ~(1 << 2);
112
    cur_priority = get_priority(s, mask);
113
    if (priority < cur_priority) {
114
        /* higher priority found: an irq should be generated */
115
        return (priority + s->priority_add) & 7;
116
    } else {
117
        return -1;
118
    }
119
}
120

  
121
/* raise irq to CPU if necessary. must be called every time the active
122
   irq may change */
123
void pic_update_irq(void)
124
{
125
    int irq2, irq;
126

  
127
    /* first look at slave pic */
128
    irq2 = pic_get_irq(&pics[1]);
129
    if (irq2 >= 0) {
130
        /* if irq request by slave pic, signal master PIC */
131
        pic_set_irq1(&pics[0], 2, 1);
132
        pic_set_irq1(&pics[0], 2, 0);
133
    }
134
    /* look at requested irq */
135
    irq = pic_get_irq(&pics[0]);
136
    if (irq >= 0) {
137
        if (irq == 2) {
138
            /* from slave pic */
139
            pic_irq_requested = 8 + irq2;
140
        } else {
141
            /* from master pic */
142
            pic_irq_requested = irq;
143
        }
144
#if defined(DEBUG_PIC)
145
        {
146
            int i;
147
            for(i = 0; i < 2; i++) {
148
                printf("pic%d: imr=%x irr=%x padd=%d\n", 
149
                       i, pics[i].imr, pics[i].irr, pics[i].priority_add);
150
                
151
            }
152
        }
153
        printf("pic: cpu_interrupt req=%d\n", pic_irq_requested);
154
#endif
155
        cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
156
    }
157
}
158

  
159
#ifdef DEBUG_IRQ_LATENCY
160
int64_t irq_time[16];
161
int64_t cpu_get_ticks(void);
162
#endif
163
#if defined(DEBUG_PIC)
164
int irq_level[16];
165
#endif
166

  
167
void pic_set_irq(int irq, int level)
168
{
169
#if defined(DEBUG_PIC)
170
    if (level != irq_level[irq]) {
171
        printf("pic_set_irq: irq=%d level=%d\n", irq, level);
172
        irq_level[irq] = level;
173
    }
174
#endif
175
#ifdef DEBUG_IRQ_LATENCY
176
    if (level) {
177
        irq_time[irq] = cpu_get_ticks();
178
    }
179
#endif
180
    pic_set_irq1(&pics[irq >> 3], irq & 7, level);
181
    pic_update_irq();
182
}
183

  
184
/* acknowledge interrupt 'irq' */
185
static inline void pic_intack(PicState *s, int irq)
186
{
187
    if (s->auto_eoi) {
188
        if (s->rotate_on_auto_eoi)
189
            s->priority_add = (irq + 1) & 7;
190
    } else {
191
        s->isr |= (1 << irq);
192
    }
193
    s->irr &= ~(1 << irq);
194
}
195

  
196
int cpu_x86_get_pic_interrupt(CPUState *env)
197
{
198
    int irq, irq2, intno;
199

  
200
    /* signal the pic that the irq was acked by the CPU */
201
    irq = pic_irq_requested;
202
#ifdef DEBUG_IRQ_LATENCY
203
    printf("IRQ%d latency=%0.3fus\n", 
204
           irq, 
205
           (double)(cpu_get_ticks() - irq_time[irq]) * 1000000.0 / ticks_per_sec);
206
#endif
207
#if defined(DEBUG_PIC)
208
    printf("pic_interrupt: irq=%d\n", irq);
209
#endif
210

  
211
    if (irq >= 8) {
212
        irq2 = irq & 7;
213
        pic_intack(&pics[1], irq2);
214
        irq = 2;
215
        intno = pics[1].irq_base + irq2;
216
    } else {
217
        intno = pics[0].irq_base + irq;
218
    }
219
    pic_intack(&pics[0], irq);
220
    return intno;
221
}
222

  
223
void pic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
224
{
225
    PicState *s;
226
    int priority, cmd, irq;
227

  
228
#ifdef DEBUG_PIC
229
    printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
230
#endif
231
    s = &pics[addr >> 7];
232
    addr &= 1;
233
    if (addr == 0) {
234
        if (val & 0x10) {
235
            /* init */
236
            memset(s, 0, sizeof(PicState));
237
            s->init_state = 1;
238
            s->init4 = val & 1;
239
            if (val & 0x02)
240
                hw_error("single mode not supported");
241
            if (val & 0x08)
242
                hw_error("level sensitive irq not supported");
243
        } else if (val & 0x08) {
244
            if (val & 0x04)
245
                s->poll = 1;
246
            if (val & 0x02)
247
                s->read_reg_select = val & 1;
248
            if (val & 0x40)
249
                s->special_mask = (val >> 5) & 1;
250
        } else {
251
            cmd = val >> 5;
252
            switch(cmd) {
253
            case 0:
254
            case 4:
255
                s->rotate_on_auto_eoi = cmd >> 2;
256
                break;
257
            case 1: /* end of interrupt */
258
            case 5:
259
                priority = get_priority(s, s->isr);
260
                if (priority != 8) {
261
                    irq = (priority + s->priority_add) & 7;
262
                    s->isr &= ~(1 << irq);
263
                    if (cmd == 5)
264
                        s->priority_add = (irq + 1) & 7;
265
                    pic_update_irq();
266
                }
267
                break;
268
            case 3:
269
                irq = val & 7;
270
                s->isr &= ~(1 << irq);
271
                pic_update_irq();
272
                break;
273
            case 6:
274
                s->priority_add = (val + 1) & 7;
275
                pic_update_irq();
276
                break;
277
            case 7:
278
                irq = val & 7;
279
                s->isr &= ~(1 << irq);
280
                s->priority_add = (irq + 1) & 7;
281
                pic_update_irq();
282
                break;
283
            default:
284
                /* no operation */
285
                break;
286
            }
287
        }
288
    } else {
289
        switch(s->init_state) {
290
        case 0:
291
            /* normal mode */
292
            s->imr = val;
293
            pic_update_irq();
294
            break;
295
        case 1:
296
            s->irq_base = val & 0xf8;
297
            s->init_state = 2;
298
            break;
299
        case 2:
300
            if (s->init4) {
301
                s->init_state = 3;
302
            } else {
303
                s->init_state = 0;
304
            }
305
            break;
306
        case 3:
307
            s->special_fully_nested_mode = (val >> 4) & 1;
308
            s->auto_eoi = (val >> 1) & 1;
309
            s->init_state = 0;
310
            break;
311
        }
312
    }
313
}
314

  
315
static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
316
{
317
    int ret;
318

  
319
    ret = pic_get_irq(s);
320
    if (ret >= 0) {
321
        if (addr1 >> 7) {
322
            pics[0].isr &= ~(1 << 2);
323
            pics[0].irr &= ~(1 << 2);
324
        }
325
        s->irr &= ~(1 << ret);
326
        s->isr &= ~(1 << ret);
327
        if (addr1 >> 7 || ret != 2)
328
            pic_update_irq();
329
    } else {
330
        ret = 0x07;
331
        pic_update_irq();
332
    }
333

  
334
    return ret;
335
}
336

  
337
uint32_t pic_ioport_read(CPUState *env, uint32_t addr1)
338
{
339
    PicState *s;
340
    unsigned int addr;
341
    int ret;
342

  
343
    addr = addr1;
344
    s = &pics[addr >> 7];
345
    addr &= 1;
346
    if (s->poll) {
347
        ret = pic_poll_read(s, addr1);
348
        s->poll = 0;
349
    } else {
350
        if (addr == 0) {
351
            if (s->read_reg_select)
352
                ret = s->isr;
353
            else
354
                ret = s->irr;
355
        } else {
356
            ret = s->imr;
357
        }
358
    }
359
#ifdef DEBUG_PIC
360
    printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
361
#endif
362
    return ret;
363
}
364

  
365
/* memory mapped interrupt status */
366
uint32_t pic_intack_read(CPUState *env)
367
{
368
    int ret;
369

  
370
    ret = pic_poll_read(&pics[0], 0x00);
371
    if (ret == 2)
372
        ret = pic_poll_read(&pics[1], 0x80) + 8;
373
    /* Prepare for ISR read */
374
    pics[0].read_reg_select = 1;
375
    
376
    return ret;
377
}
378

  
379
void pic_init(void)
380
{
381
#if defined (TARGET_I386) || defined (TARGET_PPC)
382
    register_ioport_write(0x20, 2, pic_ioport_write, 1);
383
    register_ioport_read(0x20, 2, pic_ioport_read, 1);
384
    register_ioport_write(0xa0, 2, pic_ioport_write, 1);
385
    register_ioport_read(0xa0, 2, pic_ioport_read, 1);
386
#endif
387
}
388

  
b/hw/mc146818rtc.c
1
/*
2
 * QEMU MC146818 RTC emulation
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

  
43
#include "cpu.h"
44
#include "vl.h"
45

  
46
//#define DEBUG_CMOS
47

  
48
#define RTC_SECONDS             0
49
#define RTC_SECONDS_ALARM       1
50
#define RTC_MINUTES             2
51
#define RTC_MINUTES_ALARM       3
52
#define RTC_HOURS               4
53
#define RTC_HOURS_ALARM         5
54
#define RTC_ALARM_DONT_CARE    0xC0
55

  
56
#define RTC_DAY_OF_WEEK         6
57
#define RTC_DAY_OF_MONTH        7
58
#define RTC_MONTH               8
59
#define RTC_YEAR                9
60

  
61
#define RTC_REG_A               10
62
#define RTC_REG_B               11
63
#define RTC_REG_C               12
64
#define RTC_REG_D               13
65

  
66
/* PC cmos mappings */
67
#define REG_IBM_CENTURY_BYTE        0x32
68
#define REG_IBM_PS2_CENTURY_BYTE    0x37
69

  
70
RTCState rtc_state;
71

  
72
static void cmos_ioport_write(CPUState *env, uint32_t addr, uint32_t data)
73
{
74
    RTCState *s = &rtc_state;
75

  
76
    if ((addr & 1) == 0) {
77
        s->cmos_index = data & 0x7f;
78
    } else {
79
#ifdef DEBUG_CMOS
80
        printf("cmos: write index=0x%02x val=0x%02x\n",
81
               s->cmos_index, data);
82
#endif        
83
        switch(addr) {
84
        case RTC_SECONDS_ALARM:
85
        case RTC_MINUTES_ALARM:
86
        case RTC_HOURS_ALARM:
87
            /* XXX: not supported */
88
            s->cmos_data[s->cmos_index] = data;
89
            break;
90
        case RTC_SECONDS:
91
        case RTC_MINUTES:
92
        case RTC_HOURS:
93
        case RTC_DAY_OF_WEEK:
94
        case RTC_DAY_OF_MONTH:
95
        case RTC_MONTH:
96
        case RTC_YEAR:
97
            s->cmos_data[s->cmos_index] = data;
98
            break;
99
        case RTC_REG_A:
100
        case RTC_REG_B:
101
            s->cmos_data[s->cmos_index] = data;
102
            break;
103
        case RTC_REG_C:
104
        case RTC_REG_D:
105
            /* cannot write to them */
106
            break;
107
        default:
108
            s->cmos_data[s->cmos_index] = data;
109
            break;
110
        }
111
    }
112
}
113

  
114
static inline int to_bcd(int a)
115
{
116
    return ((a / 10) << 4) | (a % 10);
117
}
118

  
119
static void cmos_update_time(RTCState *s)
120
{
121
    struct tm *tm;
122
    time_t ti;
123

  
124
    ti = time(NULL);
125
    tm = gmtime(&ti);
126
    s->cmos_data[RTC_SECONDS] = to_bcd(tm->tm_sec);
127
    s->cmos_data[RTC_MINUTES] = to_bcd(tm->tm_min);
128
    s->cmos_data[RTC_HOURS] = to_bcd(tm->tm_hour);
129
    s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(tm->tm_wday);
130
    s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(tm->tm_mday);
131
    s->cmos_data[RTC_MONTH] = to_bcd(tm->tm_mon + 1);
132
    s->cmos_data[RTC_YEAR] = to_bcd(tm->tm_year % 100);
133
    s->cmos_data[REG_IBM_CENTURY_BYTE] = to_bcd((tm->tm_year / 100) + 19);
134
    s->cmos_data[REG_IBM_PS2_CENTURY_BYTE] = s->cmos_data[REG_IBM_CENTURY_BYTE];
135
}
136

  
137
static uint32_t cmos_ioport_read(CPUState *env, uint32_t addr)
138
{
139
    RTCState *s = &rtc_state;
140
    int ret;
141
    if ((addr & 1) == 0) {
142
        return 0xff;
143
    } else {
144
        switch(s->cmos_index) {
145
        case RTC_SECONDS:
146
        case RTC_MINUTES:
147
        case RTC_HOURS:
148
        case RTC_DAY_OF_WEEK:
149
        case RTC_DAY_OF_MONTH:
150
        case RTC_MONTH:
151
        case RTC_YEAR:
152
        case REG_IBM_CENTURY_BYTE:
153
        case REG_IBM_PS2_CENTURY_BYTE:
154
            cmos_update_time(s);
155
            ret = s->cmos_data[s->cmos_index];
156
            break;
157
        case RTC_REG_A:
158
            ret = s->cmos_data[s->cmos_index];
159
            /* toggle update-in-progress bit for Linux (same hack as
160
               plex86) */
161
            s->cmos_data[RTC_REG_A] ^= 0x80; 
162
            break;
163
        case RTC_REG_C:
164
            ret = s->cmos_data[s->cmos_index];
165
            pic_set_irq(s->irq, 0);
166
            s->cmos_data[RTC_REG_C] = 0x00; 
167
            break;
168
        default:
169
            ret = s->cmos_data[s->cmos_index];
170
            break;
171
        }
172
#ifdef DEBUG_CMOS
173
        printf("cmos: read index=0x%02x val=0x%02x\n",
174
               s->cmos_index, ret);
175
#endif
176
        return ret;
177
    }
178
}
179

  
180
void rtc_timer(void)
181
{
182
    RTCState *s = &rtc_state;
183
    if (s->cmos_data[RTC_REG_B] & 0x50) {
184
        pic_set_irq(s->irq, 1);
185
    }
186
}
187

  
188
void rtc_init(int base, int irq)
189
{
190
    RTCState *s = &rtc_state;
191

  
192
    cmos_update_time(s);
193

  
194
    s->irq = irq;
195
    s->cmos_data[RTC_REG_A] = 0x26;
196
    s->cmos_data[RTC_REG_B] = 0x02;
197
    s->cmos_data[RTC_REG_C] = 0x00;
198
    s->cmos_data[RTC_REG_D] = 0x80;
199

  
200
    register_ioport_write(base, 2, cmos_ioport_write, 1);
201
    register_ioport_read(base, 2, cmos_ioport_read, 1);
202
}
203

  
b/hw/ne2000.c
1
/*
2
 * QEMU NE2000 emulation
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

  
43
#include "cpu.h"
44
#include "vl.h"
45

  
46
/* debug NE2000 card */
47
//#define DEBUG_NE2000
48

  
49
/***********************************************************/
50
/* ne2000 emulation */
51

  
52
#define E8390_CMD	0x00  /* The command register (for all pages) */
53
/* Page 0 register offsets. */
54
#define EN0_CLDALO	0x01	/* Low byte of current local dma addr  RD */
55
#define EN0_STARTPG	0x01	/* Starting page of ring bfr WR */
56
#define EN0_CLDAHI	0x02	/* High byte of current local dma addr  RD */
57
#define EN0_STOPPG	0x02	/* Ending page +1 of ring bfr WR */
58
#define EN0_BOUNDARY	0x03	/* Boundary page of ring bfr RD WR */
59
#define EN0_TSR		0x04	/* Transmit status reg RD */
60
#define EN0_TPSR	0x04	/* Transmit starting page WR */
61
#define EN0_NCR		0x05	/* Number of collision reg RD */
62
#define EN0_TCNTLO	0x05	/* Low  byte of tx byte count WR */
63
#define EN0_FIFO	0x06	/* FIFO RD */
64
#define EN0_TCNTHI	0x06	/* High byte of tx byte count WR */
65
#define EN0_ISR		0x07	/* Interrupt status reg RD WR */
66
#define EN0_CRDALO	0x08	/* low byte of current remote dma address RD */
67
#define EN0_RSARLO	0x08	/* Remote start address reg 0 */
68
#define EN0_CRDAHI	0x09	/* high byte, current remote dma address RD */
69
#define EN0_RSARHI	0x09	/* Remote start address reg 1 */
70
#define EN0_RCNTLO	0x0a	/* Remote byte count reg WR */
71
#define EN0_RCNTHI	0x0b	/* Remote byte count reg WR */
72
#define EN0_RSR		0x0c	/* rx status reg RD */
73
#define EN0_RXCR	0x0c	/* RX configuration reg WR */
74
#define EN0_TXCR	0x0d	/* TX configuration reg WR */
75
#define EN0_COUNTER0	0x0d	/* Rcv alignment error counter RD */
76
#define EN0_DCFG	0x0e	/* Data configuration reg WR */
77
#define EN0_COUNTER1	0x0e	/* Rcv CRC error counter RD */
78
#define EN0_IMR		0x0f	/* Interrupt mask reg WR */
79
#define EN0_COUNTER2	0x0f	/* Rcv missed frame error counter RD */
80

  
81
#define EN1_PHYS        0x11
82
#define EN1_CURPAG      0x17
83
#define EN1_MULT        0x18
84

  
85
/*  Register accessed at EN_CMD, the 8390 base addr.  */
86
#define E8390_STOP	0x01	/* Stop and reset the chip */
87
#define E8390_START	0x02	/* Start the chip, clear reset */
88
#define E8390_TRANS	0x04	/* Transmit a frame */
89
#define E8390_RREAD	0x08	/* Remote read */
90
#define E8390_RWRITE	0x10	/* Remote write  */
91
#define E8390_NODMA	0x20	/* Remote DMA */
92
#define E8390_PAGE0	0x00	/* Select page chip registers */
93
#define E8390_PAGE1	0x40	/* using the two high-order bits */
94
#define E8390_PAGE2	0x80	/* Page 3 is invalid. */
95

  
96
/* Bits in EN0_ISR - Interrupt status register */
97
#define ENISR_RX	0x01	/* Receiver, no error */
98
#define ENISR_TX	0x02	/* Transmitter, no error */
99
#define ENISR_RX_ERR	0x04	/* Receiver, with error */
100
#define ENISR_TX_ERR	0x08	/* Transmitter, with error */
101
#define ENISR_OVER	0x10	/* Receiver overwrote the ring */
102
#define ENISR_COUNTERS	0x20	/* Counters need emptying */
103
#define ENISR_RDC	0x40	/* remote dma complete */
104
#define ENISR_RESET	0x80	/* Reset completed */
105
#define ENISR_ALL	0x3f	/* Interrupts we will enable */
106

  
107
/* Bits in received packet status byte and EN0_RSR*/
108
#define ENRSR_RXOK	0x01	/* Received a good packet */
109
#define ENRSR_CRC	0x02	/* CRC error */
110
#define ENRSR_FAE	0x04	/* frame alignment error */
111
#define ENRSR_FO	0x08	/* FIFO overrun */
112
#define ENRSR_MPA	0x10	/* missed pkt */
113
#define ENRSR_PHY	0x20	/* physical/multicast address */
114
#define ENRSR_DIS	0x40	/* receiver disable. set in monitor mode */
115
#define ENRSR_DEF	0x80	/* deferring */
116

  
117
/* Transmitted packet status, EN0_TSR. */
118
#define ENTSR_PTX 0x01	/* Packet transmitted without error */
119
#define ENTSR_ND  0x02	/* The transmit wasn't deferred. */
120
#define ENTSR_COL 0x04	/* The transmit collided at least once. */
121
#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
122
#define ENTSR_CRS 0x10	/* The carrier sense was lost. */
123
#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
124
#define ENTSR_CDH 0x40	/* The collision detect "heartbeat" signal was lost. */
125
#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
126

  
127
#define NE2000_MEM_SIZE 32768
128

  
129
typedef struct NE2000State {
130
    uint8_t cmd;
131
    uint32_t start;
132
    uint32_t stop;
133
    uint8_t boundary;
134
    uint8_t tsr;
135
    uint8_t tpsr;
136
    uint16_t tcnt;
137
    uint16_t rcnt;
138
    uint32_t rsar;
139
    uint8_t isr;
140
    uint8_t dcfg;
141
    uint8_t imr;
142
    uint8_t phys[6]; /* mac address */
143
    uint8_t curpag;
144
    uint8_t mult[8]; /* multicast mask array */
145
    int irq;
146
    uint8_t mem[NE2000_MEM_SIZE];
147
} NE2000State;
148

  
149
static NE2000State ne2000_state;
150
int net_fd = -1;
151

  
152
static void ne2000_reset(NE2000State *s)
153
{
154
    int i;
155

  
156
    s->isr = ENISR_RESET;
157
    s->mem[0] = 0x52;
158
    s->mem[1] = 0x54;
159
    s->mem[2] = 0x00;
160
    s->mem[3] = 0x12;
161
    s->mem[4] = 0x34;
162
    s->mem[5] = 0x56;
163
    s->mem[14] = 0x57;
164
    s->mem[15] = 0x57;
165

  
166
    /* duplicate prom data */
167
    for(i = 15;i >= 0; i--) {
168
        s->mem[2 * i] = s->mem[i];
169
        s->mem[2 * i + 1] = s->mem[i];
170
    }
171
}
172

  
173
static void ne2000_update_irq(NE2000State *s)
174
{
175
    int isr;
176
    isr = s->isr & s->imr;
177
    if (isr)
178
        pic_set_irq(s->irq, 1);
179
    else
180
        pic_set_irq(s->irq, 0);
181
}
182

  
183
/* return true if the NE2000 can receive more data */
184
int ne2000_can_receive(void)
185
{
186
    NE2000State *s = &ne2000_state;
187
    int avail, index, boundary;
188
    
189
    if (s->cmd & E8390_STOP)
190
        return 0;
191
    index = s->curpag << 8;
192
    boundary = s->boundary << 8;
193
    if (index < boundary)
194
        avail = boundary - index;
195
    else
196
        avail = (s->stop - s->start) - (index - boundary);
197
    if (avail < (MAX_ETH_FRAME_SIZE + 4))
198
        return 0;
199
    return 1;
200
}
201

  
202
void ne2000_receive(uint8_t *buf, int size)
203
{
204
    NE2000State *s = &ne2000_state;
205
    uint8_t *p;
206
    int total_len, next, avail, len, index;
207

  
208
#if defined(DEBUG_NE2000)
209
    printf("NE2000: received len=%d\n", size);
210
#endif
211

  
212
    index = s->curpag << 8;
213
    /* 4 bytes for header */
214
    total_len = size + 4;
215
    /* address for next packet (4 bytes for CRC) */
216
    next = index + ((total_len + 4 + 255) & ~0xff);
217
    if (next >= s->stop)
218
        next -= (s->stop - s->start);
219
    /* prepare packet header */
220
    p = s->mem + index;
221
    p[0] = ENRSR_RXOK; /* receive status */
222
    p[1] = next >> 8;
223
    p[2] = total_len;
224
    p[3] = total_len >> 8;
225
    index += 4;
226

  
227
    /* write packet data */
228
    while (size > 0) {
229
        avail = s->stop - index;
230
        len = size;
231
        if (len > avail)
232
            len = avail;
233
        memcpy(s->mem + index, buf, len);
234
        buf += len;
235
        index += len;
236
        if (index == s->stop)
237
            index = s->start;
238
        size -= len;
239
    }
240
    s->curpag = next >> 8;
241
    
242
    /* now we can signal we have receive something */
243
    s->isr |= ENISR_RX;
244
    ne2000_update_irq(s);
245
}
246

  
247
static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
248
{
249
    NE2000State *s = &ne2000_state;
250
    int offset, page;
251

  
252
    addr &= 0xf;
253
#ifdef DEBUG_NE2000
254
    printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
255
#endif
256
    if (addr == E8390_CMD) {
257
        /* control register */
258
        s->cmd = val;
259
        if (val & E8390_START) {
260
            /* test specific case: zero length transfert */
261
            if ((val & (E8390_RREAD | E8390_RWRITE)) &&
262
                s->rcnt == 0) {
263
                s->isr |= ENISR_RDC;
264
                ne2000_update_irq(s);
265
            }
266
            if (val & E8390_TRANS) {
267
                net_send_packet(net_fd, s->mem + (s->tpsr << 8), s->tcnt);
268
                /* signal end of transfert */
269
                s->tsr = ENTSR_PTX;
270
                s->isr |= ENISR_TX;
271
                ne2000_update_irq(s);
272
            }
273
        }
274
    } else {
275
        page = s->cmd >> 6;
276
        offset = addr | (page << 4);
277
        switch(offset) {
278
        case EN0_STARTPG:
279
            s->start = val << 8;
280
            break;
281
        case EN0_STOPPG:
282
            s->stop = val << 8;
283
            break;
284
        case EN0_BOUNDARY:
285
            s->boundary = val;
286
            break;
287
        case EN0_IMR:
288
            s->imr = val;
289
            ne2000_update_irq(s);
290
            break;
291
        case EN0_TPSR:
292
            s->tpsr = val;
293
            break;
294
        case EN0_TCNTLO:
295
            s->tcnt = (s->tcnt & 0xff00) | val;
296
            break;
297
        case EN0_TCNTHI:
298
            s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
299
            break;
300
        case EN0_RSARLO:
301
            s->rsar = (s->rsar & 0xff00) | val;
302
            break;
303
        case EN0_RSARHI:
304
            s->rsar = (s->rsar & 0x00ff) | (val << 8);
305
            break;
306
        case EN0_RCNTLO:
307
            s->rcnt = (s->rcnt & 0xff00) | val;
308
            break;
309
        case EN0_RCNTHI:
310
            s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
311
            break;
312
        case EN0_DCFG:
313
            s->dcfg = val;
314
            break;
315
        case EN0_ISR:
316
            s->isr &= ~val;
317
            ne2000_update_irq(s);
318
            break;
319
        case EN1_PHYS ... EN1_PHYS + 5:
320
            s->phys[offset - EN1_PHYS] = val;
321
            break;
322
        case EN1_CURPAG:
323
            s->curpag = val;
324
            break;
325
        case EN1_MULT ... EN1_MULT + 7:
326
            s->mult[offset - EN1_MULT] = val;
327
            break;
328
        }
329
    }
330
}
331

  
332
static uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr)
333
{
334
    NE2000State *s = &ne2000_state;
335
    int offset, page, ret;
336

  
337
    addr &= 0xf;
338
    if (addr == E8390_CMD) {
339
        ret = s->cmd;
340
    } else {
341
        page = s->cmd >> 6;
342
        offset = addr | (page << 4);
343
        switch(offset) {
344
        case EN0_TSR:
345
            ret = s->tsr;
346
            break;
347
        case EN0_BOUNDARY:
348
            ret = s->boundary;
349
            break;
350
        case EN0_ISR:
351
            ret = s->isr;
352
            break;
353
        case EN1_PHYS ... EN1_PHYS + 5:
354
            ret = s->phys[offset - EN1_PHYS];
355
            break;
356
        case EN1_CURPAG:
357
            ret = s->curpag;
358
            break;
359
        case EN1_MULT ... EN1_MULT + 7:
360
            ret = s->mult[offset - EN1_MULT];
361
            break;
362
        default:
363
            ret = 0x00;
364
            break;
365
        }
366
    }
367
#ifdef DEBUG_NE2000
368
    printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
369
#endif
370
    return ret;
371
}
372

  
373
static void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
374
{
375
    NE2000State *s = &ne2000_state;
376
    uint8_t *p;
377

  
378
#ifdef DEBUG_NE2000
379
    printf("NE2000: asic write val=0x%04x\n", val);
380
#endif
381
    p = s->mem + s->rsar;
382
    if (s->dcfg & 0x01) {
383
        /* 16 bit access */
384
        p[0] = val;
385
        p[1] = val >> 8;
386
        s->rsar += 2;
387
        s->rcnt -= 2;
388
    } else {
389
        /* 8 bit access */
390
        p[0] = val;
391
        s->rsar++;
392
        s->rcnt--;
393
    }
394
    /* wrap */
395
    if (s->rsar == s->stop)
396
        s->rsar = s->start;
397
    if (s->rcnt == 0) {
398
        /* signal end of transfert */
399
        s->isr |= ENISR_RDC;
400
        ne2000_update_irq(s);
401
    }
402
}
403

  
404
static uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr)
405
{
406
    NE2000State *s = &ne2000_state;
407
    uint8_t *p;
408
    int ret;
409

  
410
    p = s->mem + s->rsar;
411
    if (s->dcfg & 0x01) {
412
        /* 16 bit access */
413
        ret = p[0] | (p[1] << 8);
414
        s->rsar += 2;
415
        s->rcnt -= 2;
416
    } else {
417
        /* 8 bit access */
418
        ret = p[0];
419
        s->rsar++;
420
        s->rcnt--;
421
    }
422
    /* wrap */
423
    if (s->rsar == s->stop)
424
        s->rsar = s->start;
425
    if (s->rcnt == 0) {
426
        /* signal end of transfert */
427
        s->isr |= ENISR_RDC;
428
        ne2000_update_irq(s);
429
    }
430
#ifdef DEBUG_NE2000
431
    printf("NE2000: asic read val=0x%04x\n", ret);
432
#endif
433
    return ret;
434
}
435

  
436
static void ne2000_reset_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
437
{
438
    /* nothing to do (end of reset pulse) */
439
}
440

  
441
static uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr)
442
{
443
    NE2000State *s = &ne2000_state;
444
    ne2000_reset(s);
445
    return 0;
446
}
447

  
448
void ne2000_init(int base, int irq)
449
{
450
    NE2000State *s = &ne2000_state;
451

  
452
    register_ioport_write(base, 16, ne2000_ioport_write, 1);
453
    register_ioport_read(base, 16, ne2000_ioport_read, 1);
454

  
455
    register_ioport_write(base + 0x10, 1, ne2000_asic_ioport_write, 1);
456
    register_ioport_read(base + 0x10, 1, ne2000_asic_ioport_read, 1);
457
    register_ioport_write(base + 0x10, 2, ne2000_asic_ioport_write, 2);
458
    register_ioport_read(base + 0x10, 2, ne2000_asic_ioport_read, 2);
459

  
460
    register_ioport_write(base + 0x1f, 1, ne2000_reset_ioport_write, 1);
461
    register_ioport_read(base + 0x1f, 1, ne2000_reset_ioport_read, 1);
462
    s->irq = irq;
463

  
464
    ne2000_reset(s);
465
}
b/hw/pc.c
1
/*
2
 * QEMU PC System Emulator
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

  
43
#include "cpu.h"
44
#include "vl.h"
45

  
46
#define BIOS_FILENAME "bios.bin"
47
#define VGABIOS_FILENAME "vgabios.bin"
48
#define LINUX_BOOT_FILENAME "linux_boot.bin"
49

  
50
#define KERNEL_LOAD_ADDR     0x00100000
51
#define INITRD_LOAD_ADDR     0x00400000
52
#define KERNEL_PARAMS_ADDR   0x00090000
53
#define KERNEL_CMDLINE_ADDR  0x00099000
54

  
55
int speaker_data_on;
56
int dummy_refresh_clock;
57

  
58
static void ioport80_write(CPUState *env, uint32_t addr, uint32_t data)
59
{
60
}
61

  
62
#define REG_EQUIPMENT_BYTE          0x14
63

  
64
static void cmos_init(int ram_size, int boot_device)
65
{
66
    RTCState *s = &rtc_state;
67
    int val;
68
    
69
    /* various important CMOS locations needed by PC/Bochs bios */
70

  
71
    s->cmos_data[REG_EQUIPMENT_BYTE] = 0x02; /* FPU is there */
72
    s->cmos_data[REG_EQUIPMENT_BYTE] |= 0x04; /* PS/2 mouse installed */
73

  
74
    /* memory size */
75
    val = (ram_size / 1024) - 1024;
76
    if (val > 65535)
77
        val = 65535;
78
    s->cmos_data[0x17] = val;
79
    s->cmos_data[0x18] = val >> 8;
80
    s->cmos_data[0x30] = val;
81
    s->cmos_data[0x31] = val >> 8;
82

  
83
    val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
84
    if (val > 65535)
85
        val = 65535;
86
    s->cmos_data[0x34] = val;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff