Files
Main_MiSTer/support/pcxt/pcxt.cpp
2022-08-25 11:07:29 +02:00

391 lines
8.5 KiB
C++

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdarg.h>
#include <ctype.h>
#include <pthread.h>
#include "../../cfg.h"
#include "../../hardware.h"
#include "../../fpga_io.h"
#include "../../menu.h"
#include "../../debug.h"
#include "../../user_io.h"
#include "../../input.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;
int timeoutEnabled = 1;
int createFile = 0;
int useCHS = 0;
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[3][1024];
} pcxt_config;
static pcxt_config config;
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();
}
void pcxt_init()
{
user_io_status_set("[0]", 1);
}
void* OpenUART(void*) {
char ComPortBuff[20];
sprintf(ComPortBuff, "/dev/ttyS1");
const char* ComPort = NULL;
ComPort = &ComPortBuff[0];
struct baudRate* baudRate = NULL;
int status;
status = user_io_status_get("[22:21]");
switch (status)
{
case 1:
baudRate = baudRateMatchString("230400");
break;
case 2:
baudRate = baudRateMatchString("460800");
break;
case 3:
baudRate = baudRateMatchString("921600");
break;
case 0:
default:
baudRate = baudRateMatchString("115200");
break;
};
Image* images[2] = { NULL, NULL };
int timeoutEnabled = 1;
FILE* fd;
long size;
// HDD CHS Calculator
unsigned long hdd_cyl = 0, hdd_sect = 0, hdd_head = 0;
bool is_hdd = false;
struct hddInfo *hdd_fi;
if (strlen(config.img_name[2]))
{
fd = fopen(config.img_name[2], "r");
if (fd)
{
is_hdd = true;
fseek(fd, 0L, SEEK_END);
size = ftell(fd);
if ((hdd_fi = FindHDDInfoBySize(size)))
{
hdd_sect = hdd_fi->sectors;
hdd_head = hdd_fi->heads;
hdd_cyl = hdd_fi->cylinders;
}
else
{
hdd_sect = 63;
hdd_head = 16;
hdd_cyl = size / (16 * 63);
}
}
}
// Prepare Images
status = user_io_status_get("[20:19]");
if (is_hdd)
{
images[0] = new FlatImage(config.img_name[2], 0, 0, createFile, hdd_cyl, hdd_head, hdd_sect, useCHS);
}
// Mount Images
serial.Connect(ComPort, baudRate);
processRequests(&serial, images[0], images[1], timeoutEnabled, verbose);
pthread_exit(NULL);
}
void log(int level, const char* message, ...)
{
va_list args;
va_start(args, message);
if (level < 0)
{
fprintf(stderr, "ERROR: ");
vfprintf(stderr, message, args);
fprintf(stderr, "\n");
if (level < -1)
{
fprintf(stderr, "\n");
//usage();
}
//exit(1);
}
else if (verbose >= level)
{
vprintf(message, args);
printf("\n");
}
va_end(args);
}
unsigned long GetTime(void)
{
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC, &now))
return 0;
return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0;
}
unsigned long GetTime_Timeout(void)
{
return(1000);
}
void pcxt_unmount_images()
{
void* status;
printf("Unmounting Images...");
if (in_process)
{
in_process = false;
serial.Disconnect();
pthread_cancel(uart_thread);
pthread_join(uart_thread, &status);
usleep(100000);
printf("OK\n");
}
else
{
printf("No serdrive is running\n");
}
}
void pcxt_load_images()
{
pcxt_unmount_images();
pthread_create(&uart_thread, NULL, OpenUART, NULL);
usleep(100000);
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);
}
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";
memset(config.img_name[num], 0, sizeof(config.img_name[num]));
if (strlen(filename))
{
memset(config.img_name[num], 0, sizeof(config.img_name[num]));
sprintf(config.img_name[num], "%s/%s", imghome, filename);
pcxt_load_images();
}
}
static char* get_config_name()
{
static char str[256];
snprintf(str, sizeof(str), "%ssys.cfg", user_io_get_core_name());
return str;
}
void pcxt_config_save()
{
config.ver = CFG_VER;
FileSaveConfig(get_config_name(), &config, sizeof(config));
}
void pcxt_config_load()
{
static pcxt_config tmp;
memset(&config, 0, sizeof(config));
if (FileLoadConfig(get_config_name(), &tmp, sizeof(tmp)) && (tmp.ver == CFG_VER))
{
memcpy(&config, &tmp, sizeof(config));
pcxt_load_images();
}
}
const char* pcxt_get_image_name(int num)
{
static char res[32];
char* name = config.img_name[num];
if (!name[0]) return NULL;
char* p = strrchr(name, '/');
if (!p) p = name;
else p++;
if (strlen(p) < 19) strcpy(res, p);
else
{
strncpy(res, p, 19);
res[19] = 0;
}
return res;
}
const char* pcxt_get_image_path(int num)
{
return config.img_name[num];
}