OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [syn/] [soc/] [firmware/] [exe/] [main.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
#include <stdio.h>
28
#include <stdarg.h>
29
#include <string.h>
30
#include <unistd.h>
31
 
32
#include <io.h>
33
#include <sys/alt_irq.h>
34
#include <system.h>
35
 
36
typedef unsigned char  uint8;
37
typedef unsigned short uint16;
38
typedef unsigned int   uint32;
39
 
40
 
41
void osd_enable(bool enable) {
42
        IOWR(VGA_BASE, 0, 0x8000 | ((enable)? 0x4000 : 0x0000));
43
}
44
 
45
void osd_print(int position, bool invert, const char *format, ...) {
46
        va_list ap;
47
 
48
        va_start(ap, format);
49
 
50
        char buf[64];
51
        memset((void *)buf, 0, (unsigned long int)sizeof(buf));
52
 
53
        int written = vsnprintf(buf, sizeof(buf), format, ap);
54
        va_end(ap);
55
 
56
        for(int i=0; i<written; i++) IOWR(VGA_BASE, position+i, buf[i] | ((invert)? 0x100 : 0x000));
57
}
58
 
59
int read_byte_if_possible() {
60
        uint32 rd = IORD(JTAG_UART_BASE, 0);
61
        if((rd >> 15) & 1) return rd & 0xFF;
62
        return -1;
63
}
64
 
65
inline uint8 read_byte() {
66
        while(true) {
67
                unsigned int rd = IORD(JTAG_UART_BASE, 0);
68
                if((rd >> 15) & 1) return rd & 0xFF;
69
        }
70
}
71
 
72
uint32 read_int() {
73
        uint32 rd = 0;
74
        rd |= read_byte() << 0;
75
        rd |= read_byte() << 8;
76
        rd |= read_byte() << 16;
77
        rd |= read_byte() << 24;
78
        return rd;
79
}
80
 
81
void crc32(uint8 *ptr, uint32 *crc_output) {
82
    static uint8 crc[32];
83
 
84
    //do nothing
85
    if(ptr != NULL && crc_output != NULL) return;
86
 
87
    //initialize
88
    if(ptr == NULL && crc_output == NULL) {
89
        for(int i=0; i<32; i++) crc[i] = 1;
90
        return;
91
    }
92
 
93
    //output
94
    if(ptr == NULL && crc_output != NULL) {
95
        *crc_output = 0;
96
                for(int i=0; i<32; i++) {
97
                        (*crc_output) |= crc[i] << (31-i);
98
                }
99
                (*crc_output) = ~(*crc_output);
100
                return;
101
    }
102
 
103
    uint8 in[8];
104
    for(int j=0; j<8; j++) in[j] = ((*ptr) >> j) & 1;
105
 
106
    uint8 new_crc[32];
107
 
108
        new_crc[31] = in[2] ^ crc[23] ^ crc[29];
109
        new_crc[30] = in[0] ^ in[3] ^ crc[22] ^ crc[28] ^ crc[31];
110
        new_crc[29] = in[0] ^ in[1] ^ in[4] ^ crc[21] ^ crc[27] ^ crc[30] ^ crc[31];
111
        new_crc[28] = in[1] ^ in[2] ^ in[5] ^ crc[20] ^ crc[26] ^ crc[29] ^ crc[30];
112
        new_crc[27] = in[0] ^ in[2] ^ in[3] ^ in[6] ^ crc[19] ^ crc[25] ^ crc[28] ^ crc[29] ^ crc[31];
113
        new_crc[26] = in[1] ^ in[3] ^ in[4] ^ in[7] ^ crc[18] ^ crc[24] ^ crc[27] ^ crc[28] ^ crc[30];
114
        new_crc[25] = in[4] ^ in[5] ^ crc[17] ^ crc[26] ^ crc[27];
115
        new_crc[24] = in[0] ^ in[5] ^ in[6] ^ crc[16] ^ crc[25] ^ crc[26] ^ crc[31];
116
        new_crc[23] = in[1] ^ in[6] ^ in[7] ^ crc[15] ^ crc[24] ^ crc[25] ^ crc[30];
117
        new_crc[22] = in[7] ^ crc[14] ^ crc[24];
118
        new_crc[21] = in[2] ^ crc[13] ^ crc[29];
119
        new_crc[20] = in[3] ^ crc[12] ^ crc[28];
120
        new_crc[19] = in[0] ^ in[4] ^ crc[11] ^ crc[27] ^ crc[31];
121
        new_crc[18] = in[0] ^ in[1] ^ in[5] ^ crc[10] ^ crc[26] ^ crc[30] ^ crc[31];
122
        new_crc[17] = in[1] ^ in[2] ^ in[6] ^ crc[9] ^ crc[25] ^ crc[29] ^ crc[30];
123
        new_crc[16] = in[2] ^ in[3] ^ in[7] ^ crc[8] ^ crc[24] ^ crc[28] ^ crc[29];
124
        new_crc[15] = in[0] ^ in[2] ^ in[3] ^ in[4] ^ crc[7] ^ crc[27] ^ crc[28] ^ crc[29] ^ crc[31];
125
        new_crc[14] = in[0] ^ in[1] ^ in[3] ^ in[4] ^ in[5] ^ crc[6] ^ crc[26] ^ crc[27] ^ crc[28] ^ crc[30] ^ crc[31];
126
        new_crc[13] = in[0] ^ in[1] ^ in[2] ^ in[4] ^ in[5] ^ in[6] ^ crc[5] ^ crc[25] ^ crc[26] ^ crc[27] ^ crc[29] ^ crc[30] ^ crc[31];
127
        new_crc[12] = in[1] ^ in[2] ^ in[3] ^ in[5] ^ in[6] ^ in[7] ^ crc[4] ^ crc[24] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29] ^ crc[30];
128
        new_crc[11] = in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[3] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28];
