~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/SLOF/clients/net-snk/app/biosemu/mem.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * Copyright (c) 2004, 2008 IBM Corporation
 
3
 * All rights reserved.
 
4
 * This program and the accompanying materials
 
5
 * are made available under the terms of the BSD License
 
6
 * which accompanies this distribution, and is available at
 
7
 * http://www.opensource.org/licenses/bsd-license.php
 
8
 *
 
9
 * Contributors:
 
10
 *     IBM Corporation - initial implementation
 
11
 *****************************************************************************/
 
12
 
 
13
#include <stdio.h>
 
14
#include <stdint.h>
 
15
#include <cpu.h>
 
16
#include "debug.h"
 
17
#include "device.h"
 
18
#include "x86emu/x86emu.h"
 
19
#include "biosemu.h"
 
20
#include <time.h>
 
21
#include "mem.h"
 
22
 
 
23
// define a check for access to certain (virtual) memory regions (interrupt handlers, BIOS Data Area, ...)
 
24
#ifdef DEBUG
 
25
static uint8_t in_check = 0;    // to avoid recursion...
 
26
uint16_t ebda_segment;
 
27
uint32_t ebda_size;
 
28
 
 
29
//TODO: these macros have grown so large, that they should be changed to an inline function,
 
30
//just for the sake of readability...
 
31
 
 
32
//declare prototypes of the functions to follow, for use in DEBUG_CHECK_VMEM_ACCESS
 
33
uint8_t my_rdb(uint32_t);
 
34
uint16_t my_rdw(uint32_t);
 
35
uint32_t my_rdl(uint32_t);
 
36
 
 
37
#define DEBUG_CHECK_VMEM_READ(_addr, _rval) \
 
