pcxt: FDD support, based on AO486 (#700)
This commit is contained in:
3
menu.cpp
3
menu.cpp
@@ -2067,7 +2067,7 @@ void HandleUI(void)
|
||||
}
|
||||
|
||||
ioctl_index = 0;
|
||||
if ((p[idx] >= '0' && p[idx] <= '9') || is_x86()) ioctl_index = p[idx] - '0';
|
||||
if ((p[idx] >= '0' && p[idx] <= '9') || is_x86() || is_pcxt()) ioctl_index = p[idx] - '0';
|
||||
substrcpy(ext, p, 1);
|
||||
while (strlen(ext) % 3) strcat(ext, " ");
|
||||
|
||||
@@ -2078,6 +2078,7 @@ void HandleUI(void)
|
||||
|
||||
memcpy(Selected_tmp, Selected_S[(int)ioctl_index], sizeof(Selected_tmp));
|
||||
if (is_x86()) strcpy(Selected_tmp, x86_get_image_path(ioctl_index));
|
||||
if (is_pcxt()) strcpy(Selected_tmp, pcxt_get_image_path(ioctl_index));
|
||||
if (is_psx() && (ioctl_index == 2 || ioctl_index == 3)) fs_Options |= SCANO_SAVES;
|
||||
|
||||
if (is_pce() || is_megacd() || is_x86() || (is_psx() && !(fs_Options & SCANO_SAVES)))
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
#include "../../debug.h"
|
||||
#include "../../user_io.h"
|
||||
#include "../../input.h"
|
||||
#include "../x86/x86_share.h"
|
||||
#include "../../support.h"
|
||||
#include "../../lib/serial_server/library/Library.h"
|
||||
#include "../../lib/serial_server/library/FlatImage.h"
|
||||
#include "../../ide.h"
|
||||
#include "pcxt.h"
|
||||
|
||||
int verbose = 0;
|
||||
@@ -30,16 +32,95 @@ pthread_t uart_thread;
|
||||
SerialAccess serial;
|
||||
bool in_process;
|
||||
|
||||
#define FDD0_BASE 0xF200
|
||||
#define FDD1_BASE 0xF300
|
||||
#define CFG_VER 1
|
||||
|
||||
#define FDD_TYPE_NONE 0
|
||||
#define FDD_TYPE_160 1
|
||||
#define FDD_TYPE_180 2
|
||||
#define FDD_TYPE_320 3
|
||||
#define FDD_TYPE_360 4
|
||||
#define FDD_TYPE_720 5
|
||||
#define FDD_TYPE_1200 6
|
||||
#define FDD_TYPE_1440 7
|
||||
#define FDD_TYPE_1680 8
|
||||
#define FDD_TYPE_2880 9
|
||||
|
||||
static char floppy_type[2] = { FDD_TYPE_NONE, FDD_TYPE_NONE };
|
||||
|
||||
static fileTYPE fdd0_image = {};
|
||||
static fileTYPE fdd1_image = {};
|
||||
|
||||
#define IOWR(base, reg, value) x86_dma_set((base) + (reg), value)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ver;
|
||||
char img_name[2][1024];
|
||||
char img_name[3][1024];
|
||||
} pcxt_config;
|
||||
|
||||
static pcxt_config config;
|
||||
|
||||
static int img_read(fileTYPE* f, uint32_t lba, void* buf, uint32_t cnt)
|
||||
{
|
||||
if (!FileSeekLBA(f, lba)) return 0;
|
||||
return FileReadAdv(f, buf, cnt * 512);
|
||||
}
|
||||
|
||||
static uint32_t img_write(fileTYPE* f, uint32_t lba, void* buf, uint32_t cnt)
|
||||
{
|
||||
if (!FileSeekLBA(f, lba)) return 0;
|
||||
return FileWriteAdv(f, buf, cnt * 512);
|
||||
}
|
||||
|
||||
static void x86_dma_set(uint32_t address, uint32_t data)
|
||||
{
|
||||
EnableIO();
|
||||
spi8(UIO_DMA_WRITE);
|
||||
spi32_w(address);
|
||||
spi_w((uint16_t)data);
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
static void x86_dma_sendbuf(uint32_t address, uint32_t length, uint32_t* data)
|
||||
{
|
||||
EnableIO();
|
||||
fpga_spi_fast(UIO_DMA_WRITE);
|
||||
fpga_spi_fast(address);
|
||||
fpga_spi_fast(0);
|
||||
|
||||
if (address < FDD0_BASE) fpga_spi_fast_block_write((uint16_t*)data, length * 2);
|
||||
else
|
||||
{
|
||||
uint8_t* buf = (uint8_t*)data;
|
||||
length *= 4;
|
||||
while (length--) spi_w(*buf++);
|
||||
}
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
static void x86_dma_recvbuf(uint32_t address, uint32_t length, uint32_t* data)
|
||||
{
|
||||
EnableIO();
|
||||
fpga_spi_fast(UIO_DMA_READ);
|
||||
fpga_spi_fast(address);
|
||||
fpga_spi_fast(0);
|
||||
|
||||
if (address < FDD0_BASE) fpga_spi_fast_block_read((uint16_t*)data, length * 2);
|
||||
else if (address == FDD0_BASE)
|
||||
{
|
||||
while (length--) *data++ = spi_w(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t* buf = (uint8_t*)data;
|
||||
length *= 4;
|
||||
while (length--) *buf++ = spi_w(0);
|
||||
}
|
||||
DisableIO();
|
||||
}
|
||||
|
||||
void pcxt_init()
|
||||
{
|
||||
user_io_status_set("[0]", 1);
|
||||
@@ -77,36 +158,6 @@ void* OpenUART(void*) {
|
||||
int timeoutEnabled = 1;
|
||||
FILE* fd;
|
||||
long size;
|
||||
|
||||
// FDD CHS Calculator
|
||||
|
||||
unsigned long fdd_cyl = 0, fdd_sect = 0, fdd_head = 0;
|
||||
bool is_fdd = false;
|
||||
struct floppyInfo* fdd_fi;
|
||||
|
||||
if (strlen(config.img_name[1]))
|
||||
{
|
||||
fd = fopen(config.img_name[1], "r");
|
||||
if (fd)
|
||||
{
|
||||
is_fdd = true;
|
||||
fseek(fd, 0L, SEEK_END);
|
||||
size = ftell(fd);
|
||||
|
||||
if ((fdd_fi = FindFloppyInfoBySize(size)))
|
||||
{
|
||||
fdd_sect = fdd_fi->sectors;
|
||||
fdd_head = fdd_fi->heads;
|
||||
fdd_cyl = fdd_fi->cylinders;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdd_sect = 63;
|
||||
fdd_head = 16;
|
||||
fdd_cyl = size / (16 * 63);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HDD CHS Calculator
|
||||
|
||||
@@ -114,9 +165,9 @@ void* OpenUART(void*) {
|
||||
bool is_hdd = false;
|
||||
struct hddInfo *hdd_fi;
|
||||
|
||||
if (strlen(config.img_name[0]))
|
||||
if (strlen(config.img_name[2]))
|
||||
{
|
||||
fd = fopen(config.img_name[0], "r");
|
||||
fd = fopen(config.img_name[2], "r");
|
||||
if (fd)
|
||||
{
|
||||
is_hdd = true;
|
||||
@@ -143,16 +194,7 @@ void* OpenUART(void*) {
|
||||
|
||||
if (is_hdd)
|
||||
{
|
||||
images[0] = new FlatImage(config.img_name[0], status & 2, 0, createFile, hdd_cyl, hdd_head, hdd_sect, useCHS);
|
||||
|
||||
if (is_fdd)
|
||||
{
|
||||
images[1] = new FlatImage(config.img_name[1], status & 1, 1, createFile, fdd_cyl, fdd_head, fdd_sect, useCHS);
|
||||
}
|
||||
}
|
||||
else if (is_fdd)
|
||||
{
|
||||
images[0] = new FlatImage(config.img_name[1], status & 1, 0, createFile, fdd_cyl, fdd_head, fdd_sect, useCHS);
|
||||
images[0] = new FlatImage(config.img_name[2], 0, 0, createFile, hdd_cyl, hdd_head, hdd_sect, useCHS);
|
||||
}
|
||||
|
||||
// Mount Images
|
||||
@@ -236,7 +278,198 @@ void pcxt_load_images()
|
||||
in_process = true;
|
||||
}
|
||||
|
||||
static void fdd_set(int num, char* filename)
|
||||
{
|
||||
floppy_type[num] = FDD_TYPE_1440;
|
||||
|
||||
fileTYPE* fdd_image = num ? &fdd1_image : &fdd0_image;
|
||||
|
||||
int floppy = ide_img_mount(fdd_image, filename, 1);
|
||||
uint32_t size = fdd_image->size / 512;
|
||||
printf("floppy size: %d blks\n", size);
|
||||
if (floppy && size)
|
||||
{
|
||||
if (size >= 8000)
|
||||
{
|
||||
floppy = 0;
|
||||
FileClose(fdd_image);
|
||||
printf("Image size is too large for floppy. Closing...\n");
|
||||
}
|
||||
else if (size >= 5760) floppy_type[num] = FDD_TYPE_2880;
|
||||
else if (size >= 3360) floppy_type[num] = FDD_TYPE_1680;
|
||||
else if (size >= 2880) floppy_type[num] = FDD_TYPE_1440;
|
||||
else if (size >= 2400) floppy_type[num] = FDD_TYPE_1200;
|
||||
else if (size >= 1440) floppy_type[num] = FDD_TYPE_720;
|
||||
else if (size >= 720) floppy_type[num] = FDD_TYPE_360;
|
||||
else if (size >= 640) floppy_type[num] = FDD_TYPE_320;
|
||||
else if (size >= 360) floppy_type[num] = FDD_TYPE_180;
|
||||
else floppy_type[num] = FDD_TYPE_160;
|
||||
}
|
||||
else
|
||||
{
|
||||
floppy = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
0x00.[0]: media present
|
||||
0x01.[0]: media writeprotect
|
||||
0x02.[7:0]: media cylinders
|
||||
0x03.[7:0]: media sectors per track
|
||||
0x04.[31:0]: media total sector count
|
||||
0x05.[1:0]: media heads
|
||||
0x06.[31:0]: media sd base
|
||||
0x07.[15:0]: media wait cycles: 200000 us / spt
|
||||
0x08.[15:0]: media wait rate 0: 1000 us
|
||||
0x09.[15:0]: media wait rate 1: 1666 us
|
||||
0x0A.[15:0]: media wait rate 2: 2000 us
|
||||
0x0B.[15:0]: media wait rate 3: 500 us
|
||||
0x0C.[7:0]: media type: 8'h20 none; 8'h00 old; 8'hC0 720k; 8'h80 1_44M; 8'h40 2_88M
|
||||
*/
|
||||
|
||||
int floppy_spt = 0;
|
||||
int floppy_cylinders = 0;
|
||||
int floppy_heads = 0;
|
||||
|
||||
switch (floppy_type[num])
|
||||
{
|
||||
case FDD_TYPE_160: floppy_spt = 8; floppy_cylinders = 40; floppy_heads = 1; break;
|
||||
case FDD_TYPE_180: floppy_spt = 9; floppy_cylinders = 40; floppy_heads = 1; break;
|
||||
case FDD_TYPE_320: floppy_spt = 8; floppy_cylinders = 40; floppy_heads = 2; break;
|
||||
case FDD_TYPE_360: floppy_spt = 9; floppy_cylinders = 40; floppy_heads = 2; break;
|
||||
case FDD_TYPE_720: floppy_spt = 9; floppy_cylinders = 80; floppy_heads = 2; break;
|
||||
case FDD_TYPE_1200: floppy_spt = 15; floppy_cylinders = 80; floppy_heads = 2; break;
|
||||
case FDD_TYPE_1440: floppy_spt = 18; floppy_cylinders = 80; floppy_heads = 2; break;
|
||||
case FDD_TYPE_1680: floppy_spt = 21; floppy_cylinders = 80; floppy_heads = 2; break;
|
||||
case FDD_TYPE_2880: floppy_spt = 36; floppy_cylinders = 80; floppy_heads = 2; break;
|
||||
}
|
||||
|
||||
int floppy_total_sectors = floppy_spt * floppy_heads * floppy_cylinders;
|
||||
|
||||
printf("floppy:\n");
|
||||
printf(" cylinders: %d\n", floppy_cylinders);
|
||||
printf(" heads: %d\n", floppy_heads);
|
||||
printf(" spt: %d\n", floppy_spt);
|
||||
printf(" total_sectors: %d\n\n", floppy_total_sectors);
|
||||
|
||||
uint32_t subaddr = num << 7;
|
||||
|
||||
IOWR(FDD0_BASE + subaddr, 0x0, 0); // Always eject floppy before insertion
|
||||
usleep(100000);
|
||||
|
||||
IOWR(FDD0_BASE + subaddr, 0x0, floppy ? 1 : 0);
|
||||
IOWR(FDD0_BASE + subaddr, 0x1, (floppy && (fdd_image->mode & O_RDWR)) ? 0 : 1);
|
||||
IOWR(FDD0_BASE + subaddr, 0x2, floppy_cylinders);
|
||||
IOWR(FDD0_BASE + subaddr, 0x3, floppy_spt);
|
||||
IOWR(FDD0_BASE + subaddr, 0x4, floppy_total_sectors);
|
||||
IOWR(FDD0_BASE + subaddr, 0x5, floppy_heads);
|
||||
IOWR(FDD0_BASE + subaddr, 0x6, 0); // base LBA
|
||||
IOWR(FDD0_BASE + subaddr, 0xC, 0);
|
||||
}
|
||||
|
||||
static void fdd_io(uint8_t read)
|
||||
{
|
||||
fileTYPE* img = &fdd0_image;
|
||||
|
||||
struct sd_param_t
|
||||
{
|
||||
uint32_t lba;
|
||||
uint32_t cnt;
|
||||
};
|
||||
|
||||
static struct sd_param_t sd_params = {};
|
||||
static uint32_t secbuf[128 * 16];
|
||||
|
||||
x86_dma_recvbuf(FDD0_BASE, sizeof(sd_params) >> 2, (uint32_t*)&sd_params);
|
||||
|
||||
if (sd_params.lba >> 15)
|
||||
{
|
||||
// Floppy B:
|
||||
sd_params.lba &= 0x7FFF;
|
||||
img = &fdd1_image;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
if (read)
|
||||
{
|
||||
//printf("Read: 0x%08x, %d, %d\n", basereg, sd_params.lba, sd_params.cnt);
|
||||
|
||||
if (img->size)
|
||||
{
|
||||
if (img_read(img, sd_params.lba, &secbuf, 1))
|
||||
{
|
||||
x86_dma_sendbuf(FDD0_BASE + 255, 128, secbuf);
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: image is not ready.\n");
|
||||
}
|
||||
|
||||
if (!res)
|
||||
{
|
||||
memset(secbuf, 0, 512);
|
||||
x86_dma_sendbuf(FDD0_BASE + 255, 128, secbuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Write: 0x%08x, 0x%08x, %d\n", basereg, sd_params.lba, sd_params.cnt);
|
||||
|
||||
x86_dma_recvbuf(FDD0_BASE + 255, sd_params.cnt * 128, secbuf);
|
||||
if (img->size)
|
||||
{
|
||||
if (sd_params.cnt > 0 && sd_params.cnt <= 16)
|
||||
{
|
||||
if (img->mode & O_RDWR)
|
||||
{
|
||||
if (img_write(img, sd_params.lba, secbuf, sd_params.cnt))
|
||||
{
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: image is read-only.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: Block count %d is out of range 1..16.\n", sd_params.cnt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: image is not ready.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pcxt_poll()
|
||||
{
|
||||
x86_share_poll();
|
||||
|
||||
uint16_t sd_req = ide_check();
|
||||
if (sd_req)
|
||||
{
|
||||
ide_io(0, sd_req & 7);
|
||||
sd_req >>= 3;
|
||||
ide_io(1, sd_req & 7);
|
||||
|
||||
sd_req >>= 3;
|
||||
if (sd_req & 3) fdd_io(sd_req & 1);
|
||||
}
|
||||
}
|
||||
|
||||
void pcxt_set_image(int num, char* filename)
|
||||
{
|
||||
memset(config.img_name[num], 0, sizeof(config.img_name[0]));
|
||||
strcpy(config.img_name[num], filename);
|
||||
if (num < 2) fdd_set(num, filename);
|
||||
else hdd_set(num, filename);
|
||||
}
|
||||
|
||||
void hdd_set(int num, char* filename)
|
||||
{
|
||||
const char* imghome = "/media/fat";
|
||||
|
||||
@@ -274,6 +507,16 @@ void pcxt_config_load()
|
||||
memcpy(&config, &tmp, sizeof(config));
|
||||
pcxt_load_images();
|
||||
}
|
||||
if (strlen(config.img_name[0]))
|
||||
{
|
||||
printf("Imagen de disco: %s\n", config.img_name[0]);
|
||||
fdd_set(0, config.img_name[0]);
|
||||
}
|
||||
if (strlen(config.img_name[1]))
|
||||
{
|
||||
printf("Imagen de disco: %s\n", config.img_name[1]);
|
||||
fdd_set(1, config.img_name[1]);
|
||||
}
|
||||
}
|
||||
|
||||
const char* pcxt_get_image_name(int num)
|
||||
|
||||
@@ -9,9 +9,11 @@ void log(int level, const char* message, ...);
|
||||
unsigned long GetTime(void);
|
||||
unsigned long GetTime_Timeout(void);
|
||||
|
||||
void pcxt_poll();
|
||||
void pcxt_unmount_images();
|
||||
void pcxt_load_images();
|
||||
void pcxt_set_image(int num, char* selPath);
|
||||
void hdd_set(int num, char* selPath);
|
||||
void pcxt_config_load();
|
||||
void pcxt_config_save();
|
||||
const char* pcxt_get_image_name(int num);
|
||||
|
||||
@@ -840,6 +840,10 @@ static void parse_config()
|
||||
{
|
||||
x86_set_image(idx, str);
|
||||
}
|
||||
else if (is_pcxt())
|
||||
{
|
||||
pcxt_set_image(idx, str);
|
||||
}
|
||||
else if (is_megacd())
|
||||
{
|
||||
mcd_set_image(idx, str);
|
||||
@@ -2730,6 +2734,7 @@ void user_io_send_buttons(char force)
|
||||
if (is_pce()) pcecd_reset();
|
||||
if (is_saturn()) saturn_reset();
|
||||
if (is_x86()) x86_init();
|
||||
if (is_pcxt()) pcxt_init();
|
||||
ResetUART();
|
||||
}
|
||||
|
||||
@@ -2863,6 +2868,10 @@ void user_io_poll()
|
||||
{
|
||||
x86_poll();
|
||||
}
|
||||
else if (is_pcxt())
|
||||
{
|
||||
pcxt_poll();
|
||||
}
|
||||
else if ((core_type == CORE_TYPE_8BIT) && !is_menu() && !is_minimig())
|
||||
{
|
||||
if (is_st()) tos_poll();
|
||||
|
||||
Reference in New Issue
Block a user