#include "compiler.h"
// winでidentifyまでは取得に行くんだけどな…ってAnex86も同じか
#if defined(SUPPORT_IDEIO)
#include "dosio.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "ideio.h"
#include "atapicmd.h"
#include "sxsi.h"
#include "sound.h"
#include "idebios.res"
IDEIO ideio;
static IDEDEV getidedev(void) {
UINT bank;
bank = ideio.bank[1] & 0x7f;
if (bank < 2) {
return(ideio.dev + bank);
}
else {
return(NULL);
}
}
static IDEDRV getidedrv(void) {
IDEDEV dev;
IDEDRV drv;
dev = getidedev();
if (dev) {
drv = dev->drv + dev->drivesel;
if (drv->device != IDETYPE_NONE) {
return(drv);
}
}
return(NULL);
}
static const char serial[] = "824919341192 ";
static const char firm[] = "A5U.1200";
static const char model[] = "QUANTUM FIREBALL CR ";
static const char cdrom_serial[] = "1.0 ";
static const char cdrom_firm[] = " ";
static const char cdrom_model[] = "NEC CD-ROM DRIVE ";
static BRESULT setidentify(IDEDRV drv) {
SXSIDEV sxsi;
UINT16 tmp[256];
UINT8 *p;
UINT i;
UINT32 size;
sxsi = sxsi_getptr(drv->sxsidrv);
if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) {
return(FAILURE);
}
ZeroMemory(tmp, sizeof(tmp));
// とりあえず使ってる部分だけ
if (drv->device == IDETYPE_HDD) {
tmp[0] = 0x0040; // non removable device
tmp[1] = sxsi->cylinders;
tmp[3] = sxsi->surfaces;
tmp[4] = sxsi->sectors * 512;
tmp[6] = sxsi->sectors;
for (i=0; i<10; i++) {
tmp[10+i] = (serial[i*2] << 8) + serial[i*2+1];
}
tmp[22] = 4;
for (i=0; i<4; i++) {
tmp[23+i] = (firm[i*2] << 8) + firm[i*2+1];
}
for (i=0; i<20; i++) {
tmp[27+i] = (model[i*2] << 8) + model[i*2+1];
}
#if IDEIO_MULTIPLE_MAX > 0
tmp[47] = 0x8000 | IDEIO_MULTIPLE_MAX; // multiple
#endif
tmp[49] = 0x0200; // support LBA
tmp[51] = 0x0200;
tmp[53] = 0x0001;
tmp[54] = sxsi->cylinders;
tmp[55] = sxsi->surfaces;
tmp[56] = sxsi->sectors;
size = sxsi->cylinders * sxsi->surfaces * sxsi->sectors;
tmp[57] = (UINT16)size;
tmp[58] = (UINT16)(size >> 16);
#if IDEIO_MULTIPLE_MAX > 0
tmp[59] = 0x0100 | drv->mulmode; // current multiple mode
#endif
tmp[60] = (UINT16)size;
tmp[61] = (UINT16)(size >> 16);
tmp[63] = 0x0000; // no support multiword DMA
tmp[80] = 0x0006; // only support ATA-1/2
tmp[81] = 0;
tmp[82] = 0x0200; // support DEVICE RESET
}
else if (drv->device == IDETYPE_CDROM) {
tmp[0] = 0x8580; // ATAPI,CD-ROM,removable,12bytes PACKET
for (i=0; i<10; i++) {
tmp[10+i] = (cdrom_serial[i*2] << 8) + cdrom_serial[i*2+1];
}
for (i=0; i<4; i++) {
tmp[23+i] = (cdrom_firm[i*2] << 8) + cdrom_firm[i*2+1];
}
for (i=0; i<20; i++) {
tmp[27+i] = (cdrom_model[i*2] << 8) + cdrom_model[i*2+1];
}
tmp[49] = 0x0200; // support LBA
tmp[53] = 0x0001;
tmp[63] = 0x0000; // no support multiword DMA
tmp[80] = 0x000e; // only support ATA-1/2
tmp[82] = 0x0210; // support PACKET/DEVICE RESET
tmp[126] = 0x0000; // ATAPI byte count
}
p = drv->buf;
for (i=0; i<256; i++) {
p[0] = (UINT8)tmp[i];
p[1] = (UINT8)(tmp[i] >> 8);
p += 2;
}
drv->bufdir = IDEDIR_IN;
drv->buftc = IDETC_TRANSFEREND;
drv->bufpos = 0;
drv->bufsize = 512;
return(SUCCESS);
}
static void setintr(IDEDRV drv) {
if (!(drv->ctrl & IDECTRL_NIEN)) {
TRACEOUT(("ideio: setintr()"));
ideio.bank[0] = ideio.bank[1] | 0x80; // ????
pic_setirq(IDE_IRQ);
}
}
static void cmdabort(IDEDRV drv) {
TRACEOUT(("ideio: cmdabort()"));
drv->status = IDESTAT_DRDY | IDESTAT_ERR;
drv->error = IDEERR_ABRT;
setintr(drv);
}
static void drvreset(IDEDRV drv) {
if (drv->device == IDETYPE_CDROM) {
drv->hd = 0x10;
drv->sc = 0x01;
drv->sn = 0x01;
drv->cy = 0xeb14;
drv->status = 0;
}
else {
drv->hd = 0x00;
drv->sc = 0x01;
drv->sn = 0x01;
drv->cy = 0x0000;
drv->status = IDESTAT_DRDY;
}
}
static void panic(const char *str, ...) {
char buf[2048];
va_list ap;
va_start(ap, str);
vsnprintf(buf, sizeof(buf), str, ap);
va_end(ap);
msgbox("ide_panic", buf);
exit(1);
}
// ----
static void incsec(IDEDRV drv) {
if (!(drv->dr & IDEDEV_LBA)) {
drv->sn++;
if (drv->sn <= drv->sectors) {
return;
}
drv->sn = 1;
drv->hd++;
if (drv->hd < drv->surfaces) {
return;
}
drv->hd = 0;
drv->cy++;
}
else {
drv->sn++;
if (drv->sn) {
return;
}
drv->cy++;
if (drv->cy) {
return;
}
drv->hd++;
}
}
static long getcursec(const IDEDRV drv) {
long ret;
if (!(drv->dr & IDEDEV_LBA)) {
ret = drv->cy;
ret *= drv->surfaces;
ret += drv->hd;
ret *= drv->sectors;
ret += (drv->sn - 1);
}
else {
ret = drv->sn;
ret |= (drv->cy << 8);
ret |= (drv->hd << 24);
}
return(ret);
}
static void readsec(IDEDRV drv) {
long sec;
if (drv->device != IDETYPE_HDD) {
goto read_err;
}
sec = getcursec(drv);
TRACEOUT(("readsec->drv %d sec %x cnt %d thr %d",
drv->sxsidrv, sec, drv->mulcnt, drv->multhr));
if (sxsi_read(drv->sxsidrv, sec, drv->buf, 512)) {
TRACEOUT(("read error!"));
goto read_err;
}
drv->bufdir = IDEDIR_IN;
drv->buftc = IDETC_TRANSFEREND;
drv->bufpos = 0;
drv->bufsize = 512;
if ((drv->mulcnt & (drv->multhr - 1)) == 0) {
drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ;
drv->error = 0;
setintr(drv);
}
drv->mulcnt++;
return;
read_err:
cmdabort(drv);
}
static void writesec(IDEDRV drv) {
if (drv->device == IDETYPE_NONE) {
goto write_err;
}
drv->bufdir = IDEDIR_OUT;
drv->buftc = IDETC_TRANSFEREND;
drv->bufpos = 0;
drv->bufsize = 512;
if ((drv->mulcnt & (drv->multhr - 1)) == 0) {
drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ;
drv->error = 0;
setintr(drv);
}
return;
write_err:
cmdabort(drv);
}
// ----
static void IOOUTCALL ideio_o430(UINT port, REG8 dat) {
TRACEOUT(("ideio setbank%d %.2x [%.4x:%.8x]",
(port >> 1) & 1, dat, CPU_CS, CPU_EIP));
if (!(dat & 0x80)) {
ideio.bank[(port >> 1) & 1] = dat;
}
}
static REG8 IOINPCALL ideio_i430(UINT port) {
UINT bank;
REG8 ret;
bank = (port >> 1) & 1;
ret = ideio.bank[bank];
ideio.bank[bank] = ret & (~0x80);
TRACEOUT(("ideio getbank%d %.2x [%.4x:%.8x]",
(port >> 1) & 1, ret, CPU_CS, CPU_EIP));
return(ret & 0x81);
}
// ----
static void IOOUTCALL ideio_o642(UINT port, REG8 dat) {
IDEDRV drv;
drv = getidedrv();
if (drv) {
drv->wp = dat;
TRACEOUT(("ideio set WP %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
}
(void)port;
}
static void IOOUTCALL ideio_o644(UINT port, REG8 dat) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
drv->sc = dat;
TRACEOUT(("ideio set SC %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
}
(void)port;
}
static void IOOUTCALL ideio_o646(UINT port, REG8 dat) {
IDEDRV drv;
drv = getidedrv();
if (drv) {
drv->sn = dat;
TRACEOUT(("ideio set SN %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
}
(void)port;
}
static void IOOUTCALL ideio_o648(UINT port, REG8 dat) {
IDEDRV drv;
drv = getidedrv();
if (drv) {
drv->cy &= 0xff00;
drv->cy |= dat;
TRACEOUT(("ideio set CYL %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
}
(void)port;
}
static void IOOUTCALL ideio_o64a(UINT port, REG8 dat) {
IDEDRV drv;
drv = getidedrv();
if (drv) {
drv->cy &= 0x00ff;
drv->cy |= dat << 8;
TRACEOUT(("ideio set CYH %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
}
(void)port;
}
static void IOOUTCALL ideio_o64c(UINT port, REG8 dat) {
IDEDEV dev;
UINT drvnum;
dev = getidedev();
if (dev == NULL) {
return;
}
#if defined(TRACE)
if ((dat & 0xf0) != 0xa0) {
TRACEOUT(("ideio set SDH illegal param? (%.2x)", dat));
}
#endif
drvnum = (dat >> 4) & 1;
dev->drivesel = drvnum;
dev->drv[drvnum].dr = dat & 0xf0;
dev->drv[drvnum].hd = dat & 0x0f;
TRACEOUT(("ideio set DRHD %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
(void)port;
}
static void IOOUTCALL ideio_o64e(UINT port, REG8 dat) {
IDEDRV drv, d;
IDEDEV dev;
int i;
// execute device diagnostic
if (dat == 0x90) {
TRACEOUT(("ideio set cmd %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
TRACEOUT(("ideio: execute device diagnostic"));
dev = getidedev();
if (dev) {
for (i = 0; i < 2; i++) {
d = dev->drv + i;
drvreset(d);
d->error = 0x01;
if (dev->drv[i].device == IDETYPE_NONE) {
d->error = 0x00;
}
if (i == 0) {
if (dev->drv[1].device == IDETYPE_NONE) {
d->error |= 0x80;
}
}
}
}
return;
}
drv = getidedrv();
if (drv == NULL) {
return;
}
drv->cmd = dat;
TRACEOUT(("ideio set cmd %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
switch(dat) {
case 0x08: // device reset
TRACEOUT(("ideio: device reset"));
drvreset(drv);
drv->error = 0x01;
dev = getidedev();
if (dev) {
if (dev->drv[dev->drivesel].device == IDETYPE_NONE) {
drv->error = 0x00;
}
if (dev->drivesel == 0) {
if (dev->drv[1].device == IDETYPE_NONE) {
drv->error |= 0x80;
}
}
}
setintr(drv);
break;
case 0x10: case 0x11: case 0x12: case 0x13: // recalibrate
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1a: case 0x1b:
case 0x1c: case 0x1d: case 0x1e: case 0x1f:
TRACEOUT(("ideio: recalibrate"));
if (drv->device == IDETYPE_HDD) {
drv->hd = 0x00;
drv->sc = 0x00;
drv->cy = 0x0000;
if (!(drv->dr & IDEDEV_LBA)) {
drv->sn = 0x01;
}
else {
drv->sn = 0x00;
}
drv->status = IDESTAT_DRDY | IDESTAT_DSC;
drv->error = 0;
setintr(drv);
}
else {
cmdabort(drv);
}
break;
case 0x20: // read (with retry)
case 0x21: // read
TRACEOUT(("ideio: read sector"));
if (drv->device == IDETYPE_HDD) {
drv->mulcnt = 0;
drv->multhr = 1;
readsec(drv);
}
else {
cmdabort(drv);
}
break;
case 0x30: // write (with retry)
case 0x31: // write
TRACEOUT(("ideio: write sector"));
if (drv->device == IDETYPE_HDD) {
drv->mulcnt = 0;
drv->multhr = 1;
writesec(drv);
}
else {
cmdabort(drv);
}
break;
case 0x91: // set parameters
TRACEOUT(("ideio: set parameters dh=%x sec=%x",
drv->dr | drv->hd, drv->sc));
if (drv->device == IDETYPE_HDD) {
drv->surfaces = drv->hd + 1;
drv->sectors = drv->sc;
drv->status &= ~(IDESTAT_BSY | IDESTAT_DRQ | IDESTAT_ERR);
drv->status |= IDESTAT_DRDY;
setintr(drv);
}
else {
cmdabort(drv);
}
break;
case 0xa0: // send packet
TRACEOUT(("ideio: packet"));
if (drv->device == IDETYPE_CDROM) {
drv->sc &= ~(IDEINTR_REL | IDEINTR_IO);
drv->sc |= IDEINTR_CD;
drv->status &= ~(IDESTAT_BSY | IDESTAT_DMRD | IDESTAT_SERV | IDESTAT_CHK);
drv->status |= IDESTAT_DRQ;
drv->error = 0;
drv->bufpos = 0;
drv->bufsize = 12;
drv->bufdir = IDEDIR_OUT;
drv->buftc = IDETC_TRANSFEREND;
break;
}
cmdabort(drv);
break;
case 0xa1: // identify packet device
TRACEOUT(("ideio: identify packet device"));
if (drv->device == IDETYPE_CDROM && setidentify(drv) == SUCCESS) {
drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ;
drv->error = 0;
setintr(drv);
}
else {
cmdabort(drv);
}
break;
break;
case 0xc4: // read multiple
TRACEOUT(("ideio: read multiple"));
#if IDEIO_MULTIPLE_MAX > 0
if (drv->device == IDETYPE_HDD) {
drv->mulcnt = 0;
drv->multhr = drv->mulmode;
readsec(drv);
break;
}
#endif
cmdabort(drv);
break;
case 0xc5: // write multiple
TRACEOUT(("ideio: write multiple"));
#if IDEIO_MULTIPLE_MAX > 0
if (drv->device == IDETYPE_HDD) {
drv->mulcnt = 0;
drv->multhr = drv->mulmode;
writesec(drv);
break;
}
#endif
cmdabort(drv);
break;
case 0xc6: // set multiple mode
TRACEOUT(("ideio: set multiple mode"));
if (drv->device == IDETYPE_HDD) {
switch(drv->sc) {
#if IDEIO_MULTIPLE_MAX > 0
case 2: case 4: case 8: case 16: case 32: case 64: case 128:
if (drv->sc <= IDEIO_MULTIPLE_MAX) {
drv->mulmode = drv->sc;
setintr(drv);
break;
}
/*FALLTHROUGH*/
#endif
default:
cmdabort(drv);
break;
}
}
else {
cmdabort(drv);
}
break;
case 0xe7: // flush cache
TRACEOUT(("ideio: flush cache"));
drv->status = IDESTAT_DRDY;
drv->error = 0;
setintr(drv);
break;
case 0xec: // identify device
TRACEOUT(("ideio: identify device"));
if (drv->device == IDETYPE_HDD && setidentify(drv) == SUCCESS) {
drv->status = IDESTAT_DRDY | IDESTAT_DSC | IDESTAT_DRQ;
drv->error = 0;
setintr(drv);
}
else {
cmdabort(drv);
}
break;
case 0xef: // set features
TRACEOUT(("ideio: set features reg = %.2x", drv->wp));
cmdabort(drv);
break;
default:
panic("ideio: unknown command %.2x", dat);
break;
}
(void)port;
}
static void IOOUTCALL ideio_o74c(UINT port, REG8 dat) {
IDEDEV dev;
REG8 modify;
dev = getidedev();
if (dev == NULL) {
return;
}
modify = dev->drv[0].ctrl ^ dat;
dev->drv[0].ctrl = dat;
dev->drv[1].ctrl = dat;
if (modify & IDECTRL_SRST) {
if (dat & IDECTRL_SRST) {
dev->drv[0].status = 0;
dev->drv[0].error = 0;
dev->drv[1].status = 0;
dev->drv[1].error = 0;
}
else {
drvreset(&dev->drv[0]);
if (dev->drv[0].device == IDETYPE_HDD) {
dev->drv[0].status = IDESTAT_DRDY | IDESTAT_DSC;
dev->drv[0].error = IDEERR_AMNF;
}
drvreset(&dev->drv[1]);
if (dev->drv[1].device == IDETYPE_HDD) {
dev->drv[1].status = IDESTAT_DRDY | IDESTAT_DSC;
dev->drv[1].error = IDEERR_AMNF;
}
}
}
TRACEOUT(("ideio interrupt %sable", (dat & IDECTRL_NIEN) ? "dis" : "en"));
TRACEOUT(("ideio devctrl %.2x [%.4x:%.8x]", dat, CPU_CS, CPU_EIP));
(void)port;
}
static void IOOUTCALL ideio_o74e(UINT port, REG8 dat) {
TRACEOUT(("ideio %.4x,%.2x [%.4x:%.8x]", port, dat, CPU_CS, CPU_EIP));
(void)port;
(void)dat;
}
// ----
static REG8 IOINPCALL ideio_i642(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
drv->status &= ~IDESTAT_ERR;
TRACEOUT(("ideio get error %.2x [%.4x:%.8x]",
drv->error, CPU_CS, CPU_EIP));
return(drv->error);
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i644(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
TRACEOUT(("ideio get SC %.2x [%.4x:%.8x]", drv->sc, CPU_CS, CPU_EIP));
return(drv->sc);
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i646(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
TRACEOUT(("ideio get SN %.2x [%.4x:%.8x]", drv->sn, CPU_CS, CPU_EIP));
return(drv->sn);
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i648(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
TRACEOUT(("ideio get CYL %.4x [%.4x:%.8x]", drv->cy, CPU_CS, CPU_EIP));
return((UINT8)drv->cy);
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i64a(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
TRACEOUT(("ideio get CYH %.4x [%.4x:%.8x]", drv->cy, CPU_CS, CPU_EIP));
return((REG8)(drv->cy >> 8));
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i64c(UINT port) {
IDEDRV drv;
REG8 ret;
(void)port;
drv = getidedrv();
if (drv) {
ret = drv->dr | drv->hd;
TRACEOUT(("ideio get DRHD %.2x [%.4x:%.8x]", ret, CPU_CS, CPU_EIP));
return(ret);
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i64e(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
TRACEOUT(("ideio status %.2x [%.4x:%.8x]",
drv->status, CPU_CS, CPU_EIP));
if (!(drv->ctrl & IDECTRL_NIEN)) {
TRACEOUT(("ideio: resetirq"));
pic_resetirq(IDE_IRQ);
}
return(drv->status);
}
else {
return(0xff);
}
}
static REG8 IOINPCALL ideio_i74c(UINT port) {
IDEDRV drv;
(void)port;
drv = getidedrv();
if (drv) {
TRACEOUT(("ideio alt status %.2x [%.4x:%.8x]",
drv->status, CPU_CS, CPU_EIP));
return(drv->status);
}
else {
return(0xff);
}
}
// ---- data
void IOOUTCALL ideio_w16(UINT port, REG16 value) {
IDEDRV drv;
BYTE *p;
long sec;
drv = getidedrv();
if ((drv != NULL) &&
(drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_OUT)) {
p = drv->buf + drv->bufpos;
p[0] = (BYTE)value;
p[1] = (BYTE)(value >> 8);
TRACEOUT(("ide-data send %.4x (%.4x) [%.4x:%.8x]",
value, drv->bufpos, CPU_CS, CPU_EIP));
drv->bufpos += 2;
if (drv->bufpos >= drv->bufsize) {
drv->status &= ~IDESTAT_DRQ;
switch(drv->cmd) {
case 0x30:
case 0x31:
case 0xc5:
sec = getcursec(drv);
TRACEOUT(("writesec->drv %d sec %x cnt %d thr %d",
drv->sxsidrv, sec, drv->mulcnt, drv->multhr));
if (sxsi_write(drv->sxsidrv, sec, drv->buf, drv->bufsize)) {
TRACEOUT(("write error!"));
cmdabort(drv);
break;
}
drv->mulcnt++;
incsec(drv);
drv->sc--;
if (drv->sc) {
writesec(drv);
}
break;
case 0xa0:
TRACEOUT(("ideio: execute atapi packet command"));
atapicmd_a0(drv);
break;
}
}
}
(void)port;
}
REG16 IOINPCALL ideio_r16(UINT port) {
IDEDRV drv;
REG16 ret;
UINT8 *p;
(void)port;
drv = getidedrv();
if (drv == NULL) {
return(0xff);
}
ret = 0;
if ((drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_IN)) {
p = drv->buf + drv->bufpos;
ret = p[0] + (p[1] << 8);
TRACEOUT(("ide-data recv %.4x (%.4x) [%.4x:%.8x]",
ret, drv->bufpos, CPU_CS, CPU_EIP));
drv->bufpos += 2;
if (drv->bufpos >= drv->bufsize) {
drv->status &= ~IDESTAT_DRQ;
switch(drv->cmd) {
case 0x20:
case 0x21:
case 0xc4:
incsec(drv);
drv->sc--;
if (drv->sc) {
readsec(drv);
}
break;
case 0xa0:
if (drv->buftc == IDETC_ATAPIREAD) {
atapi_dataread(drv);
break;
}
drv->sc = IDEINTR_IO | IDEINTR_CD;
drv->status &= ~(IDESTAT_BSY | IDESTAT_SERV | IDESTAT_CHK);
drv->status |= IDESTAT_DRDY;
drv->error = 0;
setintr(drv);
break;
}
}
}
return(ret);
}
// ----
#if 1
static BRESULT SOUNDCALL playdevaudio(IDEDRV drv, SINT32 *pcm, UINT count) {
SXSIDEV sxsi;
UINT r;
const UINT8 *ptr;
SINT sampl;
SINT sampr;
sxsi = sxsi_getptr(drv->sxsidrv);
if ((sxsi == NULL) || (sxsi->devtype != SXSIDEV_CDROM) ||
(!(sxsi->flag & SXSIFLAG_READY))) {
drv->daflag = 0x14;
return(FAILURE);
}
while(count) {
r = min(count, drv->dabufrem);
if (r) {
count -= r;
ptr = drv->dabuf + 2352 - (drv->dabufrem * 4);
drv->dabufrem -= r;
do {
sampl = ((SINT8)ptr[1] << 8) + ptr[0];
sampr = ((SINT8)ptr[3] << 8) + ptr[2];
pcm[0] += sampl;
pcm[1] += sampr;
ptr += 4;
pcm += 2;
} while(--r);
}
if (count == 0) {
break;
}
if (drv->dalength == 0) {
drv->daflag = 0x13;
return(FAILURE);
}
if (sxsicd_readraw(sxsi, drv->dacurpos, drv->dabuf) != SUCCESS) {
drv->daflag = 0x14;
return(FAILURE);
}
drv->dalength--;
drv->dacurpos++;
drv->dabufrem = sizeof(drv->dabuf) / 4;
}
return(SUCCESS);
}
static void SOUNDCALL playaudio(void *hdl, SINT32 *pcm, UINT count) {
UINT bit;
IDEDRV drv;
bit = ideio.daplaying;
if (!bit) {
return;
}
if (bit & 4) {
drv = ideio.dev[1].drv + 0;
if (playdevaudio(drv, pcm, count) != SUCCESS) {
bit = bit & (~4);
}
}
ideio.daplaying = bit;
}
#endif
// ----
static void devinit(IDEDRV drv, REG8 sxsidrv) {
SXSIDEV sxsi;
ZeroMemory(drv, sizeof(_IDEDRV));
drv->sxsidrv = sxsidrv;
sxsi = sxsi_getptr(sxsidrv);
if ((sxsi != NULL) &&
(sxsi->devtype == SXSIDEV_HDD) && (sxsi->flag & SXSIFLAG_READY)) {
drv->status = IDESTAT_DRDY | IDESTAT_DSC;
drv->error = IDEERR_AMNF;
drv->device = IDETYPE_HDD;
drv->surfaces = sxsi->surfaces;
drv->sectors = sxsi->sectors;
drv->mulmode = IDEIO_MULTIPLE_MAX;
}
else if ((sxsi != NULL) && (sxsi->devtype == SXSIDEV_CDROM)) {
drv->device = IDETYPE_CDROM;
drvreset(drv);
drv->error = 0;
drv->media = IDEIO_MEDIA_EJECTABLE;
if (sxsi->flag & SXSIFLAG_READY) {
drv->media |= (IDEIO_MEDIA_CHANGED|IDEIO_MEDIA_LOADED);
}
drv->daflag = 0x15;
}
else {
drv->status = IDESTAT_ERR;
drv->error = IDEERR_TR0;
drv->device = IDETYPE_NONE;
}
}
void ideio_reset(const NP2CFG *pConfig) {
REG8 i;
IDEDRV drv;
ZeroMemory(&ideio, sizeof(ideio));
for (i=0; i<4; i++) {
drv = ideio.dev[i >> 1].drv + (i & 1);
devinit(drv, i);
}
CopyMemory(mem + 0xd0000, idebios, sizeof(idebios));
TRACEOUT(("use simulate ide.rom"));
(void)pConfig;
}
void ideio_bind(void) {
if (pccore.hddif & PCHDD_IDE) {
#if 1
sound_streamregist(NULL, (SOUNDCB)playaudio);
#endif
iocore_attachout(0x0430, ideio_o430);
iocore_attachout(0x0432, ideio_o430);
iocore_attachinp(0x0430, ideio_i430);
iocore_attachinp(0x0432, ideio_i430);
iocore_attachout(0x0642, ideio_o642);
iocore_attachout(0x0644, ideio_o644);
iocore_attachout(0x0646, ideio_o646);
iocore_attachout(0x0648, ideio_o648);
iocore_attachout(0x064a, ideio_o64a);
iocore_attachout(0x064c, ideio_o64c);
iocore_attachout(0x064e, ideio_o64e);
iocore_attachinp(0x0642, ideio_i642);
iocore_attachinp(0x0644, ideio_i644);
iocore_attachinp(0x0646, ideio_i646);
iocore_attachinp(0x0648, ideio_i648);
iocore_attachinp(0x064a, ideio_i64a);
iocore_attachinp(0x064c, ideio_i64c);
iocore_attachinp(0x064e, ideio_i64e);
iocore_attachout(0x074c, ideio_o74c);
iocore_attachout(0x074e, ideio_o74e);
iocore_attachinp(0x074c, ideio_i74c);
}
}
void ideio_notify(REG8 sxsidrv, UINT action) {
SXSIDEV sxsi;
IDEDRV drv;
REG8 i;
sxsi = sxsi_getptr(sxsidrv);
if ((sxsi == NULL)
|| (!(sxsi->flag & SXSIFLAG_READY))
|| (sxsi->devtype != SXSIDEV_CDROM)) {
return;
}
for (i=0; i<4; i++) {
drv = ideio.dev[i >> 1].drv + (i & 1);
if ((drv != NULL) && (drv->sxsidrv == sxsidrv)) {
goto do_notify;
}
}
return;
do_notify:
switch(action) {
case 1:
drv->media |= (IDEIO_MEDIA_CHANGED|IDEIO_MEDIA_LOADED);
if (sxsi->mediatype & SXSIMEDIA_DATA)
drv->media |= IDEIO_MEDIA_DATA;
if (sxsi->mediatype & SXSIMEDIA_AUDIO)
drv->media |= IDEIO_MEDIA_AUDIO;
break;
case 0:
drv->media &= ~(IDEIO_MEDIA_LOADED|IDEIO_MEDIA_COMBINE);
break;
}
}
#endif /* SUPPORT_IDEIO */
RetroPC.NET-CVS <cvs@retropc.net>