diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj
index 61ec713..64edaeb 100644
--- a/MiSTer.vcxproj
+++ b/MiSTer.vcxproj
@@ -57,6 +57,7 @@
+
@@ -86,6 +87,7 @@
+
diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters
index f2d1745..17969eb 100644
--- a/MiSTer.vcxproj.filters
+++ b/MiSTer.vcxproj.filters
@@ -65,6 +65,9 @@
Source Files
+
+ Source Files
+
@@ -148,6 +151,9 @@
Header Files
+
+ Header Files
+
diff --git a/spi.c b/spi.c
index d2e831a..ed2d166 100644
--- a/spi.c
+++ b/spi.c
@@ -132,6 +132,14 @@ void spi32(uint32_t parm)
spi8(parm >> 0);
}
+uint32_t spi32w(uint32_t parm)
+{
+ uint32_t res;
+ res = spi_w(parm);
+ res |= (spi_w(parm>>16))<<16;
+ return res;
+}
+
// little endian: lsb first
void spi32le(uint32_t parm)
{
diff --git a/spi.h b/spi.h
index 35414a7..26ff901 100644
--- a/spi.h
+++ b/spi.h
@@ -29,6 +29,7 @@ void spi24(uint32_t parm);
void spi32(uint32_t parm);
void spi32le(uint32_t parm);
void spi_n(uint8_t value, uint16_t cnt);
+uint32_t spi32w(uint32_t parm);
/* block transfer functions */
void spi_block_read(uint8_t *addr, int wide);
diff --git a/user_io.c b/user_io.c
index bb679c6..5db3419 100644
--- a/user_io.c
+++ b/user_io.c
@@ -20,6 +20,7 @@
#include "file_io.h"
#include "config.h"
#include "menu.h"
+#include "x86.h"
#define BREAK 0x8000
@@ -133,9 +134,17 @@ char is_menu_core()
return (is_menu_type == 1);
}
+static int is_x86_type = 0;
+char is_x86_core()
+{
+ if (!is_x86_type) is_x86_type = strcasecmp(core_name, "AO486") ? 2 : 1;
+ return (is_x86_type == 1);
+}
+
static void user_io_read_core_name()
{
is_menu_type = 0;
+ is_x86_type = 0;
core_name[0] = 0;
if (user_io_is_8bit_with_config_string())
@@ -276,21 +285,46 @@ void user_io_detect_core_type()
user_io_8bit_set_status(status, 0xffffffff);
}
- // check if there's a .rom present
- sprintf(mainpath, "%s/boot.rom", user_io_get_core_name());
- if (!user_io_file_tx(mainpath, 0))
+ // check for multipart rom
+ sprintf(mainpath, "%s/boot0.rom", user_io_get_core_name());
+ if (user_io_file_tx(mainpath, 0))
{
- strcpy(name + strlen(name) - 3, "ROM");
- user_io_file_tx(name, 0);
+ sprintf(mainpath, "%s/boot1.rom", user_io_get_core_name());
+ if (user_io_file_tx(mainpath, 0x40))
+ {
+ sprintf(mainpath, "%s/boot2.rom", user_io_get_core_name());
+ if (user_io_file_tx(mainpath, 0x80))
+ {
+ sprintf(mainpath, "%s/boot3.rom", user_io_get_core_name());
+ user_io_file_tx(mainpath, 0xC0);
+ }
+ }
+ }
+ else
+ {
+ // legacy style of rom
+ sprintf(mainpath, "%s/boot.rom", user_io_get_core_name());
+ if (!user_io_file_tx(mainpath, 0))
+ {
+ strcpy(name + strlen(name) - 3, "ROM");
+ user_io_file_tx(name, 0);
+ }
}
- // check if there's a .vhd present
- sprintf(mainpath, "%s/boot.vhd", user_io_get_core_name());
- user_io_set_index(0);
- if (!user_io_file_mount(0, mainpath))
+ if (is_x86_core())
{
- strcpy(name + strlen(name) - 3, "VHD");
- user_io_file_mount(0, name);
+ x86_init();
+ }
+ else
+ {
+ // check if there's a .vhd present
+ sprintf(mainpath, "%s/boot.vhd", user_io_get_core_name());
+ user_io_set_index(0);
+ if (!user_io_file_mount(0, mainpath))
+ {
+ strcpy(name + strlen(name) - 3, "VHD");
+ user_io_file_mount(0, name);
+ }
}
}
@@ -613,6 +647,14 @@ int user_io_file_tx(char* name, unsigned char index)
/* transmit the entire file using one transfer */
iprintf("Selected file %s with %lu bytes to send for index %d.%d\n", name, bytes2send, index&0x3F, index>>6);
+ if (is_x86_core())
+ {
+ printf("using DMA transfer mode\n");
+ x86_send(&f, index);
+ FileClose(&f);
+ return 1;
+ }
+
// set index byte (0=bios rom, 1-n=OSD entry index)
user_io_set_index(index);
@@ -654,7 +696,7 @@ int user_io_file_tx(char* name, unsigned char index)
spi8(0x00);
DisableFpga();
- iprintf("\n");
+ printf("\n");
return 1;
}
@@ -897,6 +939,11 @@ void user_io_poll()
*/
// sd card emulation
+ if (is_x86_core())
+ {
+ x86_poll();
+ }
+ else
{
static char buffer[4][512];
static uint64_t buffer_lba[4] = { -1,-1,-1,-1 };
diff --git a/user_io.h b/user_io.h
index 27fc306..ef38875 100644
--- a/user_io.h
+++ b/user_io.h
@@ -64,6 +64,11 @@
#define UIO_FILE_INDEX 0x55
#define UIO_FILE_INFO 0x56
+// ao486 direct memory access
+#define UIO_DMA_WRITE 0x61
+#define UIO_DMA_READ 0x62
+#define UIO_DMA_SDIO 0x63
+
#define JOY_RIGHT 0x01
#define JOY_LEFT 0x02
#define JOY_DOWN 0x04
@@ -168,6 +173,7 @@ int user_io_file_mount(int num, char *name);
char *user_io_get_core_name();
char *user_io_get_core_name_ex();
char is_menu_core();
+char is_x86_core();
emu_mode_t user_io_get_kbdemu();
diff --git a/x86.c b/x86.c
new file mode 100644
index 0000000..625b37a
--- /dev/null
+++ b/x86.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright (c) 2014, Aleksander Osman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "spi.h"
+#include "user_io.h"
+#include "file_io.h"
+
+#define ALT_CPU_CPU_FREQ 30000000u
+
+#define FLOPPY_BASE 0x8800
+#define HDD_BASE 0x8840
+#define PC_BUS_BASE 0x88a0
+#define PIO_OUTPUT_BASE 0x8860
+#define SOUND_BASE 0x9000
+#define PIT_BASE 0x8880
+#define RTC_BASE 0x8c00
+#define SD_BASE 0x0A00
+
+static uint8_t dma_sdio(int status)
+{
+ uint8_t res;
+ EnableFpga();
+ spi8(UIO_DMA_SDIO);
+ res = spi_w((uint16_t)status);
+ DisableFpga();
+ return res;
+}
+
+static uint32_t dma_get(uint32_t address)
+{
+ EnableFpga();
+ spi8(UIO_DMA_READ);
+ spi32w(address);
+ uint32_t res = spi32w(0);
+ DisableFpga();
+ return res;
+}
+
+static void dma_set(uint32_t address, uint32_t data)
+{
+ EnableFpga();
+ spi8(UIO_DMA_WRITE);
+ spi32w(address);
+ spi32w(data);
+ DisableFpga();
+}
+
+static void dma_sendbuf(uint32_t address, uint32_t length, uint32_t *data)
+{
+ EnableFpga();
+ spi8(UIO_DMA_WRITE);
+ spi32w(address);
+ while (length--) spi32w(*data++);
+ DisableFpga();
+}
+
+static void dma_rcvbuf(uint32_t address, uint32_t length, uint32_t *data)
+{
+ EnableFpga();
+ spi8(UIO_DMA_READ);
+ spi32w(address);
+ while (length--) *data++ = spi32w(0);
+ DisableFpga();
+}
+
+int x86_send(fileTYPE *f, uint8_t index)
+{
+ static uint32_t buf[128];
+
+ FileSeekLBA(f, 0);
+
+ EnableFpga();
+ spi8(UIO_DMA_WRITE);
+ spi32w( index ? 0x80C0000 : 0x80F0000 );
+
+ unsigned long bytes2send = f->size;
+
+ while (bytes2send)
+ {
+ printf(".");
+
+ uint16_t chunk = (bytes2send>512) ? 512 : bytes2send;
+ bytes2send -= chunk;
+
+ FileReadSec(f, buf);
+
+ chunk = (chunk + 3) >> 2;
+ uint32_t* p = buf;
+ while(chunk--) spi32w(*p++);
+ }
+ DisableFpga();
+
+ printf("\n");
+ return 1;
+}
+
+static void crc32(uint8_t *ptr, uint32_t *crc_output)
+{
+ static uint8_t crc[32];
+
+ //do nothing
+ if(ptr != NULL && crc_output != NULL) return;
+
+ //initialize
+ if(ptr == NULL && crc_output == NULL)
+ {
+ for(int i=0; i<32; i++) crc[i] = 1;
+ return;
+ }
+
+ //output
+ if(ptr == NULL && crc_output != NULL)
+ {
+ *crc_output = 0;
+ for(int i=0; i<32; i++)
+ {
+ (*crc_output) |= crc[i] << (31-i);
+ }
+ (*crc_output) = ~(*crc_output);
+ return;
+ }
+
+ uint8_t in[8];
+ for(int j=0; j<8; j++) in[j] = ((*ptr) >> j) & 1;
+
+ uint8_t new_crc[32];
+
+ new_crc[31] = in[2] ^ crc[23] ^ crc[29];
+ new_crc[30] = in[0] ^ in[3] ^ crc[22] ^ crc[28] ^ crc[31];
+ new_crc[29] = in[0] ^ in[1] ^ in[4] ^ crc[21] ^ crc[27] ^ crc[30] ^ crc[31];
+ new_crc[28] = in[1] ^ in[2] ^ in[5] ^ crc[20] ^ crc[26] ^ crc[29] ^ crc[30];
+ new_crc[27] = in[0] ^ in[2] ^ in[3] ^ in[6] ^ crc[19] ^ crc[25] ^ crc[28] ^ crc[29] ^ crc[31];
+ new_crc[26] = in[1] ^ in[3] ^ in[4] ^ in[7] ^ crc[18] ^ crc[24] ^ crc[27] ^ crc[28] ^ crc[30];
+ new_crc[25] = in[4] ^ in[5] ^ crc[17] ^ crc[26] ^ crc[27];
+ new_crc[24] = in[0] ^ in[5] ^ in[6] ^ crc[16] ^ crc[25] ^ crc[26] ^ crc[31];
+ new_crc[23] = in[1] ^ in[6] ^ in[7] ^ crc[15] ^ crc[24] ^ crc[25] ^ crc[30];
+ new_crc[22] = in[7] ^ crc[14] ^ crc[24];
+ new_crc[21] = in[2] ^ crc[13] ^ crc[29];
+ new_crc[20] = in[3] ^ crc[12] ^ crc[28];
+ new_crc[19] = in[0] ^ in[4] ^ crc[11] ^ crc[27] ^ crc[31];
+ new_crc[18] = in[0] ^ in[1] ^ in[5] ^ crc[10] ^ crc[26] ^ crc[30] ^ crc[31];
+ new_crc[17] = in[1] ^ in[2] ^ in[6] ^ crc[9] ^ crc[25] ^ crc[29] ^ crc[30];
+ new_crc[16] = in[2] ^ in[3] ^ in[7] ^ crc[8] ^ crc[24] ^ crc[28] ^ crc[29];
+ new_crc[15] = in[0] ^ in[2] ^ in[3] ^ in[4] ^ crc[7] ^ crc[27] ^ crc[28] ^ crc[29] ^ crc[31];
+ 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];
+ 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];
+ 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];
+ new_crc[11] = in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[3] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28];
+ new_crc[10] = in[2] ^ in[4] ^ in[5] ^ in[7] ^ crc[2] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[29];
+ new_crc[9] = in[2] ^ in[3] ^ in[5] ^ in[6] ^ crc[1] ^ crc[25] ^ crc[26] ^ crc[28] ^ crc[29];
+ new_crc[8] = in[3] ^ in[4] ^ in[6] ^ in[7] ^ crc[0] ^ crc[24] ^ crc[25] ^ crc[27] ^ crc[28];
+ new_crc[7] = in[0] ^ in[2] ^ in[4] ^ in[5] ^ in[7] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[29] ^ crc[31];
+ 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];
+ 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];
+ new_crc[4] = in[1] ^ in[3] ^ in[4] ^ in[5] ^ in[7] ^ crc[24] ^ crc[26] ^ crc[27] ^ crc[28] ^ crc[30];
+ new_crc[3] = in[0] ^ in[4] ^ in[5] ^ in[6] ^ crc[25] ^ crc[26] ^ crc[27] ^ crc[31];
+ new_crc[2] = in[0] ^ in[1] ^ in[5] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[26] ^ crc[30] ^ crc[31];
+ new_crc[1] = in[0] ^ in[1] ^ in[6] ^ in[7] ^ crc[24] ^ crc[25] ^ crc[30] ^ crc[31];
+ new_crc[0] = in[1] ^ in[7] ^ crc[24] ^ crc[30];
+
+ memcpy(crc, new_crc, sizeof(crc));
+}
+
+struct entry_t
+{
+ uint8_t type;
+ uint8_t name[15];
+
+ union args_t {
+ struct bios_t {
+ uint32_t sector;
+ uint32_t size_in_bytes;
+ uint32_t destination;
+ uint32_t crc32;
+ } bios;
+ struct hdd_t {
+ uint32_t sector;
+ uint32_t cyliders;
+ uint32_t heads;
+ uint32_t spt;
+ } hdd;
+ struct floppy_t {
+ uint32_t sector;
+ } floppy;
+ struct end_of_list_t {
+ uint32_t crc32;
+ } end_of_list;
+ } args;
+} __attribute__((packed));
+
+#define ENTRIES_COUNT 128
+static struct entry_t entries[ENTRIES_COUNT];
+
+#define TYPE_BIOS 1
+#define TYPE_VGABIOS 2
+#define TYPE_HDD 3
+#define TYPE_FD_1_44M 16
+#define TYPE_CRC32 127
+
+#define ENTRY_ABORT -500
+
+static int floppy_index = -1;
+static int hdd_index = -1;
+
+static bool floppy_is_160k = false;
+static bool floppy_is_180k = false;
+static bool floppy_is_320k = false;
+static bool floppy_is_360k = false;
+static bool floppy_is_720k = false;
+static bool floppy_is_1_2m = false;
+static bool floppy_is_1_44m= true;
+static bool floppy_is_2_88m= false;
+
+static bool floppy_writeprotect = true;
+
+#define IOWR(base, reg, value) dma_set(base+(reg<<2), value)
+
+static void set_floppy(int index)
+{
+ floppy_index = index;
+ floppy_writeprotect = true;
+
+ int floppy_sd_base = (index >= 0) ? entries[floppy_index].args.floppy.sector : 0;
+
+ int floppy_media =
+ (floppy_index < 0)? 0x20 :
+ (floppy_is_160k)? 0x00 :
+ (floppy_is_180k)? 0x00 :
+ (floppy_is_320k)? 0x00 :
+ (floppy_is_360k)? 0x00 :
+ (floppy_is_720k)? 0xC0 :
+ (floppy_is_1_2m)? 0x00 :
+ (floppy_is_1_44m)? 0x80 :
+ (floppy_is_2_88m)? 0x40 :
+ 0x20;
+
+ IOWR(FLOPPY_BASE, 0x0, floppy_index >= 0 ? 1 : 0);
+ IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0);
+ IOWR(FLOPPY_BASE, 0x6, floppy_sd_base);
+ IOWR(FLOPPY_BASE, 0xC, floppy_media);
+}
+
+static fileTYPE sd_image = { 0 };
+
+static int img_mount(char *name)
+{
+ int writable = FileCanWrite(name);
+ int ret = FileOpenEx(&sd_image, name, writable ? (O_RDWR | O_SYNC) : O_RDONLY);
+ if (!ret)
+ {
+ sd_image.size = 0;
+ printf("Failed to open file %s\n", name);
+ return 0;
+ }
+
+ printf("Mount %s as %s\n", name, writable ? "read-write" : "read-only");
+ return 1;
+}
+
+static int img_read(uint32_t lba, void *buf, uint32_t len)
+{
+ if (!FileSeekLBA(&sd_image, lba)) return 0;
+ return FileReadAdv(&sd_image, buf, len);
+}
+
+static int img_write(uint32_t lba, void *buf, uint32_t len)
+{
+ if (!FileSeekLBA(&sd_image, lba)) return 0;
+ return FileWriteAdv(&sd_image, buf, len);
+}
+
+void x86_init()
+{
+ IOWR(PC_BUS_BASE, 0, 0x00FFF0EA);
+ IOWR(PC_BUS_BASE, 1, 0x000000F0);
+
+ //resets output
+ IOWR(PIO_OUTPUT_BASE, 0, 0x01);
+
+ if (!img_mount("ao486.vhd"))
+ {
+ return;
+ }
+
+ if (!img_read(0, entries, sizeof(entries)))
+ {
+ return;
+ }
+
+ //check crc32
+ bool crc_ok = false;
+ for(int i=0; i= 0? 1 : 0);
+ IOWR(FLOPPY_BASE, 0x1, floppy_writeprotect? 1 : 0);
+ IOWR(FLOPPY_BASE, 0x2, floppy_cylinders);
+ IOWR(FLOPPY_BASE, 0x3, floppy_spt);
+ IOWR(FLOPPY_BASE, 0x4, floppy_total_sectors);
+ IOWR(FLOPPY_BASE, 0x5, floppy_heads);
+ IOWR(FLOPPY_BASE, 0x6, floppy_sd_base);
+ IOWR(FLOPPY_BASE, 0x7, (int)(floppy_wait_cycles / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+ IOWR(FLOPPY_BASE, 0x8, (int)(1000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+ IOWR(FLOPPY_BASE, 0x9, (int)(1666666.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+ IOWR(FLOPPY_BASE, 0xA, (int)(2000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+ IOWR(FLOPPY_BASE, 0xB, (int)(500000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+ IOWR(FLOPPY_BASE, 0xC, floppy_media);
+
+ //-------------------------------------------------------------------------- hdd
+
+ hdd_index = 2;
+ unsigned int hd_cylinders = entries[hdd_index].args.hdd.cyliders; //1-1024; 10 bits; implemented 16 bits
+ unsigned int hd_heads = entries[hdd_index].args.hdd.heads; //1-16; 4 bits; at least 9 heads for cmos 0x20
+ unsigned int hd_spt = entries[hdd_index].args.hdd.spt; //1-255; 8 bits;
+
+ int hdd_sd_base = entries[hdd_index].args.hdd.sector;
+
+ unsigned int hd_total_sectors = hd_cylinders * hd_heads * hd_spt;
+
+ /*
+ 0x00.[31:0]: identify write
+ 0x01.[16:0]: media cylinders
+ 0x02.[4:0]: media heads
+ 0x03.[8:0]: media spt
+ 0x04.[13:0]: media sectors per cylinder = spt * heads
+ 0x05.[31:0]: media sectors total
+ 0x06.[31:0]: media sd base
+ */
+
+ uint32_t identify[256] =
+ {
+ 0x0040, //word 0
+ (hd_cylinders > 16383)? 16383 : hd_cylinders, //word 1
+ 0x0000, //word 2 reserved
+ hd_heads, //word 3
+ (uint16_t)(512 * hd_spt), //word 4
+ 512, //word 5
+ hd_spt, //word 6
+ 0x0000, //word 7 vendor specific
+ 0x0000, //word 8 vendor specific
+ 0x0000, //word 9 vendor specific
+ ('A' << 8) | 'O', //word 10
+ ('H' << 8) | 'D', //word 11
+ ('0' << 8) | '0', //word 12
+ ('0' << 8) | '0', //word 13
+ ('0' << 8) | ' ', //word 14
+ (' ' << 8) | ' ', //word 15
+ (' ' << 8) | ' ', //word 16
+ (' ' << 8) | ' ', //word 17
+ (' ' << 8) | ' ', //word 18
+ (' ' << 8) | ' ', //word 19
+ 3, //word 20 buffer type
+ 512, //word 21 cache size
+ 4, //word 22 number of ecc bytes
+ 0,0,0,0, //words 23..26 firmware revision
+ ('A' << 8) | 'O', //words 27..46 model number
+ (' ' << 8) | 'H',
+ ('a' << 8) | 'r',
+ ('d' << 8) | 'd',
+ ('r' << 8) | 'i',
+ ('v' << 8) | 'e',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ (' ' << 8) | ' ',
+ 16, //word 47 max multiple sectors
+ 1, //word 48 dword io
+ 1<<9, //word 49 lba supported
+ 0x0000, //word 50 reserved
+ 0x0200, //word 51 pio timing
+ 0x0200, //word 52 pio timing
+ 0x0007, //word 53 valid fields
+ (hd_cylinders > 16383)? 16383 : hd_cylinders, //word 54
+ hd_heads, //word 55
+ hd_spt, //word 56
+ hd_total_sectors & 0xFFFF, //word 57
+ hd_total_sectors >> 16, //word 58
+ 0x0000, //word 59 multiple sectors
+ hd_total_sectors & 0xFFFF, //word 60
+ hd_total_sectors >> 16, //word 61
+ 0x0000, //word 62 single word dma modes
+ 0x0000, //word 63 multiple word dma modes
+ 0x0000, //word 64 pio modes
+ 120,120,120,120, //word 65..68
+ 0,0,0,0,0,0,0,0,0,0,0, //word 69..79
+ 0x007E, //word 80 ata modes
+ 0x0000, //word 81 minor version number
+ 1<<14, //word 82 supported commands
+ (1<<14) | (1<<13) | (1<<12) | (1<<10), //word 83
+ 1<<14, //word 84
+ 1<<14, //word 85
+ (1<<14) | (1<<13) | (1<<12) | (1<<10), //word 86
+ 1<<14, //word 87
+ 0x0000, //word 88
+ 0,0,0,0, //word 89..92
+ 1 | (1<<14) | 0x2000, //word 93
+ 0,0,0,0,0,0, //word 94..99
+ hd_total_sectors & 0xFFFF, //word 100
+ hd_total_sectors >> 16, //word 101
+ 0, //word 102
+ 0, //word 103
+
+ 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
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //word 128..255
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ };
+
+ for(int i=0; i<128; i++) IOWR(HDD_BASE, 0, ((unsigned int)identify[2*i+1] << 16) | (unsigned int)identify[2*i+0]);
+
+ IOWR(HDD_BASE, 1, hd_cylinders);
+ IOWR(HDD_BASE, 2, hd_heads);
+ IOWR(HDD_BASE, 3, hd_spt);
+ IOWR(HDD_BASE, 4, hd_spt * hd_heads);
+ IOWR(HDD_BASE, 5, hd_spt * hd_heads * hd_cylinders);
+ IOWR(HDD_BASE, 6, hdd_sd_base);
+
+ printf("HDD:\n hd_cylinders %d\n hd_heads %d\n hd_spt %d\n hdd_sd_base %d\n\n", hd_cylinders, hd_heads, hd_spt, hdd_sd_base);
+
+ //-------------------------------------------------------------------------- rtc
+
+ bool boot_from_floppy = true;
+
+ /*
+ 128.[26:0]: cycles in second
+ 129.[12:0]: cycles in 122.07031 us
+ */
+
+ IOWR(RTC_BASE, 128, (int)(1000000000.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+ IOWR(RTC_BASE, 129, (int)(122070.0 / (1000000000.0 / ALT_CPU_CPU_FREQ)));
+
+ unsigned char fdd_type = (floppy_is_2_88m)? 0x50 : (floppy_is_1_44m)? 0x40 : (floppy_is_720k)? 0x30 : (floppy_is_1_2m)? 0x20 : 0x10;
+
+ bool translate_none = hd_cylinders <= 1024 && hd_heads <= 16 && hd_spt <= 63;
+ bool translate_large= !translate_none && (hd_cylinders * hd_heads) <= 131072;
+ bool translate_lba = !translate_none && !translate_large;
+
+ unsigned char translate_byte = (translate_large)? 1 : (translate_lba)? 2 : 0;
+
+ //rtc contents 0-127
+ unsigned int cmos[128] = {
+ 0x00, //0x00: SEC BCD
+ 0x00, //0x01: ALARM SEC BCD
+ 0x00, //0x02: MIN BCD
+ 0x00, //0x03: ALARM MIN BCD
+ 0x12, //0x04: HOUR BCD 24h
+ 0x12, //0x05: ALARM HOUR BCD 24h
+ 0x01, //0x06: DAY OF WEEK Sunday=1
+ 0x03, //0x07: DAY OF MONTH BCD from 1
+ 0x11, //0x08: MONTH BCD from 1
+ 0x13, //0x09: YEAR BCD
+ 0x26, //0x0A: REG A
+ 0x02, //0x0B: REG B
+ 0x00, //0x0C: REG C
+ 0x80, //0x0D: REG D
+ 0x00, //0x0E: REG E - POST status
+ 0x00, //0x0F: REG F - shutdown status
+
+ fdd_type, //0x10: floppy drive type; 0-none, 1-360K, 2-1.2M, 3-720K, 4-1.44M, 5-2.88M
+ 0x00, //0x11: configuration bits; not used
+ 0xF0, //0x12: hard disk types; 0-none, 1:E-type, F-type 16+
+ 0x00, //0x13: advanced configuration bits; not used
+ 0x0D, //0x14: equipment bits
+ 0x80, //0x15: base memory in 1k LSB
+ 0x02, //0x16: base memory in 1k MSB
+ 0x00, //0x17: memory size above 1m in 1k LSB
+ 0xFC, //0x18: memory size above 1m in 1k MSB
+ 0x2F, //0x19: extended hd types 1/2; type 47d
+ 0x00, //0x1A: extended hd types 2/2
+
+ hd_cylinders & 0xFF, //0x1B: hd 0 configuration 1/9; cylinders low
+ (hd_cylinders >> 8) & 0xFF, //0x1C: hd 0 configuration 2/9; cylinders high
+ hd_heads, //0x1D: hd 0 configuration 3/9; heads
+ 0xFF, //0x1E: hd 0 configuration 4/9; write pre-comp low
+ 0xFF, //0x1F: hd 0 configuration 5/9; write pre-comp high
+ 0xC8, //0x20: hd 0 configuration 6/9; retries/bad map/heads>8
+ hd_cylinders & 0xFF, //0x21: hd 0 configuration 7/9; landing zone low
+ (hd_cylinders >> 8) & 0xFF, //0x22: hd 0 configuration 8/9; landing zone high
+ hd_spt, //0x23: hd 0 configuration 9/9; sectors/track
+
+ 0x00, //0x24: hd 1 configuration 1/9
+ 0x00, //0x25: hd 1 configuration 2/9
+ 0x00, //0x26: hd 1 configuration 3/9
+ 0x00, //0x27: hd 1 configuration 4/9
+ 0x00, //0x28: hd 1 configuration 5/9
+ 0x00, //0x29: hd 1 configuration 6/9
+ 0x00, //0x2A: hd 1 configuration 7/9
+ 0x00, //0x2B: hd 1 configuration 8/9
+ 0x00, //0x2C: hd 1 configuration 9/9
+
+ (boot_from_floppy)? 0x20u : 0x00u, //0x2D: boot sequence
+
+ 0x00, //0x2E: checksum MSB
+ 0x00, //0x2F: checksum LSB
+
+ 0x00, //0x30: memory size above 1m in 1k LSB
+ 0xFC, //0x31: memory size above 1m in 1k MSB
+
+ 0x20, //0x32: IBM century
+ 0x00, //0x33: ?
+
+ 0x00, //0x34: memory size above 16m in 64k LSB
+ 0x07, //0x35: memory size above 16m in 64k MSB; 128 MB
+
+ 0x00, //0x36: ?
+ 0x20, //0x37: IBM PS/2 century
+
+ 0x00, //0x38: eltorito boot sequence; not used
+ translate_byte, //0x39: ata translation policy 1/2
+ 0x00, //0x3A: ata translation policy 2/2
+
+ 0x00, //0x3B: ?
+ 0x00, //0x3C: ?
+
+ 0x00, //0x3D: eltorito boot sequence; not used
+
+ 0x00, //0x3E: ?
+ 0x00, //0x3F: ?
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ //count checksum
+ unsigned short sum = 0;
+ for(int i=0x10; i<=0x2D; i++) sum += cmos[i];
+
+ cmos[0x2E] = sum >> 8;
+ cmos[0x2F] = sum & 0xFF;
+
+ for(unsigned int i=0; i> 2, (uint32_t*)&sd_params);
+ printf("Read: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt);
+
+ if (sd_image.size)
+ {
+ if (sd_params.bl_cnt>0 && sd_params.bl_cnt<=4)
+ {
+ if (img_read(sd_params.lba, secbuf, sd_params.bl_cnt * 512))
+ {
+ dma_sendbuf(sd_params.addr, sd_params.bl_cnt * 128, secbuf);
+ res = 1;
+ }
+ }
+ else
+ {
+ printf("Error: Block count %d is out of range 1..4.\n", sd_params.bl_cnt);
+ }
+ }
+ else
+ {
+ printf("Error: image is not ready.\n");
+ }
+
+ dma_sdio(res ? 1 : 2);
+ }
+ else if (sd_req == 2)
+ {
+ dma_rcvbuf(SD_BASE + (4 << 2), sizeof(sd_params) >> 2, (uint32_t*)&sd_params);
+ printf("Write: 0x%08x, 0x%08x, %d\n", sd_params.addr, sd_params.lba, sd_params.bl_cnt);
+
+ if (sd_image.size)
+ {
+ if (sd_params.bl_cnt>0 && sd_params.bl_cnt <= 4)
+ {
+ if (sd_image.mode & O_RDWR)
+ {
+ dma_rcvbuf(sd_params.addr, sd_params.bl_cnt * 128, secbuf);
+ if (img_write(sd_params.lba, secbuf, sd_params.bl_cnt * 512))
+ {
+ res = 1;
+ }
+ }
+ else
+ {
+ printf("Error: image is read-only.\n");
+ }
+ }
+ else
+ {
+ printf("Error: Block count %d is out of range 1..4.\n", sd_params.bl_cnt);
+ }
+ }
+ else
+ {
+ printf("Error: image is not ready.\n");
+ }
+
+ dma_sdio(res ? 1 : 2);
+ }
+}
diff --git a/x86.h b/x86.h
new file mode 100644
index 0000000..1ccdaec
--- /dev/null
+++ b/x86.h
@@ -0,0 +1,8 @@
+#ifndef X86_H
+#define X86_H
+
+void x86_init();
+void x86_poll();
+int x86_send(fileTYPE *f, uint8_t index);
+
+#endif