pcxt: FDD support, based on AO486 (#700)

This commit is contained in:
Aitor Gómez
2022-10-06 08:39:33 +02:00
committed by GitHub
parent 3c0c6648bb
commit d0961588e1
4 changed files with 299 additions and 44 deletions

View File

@@ -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)))

View File

@@ -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)

View File

@@ -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);

View File

@@ -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();