38
   if ((debug_flags & DEBUG_CHECK_VMEM_ACCESS) && (in_check == 0)) { \
 
39
         in_check = 1; \
 
40
         /* determine ebda_segment and size \
 
41
          * since we are using my_rdx calls, make sure, this is after setting in_check! */ \
 
42
         /* offset 03 in BDA is EBDA segment */ \
 
43
         ebda_segment = my_rdw(0x40e); \
 
44
         /* first value in ebda is size in KB */ \
 
45
         ebda_size = my_rdb(ebda_segment << 4) * 1024; \
 
46
                        /* check Interrupt Vector Access (0000:0000h - 0000:0400h) */ \
 
47
                        if (_addr < 0x400) { \
 
48
                                DEBUG_PRINTF_CS_IP("%s: read from Interrupt Vector %x --> %x\n", \
 
49
                                                __FUNCTION__, _addr / 4, _rval); \
 
50
                        } \
 
51
                        /* access to BIOS Data Area (0000:0400h - 0000:0500h)*/ \
 
52
                        else if ((_addr >= 0x400) && (addr < 0x500)) { \
 
53
                                DEBUG_PRINTF_CS_IP("%s: read from BIOS Data Area: addr: %x --> %x\n", \
 
54
                                                __FUNCTION__, _addr, _rval); \
 
55
                                /* dump registers */ \
 
56
                                /* x86emu_dump_xregs(); */ \
 
57
                        } \
 
58
                        /* access to first 64k of memory... */ \
 
59
                        else if (_addr < 0x10000) { \
 
60
                                DEBUG_PRINTF_CS_IP("%s: read from segment 0000h: addr: %x --> %x\n", \
 
61
                                                __FUNCTION__, _addr, _rval); \
 
62
                                /* dump registers */ \
 
63
                                /* x86emu_dump_xregs(); */ \
 
64
                        } \
 
65
                        /* read from PMM_CONV_SEGMENT */ \
 
66
                        else if ((_addr <= ((PMM_CONV_SEGMENT << 4) | 0xffff)) && (_addr >= (PMM_CONV_SEGMENT << 4))) { \
 
67
                                DEBUG_PRINTF_CS_IP("%s: read from PMM Segment %04xh: addr: %x --> %x\n", \
 
68
                                                __FUNCTION__, PMM_CONV_SEGMENT, _addr, _rval); \
 
69
                                /* HALT_SYS(); */ \
 
70
                                /* dump registers */ \
 
71
                                /* x86emu_dump_xregs(); */ \
 
72
                        } \
 
73
                        /* read from PNP_DATA_SEGMENT */ \
 
74
                        else if ((_addr <= ((PNP_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (PNP_DATA_SEGMENT << 4))) { \
 
75
                                DEBUG_PRINTF_CS_IP("%s: read from PnP Data Segment %04xh: addr: %x --> %x\n", \
 
76
                                                __FUNCTION__, PNP_DATA_SEGMENT, _addr, _rval); \
 
77
                                /* HALT_SYS(); */ \
 
78
                                /* dump registers */ \
 
79
                                /* x86emu_dump_xregs(); */ \
 
80
                        } \
 
81
                        /* read from EBDA Segment */ \
 
82
                        else if ((_addr <= ((ebda_segment << 4) | (ebda_size - 1))) && (_addr >= (ebda_segment << 4))) { \
 
83
                                DEBUG_PRINTF_CS_IP("%s: read from Extended BIOS Data Area %04xh, size: %04x: addr: %x --> %x\n", \
 
84
                                                __FUNCTION__, ebda_segment, ebda_size, _addr, _rval); \
 
85
                        } \
 
86
                        /* read from BIOS_DATA_SEGMENT */ \
 
87
                        else if ((_addr <= ((BIOS_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (BIOS_DATA_SEGMENT << 4))) { \
 
88
                                DEBUG_PRINTF_CS_IP("%s: read from BIOS Data Segment %04xh: addr: %x --> %x\n", \
 
89
                                                __FUNCTION__, BIOS_DATA_SEGMENT, _addr, _rval); \
 
90
                                /* for PMM debugging */ \
 
91
                                /*if (_addr == BIOS_DATA_SEGMENT << 4) { \
 
92
                                        X86EMU_trace_on(); \
 
93
                                        M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; \
 
94
                                }*/ \
 
95
                                /* dump registers */ \
 
96
                                /* x86emu_dump_xregs(); */ \
 
97
                        } \
 
98
         in_check = 0; \
 
99
   }
 
100
#define DEBUG_CHECK_VMEM_WRITE(_addr, _val) \
 
101
   if ((debug_flags & DEBUG_CHECK_VMEM_ACCESS) && (in_check == 0)) { \
 
102
         in_check = 1; \
 
103
         /* determine ebda_segment and size \
 
104
          * since we are using my_rdx calls, make sure, this is after setting in_check! */ \
 
105
         /* offset 03 in BDA is EBDA segment */ \
 
106
         ebda_segment = my_rdw(0x40e); \
 
107
         /* first value in ebda is size in KB */ \
 
108
         ebda_size = my_rdb(ebda_segment << 4) * 1024; \
 
109
                        /* check Interrupt Vector Access (0000:0000h - 0000:0400h) */ \
 
110
                        if (_addr < 0x400) { \
 
111
                                DEBUG_PRINTF_CS_IP("%s: write to Interrupt Vector %x <-- %x\n", \
 
112
                                                __FUNCTION__, _addr / 4, _val); \
 
113
                        } \
 
114
                        /* access to BIOS Data Area (0000:0400h - 0000:0500h)*/ \
 
115
                        else if ((_addr >= 0x400) && (addr < 0x500)) { \
 
116
                                DEBUG_PRINTF_CS_IP("%s: write to BIOS Data Area: addr: %x <-- %x\n", \
 
117
                                                __FUNCTION__, _addr, _val); \
 
118
                                /* dump registers */ \
 
119
                                /* x86emu_dump_xregs(); */ \
 
120
                        } \
 
121
                        /* access to first 64k of memory...*/ \
 
122
                        else if (_addr < 0x10000) { \
 
123
                                DEBUG_PRINTF_CS_IP("%s: write to segment 0000h: addr: %x <-- %x\n", \
 
124
                                                __FUNCTION__, _addr, _val); \
 
125
                                /* dump registers */ \
 
126
                                /* x86emu_dump_xregs(); */ \
 
127
                        } \
 
128
                        /* write to PMM_CONV_SEGMENT... */ \
 
129
                        else if ((_addr <= ((PMM_CONV_SEGMENT << 4) | 0xffff)) && (_addr >= (PMM_CONV_SEGMENT << 4))) { \
 
130
                                DEBUG_PRINTF_CS_IP("%s: write to PMM Segment %04xh: addr: %x <-- %x\n", \
 
131
                                                __FUNCTION__, PMM_CONV_SEGMENT, _addr, _val); \
 
132
                                /* dump registers */ \
 
133
                                /* x86emu_dump_xregs(); */ \
 
134
                        } \
 
135
                        /* write to PNP_DATA_SEGMENT... */ \
 
136
                        else if ((_addr <= ((PNP_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (PNP_DATA_SEGMENT << 4))) { \
 
137
                                DEBUG_PRINTF_CS_IP("%s: write to PnP Data Segment %04xh: addr: %x <-- %x\n", \
 
138
                                                __FUNCTION__, PNP_DATA_SEGMENT, _addr, _val); \
 
139
                                /* dump registers */ \
 
140
                                /* x86emu_dump_xregs(); */ \
 
141
                        } \
 
142
                        /* write to EBDA Segment... */ \
 
143
                        else if ((_addr <= ((ebda_segment << 4) | (ebda_size - 1))) && (_addr >= (ebda_segment << 4))) { \
 
144
                                DEBUG_PRINTF_CS_IP("%s: write to Extended BIOS Data Area %04xh, size: %04x: addr: %x <-- %x\n", \
 
145
                                                __FUNCTION__, ebda_segment, ebda_size, _addr, _val); \
 
146
                        } \
 
147
                        /* write to BIOS_DATA_SEGMENT... */ \
 
148
                        else if ((_addr <= ((BIOS_DATA_SEGMENT << 4) | 0xffff)) && (_addr >= (BIOS_DATA_SEGMENT << 4))) { \
 
149
                                DEBUG_PRINTF_CS_IP("%s: write to BIOS Data Segment %04xh: addr: %x <-- %x\n", \
 
150
                                                __FUNCTION__, BIOS_DATA_SEGMENT, _addr, _val); \
 
151
                                /* dump registers */ \
 
152
                                /* x86emu_dump_xregs(); */ \
 
153
                        } \
 
154
                        /* write to current CS segment... */ \
 
155
                        else if ((_addr < ((M.x86.R_CS << 4) | 0xffff)) && (_addr > (M.x86.R_CS << 4))) { \
 
156
                                DEBUG_PRINTF_CS_IP("%s: write to CS segment %04xh: addr: %x <-- %x\n", \
 
157
                                                __FUNCTION__, M.x86.R_CS, _addr, _val); \
 
158
                                /* dump registers */ \
 
159
                                /* x86emu_dump_xregs(); */ \
 
160
                        } \
 
161
         in_check = 0; \
 
162
   }
 
163
#else
 
164
#define DEBUG_CHECK_VMEM_READ(_addr, _rval)
 
165
#define DEBUG_CHECK_VMEM_WRITE(_addr, _val)
 
166
#endif
 
167
 
 
168
//defined in net-snk/kernel/timer.c
 
169
extern uint64_t get_time(void);
 
170
 
 
171
void update_time(uint32_t);
 
172
 
 
173
// read byte from memory
 
174
uint8_t
 
175
my_rdb(uint32_t addr)
 
176
{
 
177
        uint64_t translated_addr = addr;
 
178
        uint8_t translated = dev_translate_address(&translated_addr);
 
179
        uint8_t rval;
 
180
        if (translated != 0) {
 
181
                //translation successful, access VGA Memory (BAR or Legacy...)
 
182
                DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n",
 
183
                                 __FUNCTION__, addr);
 
184
                //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
 
185
                set_ci();
 
186
                rval = *((uint8_t *) translated_addr);
 
187
                clr_ci();
 
188
                DEBUG_PRINTF_MEM("%s(%08x) VGA --> %02x\n", __FUNCTION__, addr,
 
189
                                 rval);
 
190
                return rval;
 
191
        } else if (addr > M.mem_size) {
 
192
                DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
 
193
                             __FUNCTION__, addr);
 
194
                //disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
 
195
                HALT_SYS();
 
196
        } else {
 
197
                /* read from virtual memory */
 
198
                rval = *((uint8_t *) (M.mem_base + addr));
 
199
                DEBUG_CHECK_VMEM_READ(addr, rval);
 
200
                return rval;
 
201
        }
 
202
        return -1;
 
203
}
 
204
 
 
205
//read word from memory
 
206
uint16_t
 
207
my_rdw(uint32_t addr)
 
208
{
 
209
        uint64_t translated_addr = addr;
 
210
        uint8_t translated = dev_translate_address(&translated_addr);
 
211
        uint16_t rval;
 
212
        if (translated != 0) {
 
213
                //translation successful, access VGA Memory (BAR or Legacy...)
 
214
                DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n",
 
215
                                 __FUNCTION__, addr);
 
216
                //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
 
217
                // check for legacy memory, because of the remapping to BARs, the reads must
 
218
                // be byte reads...
 
219
                if ((addr >= 0xa0000) && (addr < 0xc0000)) {
 
220
                        //read bytes a using my_rdb, because of the remapping to BARs
 
221
                        //words may not be contiguous in memory, so we need to translate
 
222
                        //every address...
 
223
                        rval = ((uint8_t) my_rdb(addr)) |
 
224
                            (((uint8_t) my_rdb(addr + 1)) << 8);
 
225
                } else {
 
226
                        if ((translated_addr & (uint64_t) 0x1) == 0) {
 
227
                                // 16 bit aligned access...
 
228
                                set_ci();
 
229
                                rval = in16le((void *) translated_addr);
 
230
                                clr_ci();
 
231
                        } else {
 
232
                                // unaligned access, read single bytes
 
233
                                set_ci();
 
234
                                rval = (*((uint8_t *) translated_addr)) |
 
235
                                    (*((uint8_t *) translated_addr + 1) << 8);
 
236
                                clr_ci();
 
237
                        }
 
238
                }
 
239
                DEBUG_PRINTF_MEM("%s(%08x) VGA --> %04x\n", __FUNCTION__, addr,
 
240
                                 rval);
 
241
                return rval;
 
242
        } else if (addr > M.mem_size) {
 
243
                DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
 
244
                             __FUNCTION__, addr);
 
245
                //disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
 
246
                HALT_SYS();
 
247
        } else {
 
248
                /* read from virtual memory */
 
249
                rval = in16le((void *) (M.mem_base + addr));
 
250
                DEBUG_CHECK_VMEM_READ(addr, rval);
 
251
                return rval;
 
252
        }
 
253
        return -1;
 
254
}
 
255
 
 
256
//read long from memory
 
257
uint32_t
 
258
my_rdl(uint32_t addr)
 
259
{
 
260
        uint64_t translated_addr = addr;
 
261
        uint8_t translated = dev_translate_address(&translated_addr);
 
262
        uint32_t rval;
 
263
        if (translated != 0) {
 
264
                //translation successful, access VGA Memory (BAR or Legacy...)
 
265
                DEBUG_PRINTF_MEM("%s(%x): access to VGA Memory\n",
 
266
                                 __FUNCTION__, addr);
 
267
                //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
 
268
                // check for legacy memory, because of the remapping to BARs, the reads must
 
269
                // be byte reads...
 
270
                if ((addr >= 0xa0000) && (addr < 0xc0000)) {
 
271
                        //read bytes a using my_rdb, because of the remapping to BARs
 
272
                        //dwords may not be contiguous in memory, so we need to translate
 
273
                        //every address...
 
274
                        rval = ((uint8_t) my_rdb(addr)) |
 
275
                            (((uint8_t) my_rdb(addr + 1)) << 8) |
 
276
                            (((uint8_t) my_rdb(addr + 2)) << 16) |
 
277
                            (((uint8_t) my_rdb(addr + 3)) << 24);
 
278
                } else {
 
279
                        if ((translated_addr & (uint64_t) 0x3) == 0) {
 
280
                                // 32 bit aligned access...
 
281
                                set_ci();
 
282
                                rval = in32le((void *) translated_addr);
 
283
                                clr_ci();
 
284
                        } else {
 
285
                                // unaligned access, read single bytes
 
286
                                set_ci();
 
287
                                rval = (*((uint8_t *) translated_addr)) |
 
288
                                    (*((uint8_t *) translated_addr + 1) << 8) |
 
289
                                    (*((uint8_t *) translated_addr + 2) << 16) |
 
290
                                    (*((uint8_t *) translated_addr + 3) << 24);
 
291
                                clr_ci();
 
292
                        }
 
293
                }
 
294
                DEBUG_PRINTF_MEM("%s(%08x) VGA --> %08x\n", __FUNCTION__, addr,
 
295
                                 rval);
 
296
                //HALT_SYS();
 
297
                return rval;
 
298
        } else if (addr > M.mem_size) {
 
299
                DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
 
300
                             __FUNCTION__, addr);
 
301
                //disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
 
302
                HALT_SYS();
 
303
        } else {
 
304
                /* read from virtual memory */
 
305
                rval = in32le((void *) (M.mem_base + addr));
 
306
                switch (addr) {
 
307
                case 0x46c:
 
308
                        //BDA Time Data, update it, before reading
 
309
                        update_time(rval);
 
310
                        rval = in32le((void *) (M.mem_base + addr));
 
311
                        break;
 
312
                }
 
313
                DEBUG_CHECK_VMEM_READ(addr, rval);
 
314
                return rval;
 
315
        }
 
316
        return -1;
 
317
}
 
318
 
 
319
//write byte to memory
 
320
void
 
321
my_wrb(uint32_t addr, uint8_t val)
 
322
{
 
323
        uint64_t translated_addr = addr;
 
324
        uint8_t translated = dev_translate_address(&translated_addr);
 
325
        if (translated != 0) {
 
326
                //translation successful, access VGA Memory (BAR or Legacy...)
 
327
                DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
 
328
                                 __FUNCTION__, addr, val);
 
329
                //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
 
330
                set_ci();
 
331
                *((uint8_t *) translated_addr) = val;
 
332
                clr_ci();
 
333
        } else if (addr > M.mem_size) {
 
334
                DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
 
335
                             __FUNCTION__, addr);
 
336
                //disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
 
337
                HALT_SYS();
 
338
        } else {
 
339
                /* write to virtual memory */
 
340
                DEBUG_CHECK_VMEM_WRITE(addr, val);
 
341
                *((uint8_t *) (M.mem_base + addr)) = val;
 
342
        }
 