129
        new_crc[10] = in[2] ^ in[4] ^ in[5] ^ in[7] ^ crc[2] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[29];
130
        new_crc[9] = in[2] ^ in[3] ^ in[5] ^ in[6] ^ crc[1] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29];
131
        new_crc[8] = in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[0] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28];
132
        new_crc[7] = in[0] ^ in[2] ^ in[4] ^ in[5] ^ in[7] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[29] ^ crc[31];
133
        new_crc[6] = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[5] ^ in[6] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29] ^ crc[30] ^ crc[31];
134
        new_crc[5] = in[0] ^ in[1] ^ in[2] ^ in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28] ^ crc[29] ^ crc[30] ^ crc[31];
135
        new_crc[4] = in[1] ^ in[3] ^ in[4] ^ in[5] ^ in[7] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[28] ^ crc[30];
136
        new_crc[3] = in[0] ^ in[4] ^ in[5] ^ in[6] ^ crc[25] ^ crc[26] ^ crc[27] ^ crc[31];
137
        new_crc[2] = in[0] ^ in[1] ^ in[5] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[26] ^ crc[30] ^ crc[31];
138
        new_crc[1] = in[0] ^ in[1] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[30] ^ crc[31];
139
        new_crc[0] = in[1] ^ in[7] ^ crc[24] ^ crc[30];
140
 
141
    memcpy(crc, new_crc, sizeof(crc));
142
}
143
 
144
#pragma pack(push)
145
#pragma pack(1)
146
 
147
struct entry_t {
148
 
149
        uint8  type;
150
        uint8  name[15];
151
 
152
        union args_t {
153
                struct bios_t {
154
                        uint32 sector;
155
                        uint32 size_in_bytes;
156
                        uint32 destination;
157
                        uint32 crc32;
158
                } bios;
159
                struct hdd_t {
160
                        uint32 sector;
161
                        uint32 cyliders;
162
                        uint32 heads;
163
                        uint32 spt;
164
                } hdd;
165
                struct floppy_t {
166
                        uint32 sector;
167
                } floppy;
168
                struct end_of_list_t {
169
                        uint32 crc32;
170
                } end_of_list;
171
        } args;
172
};
173
 
174
#pragma pack(pop)
175
 
176
#define ENTRIES_COUNT 128
177
 
178
struct entry_t entries[ENTRIES_COUNT];
179
 
180
#define TYPE_BIOS               1
181
#define TYPE_VGABIOS    2
182
#define TYPE_HDD        3
183
#define TYPE_FD_1_44M   16
184
#define TYPE_CRC32              127
185
 
186
#define ENTRY_ABORT     -500
187
 
188
int show_menu(uint8 mask, uint8 value, bool abortable) {
189
 
190
        int index_start = -1;
191
        for(int i=0; i<ENTRIES_COUNT; i++) {
192
                if((entries[i].type & mask) == value) {
193
                        index_start = i;
194
                        break;
195
                }
196
        }
197
        if(index_start == -1) {
198
                osd_print(9*16+0, true, "Index start err ");
199
                return -1;
200
        }
201
 
202
        int index_end = -1;
203
        for(int i=ENTRIES_COUNT-1; i>=0; i--) {
204
                if((entries[i].type & mask) == value) {
205
                        index_end = i;
206
                        break;
207
                }
208
        }
209
        if(index_start == -1) {
210
                osd_print(9*16+0, true, "Index end error ");
211
                return -2;
212
        }
213
        int index_size = index_end - index_start;
214
 
215
        int index = 0;
216
        bool zero_delay_last = true;
217
 
218
        while(true) {
219
                //print contents
220
                for(int i=-5; i<7; i++) {
221
                        if((index + i < 0) || (index + i > index_size)) {
222
                                osd_print((9+i)*16, false, "                ");
223
                        }
224
                        else {
225
                                int current_index = index_start + index + i;
226
                                bool invert = i == 0;
227
                                osd_print((9+i)*16, invert, "                ");
228
                                osd_print((9+i)*16, invert, " %s", entries[current_index].name);
229
                        }
230
                }
231
 
232
                char key = 0;
233
                bool zero_delay = true;
234
                while(key == 0) {
235
                        uint32 keys = IORD(PIO_INPUT_BASE, 0);
236
 
237
                        if((keys & 0x1) == 0)            key = 'v';
238
                        else if((keys & 0x2) == 0)       key = '^';
239
                        else if((keys & 0x4) == 0)  key = 'Y';
240
                        else if((keys & 0x8) == 0)  key = 'N';
241
                        else                                            key = 0;
242
 
243
                        if(key == 0) zero_delay = false;
244
                }
245
 
246
                if(key == 'Y')                          return index_start + index;
247
                if(key == 'N' && abortable) return ENTRY_ABORT;
248
 
249
                if(key == '^' && index > 0) index--;
250
                if(key == 'v' && index < index_size) index++;
251
 
252
                if(zero_delay_last && zero_delay)       usleep(100000);
253
                else                                                            usleep(300000);
254
 
255
                zero_delay_last = zero_delay;
256
        }
257
}
258
 
259
int select_and_load_bios(uint8 type, uint32 position,
260
                const char *select_txt, const char *load_txt, const char *verify_txt, const char *verify_failed_txt, const char *verify_ok_txt)
