mirror of
https://github.com/mist-devel/mist-firmware.git
synced 2026-04-27 20:58:59 +00:00
ATAPI CDROM support
- PACKET command set and subset of MMC-3 in hdd.c - ISO file "parsing" in cue_parser - CDROM configuration in Minimig menu
This commit is contained in:
3
config.c
3
config.c
@@ -488,6 +488,9 @@ static void ApplyConfiguration(char reloadkickstart)
|
||||
case HDF_CARD:
|
||||
siprintf(s, "\nHardfile %d: using entire SD card", i);
|
||||
break;
|
||||
case HDF_CDROM:
|
||||
siprintf(s, "\nHardfile %d: CDROM", i);
|
||||
break;
|
||||
default:
|
||||
siprintf(s, "\nHardfile %d: using SD card partition %d", i, hdf[i].type-HDF_CARD); // Number from 1
|
||||
break;
|
||||
|
||||
293
cue_parser.c
293
cue_parser.c
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "cue_parser.h"
|
||||
#ifdef CUE_PARSER_TEST
|
||||
#define cue_parser_debugf(a, ...) printf(a"\n", ## __VA_ARGS__)
|
||||
@@ -19,6 +20,7 @@
|
||||
#define TOKEN_AUDIO "AUDIO"
|
||||
#define TOKEN_MODE1_2048 "MODE1/2048"
|
||||
#define TOKEN_MODE1_2352 "MODE1/2352"
|
||||
#define TOKEN_MODE2_2352 "MODE2/2352"
|
||||
#define TOKEN_PREGAP "PREGAP"
|
||||
#define TOKEN_INDEX "INDEX"
|
||||
|
||||
@@ -143,143 +145,177 @@ char cue_parse(const char *filename, IDXFile *image)
|
||||
int track = 0, x, pregap = 0, tracklen;
|
||||
msf_t msf;
|
||||
int lba, lastindex1 = 0;
|
||||
char e[3];
|
||||
|
||||
memset(&toc, 0, sizeof(toc));
|
||||
|
||||
// open ini file
|
||||
#ifdef CUE_PARSER_TEST
|
||||
if ((cue_fp = fopen(filename, "rb")) == NULL) {
|
||||
#else
|
||||
if (f_open(&cue_file, filename, FA_READ) != FR_OK) {
|
||||
#endif
|
||||
cue_parser_debugf("Can't open file %s !", filename);
|
||||
return CUE_RES_NOTFOUND;
|
||||
const char *ext = GetExtension(filename);
|
||||
e[0] = e[1] = e[2] = ' ';
|
||||
if (ext) {
|
||||
if (ext[0]) e[0] = toupper(ext[0]);
|
||||
if (ext[1]) e[1] = toupper(ext[1]);
|
||||
if (ext[2]) e[2] = toupper(ext[2]);
|
||||
}
|
||||
|
||||
#ifdef CUE_PARSER_TEST
|
||||
fseek(cue_fp, 0L, SEEK_END);
|
||||
cue_size = ftell(cue_fp);
|
||||
fseek(cue_fp, 0L, SEEK_SET);
|
||||
#else
|
||||
cue_parser_debugf("Opened file %s with size %llu bytes.", filename, f_size(&cue_file));
|
||||
#endif
|
||||
cue_pt = 0;
|
||||
|
||||
// parse ini
|
||||
while (1) {
|
||||
// get line
|
||||
word_status = cue_getword(word);
|
||||
if (word_status != CUE_NOWORD) {
|
||||
//cue_parser_debugf("next word(%d): \"%s\".", word_status, word);
|
||||
switch (mode) {
|
||||
case MODE_NONE:
|
||||
submode = 0;
|
||||
if (!strcmp(word, TOKEN_FILE)) mode = MODE_FILE; else
|
||||
if (!strcmp(word, TOKEN_TRACK)) mode = MODE_TRACK; else
|
||||
if (!strcmp(word, TOKEN_PREGAP)) mode = MODE_PREGAP; else
|
||||
if (!strcmp(word, TOKEN_INDEX)) mode = MODE_INDEX;
|
||||
break;
|
||||
case MODE_FILE:
|
||||
if (submode == 0) {
|
||||
pregap = 0;
|
||||
cue_parser_debugf("Filename: %s", word);
|
||||
if (bin_valid) {
|
||||
// only one .bin supported
|
||||
error = CUE_RES_UNS;
|
||||
} else {
|
||||
#ifdef CUE_PARSER_TEST
|
||||
bin_valid = 1;
|
||||
}
|
||||
#else
|
||||
toc.file = image;
|
||||
if (IDXOpen(toc.file, word, FA_READ) == FR_OK)
|
||||
bin_valid = 1;
|
||||
else
|
||||
error = CUE_RES_BINERR;
|
||||
}
|
||||
#endif
|
||||
} else if (submode == 1) {
|
||||
cue_parser_debugf("Filemode: %s", word);
|
||||
mode = 0;
|
||||
}
|
||||
submode++;
|
||||
break;
|
||||
case MODE_TRACK:
|
||||
if (submode == 0) {
|
||||
x = strtol(word, 0, 10);
|
||||
cue_parser_debugf("Trackno: %d -> %d (%s)", track, x, word);
|
||||
if (!x || x > 99 || x != (track + 1)) error = CUE_RES_INVALID; else track = x;
|
||||
} else if (submode == 1) {
|
||||
cue_parser_debugf("Trackmode: %s", word);
|
||||
if (!strcmp(word, TOKEN_AUDIO)) {
|
||||
toc.tracks[track-1].sector_size = 2352;
|
||||
toc.tracks[track-1].type = SECTOR_AUDIO;
|
||||
} else if (!strcmp(word, TOKEN_MODE1_2352)) {
|
||||
toc.tracks[track-1].sector_size = 2352;
|
||||
toc.tracks[track-1].type = SECTOR_DATA;
|
||||
} else if (!strcmp(word, TOKEN_MODE1_2048)) {
|
||||
toc.tracks[track-1].sector_size = 2048;
|
||||
toc.tracks[track-1].type = SECTOR_DATA;
|
||||
} else {
|
||||
error = CUE_RES_INVALID;
|
||||
}
|
||||
mode = 0;
|
||||
}
|
||||
submode++;
|
||||
break;
|
||||
case MODE_PREGAP:
|
||||
cue_parser_debugf("Pregap size: %s", word);
|
||||
if (!ParseMSF(word, &msf)) {
|
||||
error = CUE_RES_INVALID;
|
||||
} else {
|
||||
pregap += MSF2LBA(msf.m, msf.s, msf.f) + 150;
|
||||
}
|
||||
mode = 0;
|
||||
break;
|
||||
case MODE_INDEX:
|
||||
if (submode == 0) {
|
||||
cue_parser_debugf("Index: %s", word);
|
||||
index = strtol(word, 0, 10);
|
||||
} else if (submode == 1) {
|
||||
if (!ParseMSF(word, &msf)) {
|
||||
error = CUE_RES_INVALID;
|
||||
} else {
|
||||
lba = MSF2LBA(msf.m, msf.s, msf.f);
|
||||
if (index == 0) {
|
||||
if (track > 1 && !toc.tracks[track - 2].end) {
|
||||
toc.tracks[track - 2].end = lba + 150 + pregap;
|
||||
}
|
||||
} else if (index == 1) {
|
||||
toc.tracks[track - 1].start = lba + 150 + pregap;
|
||||
if (track > 1) {
|
||||
tracklen = lba - lastindex1;
|
||||
toc.tracks[track - 1].offset = toc.tracks[track - 2].offset + (tracklen * toc.tracks[track - 2].sector_size);
|
||||
if (!toc.tracks[track-2].end) toc.tracks[track - 2].end = toc.tracks[track - 1].start - 1;
|
||||
} else {
|
||||
toc.tracks[0].offset = (lba + 150) * toc.tracks[0].sector_size;
|
||||
}
|
||||
lastindex1 = lba;
|
||||
}
|
||||
}
|
||||
cue_parser_debugf("Pos: (%s) = %d:%d:%d (%d)", word, msf.m, msf.s, msf.f, error);
|
||||
mode = 0;
|
||||
}
|
||||
submode++;
|
||||
break;
|
||||
}
|
||||
if (!memcmp(e, "ISO", 3)) {
|
||||
// open iso file
|
||||
#ifdef CUE_PARSER_TEST
|
||||
bin_valid = 1;
|
||||
#else
|
||||
toc.file = image;
|
||||
if (IDXOpen(toc.file, filename, FA_READ) == FR_OK) {
|
||||
bin_valid = 1;
|
||||
track = 1;
|
||||
toc.tracks[0].sector_size = 2048;
|
||||
toc.tracks[0].type = SECTOR_DATA;
|
||||
toc.tracks[0].offset = 0;
|
||||
toc.tracks[0].start = 0;
|
||||
} else {
|
||||
error = CUE_RES_BINERR;
|
||||
}
|
||||
// if end of file or error, stop
|
||||
if (word_status == CUE_EOT || error) break;
|
||||
#endif
|
||||
} else {
|
||||
// open cue file
|
||||
#ifdef CUE_PARSER_TEST
|
||||
if ((cue_fp = fopen(filename, "rb")) == NULL) {
|
||||
#else
|
||||
if (f_open(&cue_file, filename, FA_READ) != FR_OK) {
|
||||
#endif
|
||||
cue_parser_debugf("Can't open file %s !", filename);
|
||||
return CUE_RES_NOTFOUND;
|
||||
}
|
||||
|
||||
#ifdef CUE_PARSER_TEST
|
||||
fseek(cue_fp, 0L, SEEK_END);
|
||||
cue_size = ftell(cue_fp);
|
||||
fseek(cue_fp, 0L, SEEK_SET);
|
||||
#else
|
||||
cue_parser_debugf("Opened file %s with size %llu bytes.", filename, f_size(&cue_file));
|
||||
#endif
|
||||
cue_pt = 0;
|
||||
|
||||
// parse cue
|
||||
while (1) {
|
||||
// get line
|
||||
word_status = cue_getword(word);
|
||||
if (word_status != CUE_NOWORD) {
|
||||
//cue_parser_debugf("next word(%d): \"%s\".", word_status, word);
|
||||
switch (mode) {
|
||||
case MODE_NONE:
|
||||
submode = 0;
|
||||
if (!strcmp(word, TOKEN_FILE)) mode = MODE_FILE; else
|
||||
if (!strcmp(word, TOKEN_TRACK)) mode = MODE_TRACK; else
|
||||
if (!strcmp(word, TOKEN_PREGAP)) mode = MODE_PREGAP; else
|
||||
if (!strcmp(word, TOKEN_INDEX)) mode = MODE_INDEX;
|
||||
break;
|
||||
case MODE_FILE:
|
||||
if (submode == 0) {
|
||||
pregap = 0;
|
||||
cue_parser_debugf("Filename: %s", word);
|
||||
if (bin_valid) {
|
||||
// only one .bin supported
|
||||
error = CUE_RES_UNS;
|
||||
} else {
|
||||
#ifdef CUE_PARSER_TEST
|
||||
bin_valid = 1;
|
||||
}
|
||||
#else
|
||||
toc.file = image;
|
||||
if (IDXOpen(toc.file, word, FA_READ) == FR_OK)
|
||||
bin_valid = 1;
|
||||
else
|
||||
error = CUE_RES_BINERR;
|
||||
}
|
||||
#endif
|
||||
} else if (submode == 1) {
|
||||
cue_parser_debugf("Filemode: %s", word);
|
||||
mode = 0;
|
||||
}
|
||||
submode++;
|
||||
break;
|
||||
case MODE_TRACK:
|
||||
if (submode == 0) {
|
||||
x = strtol(word, 0, 10);
|
||||
cue_parser_debugf("Trackno: %d -> %d (%s)", track, x, word);
|
||||
if (!x || x > 99 || x != (track + 1)) error = CUE_RES_INVALID; else track = x;
|
||||
} else if (submode == 1) {
|
||||
cue_parser_debugf("Trackmode: %s", word);
|
||||
if (!strcmp(word, TOKEN_AUDIO)) {
|
||||
toc.tracks[track-1].sector_size = 2352;
|
||||
toc.tracks[track-1].type = SECTOR_AUDIO;
|
||||
} else if (!strcmp(word, TOKEN_MODE1_2352)) {
|
||||
toc.tracks[track-1].sector_size = 2352;
|
||||
toc.tracks[track-1].type = SECTOR_DATA;
|
||||
} else if (!strcmp(word, TOKEN_MODE2_2352)) {
|
||||
toc.tracks[track-1].sector_size = 2352;
|
||||
toc.tracks[track-1].type = SECTOR_DATA;
|
||||
} else if (!strcmp(word, TOKEN_MODE1_2048)) {
|
||||
toc.tracks[track-1].sector_size = 2048;
|
||||
toc.tracks[track-1].type = SECTOR_DATA;
|
||||
} else {
|
||||
error = CUE_RES_INVALID;
|
||||
}
|
||||
mode = 0;
|
||||
}
|
||||
submode++;
|
||||
break;
|
||||
case MODE_PREGAP:
|
||||
cue_parser_debugf("Pregap size: %s", word);
|
||||
if (!ParseMSF(word, &msf)) {
|
||||
error = CUE_RES_INVALID;
|
||||
} else {
|
||||
pregap += MSF2LBA(msf.m, msf.s, msf.f) + 150;
|
||||
}
|
||||
mode = 0;
|
||||
break;
|
||||
case MODE_INDEX:
|
||||
if (submode == 0) {
|
||||
cue_parser_debugf("Index: %s", word);
|
||||
index = strtol(word, 0, 10);
|
||||
} else if (submode == 1) {
|
||||
if (!ParseMSF(word, &msf)) {
|
||||
error = CUE_RES_INVALID;
|
||||
} else {
|
||||
lba = MSF2LBA(msf.m, msf.s, msf.f);
|
||||
if (index == 0) {
|
||||
if (track > 1 && !toc.tracks[track - 2].end) {
|
||||
toc.tracks[track - 2].end = lba + 150 + pregap;
|
||||
}
|
||||
} else if (index == 1) {
|
||||
toc.tracks[track - 1].start = lba + 150 + pregap;
|
||||
if (track > 1) {
|
||||
tracklen = lba - lastindex1;
|
||||
toc.tracks[track - 1].offset = toc.tracks[track - 2].offset + (tracklen * toc.tracks[track - 2].sector_size);
|
||||
if (!toc.tracks[track-2].end) toc.tracks[track - 2].end = toc.tracks[track - 1].start - 1;
|
||||
} else {
|
||||
toc.tracks[0].offset = (lba + 150) * toc.tracks[0].sector_size;
|
||||
}
|
||||
lastindex1 = lba;
|
||||
}
|
||||
}
|
||||
cue_parser_debugf("Pos: (%s) = %d:%d:%d (%d)", word, msf.m, msf.s, msf.f, error);
|
||||
mode = 0;
|
||||
}
|
||||
submode++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if end of file or error, stop
|
||||
if (word_status == CUE_EOT || error) break;
|
||||
}
|
||||
|
||||
#ifdef CUE_PARSER_TEST
|
||||
// close file
|
||||
fclose(cue_fp);
|
||||
#else
|
||||
f_close(&cue_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CUE_PARSER_TEST
|
||||
// close file
|
||||
fclose(cue_fp);
|
||||
#else
|
||||
f_close(&cue_file);
|
||||
#ifndef CUE_PARSET_TEST
|
||||
if (!bin_valid)
|
||||
error = CUE_RES_BINERR;
|
||||
else if (error) f_close(&toc.file->file);
|
||||
else if (error)
|
||||
f_close(&toc.file->file);
|
||||
else {
|
||||
IDXIndex(toc.file);
|
||||
if (track > 0) {
|
||||
@@ -293,6 +329,7 @@ char cue_parse(const char *filename, IDXFile *image)
|
||||
} else {
|
||||
toc.last = track;
|
||||
toc.end = toc.tracks[track-1].end;
|
||||
toc.valid = 1;
|
||||
}
|
||||
|
||||
iprintf("Tracks in the CUE file %s : %d\n", filename, toc.last);
|
||||
|
||||
@@ -26,9 +26,9 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int valid;
|
||||
int end;
|
||||
int last;
|
||||
int sectorSize;
|
||||
cd_track_t tracks[100];
|
||||
#ifndef CUE_PARSER_TEST
|
||||
IDXFile *file; // the .bin file
|
||||
|
||||
659
hdd.c
659
hdd.c
@@ -35,14 +35,33 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "hdd_internal.h"
|
||||
#include "menu.h"
|
||||
#include "fpga.h"
|
||||
#include "scsi.h"
|
||||
#include "cue_parser.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
hardfileTYPE *hardfile[HARDFILES];
|
||||
|
||||
// hardfile structure
|
||||
hdfTYPE hdf[HARDFILES];
|
||||
|
||||
#define AUDIO_PLAYING 0x11
|
||||
#define AUDIO_PAUSED 0x12
|
||||
#define AUDIO_COMPLETE 0x13
|
||||
#define AUDIO_ERROR 0x14
|
||||
#define AUDIO_NOSTAT 0x15
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char key;
|
||||
unsigned char asc;
|
||||
unsigned char ascq;
|
||||
unsigned int currentlba;
|
||||
unsigned int endlba;
|
||||
unsigned char audiostatus;
|
||||
} cdrom_t;
|
||||
|
||||
static cdrom_t cdrom;
|
||||
|
||||
static void SwapBytes(char *c, unsigned int len)
|
||||
{
|
||||
char temp;
|
||||
@@ -229,6 +248,19 @@ static void IdentifyDevice(unsigned short *pBuffer, unsigned char unit)
|
||||
pBuffer[61] = (unsigned short)(total_sectors >> 16);
|
||||
}
|
||||
|
||||
// IdentifiyDevice()
|
||||
// builds Identify Packet Device struct
|
||||
static void IdentifyPacketDevice(unsigned short *pBuffer, unsigned char unit)
|
||||
{
|
||||
memset(pBuffer, 0, 512);
|
||||
pBuffer[0] = 0x8580;
|
||||
memcpy((char*)&pBuffer[10], "iMTSiMiniMCgRDMO ", 20); // serial number - byte swapped
|
||||
memcpy((char*)&pBuffer[23], ".100 ", 8); // firmware version - byte swapped
|
||||
memcpy((char*)&pBuffer[27], " ", 40); // Model number - byte swapped
|
||||
pBuffer[49] = 0x0100;
|
||||
pBuffer[53] = 1;
|
||||
pBuffer[82] = 0x4214;
|
||||
}
|
||||
|
||||
// chs2lba()
|
||||
static unsigned long chs2lba(unsigned short cylinder, unsigned char head, unsigned short sector, unsigned char unit, char lbamode)
|
||||
@@ -301,6 +333,559 @@ static void WriteStatus(unsigned char status)
|
||||
DisableFpga();
|
||||
}
|
||||
|
||||
static void WritePacket(unsigned char unit, const unsigned char *buf, unsigned short bufsize, char lastpacket)
|
||||
{
|
||||
unsigned short bytes;
|
||||
while (bufsize) {
|
||||
bytes = MIN(bufsize, 2048);
|
||||
while (!(GetFPGAStatus() & CMD_IDECMD)); // wait for empty sector buffer
|
||||
WriteTaskFile(0, 0x02, 0, bytes & 0xff, (bytes>>8) & 0xff, 0xa0 | ((unit & 0x01)<<4));
|
||||
EnableFpga();
|
||||
SPI(CMD_IDE_DATA_WR); // write data command
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
spi_write(buf, bytes);
|
||||
DisableFpga();
|
||||
buf += bytes;
|
||||
bufsize -= bytes;
|
||||
if (lastpacket && !bufsize)
|
||||
WriteStatus(IDE_STATUS_IRQ | IDE_STATUS_END);
|
||||
else
|
||||
WriteStatus(IDE_STATUS_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
static void cdrom_setsense(unsigned char key, unsigned char asc, unsigned char ascq)
|
||||
{
|
||||
cdrom.key = key;
|
||||
cdrom.asc = asc;
|
||||
cdrom.ascq = ascq;
|
||||
}
|
||||
|
||||
static void cdrom_ok()
|
||||
{
|
||||
cdrom.key = cdrom.asc = cdrom.ascq = 0;
|
||||
}
|
||||
|
||||
static void cdrom_send_error(unsigned char unit)
|
||||
{
|
||||
WriteTaskFile((cdrom.key << 4) | 0x04, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_ERR | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
static void PKT_Read(unsigned char unit, unsigned int lba, unsigned int len, unsigned short bytelimit)
|
||||
{
|
||||
UINT br;
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
cdrom.audiostatus = AUDIO_NOSTAT;
|
||||
|
||||
WriteStatus(IDE_STATUS_RDY | IDE_STATUS_PKT); // pio in (class 1) command type
|
||||
|
||||
while ((bytelimit >= 2048) && (len--)) {
|
||||
unsigned char track = cue_gettrackbylba(lba);
|
||||
int offset = (lba - toc.tracks[track].start) * toc.tracks[track].sector_size + toc.tracks[track].offset;
|
||||
hdd_debugf("lba: %d track: %d, offset: %d", lba, track, offset);
|
||||
|
||||
if (toc.tracks[track].type != SECTOR_DATA) {
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x26, 2);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
cdrom.currentlba = lba;
|
||||
if (toc.tracks[track].sector_size != 2048) offset+=16;
|
||||
f_lseek(&toc.file->file, offset);
|
||||
f_read(&toc.file->file, sector_buffer, 2048, &br);
|
||||
|
||||
bytelimit-=2048;
|
||||
lba++;
|
||||
|
||||
WritePacket(unit, sector_buffer, 2048, bytelimit < 2048);
|
||||
}
|
||||
cdrom_ok();
|
||||
WriteStatus(IDE_STATUS_END);
|
||||
}
|
||||
|
||||
static void PKT_Read12(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_Read12 (bufsize=%d)", unit, bytelimit);
|
||||
unsigned int lba = cmd[5] | (cmd[4] << 8) | (cmd[3] << 16) | (cmd[2] << 24);
|
||||
unsigned int len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
|
||||
PKT_Read(unit, lba, len, bytelimit);
|
||||
}
|
||||
|
||||
static void PKT_Read10(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_Read10 (bufsize=%d)", unit, bytelimit);
|
||||
unsigned int lba = cmd[5] | (cmd[4] << 8) | (cmd[3] << 16) | (cmd[2] << 24);
|
||||
unsigned int len = cmd[8] | (cmd[7] << 8);
|
||||
PKT_Read(unit, lba, len, bytelimit);
|
||||
}
|
||||
|
||||
static void PKT_PlayAudio(unsigned char unit, unsigned int start, unsigned int end)
|
||||
{
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
if (start > toc.end || end > toc.end || start > end) {
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x21, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
unsigned char track = cue_gettrackbylba(start);
|
||||
if (toc.tracks[track].type != SECTOR_AUDIO) {
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x64, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
cdrom.currentlba = start;
|
||||
cdrom.endlba = end;
|
||||
cdrom.audiostatus = AUDIO_PLAYING;
|
||||
cdrom_ok();
|
||||
WriteTaskFile(0, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
static void PKT_PlayAudioMSF(unsigned char *cmd, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_PlayAudioMSF", unit);
|
||||
unsigned int start = (cmd[2] == 0xff && cmd[3] == 0xff && cmd[5] == 0xff) ? cdrom.currentlba : MSF2LBA(cmd[3], cmd[4], cmd[5]);
|
||||
unsigned int end = MSF2LBA(cmd[6], cmd[7], cmd[8]);
|
||||
PKT_PlayAudio(unit, start, end);
|
||||
}
|
||||
|
||||
static void PKT_PlayAudio10(unsigned char *cmd, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_PlayAudio10", unit);
|
||||
unsigned int start = (cmd[2] << 24) | (cmd[3] << 16) | (cmd[4] << 8) | cmd[5];
|
||||
if (start == 0xffffffff) start = cdrom.currentlba;
|
||||
unsigned int end = start + (cmd[7] << 8) + cmd[8];
|
||||
PKT_PlayAudio(unit, start, end);
|
||||
}
|
||||
|
||||
static void PKT_PauseResume(unsigned char *cmd, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_PauseResume", unit);
|
||||
int resume = cmd[8] & 0x01;
|
||||
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((resume && cdrom.audiostatus != AUDIO_PAUSED) || (!resume && cdrom.audiostatus != AUDIO_PLAYING)) {
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x2c, 0);
|
||||
cdrom_send_error(unit);
|
||||
} else {
|
||||
cdrom.audiostatus = resume ? AUDIO_PLAYING : AUDIO_PAUSED;
|
||||
cdrom_ok();
|
||||
WriteTaskFile(0, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
static void PKT_StopPlayScan(unsigned char *cmd, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_StopPlayScan", unit);
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
cdrom.audiostatus = AUDIO_NOSTAT;
|
||||
cdrom_ok();
|
||||
WriteTaskFile(0, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
static void PKT_SubChannel(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_SubChannel (bufsize=%d)", unit, bytelimit);
|
||||
unsigned short bufsize = MIN(bytelimit, (cmd[7] << 8) | cmd[8]);
|
||||
unsigned char track;
|
||||
unsigned char msftime = cmd[1] & 0x02;
|
||||
unsigned short respsize = 0;
|
||||
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
|
||||
track = cue_gettrackbylba(cdrom.currentlba);
|
||||
if (track >= toc.last) track = toc.last - 1;
|
||||
memset(sector_buffer, 0, 24);
|
||||
sector_buffer[1] = cdrom.audiostatus;
|
||||
switch (cmd[3]) {
|
||||
case 1:
|
||||
// current position
|
||||
respsize = (cmd[2] & 0x40) ? 16 : 4;
|
||||
sector_buffer[4] = 0x01;
|
||||
sector_buffer[5] = (1 << 4) | ((toc.tracks[track-1].type == SECTOR_DATA) ? 4 : 0);
|
||||
sector_buffer[6] = track + 1;
|
||||
sector_buffer[7] = cdrom.currentlba >= toc.tracks[track].start ? 1 : 0; // TODO: support more than 1 indices
|
||||
unsigned int rellba = cdrom.currentlba - toc.tracks[track].start;
|
||||
iprintf("track = %d, rellba = %d\n", track, rellba);
|
||||
if (msftime) {
|
||||
msf_t MSF;
|
||||
LBA2MSF(cdrom.currentlba+150, &MSF);
|
||||
sector_buffer[9] = MSF.m;
|
||||
sector_buffer[10] = MSF.s;
|
||||
sector_buffer[11] = MSF.f;
|
||||
LBA2MSF(rellba, &MSF);
|
||||
sector_buffer[13] = MSF.m;
|
||||
sector_buffer[14] = MSF.s;
|
||||
sector_buffer[15] = MSF.f;
|
||||
} else {
|
||||
sector_buffer[8] = (cdrom.currentlba >> 24) & 0xff;
|
||||
sector_buffer[9] = (cdrom.currentlba >> 16) & 0xff;
|
||||
sector_buffer[10] = (cdrom.currentlba >> 8) & 0xff;
|
||||
sector_buffer[11] = cdrom.currentlba & 0xff;
|
||||
sector_buffer[12] = (rellba >> 24) & 0xff;
|
||||
sector_buffer[13] = (rellba >> 16) & 0xff;
|
||||
sector_buffer[14] = (rellba >> 8) & 0xff;
|
||||
sector_buffer[15] = rellba & 0xff;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Media Catalog number
|
||||
respsize = 24;
|
||||
sector_buffer[4] = 0x02;
|
||||
break;
|
||||
case 3:
|
||||
// ISRC
|
||||
respsize = 24;
|
||||
sector_buffer[4] = 0x02;
|
||||
break;
|
||||
default:
|
||||
// reserved
|
||||
break;
|
||||
}
|
||||
sector_buffer[3] = respsize - 4;
|
||||
|
||||
cdrom_ok();
|
||||
bufsize = MIN(bufsize, respsize);
|
||||
WriteStatus(IDE_STATUS_RDY | IDE_STATUS_PKT); // pio in (class 1) command type
|
||||
WritePacket(unit, sector_buffer, bufsize, 1);
|
||||
}
|
||||
|
||||
static void PKT_ReadCapacity(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_ReadCapacity (bufsize=%d)", unit, bytelimit);
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
|
||||
sector_buffer[0] = (toc.end >> 24) & 0xff;
|
||||
sector_buffer[1] = (toc.end >> 16) & 0xff;
|
||||
sector_buffer[2] = (toc.end >> 8) & 0xff;
|
||||
sector_buffer[3] = toc.end & 0xff;
|
||||
sector_buffer[4] = sector_buffer[5] = 0;
|
||||
sector_buffer[6] = (2048 >> 8) & 0xff;
|
||||
sector_buffer[7] = 2048 & 0xff;
|
||||
hexdump(sector_buffer, 8, 0);
|
||||
cdrom_ok();
|
||||
WriteStatus(IDE_STATUS_RDY | IDE_STATUS_PKT); // pio in (class 1) command type
|
||||
WritePacket(unit, sector_buffer, MIN(bytelimit, 8), 1);
|
||||
}
|
||||
|
||||
static void PKT_ReadTOC(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_ReadTOC (bufsize=%d)", unit, bytelimit);
|
||||
unsigned short bufsize = MIN(bytelimit, (cmd[7] << 8) | cmd[8]);
|
||||
unsigned char track = cmd[6];
|
||||
unsigned char msftime = cmd[1] & 0x02;
|
||||
unsigned short tocsize = 2;
|
||||
unsigned char *p = sector_buffer;
|
||||
int lba;
|
||||
|
||||
if (!toc.valid) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
switch(cmd[2] & 0x0f) {
|
||||
case 0:
|
||||
hdd_debugf("TOC format 0");
|
||||
if (track > toc.last && track != 0xAA) {
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x26, 2);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
sector_buffer[2] = 1;
|
||||
sector_buffer[3] = toc.last;
|
||||
p += 4;
|
||||
for (int i=1; i<=toc.last; i++) {
|
||||
if (i>=track) {
|
||||
p[0] = p[3] = 0;
|
||||
p[1] = (1 << 4) | ((toc.tracks[i-1].type == SECTOR_DATA) ? 4 : 0);
|
||||
p[2] = i;
|
||||
lba = toc.tracks[i-1].start;
|
||||
hdd_debugf("track %d lba: %d", i, lba);
|
||||
if (msftime) {
|
||||
msf_t MSF;
|
||||
LBA2MSF(lba+150, &MSF);
|
||||
p[4] = 0;
|
||||
p[5] = MSF.m;
|
||||
p[6] = MSF.s;
|
||||
p[7] = MSF.f;
|
||||
} else {
|
||||
p[4] = (lba >> 24) & 0xff;
|
||||
p[5] = (lba >> 16) & 0xff;
|
||||
p[6] = (lba >> 8) & 0xff;
|
||||
p[7] = lba & 0xff;
|
||||
}
|
||||
p+=8;
|
||||
tocsize+=8;
|
||||
}
|
||||
}
|
||||
|
||||
p[0] = p[3] = 0;
|
||||
p[1] = 0x14;
|
||||
p[2] = 0xAA;
|
||||
lba = toc.end;
|
||||
if (msftime) {
|
||||
msf_t MSF;
|
||||
LBA2MSF(lba+150, &MSF);
|
||||
p[4] = 0;
|
||||
p[5] = MSF.m;
|
||||
p[6] = MSF.s;
|
||||
p[7] = MSF.f;
|
||||
} else {
|
||||
p[4] = (lba >> 24) & 0xff;
|
||||
p[5] = (lba >> 16) & 0xff;
|
||||
p[6] = (lba >> 8) & 0xff;
|
||||
p[7] = lba & 0xff;
|
||||
}
|
||||
tocsize += 8;
|
||||
break;
|
||||
case 1:
|
||||
hdd_debugf("TOC format 1");
|
||||
tocsize = 12;
|
||||
memset(sector_buffer, 0, tocsize);
|
||||
sector_buffer[2] = sector_buffer[3] = 1; // first/last session numbers
|
||||
sector_buffer[5] = (1 << 4) | ((toc.tracks[0].type == SECTOR_DATA) ? 4 : 0);
|
||||
sector_buffer[6] = 1;
|
||||
lba = toc.tracks[0].start;
|
||||
if (msftime) {
|
||||
msf_t MSF;
|
||||
LBA2MSF(lba+150, &MSF);
|
||||
sector_buffer[5] = MSF.m;
|
||||
sector_buffer[6] = MSF.s;
|
||||
sector_buffer[7] = MSF.f;
|
||||
} else {
|
||||
sector_buffer[4] = (lba >> 24) & 0xff;
|
||||
sector_buffer[5] = (lba >> 16) & 0xff;
|
||||
sector_buffer[6] = (lba >> 8) & 0xff;
|
||||
sector_buffer[7] = lba & 0xff;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x26, 1);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
sector_buffer[0] = (tocsize>>8) & 0xff;
|
||||
sector_buffer[1] = tocsize & 0xff;
|
||||
|
||||
cdrom_ok();
|
||||
bufsize = MIN(bufsize, tocsize);
|
||||
hexdump(sector_buffer, bufsize, 0);
|
||||
WriteStatus(IDE_STATUS_RDY | IDE_STATUS_PKT); // pio in (class 1) command type
|
||||
WritePacket(unit, sector_buffer, bufsize, 1);
|
||||
}
|
||||
|
||||
static void PKT_ModeSense(unsigned char *cmd, unsigned char unit, unsigned short bytelimit, unsigned char page)
|
||||
{
|
||||
//TODO: implement
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x20, 0);
|
||||
cdrom_send_error(unit);
|
||||
}
|
||||
|
||||
static void PKT_ModeSense10(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_ModeSense10 (bufsize=%d)", unit, bytelimit);
|
||||
unsigned short bufsize = MIN(bytelimit, (cmd[7] << 8) | cmd[8]);
|
||||
unsigned char page = cmd[2] & 0x3f;
|
||||
PKT_ModeSense(cmd, unit, bytelimit, page);
|
||||
}
|
||||
|
||||
static void PKT_ModeSense6(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_ModeSense6 (bufsize=%d)", unit, bytelimit);
|
||||
unsigned short bufsize = MIN(bytelimit, cmd[4]);
|
||||
unsigned char page = cmd[2] & 0x3f;
|
||||
PKT_ModeSense(cmd, unit, bytelimit, page);
|
||||
}
|
||||
|
||||
static void PKT_Inquiry(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_Inquiry (bufsize=%d)", unit, bytelimit);
|
||||
unsigned short bufsize = MIN(bytelimit, (cmd[3] << 8) | cmd[4]);
|
||||
INQUIRYDATA_t *inq = (INQUIRYDATA_t*)§or_buffer;
|
||||
|
||||
memset(sector_buffer, 0, 36);
|
||||
inq->DeviceType = 0x05; // MMC3
|
||||
inq->RemovableMedia = 1; // removable
|
||||
inq->Versions = 0x02;
|
||||
inq->ResponseDataFormat = 0x02;
|
||||
memcpy(inq->VendorId, "MiST ", 8);
|
||||
memcpy(inq->ProductId, "CDROM ", 16);
|
||||
bufsize = MIN(bufsize, 36);
|
||||
cdrom_ok();
|
||||
WriteStatus(IDE_STATUS_RDY | IDE_STATUS_PKT); // pio in (class 1) command type
|
||||
WritePacket(unit, sector_buffer, bufsize, 1);
|
||||
}
|
||||
|
||||
static void PKT_TestUnitReady(unsigned char *cmd, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_TestUnitReady", unit);
|
||||
WriteTaskFile(0, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
if (toc.valid) {
|
||||
cdrom_ok();
|
||||
WriteTaskFile(0, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
} else {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_ERR | IDE_STATUS_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
static void PKT_RequestSense(unsigned char *cmd, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_RequestSense (bufsize=%d)", unit, bytelimit);
|
||||
unsigned short bufsize = MIN(bytelimit, cmd[4]);
|
||||
SENSEDATA_t *sense = (SENSEDATA_t*)§or_buffer;
|
||||
|
||||
memset(sector_buffer, 0, 16);
|
||||
sense->ErrorCode = 0x70;
|
||||
sense->Valid = 1;
|
||||
sense->SenseKey = cdrom.key;
|
||||
sense->AdditionalSenseCode = cdrom.asc;
|
||||
sense->AdditionalSenseCodeQualifier = cdrom.ascq;
|
||||
bufsize = MIN(bufsize, 16);
|
||||
WriteStatus(IDE_STATUS_RDY | IDE_STATUS_PKT); // pio in (class 1) command type
|
||||
WritePacket(unit, sector_buffer, bufsize, 1);
|
||||
}
|
||||
|
||||
static void PKT_StartStopUnit(unsigned char *cmd, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("IDE%d: PKT_StartStopUnit", unit);
|
||||
char start = cmd[4] & 0x01;
|
||||
|
||||
if ((start && toc.valid) || !start) {
|
||||
cdrom_ok();
|
||||
WriteTaskFile(0, 0x03, 0, 0, 0, 0xa0 | ((unit & 0x01)<<4));
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
} else {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x3A, 0);
|
||||
cdrom_send_error(unit);
|
||||
}
|
||||
}
|
||||
|
||||
// ATA_Packet()
|
||||
static inline void ATA_Packet(unsigned char *tfr, unsigned char unit, unsigned short bytelimit)
|
||||
{
|
||||
unsigned char cmdpkt[12];
|
||||
hdd_debugf("IDE%d: ATA_Packet", unit);
|
||||
if (hdf[unit].type != HDF_CDROM) {
|
||||
tfr[TFR_ERR] = 0x02; // command aborted
|
||||
WriteTaskFile(tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]);
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ | IDE_STATUS_ERR);
|
||||
return;
|
||||
}
|
||||
if (!bytelimit) bytelimit = 0xfffe;
|
||||
tfr[TFR_ERR] = 0x00;
|
||||
tfr[TFR_SCOUNT] = 0x01; //C/D flag
|
||||
WriteTaskFile(tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]);
|
||||
WriteStatus(IDE_STATUS_REQ | IDE_STATUS_PKT); // wait for command packet
|
||||
unsigned long to = GetTimer(20);
|
||||
while (!(GetFPGAStatus() & CMD_IDEDAT)) { // wait for full write buffer
|
||||
if (CheckTimer(to)) {
|
||||
cdrom_setsense(SENSEKEY_NOT_READY, 0x04, 0);
|
||||
cdrom_send_error(unit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
EnableFpga();
|
||||
SPI(CMD_IDE_DATA_RD); // read data command
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
SPI(0x00);
|
||||
for (int i=0; i<12; i++) {
|
||||
cmdpkt[i] = SPI(0xFF);
|
||||
}
|
||||
DisableFpga();
|
||||
hdd_debugf("CMD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
cmdpkt[0], cmdpkt[1], cmdpkt[2], cmdpkt[3], cmdpkt[4], cmdpkt[5],
|
||||
cmdpkt[6], cmdpkt[7], cmdpkt[8], cmdpkt[9], cmdpkt[10], cmdpkt[11]);
|
||||
switch(cmdpkt[0]) {
|
||||
case 0:
|
||||
PKT_TestUnitReady(cmdpkt, unit);
|
||||
break;
|
||||
case 3:
|
||||
PKT_RequestSense(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x12:
|
||||
PKT_Inquiry(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x1a:
|
||||
PKT_ModeSense6(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x5a:
|
||||
PKT_ModeSense10(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x43:
|
||||
PKT_ReadTOC(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x25:
|
||||
PKT_ReadCapacity(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x28:
|
||||
PKT_Read10(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0xA8:
|
||||
PKT_Read12(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x42:
|
||||
PKT_SubChannel(cmdpkt, unit, bytelimit);
|
||||
break;
|
||||
case 0x45:
|
||||
PKT_PlayAudio10(cmdpkt, unit);
|
||||
break;
|
||||
case 0x47:
|
||||
PKT_PlayAudioMSF(cmdpkt, unit);
|
||||
break;
|
||||
case 0x4B:
|
||||
PKT_PauseResume(cmdpkt, unit);
|
||||
break;
|
||||
case 0x4E:
|
||||
PKT_StopPlayScan(cmdpkt, unit);
|
||||
break;
|
||||
case 0x1B:
|
||||
PKT_StartStopUnit(cmdpkt, unit);
|
||||
break;
|
||||
default:
|
||||
iprintf("HDD%d: Unknown PACKET command: %02x\n", unit, cmdpkt[0]);
|
||||
cdrom_setsense(SENSEKEY_ILLEGAL_REQUEST, 0x3a, 0);
|
||||
cdrom_send_error(unit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ATA_Recalibrate()
|
||||
static inline void ATA_Recalibrate(unsigned char* tfr, unsigned char unit)
|
||||
@@ -321,15 +906,37 @@ static inline void ATA_Diagnostic(unsigned char* tfr)
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
|
||||
// ATA_IdentifyDevice()
|
||||
static inline void ATA_IdentifyDevice(unsigned char* tfr, unsigned char unit)
|
||||
static void ATA_IdentifyDevice(unsigned char* tfr, unsigned char unit, char packet)
|
||||
{
|
||||
int i;
|
||||
unsigned short *id = (unsigned short *)sector_buffer;
|
||||
// Identify Device (0xec)
|
||||
hdd_debugf("IDE%d: Identify Device", unit);
|
||||
IdentifyDevice(id, unit);
|
||||
hdd_debugf("IDE%d: Identify %s Device", unit, packet ? "Packet" : "");
|
||||
tfr[TFR_SCOUNT] = 0x01;
|
||||
tfr[TFR_SNUM] = 0x01;
|
||||
if (hdf[unit].type == HDF_CDROM) {
|
||||
tfr[TFR_ERR] = 0x02; // command aborted
|
||||
tfr[TFR_CYLL] = 0x14;
|
||||
tfr[TFR_CYLH] = 0xEB;
|
||||
tfr[TFR_SDH] = 0x00;
|
||||
} else {
|
||||
tfr[TFR_ERR] = 0x00;
|
||||
tfr[TFR_CYLL] = 0x00;
|
||||
tfr[TFR_CYLH] = 0x00;
|
||||
tfr[TFR_SDH] = 0x00;
|
||||
}
|
||||
if ((!packet && hdf[unit].type == HDF_CDROM) || (packet && hdf[unit].type != HDF_CDROM)) {
|
||||
WriteTaskFile(tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]);
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ | IDE_STATUS_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet)
|
||||
IdentifyPacketDevice(id, unit);
|
||||
else
|
||||
IdentifyDevice(id, unit);
|
||||
|
||||
WriteTaskFile(0, tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]);
|
||||
WriteStatus(IDE_STATUS_RDY); // pio in (class 1) command type
|
||||
EnableFpga();
|
||||
@@ -369,6 +976,30 @@ static inline void ATA_SetMultipleMode(unsigned char* tfr, unsigned char unit)
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
static inline void ATA_NOP(unsigned char *tfr, unsigned char unit)
|
||||
{
|
||||
WriteTaskFile(tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]);
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
static inline void ATA_DeviceReset(unsigned char *tfr, unsigned char unit)
|
||||
{
|
||||
hdd_debugf("Device Reset");
|
||||
hdd_debugf("IDE%d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X", unit, tfr[0], tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6], tfr[7]);
|
||||
tfr[TFR_SCOUNT] = 0x01;
|
||||
tfr[TFR_SNUM] = 0x01;
|
||||
tfr[TFR_ERR] = 0x00;
|
||||
//tfr[TFR_SDH] = 0x00;
|
||||
if (hdf[unit].type == HDF_CDROM) {
|
||||
tfr[TFR_CYLL] = 0x14;
|
||||
tfr[TFR_CYLH] = 0xEB;
|
||||
} else {
|
||||
tfr[TFR_CYLL] = 0x00;
|
||||
tfr[TFR_CYLH] = 0x00;
|
||||
}
|
||||
WriteTaskFile(tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]);
|
||||
WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ);
|
||||
}
|
||||
|
||||
// ATA_ReadSectors()
|
||||
static inline void ATA_ReadSectors(unsigned char* tfr, unsigned short sector, unsigned short cylinder, unsigned char head, unsigned char unit, unsigned short sector_count, unsigned char multiple, char lbamode)
|
||||
@@ -663,7 +1294,9 @@ void HandleHDD(unsigned char c1, unsigned char c2, unsigned char cs1ena)
|
||||
} else if (tfr[7] == ACMD_DIAGNOSTIC) {
|
||||
ATA_Diagnostic(tfr);
|
||||
} else if (tfr[7] == ACMD_IDENTIFY_DEVICE) {
|
||||
ATA_IdentifyDevice(tfr, unit);
|
||||
ATA_IdentifyDevice(tfr, unit, 0);
|
||||
} else if (tfr[7] == ACMD_IDENTIFY_PACKET_DEVICE) {
|
||||
ATA_IdentifyDevice(tfr, unit, 1);
|
||||
} else if (tfr[7] == ACMD_INITIALIZE_DEVICE_PARAMETERS) {
|
||||
ATA_Initialize(tfr, unit);
|
||||
} else if (tfr[7] == ACMD_SET_MULTIPLE_MODE) {
|
||||
@@ -676,6 +1309,12 @@ void HandleHDD(unsigned char c1, unsigned char c2, unsigned char cs1ena)
|
||||
ATA_WriteSectors(tfr, sector, cylinder, head, unit, sector_count ,0, lbamode);
|
||||
} else if (tfr[7] == ACMD_WRITE_MULTIPLE) {
|
||||
ATA_WriteSectors(tfr, sector, cylinder, head, unit, sector_count, 1, lbamode);
|
||||
} else if (tfr[7] == ACMD_PACKET) {
|
||||
ATA_Packet(tfr, unit, cylinder);
|
||||
} else if (tfr[7] == ACMD_DEVICE_RESET) {
|
||||
ATA_DeviceReset(tfr, unit);
|
||||
} else if (tfr[7] == ACMD_NOP) {
|
||||
ATA_NOP(tfr, unit);
|
||||
} else {
|
||||
hdd_debugf("Unknown ATA command");
|
||||
hdd_debugf("IDE%d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X", unit, tfr[0], tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6], tfr[7]);
|
||||
@@ -812,6 +1451,14 @@ unsigned char OpenHardfile(unsigned char unit)
|
||||
GetHardfileGeometry(&hdf[unit]);
|
||||
return 1;
|
||||
break;
|
||||
case HDF_CDROM:
|
||||
hdf[unit].type = HDF_CDROM;
|
||||
hardfile[unit]->present = 1;
|
||||
cdrom.key = cdrom.asc = cdrom.ascq = 0;
|
||||
cdrom.currentlba = 0;
|
||||
cdrom.audiostatus = AUDIO_NOSTAT;
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
hardfile[unit]->present = 0;
|
||||
return 0;
|
||||
|
||||
16
hdd.h
16
hdd.h
@@ -17,11 +17,14 @@
|
||||
#define CMD_IDE_STATUS_WR 0xF0
|
||||
|
||||
#define IDE_STATUS_END 0x80
|
||||
#define IDE_STATUS_PKT 0x20
|
||||
#define IDE_STATUS_IRQ 0x10
|
||||
#define IDE_STATUS_RDY 0x08
|
||||
#define IDE_STATUS_REQ 0x04
|
||||
#define IDE_STATUS_ERR 0x01
|
||||
|
||||
#define ACMD_NOP 0x00
|
||||
#define ACMD_DEVICE_RESET 0x08
|
||||
#define ACMD_RECALIBRATE 0x10
|
||||
#define ACMD_DIAGNOSTIC 0x90
|
||||
#define ACMD_IDENTIFY_DEVICE 0xEC
|
||||
@@ -31,6 +34,8 @@
|
||||
#define ACMD_READ_MULTIPLE 0xC4
|
||||
#define ACMD_WRITE_MULTIPLE 0xC5
|
||||
#define ACMD_SET_MULTIPLE_MODE 0xC6
|
||||
#define ACMD_PACKET 0xA0
|
||||
#define ACMD_IDENTIFY_PACKET_DEVICE 0xA1
|
||||
|
||||
#define HDF_DISABLED 0
|
||||
#define HDF_FILE 1
|
||||
@@ -39,6 +44,7 @@
|
||||
#define HDF_CARDPART1 4
|
||||
#define HDF_CARDPART2 5
|
||||
#define HDF_CARDPART3 6
|
||||
#define HDF_CDROM 10
|
||||
#define HDF_TYPEMASK 15
|
||||
#define HDF_SYNTHRDB 128 // flag to indicate whether we should auto-synthesize a RigidDiskBlock
|
||||
|
||||
@@ -49,10 +55,18 @@
|
||||
|
||||
#define HARDFILES 4
|
||||
|
||||
#define TFR_ERR 1
|
||||
#define TFR_SCOUNT 2
|
||||
#define TFR_SNUM 3
|
||||
#define TFR_CYLL 4
|
||||
#define TFR_CYLH 5
|
||||
#define TFR_SDH 6
|
||||
#define TFR_STAT 7
|
||||
|
||||
// types
|
||||
typedef struct
|
||||
{
|
||||
unsigned char enabled; // 0: Disabled, 1: Hard file, 2: MMC (entire card), 3-6: Partition 1-4 of MMC card
|
||||
unsigned char enabled; // 0: Disabled, 1: Hard file, 2: MMC (entire card), 3-6: Partition 1-4 of MMC card, 10-CDROM
|
||||
unsigned char present;
|
||||
char name[64];
|
||||
} hardfileTYPE;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "boot.h"
|
||||
#include "user_io.h"
|
||||
#include "misc_cfg.h"
|
||||
#include "cue_parser.h"
|
||||
|
||||
// TODO!
|
||||
#define SPIN() asm volatile ( "mov r0, r0\n\t" \
|
||||
@@ -201,6 +202,20 @@ static char HardFileSelected(uint8_t idx, const char *SelectedName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char CueISOFileSelected(uint8_t idx, const char *SelectedName) {
|
||||
int hdf_idx;
|
||||
if (idx == 10) // master drive selected
|
||||
hdf_idx = t_ide_idx << 1;
|
||||
else if (idx == 12) // slave drive selected
|
||||
hdf_idx = (t_ide_idx << 1) + 1;
|
||||
else // invalid
|
||||
return 0;
|
||||
|
||||
char res;
|
||||
res = cue_parse(SelectedName, &sd_image[hdf_idx]);
|
||||
if (res) ErrorMessage(cue_error_msg[res-1], res);
|
||||
}
|
||||
|
||||
static char KickstartReload(uint8_t idx) {
|
||||
if (idx == 0) {// yes
|
||||
CloseMenu();
|
||||
@@ -409,6 +424,8 @@ static char GetMenuItem_Minimig(uint8_t idx, char action, menu_item_t *item) {
|
||||
strcpy(s, slave ? " Slave : " : " Master : ");
|
||||
if(config.hardfile[(t_ide_idx << 1)+slave].enabled==(HDF_FILE|HDF_SYNTHRDB))
|
||||
strcat(s,"Hardfile (filesys)");
|
||||
else if(config.hardfile[(t_ide_idx << 1)+slave].enabled==HDF_CDROM)
|
||||
strcat(s,"CDROM");
|
||||
else
|
||||
strcat(s, config_hdf_msg[config.hardfile[(t_ide_idx << 1)+slave].enabled & HDF_TYPEMASK]);
|
||||
item->item = s;
|
||||
@@ -421,11 +438,14 @@ static char GetMenuItem_Minimig(uint8_t idx, char action, menu_item_t *item) {
|
||||
uint8_t slave = idx == 12;
|
||||
if (config.hardfile[(t_ide_idx << 1)+slave].present) {
|
||||
strcpy(s, " ");
|
||||
strncpy(&s[14], config.hardfile[(t_ide_idx << 1)+slave].name, sizeof(config.hardfile[0].name));
|
||||
if(config.hardfile[(t_ide_idx << 1)+slave].enabled == HDF_CDROM)
|
||||
strcpy(&s[14], toc.valid ? "* Inserted *" : "* Empty *");
|
||||
else
|
||||
strncpy(&s[14], config.hardfile[(t_ide_idx << 1)+slave].name, sizeof(config.hardfile[0].name));
|
||||
} else
|
||||
strcpy(s, " ** file not found **");
|
||||
item->item = s;
|
||||
item->active = config.enable_ide[t_ide_idx] && ((config.hardfile[(t_ide_idx << 1)+slave].enabled&HDF_TYPEMASK)==HDF_FILE);
|
||||
item->active = config.enable_ide[t_ide_idx] && (config.hardfile[(t_ide_idx << 1)+slave].enabled&HDF_TYPEMASK&(HDF_FILE | HDF_CDROM));
|
||||
item->stipple = !item->active;
|
||||
}
|
||||
break;
|
||||
@@ -623,15 +643,35 @@ static char GetMenuItem_Minimig(uint8_t idx, char action, menu_item_t *item) {
|
||||
} else if(config.hardfile[hdf_idx].enabled==(HDF_FILE|HDF_SYNTHRDB)) {
|
||||
config.hardfile[hdf_idx].enabled&=~HDF_SYNTHRDB;
|
||||
config.hardfile[hdf_idx].enabled +=1;
|
||||
} else if(config.hardfile[hdf_idx].enabled==(HDF_CARDPART0+partitioncount)) {
|
||||
// only one CDROM is supported, so check if already choosen
|
||||
if (config.hardfile[0].enabled != HDF_CDROM &&
|
||||
config.hardfile[1].enabled != HDF_CDROM &&
|
||||
config.hardfile[2].enabled != HDF_CDROM &&
|
||||
config.hardfile[3].enabled != HDF_CDROM) {
|
||||
config.hardfile[hdf_idx].enabled = HDF_CDROM;
|
||||
} else {
|
||||
config.hardfile[hdf_idx].enabled = HDF_FILE;
|
||||
}
|
||||
} else if(config.hardfile[hdf_idx].enabled==HDF_CDROM) {
|
||||
config.hardfile[hdf_idx].enabled = HDF_FILE;
|
||||
} else {
|
||||
config.hardfile[hdf_idx].enabled +=1;
|
||||
config.hardfile[hdf_idx].enabled %=HDF_CARDPART0+partitioncount;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
case 12:
|
||||
SelectFileNG("HDF", SCAN_LFN, HardFileSelected, 0);
|
||||
case 12: {
|
||||
uint8_t hdf_idx = (t_ide_idx << 1) + (idx == 12);
|
||||
if(config.hardfile[hdf_idx].enabled==HDF_CDROM) {
|
||||
if(toc.valid)
|
||||
toc.valid = 0;
|
||||
else
|
||||
SelectFileNG("CUEISO", SCAN_DIR | SCAN_LFN, CueISOFileSelected, 0);
|
||||
} else {
|
||||
SelectFileNG("HDF", SCAN_LFN, HardFileSelected, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Page 2 - Settings
|
||||
|
||||
82
scsi.h
Normal file
82
scsi.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
scsi.h
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SCSI_H
|
||||
#define SCSI_H
|
||||
|
||||
|
||||
#define SENSEKEY_NO_SENSE 0x0
|
||||
#define SENSEKEY_SOFT_ERROR 0x1
|
||||
#define SENSEKEY_NOT_READY 0x2
|
||||
#define SENSEKEY_MEDIUM_ERROR 0x3
|
||||
#define SENSEKEY_HARDWARE_ERROR 0x4
|
||||
#define SENSEKEY_ILLEGAL_REQUEST 0x5
|
||||
#define SENSEKEY_UNIT_ATTENTION 0x6
|
||||
#define SENSEKEY_ABORTED_COMMAND 0xB
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t DeviceType : 5;
|
||||
uint8_t DeviceTypeQualifier : 3;
|
||||
uint8_t DeviceTypeModifier : 7;
|
||||
uint8_t RemovableMedia : 1;
|
||||
uint8_t Versions;
|
||||
uint8_t ResponseDataFormat : 4;
|
||||
uint8_t HiSupport : 1;
|
||||
uint8_t NormACA : 1;
|
||||
uint8_t ReservedBit : 1;
|
||||
uint8_t AERC : 1;
|
||||
uint8_t AdditionalLength;
|
||||
uint8_t Reserved[2];
|
||||
uint8_t SoftReset : 1;
|
||||
uint8_t CommandQueue : 1;
|
||||
uint8_t Reserved2 : 1;
|
||||
uint8_t LinkedCommands : 1;
|
||||
uint8_t Synchronous : 1;
|
||||
uint8_t Wide16Bit : 1;
|
||||
uint8_t Wide32Bit : 1;
|
||||
uint8_t RelativeAddressing : 1;
|
||||
uint8_t VendorId[8];
|
||||
uint8_t ProductId[16];
|
||||
uint8_t ProductRevisionLevel[4];
|
||||
uint8_t VendorSpecific[20];
|
||||
uint8_t Reserved3[2];
|
||||
uint8_t VersionDescriptors[8];
|
||||
uint8_t Reserved4[30];
|
||||
} __attribute__ ((packed)) INQUIRYDATA_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t ErrorCode :7;
|
||||
uint8_t Valid :1;
|
||||
uint8_t SegmentNumber;
|
||||
uint8_t SenseKey :4;
|
||||
uint8_t Reserved :1;
|
||||
uint8_t IncorrectLength :1;
|
||||
uint8_t EndOfMedia :1;
|
||||
uint8_t FileMark :1;
|
||||
uint8_t Information[4];
|
||||
uint8_t AdditionalSenseLength;
|
||||
uint8_t CommandSpecificInformation[4];
|
||||
uint8_t AdditionalSenseCode;
|
||||
uint8_t AdditionalSenseCodeQualifier;
|
||||
uint8_t FieldReplaceableUnitCode;
|
||||
uint8_t SenseKeySpecific[3];
|
||||
} __attribute__ ((packed)) SENSEDATA_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t LBA;
|
||||
uint32_t blocklen;
|
||||
} __attribute__ ((packed)) CAPACITYDATA_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Reserved[3];
|
||||
uint8_t Length;
|
||||
uint32_t Blocks;
|
||||
uint8_t DescriptorType :1;
|
||||
uint8_t Reserved2 : 7;
|
||||
uint8_t Blocklen[3];
|
||||
} __attribute__ ((packed)) FORMATCAPACITYDATA_t;
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "swab.h"
|
||||
#include "scsi.h"
|
||||
#include "utils.h"
|
||||
#include "storage_control.h"
|
||||
#include "fat_compat.h"
|
||||
@@ -15,14 +16,6 @@
|
||||
#include "FatFs/diskio.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define SENSEKEY_NO_SENSE 0x0
|
||||
#define SENSEKEY_NOT_READY 0x2
|
||||
#define SENSEKEY_MEDIUM_ERROR 0x3
|
||||
#define SENSEKEY_HARDWARE_ERROR 0x4
|
||||
#define SENSEKEY_ILLEGAL_REQUEST 0x5
|
||||
#define SENSEKEY_UNIT_ATTENTION 0x6
|
||||
#define SENSEKEY_ABORTED_COMMAND 0xB
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t key;
|
||||
@@ -49,68 +42,6 @@ typedef struct {
|
||||
uint8_t bCSWStatus;
|
||||
} __attribute__ ((packed)) CSW_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t DeviceType : 5;
|
||||
uint8_t DeviceTypeQualifier : 3;
|
||||
uint8_t DeviceTypeModifier : 7;
|
||||
uint8_t RemovableMedia : 1;
|
||||
uint8_t Versions;
|
||||
uint8_t ResponseDataFormat : 4;
|
||||
uint8_t HiSupport : 1;
|
||||
uint8_t NormACA : 1;
|
||||
uint8_t ReservedBit : 1;
|
||||
uint8_t AERC : 1;
|
||||
uint8_t AdditionalLength;
|
||||
uint8_t Reserved[2];
|
||||
uint8_t SoftReset : 1;
|
||||
uint8_t CommandQueue : 1;
|
||||
uint8_t Reserved2 : 1;
|
||||
uint8_t LinkedCommands : 1;
|
||||
uint8_t Synchronous : 1;
|
||||
uint8_t Wide16Bit : 1;
|
||||
uint8_t Wide32Bit : 1;
|
||||
uint8_t RelativeAddressing : 1;
|
||||
uint8_t VendorId[8];
|
||||
uint8_t ProductId[16];
|
||||
uint8_t ProductRevisionLevel[4];
|
||||
uint8_t VendorSpecific[20];
|
||||
uint8_t Reserved3[2];
|
||||
uint8_t VersionDescriptors[8];
|
||||
uint8_t Reserved4[30];
|
||||
} __attribute__ ((packed)) INQUIRYDATA_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t ErrorCode :7;
|
||||
uint8_t Valid :1;
|
||||
uint8_t SegmentNumber;
|
||||
uint8_t SenseKey :4;
|
||||
uint8_t Reserved :1;
|
||||
uint8_t IncorrectLength :1;
|
||||
uint8_t EndOfMedia :1;
|
||||
uint8_t FileMark :1;
|
||||
uint8_t Information[4];
|
||||
uint8_t AdditionalSenseLength;
|
||||
uint8_t CommandSpecificInformation[4];
|
||||
uint8_t AdditionalSenseCode;
|
||||
uint8_t AdditionalSenseCodeQualifier;
|
||||
uint8_t FieldReplaceableUnitCode;
|
||||
uint8_t SenseKeySpecific[3];
|
||||
} __attribute__ ((packed)) SENSEDATA_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t LBA;
|
||||
uint32_t blocklen;
|
||||
} __attribute__ ((packed)) CAPACITYDATA_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Reserved[3];
|
||||
uint8_t Length;
|
||||
uint32_t Blocks;
|
||||
uint8_t DescriptorType :1;
|
||||
uint8_t Reserved2 : 7;
|
||||
uint8_t Blocklen[3];
|
||||
} __attribute__ ((packed)) FORMATCAPACITYDATA_t;
|
||||
|
||||
static void clear_sense() {
|
||||
sense.key = sense.asc = sense.ascq = 0;
|
||||
}
|
||||
|
||||
57
user_io.c
57
user_io.c
@@ -10,6 +10,7 @@
|
||||
#include "data_io.h"
|
||||
#include "archie.h"
|
||||
#include "pcecd.h"
|
||||
#include "hdd.h"
|
||||
#include "cdc_control.h"
|
||||
#include "usb.h"
|
||||
#include "debug.h"
|
||||
@@ -37,7 +38,6 @@ unsigned char key_remap_table[MAX_REMAP][2];
|
||||
#define BREAK 0x8000
|
||||
|
||||
static char umounted; // 1st image is file or direct SD?
|
||||
static char cue_valid = 0;
|
||||
static char buffer[512];
|
||||
static uint8_t buffer_drive_index = 0;
|
||||
static uint32_t buffer_lba = 0xffffffff;
|
||||
@@ -114,6 +114,9 @@ static uint32_t autofire_map;
|
||||
static uint32_t autofire_mask;
|
||||
static char autofire_joy;
|
||||
|
||||
// ATA drives
|
||||
hardfileTYPE hardfiles[4];
|
||||
|
||||
char user_io_osd_is_visible() {
|
||||
return osd_is_visible;
|
||||
}
|
||||
@@ -122,11 +125,15 @@ void user_io_reset() {
|
||||
// no sd card image selected, SD card accesses will go directly
|
||||
// to the card (first slot, and only until the first unmount)
|
||||
umounted = 0;
|
||||
cue_valid = 0;
|
||||
toc.valid = 0;
|
||||
sd_image[0].valid = 0;
|
||||
sd_image[1].valid = 0;
|
||||
sd_image[2].valid = 0;
|
||||
sd_image[3].valid = 0;
|
||||
hardfiles[0].enabled = HDF_DISABLED;
|
||||
hardfiles[1].enabled = HDF_DISABLED;
|
||||
hardfiles[2].enabled = HDF_DISABLED;
|
||||
hardfiles[3].enabled = HDF_CDROM;
|
||||
core_mod = 0;
|
||||
core_features = 0;
|
||||
ps2_kbd_state = PS2_KBD_IDLE;
|
||||
@@ -376,6 +383,28 @@ void user_io_detect_core_type() {
|
||||
user_io_file_mount(s, i);
|
||||
}
|
||||
}
|
||||
// check for <core>.IDx files (IDE drives)
|
||||
if(core_features & FEAT_IDE) {
|
||||
for (int i = 0; i < SD_IMAGES; i++) {
|
||||
hardfile[i] = &hardfiles[i];
|
||||
}
|
||||
|
||||
if(!user_io_create_config_name(s, "ID0", CONFIG_ROOT | CONFIG_VHD)) {
|
||||
for (int i = 0; i < HARDFILES-1; i++) {
|
||||
if (!user_io_is_mounted(i)) {
|
||||
s[strlen(s)-1] = '0'+i;
|
||||
iprintf("Looking for %s\n", s);
|
||||
hardfiles[i].enabled = HDF_FILE;
|
||||
strncpy(hardfiles[i].name, s, sizeof(hardfiles[0].name));
|
||||
hardfiles[i].name[sizeof(hardfiles[0].name)-1] = 0;
|
||||
OpenHardfile(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
OpenHardfile(3); // CDROM
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,23 +735,22 @@ static void kbd_fifo_poll() {
|
||||
|
||||
|
||||
char user_io_is_cue_mounted() {
|
||||
return cue_valid;
|
||||
return toc.valid;
|
||||
}
|
||||
|
||||
char user_io_cue_mount(const unsigned char *name) {
|
||||
char res = CUE_RES_OK;
|
||||
cue_valid = 0;
|
||||
toc.valid = 0;
|
||||
if (name) {
|
||||
res = cue_parse(name, &sd_image[3]);
|
||||
if (res == CUE_RES_OK) cue_valid = 1;
|
||||
}
|
||||
|
||||
// send mounted image size first then notify about mounting
|
||||
EnableIO();
|
||||
SPI(UIO_SET_SDINFO);
|
||||
// use LE version, so following BYTE(s) may be used for size extension in the future.
|
||||
spi32le(cue_valid ? f_size(&toc.file->file) : 0);
|
||||
spi32le(cue_valid ? f_size(&toc.file->file) >> 32 : 0);
|
||||
spi32le(toc.valid ? f_size(&toc.file->file) : 0);
|
||||
spi32le(toc.valid ? f_size(&toc.file->file) >> 32 : 0);
|
||||
spi32le(0); // reserved for future expansion
|
||||
spi32le(0); // reserved for future expansion
|
||||
DisableIO();
|
||||
@@ -1621,6 +1649,21 @@ void user_io_poll() {
|
||||
if(core_type == CORE_TYPE_ARCHIE)
|
||||
archie_poll();
|
||||
|
||||
if(core_features & FEAT_IDE)
|
||||
{
|
||||
unsigned char c1;
|
||||
|
||||
EnableFpga();
|
||||
c1 = SPI(0); // cmd request
|
||||
SPI(0);
|
||||
SPI(0);
|
||||
SPI(0);
|
||||
SPI(0);
|
||||
SPI(0);
|
||||
DisableFpga();
|
||||
HandleHDD(c1, 0, 1);
|
||||
}
|
||||
|
||||
if((core_type == CORE_TYPE_MINIMIG2) ||
|
||||
(core_type == CORE_TYPE_MIST2) ||
|
||||
(core_type == CORE_TYPE_ARCHIE) ||
|
||||
|
||||
Reference in New Issue
Block a user