343
}
 
344
 
 
345
void
 
346
my_wrw(uint32_t addr, uint16_t val)
 
347
{
 
348
        uint64_t translated_addr = addr;
 
349
        uint8_t translated = dev_translate_address(&translated_addr);
 
350
        if (translated != 0) {
 
351
                //translation successful, access VGA Memory (BAR or Legacy...)
 
352
                DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
 
353
                                 __FUNCTION__, addr, val);
 
354
                //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
 
355
                // check for legacy memory, because of the remapping to BARs, the reads must
 
356
                // be byte reads...
 
357
                if ((addr >= 0xa0000) && (addr < 0xc0000)) {
 
358
                        //read bytes a using my_rdb, because of the remapping to BARs
 
359
                        //words may not be contiguous in memory, so we need to translate
 
360
                        //every address...
 
361
                        my_wrb(addr, (uint8_t) (val & 0x00FF));
 
362
                        my_wrb(addr + 1, (uint8_t) ((val & 0xFF00) >> 8));
 
363
                } else {
 
364
                        if ((translated_addr & (uint64_t) 0x1) == 0) {
 
365
                                // 16 bit aligned access...
 
366
                                set_ci();
 
367
                                out16le((void *) translated_addr, val);
 
368
                                clr_ci();
 
369
                        } else {
 
370
                                // unaligned access, write single bytes
 
371
                                set_ci();
 
372
                                *((uint8_t *) translated_addr) =
 
373
                                    (uint8_t) (val & 0x00FF);
 
374
                                *((uint8_t *) translated_addr + 1) =
 
375
                                    (uint8_t) ((val & 0xFF00) >> 8);
 
376
                                clr_ci();
 
377
                        }
 
378
                }
 
379
        } else if (addr > M.mem_size) {
 
380
                DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
 
381
                             __FUNCTION__, addr);
 