261
{
262
        osd_print(3*16+0, false, select_txt);
263
 
264
        int menu_result = show_menu(0xFF, type, false);
265
        if(menu_result < 0) return menu_result;
266
 
267
        for(int i=48; i<16*16; i++) IOWR(VGA_BASE, i, 0);
268
 
269
        //load bios
270
        osd_print(16*position, false, load_txt);
271
 
272
        uint8 *dst_ptr = (uint8 *)entries[menu_result].args.bios.destination;
273
        uint32 size_in_bytes = entries[menu_result].args.bios.size_in_bytes;
274
        uint32 sector = entries[menu_result].args.bios.sector;
275
 
276
        uint8 sector_buf[4096];
277
        while(size_in_bytes > 0) {
278
                IOWR(DRIVER_SD_BASE, 0, (int)sector_buf);                //Avalon address base
279
                IOWR(DRIVER_SD_BASE, 1, sector);                                //SD sector
280
                IOWR(DRIVER_SD_BASE, 2, 8);                                     //sector count
281
                IOWR(DRIVER_SD_BASE, 3, 2);                                     //control READ
282
 
283
                //wait for ready
284
                int sd_status = -1;
285
                while(sd_status != 2) {
286
                        usleep(100000);
287
                        sd_status = IORD(DRIVER_SD_BASE, 0);
288
                }
289
 
290
                uint32 current_size = (size_in_bytes > 4096)? 4096 : size_in_bytes;
291
                memcpy(dst_ptr, sector_buf, current_size);
292
 
293
                dst_ptr += current_size;
294
                size_in_bytes -= current_size;
295
                sector += 8;
296
        }
297
 
298
/*  //currently disable crc32 verification
299
        osd_print(16*position, false, verify_txt);
300
 
301
        dst_ptr = (uint8 *)entries[menu_result].args.bios.destination;
302
        size_in_bytes = entries[menu_result].args.bios.size_in_bytes;
303
 
304
        crc32(NULL, NULL);
305
        for(uint32 i=0; i<size_in_bytes; i++) {
306
                crc32(dst_ptr+i, NULL);
307
        }
308
 
309
        uint32 crc_calculated = 0;
310
        crc32(NULL, &crc_calculated);
311
 
312
        if(crc_calculated != entries[menu_result].args.bios.crc32) {
313
                osd_print(16*position, false, verify_failed_txt);
314
                return -1;
315
        }
316
*/
317
        osd_print(16*position, false, verify_ok_txt);
318
        return 0;
319
}
320
 
321
 
322
int floppy_index = -1;
323
int hdd_index    = -1;
324
 
325
bool floppy_is_160k = false;
326
bool floppy_is_180k = false;
327
bool floppy_is_320k = false;
328
bool floppy_is_360k = false;
329
bool floppy_is_720k = false;
330
bool floppy_is_1_2m = false;
331
bool floppy_is_1_44m= true;
332
bool floppy_is_2_88m= false;
333
 
334
bool floppy_writeprotect = true;
335
 
336
void runtime_menu_no_floppy() {
337
        osd_print(16*1, false, "No floppy");
338
 
339
        osd_print(16*9, false, "Insert floppy");
340
        for(int i=0; i<16; i++) IOWR(VGA_BASE, 16*9+i, 0x100 | (IORD(VGA_BASE, 16*9+i) & 0xFF));
341
 
342
        bool zero_delay_last = true;
343
        while(true) {
344
                char key = 0;
345
                bool zero_delay = true;
346
                while(key == 0) {
347
                        uint32 keys = IORD(PIO_INPUT_BASE, 0);
348
 
349
                        if((keys & 0x1) == 0)            key = 'v';
350
                        else if((keys & 0x2) == 0)       key = '^';
351
                        else if((keys & 0x4) == 0)  key = 'Y';
352
                        else if((keys & 0x8) == 0)  key = 'N';
353
                        else                                            key = 0;
354
 
355
                        if(key == 0) zero_delay = false;
356
                }
357
 
358
                if(key == 'Y') {
359
                        //wait for key release
360
                        while((IORD(PIO_INPUT_BASE, 0) & 0xF) != 0xF) { ; }
361
 
362
                        int menu_result = show_menu(0xF0, TYPE_FD_1_44M, true);
363
                        if(menu_result == ENTRY_ABORT) {
364
                                return;
365
                        }
366
                        else if(menu_result < 0) {
367
                                usleep(2000000);
368
                                return;
369
                        }
370
 
371
                        floppy_index = menu_result;
372
 
373
                        floppy_writeprotect = true;
374
 
375
                        int floppy_sd_base = entries[floppy_index].args.floppy.sector;
376
 
377
                        int floppy_media =
378
                                (floppy_index < 0)? 0x20 :
379
                                (floppy_is_160k)?   0x00 :
380
                                (floppy_is_180k)?   0x00 :
381
                                (floppy_is_320k)?   0x00 :
382
                                (floppy_is_360k)?   0x00 :
383
                                (floppy_is_720k)?   0xC0 :
384
                                (floppy_is_1_2m)?   0x00 :
385
                                (floppy_is_1_44m)?  0x80 :
386
                                (floppy_is_2_88m)?  0x40 :
387
                                                                    0x20;
388
 
389
                        IOWR(FLOPPY_BASE, 0x0, floppy_index >= 0?        1 : 0);
390
                        IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0);
391
                        IOWR(FLOPPY_BASE, 0x6, floppy_sd_base);
392
                        IOWR(FLOPPY_BASE, 0xC, floppy_media);
393
 
394
                        return;
395
                }
396
 
397
                if(key == 'N') return;
398
 
399
                if(zero_delay_last && zero_delay)       usleep(100000);
400
                else                                                            usleep(300000);
401
 
402
                zero_delay_last = zero_delay;
403
        }
404
}
405
 