382
                //disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
 
383
                HALT_SYS();
 
384
        } else {
 
385
                /* write to virtual memory */
 
386
                DEBUG_CHECK_VMEM_WRITE(addr, val);
 
387
                out16le((void *) (M.mem_base + addr), val);
 
388
        }
 
389
}
 
390
void
 
391
my_wrl(uint32_t addr, uint32_t val)
 
392
{
 
393
        uint64_t translated_addr = addr;
 
394
        uint8_t translated = dev_translate_address(&translated_addr);
 
395
        if (translated != 0) {
 
396
                //translation successful, access VGA Memory (BAR or Legacy...)
 
397
                DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
 
398
                                 __FUNCTION__, addr, val);
 
399
                //DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n",  __FUNCTION__, addr, translated_addr);
 
400
                // check for legacy memory, because of the remapping to BARs, the reads must
 
401
                // be byte reads...
 
402
                if ((addr >= 0xa0000) && (addr < 0xc0000)) {
 
403
                        //read bytes a using my_rdb, because of the remapping to BARs
 
404
                        //words may not be contiguous in memory, so we need to translate
 
405
                        //every address...
 
406
                        my_wrb(addr, (uint8_t) (val & 0x000000FF));
 
407
                        my_wrb(addr + 1, (uint8_t) ((val & 0x0000FF00) >> 8));
 
408
                        my_wrb(addr + 2, (uint8_t) ((val & 0x00FF0000) >> 16));
 
409
                        my_wrb(addr + 3, (uint8_t) ((val & 0xFF000000) >> 24));
 
410
                } else {
 
411
                        if ((translated_addr & (uint64_t) 0x3) == 0) {
 
412
                                // 32 bit aligned access...
 
413
                                set_ci();
 
414
                                out32le((void *) translated_addr, val);
 
415
                                clr_ci();
 
416
                        } else {
 
417
                                // unaligned access, write single bytes
 
418
                                set_ci();
 
419
                                *((uint8_t *) translated_addr) =
 
420
                                    (uint8_t) (val & 0x000000FF);
 
421
                                *((uint8_t *) translated_addr + 1) =
 
422
                                    (uint8_t) ((val & 0x0000FF00) >> 8);
 
423
                                *((uint8_t *) translated_addr + 2) =
 
424
                                    (uint8_t) ((val & 0x00FF0000) >> 16);
 
425
                                *((uint8_t *) translated_addr + 3) =
 
426
                                    (uint8_t) ((val & 0xFF000000) >> 24);
 
427
                                clr_ci();
 
428
                        }
 
429
                }
 
430
        } else if (addr > M.mem_size) {
 
431
                DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
 
432
                             __FUNCTION__, addr);
 