406
void runtime_menu_floppy() {
407
        osd_print(16*1, false, "Floppy inserted");
408
 
409
        int index = 9;
410
 
411
        bool zero_delay_last = true;
412
        while(true) {
413
                //draw contents
414
                for(int i=16*2; i<16*16; i++) IOWR(VGA_BASE, i, 0);
415
 
416
                osd_print(16*index, false, "Eject floppy");
417
                osd_print(16*(index+1), false, floppy_writeprotect? "Clear writeprot" : "Set writeprotect");
418
                for(int i=0; i<16; i++) IOWR(VGA_BASE, 16*9+i, 0x100 | (IORD(VGA_BASE, 16*9+i) & 0xFF));
419
 
420
                char key = 0;
421
                bool zero_delay = true;
422
                while(key == 0) {
423
                        uint32 keys = IORD(PIO_INPUT_BASE, 0);
424
 
425
                        if((keys & 0x1) == 0)            key = 'v';
426
                        else if((keys & 0x2) == 0)       key = '^';
427
                        else if((keys & 0x4) == 0)  key = 'Y';
428
                        else if((keys & 0x8) == 0)  key = 'N';
429
                        else                                            key = 0;
430
 
431
                        if(key == 0) zero_delay = false;
432
                }
433
 
434
                if(key == 'Y') {
435
                        if(index == 9) { //eject
436
                                floppy_index = -1;
437
 
438
                                floppy_writeprotect = true;
439
 
440
                                int floppy_media =
441
                                        (floppy_index < 0)? 0x20 :
442
                                        (floppy_is_160k)?   0x00 :
443
                                        (floppy_is_180k)?   0x00 :
444
                                        (floppy_is_320k)?   0x00 :
445
                                        (floppy_is_360k)?   0x00 :
446
                                        (floppy_is_720k)?   0xC0 :
447
                                        (floppy_is_1_2m)?   0x00 :
448
                                        (floppy_is_1_44m)?  0x80 :
449
                                        (floppy_is_2_88m)?  0x40 :
450
                                                                                0x20;
451
 
452
                                IOWR(FLOPPY_BASE, 0x0, floppy_index >= 0?        1 : 0);
453
                                IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0);
454
                                IOWR(FLOPPY_BASE, 0xC, floppy_media);
455
                        }
456
                        if(index == 8) { //writeprotect
457
                                floppy_writeprotect = !floppy_writeprotect;
458
 
459
                                IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0);
460
                        }
461
 
462
                        return;
463
                }
464
 
465
                if(key == 'N') return;
466
 
467
                if(key == '^' && index == 8) index++;
468
                if(key == 'v' && index == 9) index--;
469
 
470
 
471
                if(zero_delay_last && zero_delay)       usleep(100000);
472
                else                                                            usleep(300000);
473
 
474
                zero_delay_last = zero_delay;
475
        }
476
}
477
 
478
void runtime_menu() {
479
        //clear osd
480
        for(int i=16; i<16*16; i++) IOWR(VGA_BASE, i, 0);
481
 
482
        osd_enable(true);
483
 
484
        //wait for key release
485
        while((IORD(PIO_INPUT_BASE, 0) & 0xF) != 0xF) { ; }
486
 
487
        if(floppy_index < 0)     runtime_menu_no_floppy();
488
        else                                    runtime_menu_floppy();
489
 
490
        osd_enable(false);
491
 
492
        //wait for key release
493
        while((IORD(PIO_INPUT_BASE, 0) & 0xF) != 0xF) { ; }
494
}
495
 
496
int main() {
497
 
498
        //pc_bus
499
        IOWR(PC_BUS_BASE, 0, 0x00FFF0EA);
500
        IOWR(PC_BUS_BASE, 1, 0x000000F0);
501
 
502
        //resets output
503
    IOWR(PIO_OUTPUT_BASE, 0, 0x01);
504
 
505
        //vga
506
        osd_enable(false);
507
        usleep(1000000);
508
 
509
        for(int i=0; i<16*16; i++) IOWR(VGA_BASE, i, 0);
510
 
511
        osd_enable(true);
512
 
513
        osd_print(0*16+0, false, "ao486 SoC ver1.0");
514
 
515
        osd_print(1*16+0, false, "SD init...      ");
516
        osd_print(2*16+0, false, "SD header chk...");
517
 
518
        //clear all sdram
519
    //for(int i=0; i<134217728/4; i++) IOWR(SDRAM_BASE, i, 0);
520
 
521
        //-------------------------------------------------------------------------- check sd card presence
522
        usleep(1000000);
523
        int sd_status = IORD(DRIVER_SD_BASE, 0);
524
        while(sd_status != 2) {
525
                osd_print(1*16+0, true, "SD reinit: %d    ", sd_status);
526
 
527
                while(sd_status == 0) {
528
                        usleep(1000000);
529
                        sd_status = IORD(DRIVER_SD_BASE, 0);
530
                }
531
                if(sd_status == 1) {
532
                        IOWR(DRIVER_SD_BASE, 3, 1); //control reinit;
533
                        IOWR(DRIVER_SD_BASE, 3, 0); //control idle;
534
 
535
                        usleep(1000000);
536
                        sd_status = IORD(DRIVER_SD_BASE, 0);
537
                }
538
        }
539
        osd_print(1*16+0, false, "SD OK           ");
540
 
541
        //-------------------------------------------------------------------------- SD read header
542
 
543
        IOWR(DRIVER_SD_BASE, 0, (int)entries);           //Avalon address base
544
        IOWR(DRIVER_SD_BASE, 1, 0);                                      //SD sector
545
        IOWR(DRIVER_SD_BASE, 2, sizeof(entries)/512);   //sector count
546
        IOWR(DRIVER_SD_BASE, 3, 2);                                     //control READ
547
 
548
        //wait for ready
549
        sd_status = -1;
550
        while(sd_status != 2) {
551
                usleep(100000);
552
                sd_status = IORD(DRIVER_SD_BASE, 0);
553
        }
554
 
555
        //check crc32
556
        bool crc_ok = false;
557
        for(int i=0; i<ENTRIES_COUNT; i++) {
558
                if(entries[i].type == TYPE_CRC32) {
559
                        uint8 *ptr_start = (uint8 *)entries;
560
                        uint32 size = i*32;
561
 
562
                        crc32(NULL, NULL);
563
                        for(uint32 j=0; j<size; j++) crc32(ptr_start + j, NULL);
564
 
565
                        uint32 crc_calculated = 0;
566
                        crc32(NULL, &crc_calculated);
567
 
568
                        crc_ok = crc_calculated == entries[i].args.end_of_list.crc32;
569
                        break;
570
                }
571
        }
572
 
573
        if(crc_ok == false) {
574
                osd_print(2*16+0, true, "SD header invald");
575
                return 0;
576
        }
577
 
578
        osd_print(2*16+0, false, "SD header OK    ");
579
 
580
        //-------------------------------------------------------------------------- load bios
581
 
582
        for(int i=16; i<16*16; i++) IOWR(VGA_BASE, i, 0);
583
 
584
        int bios_result = select_and_load_bios(TYPE_BIOS, 1, "--Select BIOS:--", "Loading BIOS... ", "Verifying BIOS..", "BIOS vrfy failed", "BIOS verify OK  ");
585
        if(bios_result < 0) return 0;
586
 
587
        //-------------------------------------------------------------------------- load vgabios
588
 
589
        for(int i=32; i<16*16; i++) IOWR(VGA_BASE, i, 0);
590
 
591
        bios_result = select_and_load_bios(TYPE_VGABIOS, 2, "-Select VGABIOS:", "Loading VBIOS...", "Verfying VBIOS..", "VBIOS vrfy fail ", "VBIOS verify OK ");
592
        if(bios_result < 0) return 0;
593
 
594
        //-------------------------------------------------------------------------- select hdd
595
 
596
        for(int i=16; i<16*16; i++) IOWR(VGA_BASE, i, 0);
597
 
598
        int menu_result = show_menu(0xFF, TYPE_HDD, false);
599
        if(menu_result < 0) return 0;
600
 
601
        hdd_index = menu_result;
602
 
603
        //--------------------------------------------------------------------------
604
 
605
        osd_enable(false);
606
 
607
        //-------------------------------------------------------------------------- sound
608
        /*
609
        0-255.[15:0]: cycles in period
610
        256.[12:0]:  cycles in 80us
611
        257.[9:0]:   cycles in 1 sample: 96000 Hz
612
        */
613
 
614
        double cycle_in_ns = (1000000000.0 / ALT_CPU_CPU_FREQ); //33.333333;
615
    for(int i=0; i<256; i++) {
616
        double f = 1000000.0 / (256.0-i);
617
 
618
        double cycles_in_period = 1000000000.0 / (f * cycle_in_ns);
619
        IOWR(SOUND_BASE, i, (int)cycles_in_period);
620
    }
621
 
622
        IOWR(SOUND_BASE, 256, (int)(80000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
623
        IOWR(SOUND_BASE, 257, (int)((1000000000.0/96000.0) / (1000000000.0 / ALT_CPU_CPU_FREQ)));
624
 
625
        //-------------------------------------------------------------------------- pit
626
        /*
627
        0.[7:0]: cycles in sysclock 1193181 Hz
628
        */
629
 
630
        IOWR(PIT_BASE, 0, (int)((1000000000.0/1193181.0) / (1000000000.0 / ALT_CPU_CPU_FREQ)));
631
 
632
        //-------------------------------------------------------------------------- floppy
633
 
634
        int floppy_sd_base = 0;
635
 
636
        /*
637
         0x00.[0]:      media present
638
         0x01.[0]:      media writeprotect
639
         0x02.[7:0]:    media cylinders
640
         0x03.[7:0]:    media sectors per track
641
         0x04.[31:0]:   media total sector count
642
         0x05.[1:0]:    media heads
643
         0x06.[31:0]:   media sd base
644
         0x07.[15:0]:   media wait cycles: 200000 us / spt
645
     0x08.[15:0]:   media wait rate 0: 1000 us
646
     0x09.[15:0]:   media wait rate 1: 1666 us
647
     0x0A.[15:0]:   media wait rate 2: 2000 us
648
     0x0B.[15:0]:   media wait rate 3: 500 us
649
         0x0C.[7:0]:    media type: 8'h20 none; 8'h00 old; 8'hC0 720k; 8'h80 1_44M; 8'h40 2_88M
650
        */
651
 
652
        int floppy_cylinders = (floppy_is_2_88m || floppy_is_1_44m || floppy_is_1_2m || floppy_is_720k)? 80 : 40;
653
        int floppy_spt       =
654
                        (floppy_is_160k)?  8 :
655
                        (floppy_is_180k)?  9 :
656
                        (floppy_is_320k)?  8 :
657
                        (floppy_is_360k)?  9 :
658
                        (floppy_is_720k)?  9 :
659
                        (floppy_is_1_2m)?  15 :
660
                        (floppy_is_1_44m)? 18 :
661
                        (floppy_is_2_88m)? 36 :
662
                                                   0;
663
        int floppy_total_sectors =
664
                        (floppy_is_160k)?  320 :
665
                        (floppy_is_180k)?  360 :
666
                        (floppy_is_320k)?  640 :
667
                        (floppy_is_360k)?  720 :
668
                        (floppy_is_720k)?  1440 :
669
                        (floppy_is_1_2m)?  2400 :
670
                        (floppy_is_1_44m)? 2880 :
671
                        (floppy_is_2_88m)? 5760 :
672
                                                           0;
673
        int floppy_heads = (floppy_is_160k || floppy_is_180k)? 1 : 2;
674
 
675
        int floppy_wait_cycles = 200000000 / floppy_spt;
676
 
677
        int floppy_media =
678
                        (floppy_index < 0)? 0x20 :
679
                        (floppy_is_160k)?   0x00 :
680
                        (floppy_is_180k)?   0x00 :
681
                        (floppy_is_320k)?   0x00 :
682
                        (floppy_is_360k)?   0x00 :
683
                        (floppy_is_720k)?   0xC0 :
684
                        (floppy_is_1_2m)?   0x00 :
685
                        (floppy_is_1_44m)?  0x80 :
686
                        (floppy_is_2_88m)?  0x40 :
687
                                                            0x20;
688
 
689
        IOWR(FLOPPY_BASE, 0x0, floppy_index >= 0?        1 : 0);
690
        IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0);
691
        IOWR(FLOPPY_BASE, 0x2, floppy_cylinders);
692
        IOWR(FLOPPY_BASE, 0x3, floppy_spt);
693
        IOWR(FLOPPY_BASE, 0x4, floppy_total_sectors);
694
        IOWR(FLOPPY_BASE, 0x5, floppy_heads);
695
        IOWR(FLOPPY_BASE, 0x6, floppy_sd_base);
696
        IOWR(FLOPPY_BASE, 0x7, (int)(floppy_wait_cycles / (1000000000.0 / ALT_CPU_CPU_FREQ)));
697
        IOWR(FLOPPY_BASE, 0x8, (int)(1000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
698
        IOWR(FLOPPY_BASE, 0x9, (int)(1666666.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
699
        IOWR(FLOPPY_BASE, 0xA, (int)(2000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
700
        IOWR(FLOPPY_BASE, 0xB, (int)(500000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
701
        IOWR(FLOPPY_BASE, 0xC, floppy_media);
702
 
703
        //-------------------------------------------------------------------------- hdd
704
 
705
        unsigned int hd_cylinders = entries[hdd_index].args.hdd.cyliders; //1-1024; 10 bits; implemented 16 bits
706
        unsigned int hd_heads     = entries[hdd_index].args.hdd.heads;    //1-16;   4 bits; at least 9 heads for cmos 0x20
707
        unsigned int hd_spt       = entries[hdd_index].args.hdd.spt;      //1-255;  8 bits;
708
 
709
        int hdd_sd_base = entries[hdd_index].args.hdd.sector;
710
 
711
        unsigned int hd_total_sectors = hd_cylinders * hd_heads * hd_spt;
712
 
713
        /*
714
        0x00.[31:0]:    identify write
715
        0x01.[16:0]:    media cylinders
716
        0x02.[4:0]:     media heads
717
        0x03.[8:0]:     media spt
718
        0x04.[13:0]:    media sectors per cylinder = spt * heads
719
        0x05.[31:0]:    media sectors total
720
        0x06.[31:0]:    media sd base
721
        */
722
 
723
        unsigned int identify[256] = {
724
                0x0040,                                                                                 //word 0
725
                (hd_cylinders > 16383)? 16383 : hd_cylinders,   //word 1
726
                0x0000,                                                                                 //word 2 reserved
727
                hd_heads,                                                                               //word 3
728
                (unsigned short)(512 * hd_spt),                                 //word 4
729
                512,                                                                                    //word 5
730
                hd_spt,                                                                                 //word 6
731
                0x0000,                                                                                 //word 7 vendor specific
732
                0x0000,                                                                                 //word 8 vendor specific
733
                0x0000,                                                                                 //word 9 vendor specific
734
                ('A' << 8) | 'O',                                                               //word 10
735
                ('H' << 8) | 'D',                                                               //word 11
736
                ('0' << 8) | '0',                                                               //word 12
737
                ('0' << 8) | '0',                                                               //word 13
738
                ('0' << 8) | ' ',                                                               //word 14
739
                (' ' << 8) | ' ',                                                               //word 15
740
                (' ' << 8) | ' ',                                                               //word 16
741
                (' ' << 8) | ' ',                                                               //word 17
742
                (' ' << 8) | ' ',                                                               //word 18
743
                (' ' << 8) | ' ',                                                               //word 19
744
                3,                                                                                      //word 20 buffer type
745
                512,                                                                                    //word 21 cache size
746
                4,                                                                                              //word 22 number of ecc bytes
747
                0,0,0,0,                                                                            //words 23..26 firmware revision
748
                ('A' << 8) | 'O',                                                               //words 27..46 model number
749
                (' ' << 8) | 'H',
750
                ('a' << 8) | 'r',
751
                ('d' << 8) | 'd',
752
                ('r' << 8) | 'i',
753
                ('v' << 8) | 'e',
754
                (' ' << 8) | ' ',
755
                (' ' << 8) | ' ',
756
                (' ' << 8) | ' ',
757
                (' ' << 8) | ' ',
758
                (' ' << 8) | ' ',
759
                (' ' << 8) | ' ',
760
                (' ' << 8) | ' ',
761
                (' ' << 8) | ' ',
762
                (' ' << 8) | ' ',
763
                (' ' << 8) | ' ',
764
                (' ' << 8) | ' ',
765
                (' ' << 8) | ' ',
766
                (' ' << 8) | ' ',
767
                (' ' << 8) | ' ',
768
                16,                                                                                             //word 47 max multiple sectors
769
                1,                                                                                              //word 48 dword io
770
                1<<9,                                                                                   //word 49 lba supported
771
                0x0000,                                                                                 //word 50 reserved
772
                0x0200,                                                                                 //word 51 pio timing
773
                0x0200,                                                                                 //word 52 pio timing
774
                0x0007,                                                                                 //word 53 valid fields
775
                (hd_cylinders > 16383)? 16383 : hd_cylinders,   //word 54
776
                hd_heads,                                                                               //word 55
777
                hd_spt,                                                                                 //word 56
778
                hd_total_sectors & 0xFFFF,                                              //word 57
779
                hd_total_sectors >> 16,                                                 //word 58
780
                0x0000,                                                                                 //word 59 multiple sectors
781
                hd_total_sectors & 0xFFFF,                                              //word 60
782
                hd_total_sectors >> 16,                                                 //word 61
783
                0x0000,                                                                                 //word 62 single word dma modes
784
                0x0000,                                                                                 //word 63 multiple word dma modes
785
                0x0000,                                                                                 //word 64 pio modes
786
                120,120,120,120,                                                                //word 65..68
787
                0,0,0,0,0,0,0,0,0,0,0,                                                     //word 69..79
788
                0x007E,                                                                                 //word 80 ata modes
789
                0x0000,                                                                                 //word 81 minor version number
790
                1<<14,                                                                                  //word 82 supported commands
791
                (1<<14) | (1<<13) | (1<<12) | (1<<10),                  //word 83
792
                1<<14,                                                                          //word 84
793
                1<<14,                                                                          //word 85
794
                (1<<14) | (1<<13) | (1<<12) | (1<<10),                  //word 86
795
                1<<14,                                                                          //word 87
796
                0x0000,                                                                                 //word 88
797
                0,0,0,0,                                                                            //word 89..92
798
                1 | (1<<14) | 0x2000,                                                   //word 93
799
                0,0,0,0,0,0,                                                                  //word 94..99
800
                hd_total_sectors & 0xFFFF,                                              //word 100
801
                hd_total_sectors >> 16,                                                 //word 101
802
                0,                                                                                               //word 102
803
                0,                                                                                               //word 103
804
 
805
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,//word 104..127
806
 
807
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                                //word 128..255
808
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
809
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
810
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
811
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
812
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
813
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
814
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
815
        };
816
 
817
 
818
        for(int i=0; i<128; i++) IOWR(HDD_BASE, 0, ((unsigned int)identify[2*i+1] << 16) | (unsigned int)identify[2*i+0]);
819
 
820
        IOWR(HDD_BASE, 1, hd_cylinders);
821
        IOWR(HDD_BASE, 2, hd_heads);
822
        IOWR(HDD_BASE, 3, hd_spt);
823
        IOWR(HDD_BASE, 4, hd_spt * hd_heads);
824
        IOWR(HDD_BASE, 5, hd_spt * hd_heads * hd_cylinders);
825
        IOWR(HDD_BASE, 6, hdd_sd_base);
826
 
827
        //-------------------------------------------------------------------------- rtc
828
 
829
        bool boot_from_floppy = true;
830
 
831
        /*
832
    128.[26:0]: cycles in second
833
    129.[12:0]: cycles in 122.07031 us
834
    */
835
 
836
        IOWR(RTC_BASE, 128, (int)(1000000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
837
        IOWR(RTC_BASE, 129, (int)(122070.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
838
 
839
        unsigned char fdd_type = (floppy_is_2_88m)? 0x50 : (floppy_is_1_44m)? 0x40 : (floppy_is_720k)? 0x30 : (floppy_is_1_2m)? 0x20 : 0x10;
840
 
841
        bool translate_none = hd_cylinders <= 1024 && hd_heads <= 16 && hd_spt <= 63;
842
        bool translate_large= !translate_none && (hd_cylinders * hd_heads) <= 131072;
843
        bool translate_lba  = !translate_none && !translate_large;
844
 
845
        unsigned char translate_byte = (translate_large)? 1 : (translate_lba)? 2 : 0;
846
 
847
        //rtc contents 0-127
848
        unsigned int cmos[128] = {
849
                0x00, //0x00: SEC BCD
850
                0x00, //0x01: ALARM SEC BCD
851
                0x00, //0x02: MIN BCD
852
                0x00, //0x03: ALARM MIN BCD
853
                0x12, //0x04: HOUR BCD 24h
854
                0x12, //0x05: ALARM HOUR BCD 24h
855
                0x01, //0x06: DAY OF WEEK Sunday=1
856
                0x03, //0x07: DAY OF MONTH BCD from 1
857
                0x11, //0x08: MONTH BCD from 1
858
                0x13, //0x09: YEAR BCD
859
                0x26, //0x0A: REG A
860
                0x02, //0x0B: REG B
861
                0x00, //0x0C: REG C
862
                0x80, //0x0D: REG D
863
                0x00, //0x0E: REG E - POST status
864
                0x00, //0x0F: REG F - shutdown status
865
 
866
                fdd_type, //0x10: floppy drive type; 0-none, 1-360K, 2-1.2M, 3-720K, 4-1.44M, 5-2.88M
867
                0x00, //0x11: configuration bits; not used
868
                0xF0, //0x12: hard disk types; 0-none, 1:E-type, F-type 16+
869
                0x00, //0x13: advanced configuration bits; not used
870
                0x0D, //0x14: equipment bits
871
                0x80, //0x15: base memory in 1k LSB
872
                0x02, //0x16: base memory in 1k MSB
873
                0x00, //0x17: memory size above 1m in 1k LSB
874
                0xFC, //0x18: memory size above 1m in 1k MSB
875
                0x2F, //0x19: extended hd types 1/2; type 47d
876
                0x00, //0x1A: extended hd types 2/2
877
 
878
                hd_cylinders & 0xFF,            //0x1B: hd 0 configuration 1/9; cylinders low
879
                (hd_cylinders >> 8) & 0xFF, //0x1C: hd 0 configuration 2/9; cylinders high
880
                hd_heads,                                       //0x1D: hd 0 configuration 3/9; heads
881
                0xFF,                                           //0x1E: hd 0 configuration 4/9; write pre-comp low
882
                0xFF,                                           //0x1F: hd 0 configuration 5/9; write pre-comp high
883
                0xC8,                                           //0x20: hd 0 configuration 6/9; retries/bad map/heads>8
884
                hd_cylinders & 0xFF,            //0x21: hd 0 configuration 7/9; landing zone low
885
                (hd_cylinders >> 8) & 0xFF, //0x22: hd 0 configuration 8/9; landing zone high
886
                hd_spt,                                         //0x23: hd 0 configuration 9/9; sectors/track
887
 
888
                0x00, //0x24: hd 1 configuration 1/9
889
                0x00, //0x25: hd 1 configuration 2/9
890
                0x00, //0x26: hd 1 configuration 3/9
891
                0x00, //0x27: hd 1 configuration 4/9
892
                0x00, //0x28: hd 1 configuration 5/9
893
                0x00, //0x29: hd 1 configuration 6/9
894
                0x00, //0x2A: hd 1 configuration 7/9
895
                0x00, //0x2B: hd 1 configuration 8/9
896
                0x00, //0x2C: hd 1 configuration 9/9
897
 
898
                (boot_from_floppy)? 0x20u : 0x00u, //0x2D: boot sequence
899
 
900
                0x00, //0x2E: checksum MSB
901
                0x00, //0x2F: checksum LSB
902
 
903
                0x00, //0x30: memory size above 1m in 1k LSB
904
                0xFC, //0x31: memory size above 1m in 1k MSB
905
 
906
                0x20, //0x32: IBM century
907
                0x00, //0x33: ?
908
 
909
                0x00, //0x34: memory size above 16m in 64k LSB
910
                0x07, //0x35: memory size above 16m in 64k MSB; 128 MB
911
 
912
                0x00, //0x36: ?
913
                0x20, //0x37: IBM PS/2 century
914
 
915
                0x00,                   //0x38: eltorito boot sequence; not used
916
                translate_byte, //0x39: ata translation policy 1/2
917
                0x00,                   //0x3A: ata translation policy 2/2
918
 
919
                0x00, //0x3B: ?
920
                0x00, //0x3C: ?
921
 
922
                0x00, //0x3D: eltorito boot sequence; not used
923
 
924
                0x00, //0x3E: ?
925
                0x00, //0x3F: ?
926
 
927
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
928
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
929
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
930
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
931
        };
932
 
933
        //count checksum
934
        unsigned short sum = 0;
935
        for(int i=0x10; i<=0x2D; i++) sum += cmos[i];
936
 
937
        cmos[0x2E] = sum >> 8;
938
        cmos[0x2F] = sum & 0xFF;
939
 
940
        for(unsigned int i=0; i<sizeof(cmos)/sizeof(unsigned int); i++) IOWR(RTC_BASE, i, cmos[i]);
941
 
942
        //--------------------------------------------------------------------------
943
 
944
        //--------------------------------------------------------------------------
945
 
946
        //--------------------------------------------------------------------------
947
 
948
        alt_irq_disable_all();
949
 
950
        //release reset - start executing
951
        IOWR(PIO_OUTPUT_BASE, 0, 0x00);
952
 
953
        while(true) {
954
                uint32 keys = IORD(PIO_INPUT_BASE, 0);
955
                if((keys & 0x4) == 0) runtime_menu();
956
 
957
                int cmd = read_byte_if_possible();
958
                if(cmd < 0) continue;
959
 
960
                if(cmd == 0) {
961
                        unsigned int offset = read_int();
962
                        unsigned int size   = read_int();
963
 
964
                        crc32(NULL, NULL);
965
                        unsigned char *ptr = (unsigned char *)(SDRAM_BASE + offset);
966
 
967
                        for(unsigned int i=0; i<size; i++) {
968
                                ptr[i] = read_byte();
969
                                crc32(ptr + i, NULL);
970
                                if((i%1024) == 0) printf("%08x - %d%%\n", (unsigned int)(ptr+i), (i*100/size));
971
                        }
972
 
973
                        unsigned int recv_crc = read_int();
974
                        unsigned int copy_crc = 0;
975
                        crc32(NULL, &copy_crc);
976
 
977
                        unsigned int local_crc = 0;
978
                        crc32(NULL, NULL);
979
                        for(unsigned int i=0; i<size; i++) crc32(ptr + i, NULL);
980
                        crc32(NULL, &local_crc);
981
 
982
                        IOWR(JTAG_UART_BASE, 0, (recv_crc == copy_crc && recv_crc == local_crc)? 'Y' : 'N');
983
                }
984
                else if(cmd == 's') {
985
                        printf("\nStarting ao486...");
986
                        //release reset
987
                        IOWR(PIO_OUTPUT_BASE, 0, 0x00);
988
 
989
                        IOWR(JTAG_UART_BASE, 0, '\n');
990
 
991
                }
992
                else if(cmd == 'd') {
993
                        printf("\nStopping ao486...");
994
 
995
                        //release reset
996
                        IOWR(PIO_OUTPUT_BASE, 0, 0x01);
997
 
998
                        IOWR(JTAG_UART_BASE, 0, '\n');
999
                }
1000
                else if(cmd == 'v') {
1001
                        osd_enable(true);
1002
                }
1003
                else if(cmd == 'b') {
1004
                        osd_enable(false);
1005
                }
1006
                else if(cmd == 'j') {
1007
                        printf("\nJTAG: %08x\n", IORD(JTAG_UART_BASE, 1));
1008
                }
1009
                else {
1010
                        IOWR(JTAG_UART_BASE, 0, 'N');
1011
                }
1012
        }
1013
 
1014
        //--------------------------------------------------------------------------
1015
 
1016
        return 0;
1017
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.