433
                //disassemble_forward(M.x86.saved_cs, M.x86.saved_ip, 1);
 
434
                HALT_SYS();
 
435
        } else {
 
436
                /* write to virtual memory */
 
437
                DEBUG_CHECK_VMEM_WRITE(addr, val);
 
438
                out32le((void *) (M.mem_base + addr), val);
 
439
        }
 
440
}
 
441
 
 
442
//update time in BIOS Data Area
 
443
//DWord at offset 0x6c is the timer ticks since midnight, timer is running at 18Hz
 
444
//byte at 0x70 is timer overflow (set if midnight passed since last call to interrupt 1a function 00
 
445
//cur_val is the current value, of offset 6c...
 
446
void
 
447
update_time(uint32_t cur_val)
 
448
{
 
449
        //for convenience, we let the start of timebase be at midnight, we currently dont support
 
450
        //real daytime anyway...
 
451
        uint64_t ticks_per_day = tb_freq * 60 * 24;
 
452
        // at 18Hz a period is ~55ms, converted to ticks (tb_freq is ticks/second)
 
453
        uint32_t period_ticks = (55 * tb_freq) / 1000;
 
454
        uint64_t curr_time = get_time();
 
455
        uint64_t ticks_since_midnight = curr_time % ticks_per_day;
 
456
        uint32_t periods_since_midnight = ticks_since_midnight / period_ticks;
 
457
        // if periods since midnight is smaller than last value, set overflow
 
458
        // at BDA Offset 0x70
 
459
        if (periods_since_midnight < cur_val) {
 
460
                my_wrb(0x470, 1);
 
461
        }
 
462
        // store periods since midnight at BDA offset 0x6c
 
463
        my_wrl(0x46c, periods_since_midnight);
 
464
}