--- np2/cbus/ideio.c 2005/02/07 14:46:08 1.8 +++ np2/cbus/ideio.c 2007/11/03 00:00:19 1.15 @@ -11,6 +11,7 @@ #include "ideio.h" #include "atapicmd.h" #include "sxsi.h" +#include "sound.h" #include "idebios.res" @@ -49,7 +50,11 @@ static const char serial[] = "8249193411 static const char firm[] = "A5U.1200"; static const char model[] = "QUANTUM FIREBALL CR "; -static BOOL setidentify(IDEDRV drv) { +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]; @@ -58,49 +63,69 @@ static BOOL setidentify(IDEDRV drv) { UINT32 size; sxsi = sxsi_getptr(drv->sxsidrv); - if ((sxsi == NULL) || (sxsi->fname[0] == '\0')) { + if ((sxsi == NULL) || (!(sxsi->flag & SXSIFLAG_READY))) { return(FAILURE); } ZeroMemory(tmp, sizeof(tmp)); // とりあえず使ってる部分だけ - tmp[0] = 0x0040; - 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 (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 + tmp[47] = 0x8000 | IDEIO_MULTIPLE_MAX; // multiple #endif - tmp[49] = 0x0000; // LBA(1 << 9) - 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); + 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 + 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] = 0x0000; // DEVICE RESET(1 << 9) + 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++) { @@ -109,6 +134,7 @@ static BOOL setidentify(IDEDRV drv) { p += 2; } drv->bufdir = IDEDIR_IN; + drv->buftc = IDETC_TRANSFEREND; drv->bufpos = 0; drv->bufsize = 512; return(SUCCESS); @@ -131,6 +157,24 @@ static void cmdabort(IDEDRV drv) { 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]; @@ -163,7 +207,6 @@ static void incsec(IDEDRV drv) { drv->cy++; } else { - TRACEOUT(("ideio: incsec() LBA mode?")); drv->sn++; if (drv->sn) { return; @@ -188,7 +231,6 @@ static long getcursec(const IDEDRV drv) ret += (drv->sn - 1); } else { - TRACEOUT(("ideio: getcursec() LBA mode?")); ret = drv->sn; ret |= (drv->cy << 8); ret |= (drv->hd << 24); @@ -200,7 +242,7 @@ static void readsec(IDEDRV drv) { long sec; - if (!drv->device) { + if (drv->device != IDETYPE_HDD) { goto read_err; } sec = getcursec(drv); @@ -211,6 +253,7 @@ static void readsec(IDEDRV drv) { goto read_err; } drv->bufdir = IDEDIR_IN; + drv->buftc = IDETC_TRANSFEREND; drv->bufpos = 0; drv->bufsize = 512; @@ -226,6 +269,28 @@ 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); +} + // ---- @@ -341,8 +406,9 @@ static void IOOUTCALL ideio_o64c(UINT po static void IOOUTCALL ideio_o64e(UINT port, REG8 dat) { - IDEDRV drv; + IDEDRV drv, d; IDEDEV dev; + int i; // execute device diagnostic if (dat == 0x90) { @@ -350,30 +416,18 @@ static void IOOUTCALL ideio_o64e(UINT po TRACEOUT(("ideio: execute device diagnostic")); dev = getidedev(); if (dev) { - IDEDRV d; - int i; - for (i = 0; i < 2; i++) { d = dev->drv + i; - d->hd = 0x00; - d->sc = 0x01; - d->sn = 0x01; - d->cy = 0x0000; - d->status = IDESTAT_DRDY; + drvreset(d); d->error = 0x01; + if (dev->drv[i].device == IDETYPE_NONE) { + d->error = 0x00; + } if (i == 0) { - if (dev->drv[0].device == IDETYPE_NONE) { - d->error = 0x00; - } if (dev->drv[1].device == IDETYPE_NONE) { d->error |= 0x80; } } - else { - if (dev->drv[1].device == IDETYPE_NONE) { - d->error = 0x00; - } - } } } return; @@ -388,71 +442,76 @@ static void IOOUTCALL ideio_o64e(UINT po switch(dat) { case 0x08: // device reset TRACEOUT(("ideio: device reset")); - if (drv->device == IDETYPE_NONE) { - cmdabort(drv); - break; - } - else if (drv->device == IDETYPE_HDD) { - drv->hd = 0x00; - drv->sc = 0x01; - drv->sn = 0x01; - drv->cy = 0x0000; - } - else if (drv->device == IDETYPE_CDROM) { - drv->hd = 0x10; - drv->sc = 0x01; - drv->sn = 0x01; - drv->cy = 0xeb14; - } - drv->status = 0x00; + 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[0].device == IDETYPE_NONE) { - drv->error = 0x00; - } if (dev->drv[1].device == IDETYPE_NONE) { drv->error |= 0x80; } } - else { - if (dev->drv[1].device == IDETYPE_NONE) { - drv->error = 0x00; - } - } } setintr(drv); break; - case 0x10: // calibrate -// case 0x11: case 0x12: case 0x13: 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: calibrate")); - if (drv->device) { + 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 { - drv->status = IDESTAT_DRDY | IDESTAT_ERR; - drv->error = IDEERR_TR0; + cmdabort(drv); } - setintr(drv); break; case 0x20: // read (with retry) case 0x21: // read TRACEOUT(("ideio: read sector")); - drv->mulcnt = 0; - drv->multhr = 1; - readsec(drv); + 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_NONE) { + if (drv->device == IDETYPE_HDD) { drv->surfaces = drv->hd + 1; drv->sectors = drv->sc; drv->status &= ~(IDESTAT_BSY | IDESTAT_DRQ | IDESTAT_ERR); @@ -465,23 +524,25 @@ static void IOOUTCALL ideio_o64e(UINT po break; case 0xa0: // send packet + TRACEOUT(("ideio: packet")); if (drv->device == IDETYPE_CDROM) { - drv->status &= ~(IDESTAT_BSY | IDESTAT_DWF | IDESTAT_ERR); + 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; } - else { - cmdabort(drv); - } + cmdabort(drv); break; - case 0xa1: // identify - case 0xec: // identify - TRACEOUT(("ideio: identify")); - if (setidentify(drv) == SUCCESS) { + 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); @@ -490,21 +551,38 @@ static void IOOUTCALL ideio_o64e(UINT po cmdabort(drv); } break; + break; case 0xc4: // read multiple -#if IDEIO_MULTIPLE_MAX > 0 TRACEOUT(("ideio: read multiple")); - drv->mulcnt = 0; - drv->multhr = drv->mulmode; - readsec(drv); -#else +#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")); - switch(drv->sc) { + 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) { @@ -517,6 +595,29 @@ static void IOOUTCALL ideio_o64e(UINT po 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; @@ -552,11 +653,13 @@ static void IOOUTCALL ideio_o74c(UINT po dev->drv[1].error = 0; } else { - if (dev->drv[0].device) { + 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; } - if (dev->drv[1].device) { + 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; } @@ -721,21 +824,42 @@ static REG8 IOINPCALL ideio_i74c(UINT po void IOOUTCALL ideio_w16(UINT port, REG16 value) { IDEDRV drv; - UINT8 *p; + BYTE *p; + long sec; drv = getidedrv(); if ((drv != NULL) && (drv->status & IDESTAT_DRQ) && (drv->bufdir == IDEDIR_OUT)) { p = drv->buf + drv->bufpos; - p[0] = (UINT8)value; - p[1] = (UINT8)(value >> 8); - TRACEOUT(("ide-data send %4x (%.4x) [%.4x:%.8x]", + 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; } @@ -777,8 +901,12 @@ REG16 IOINPCALL ideio_r16(UINT port) { break; case 0xa0: + if (drv->buftc == IDETC_ATAPIREAD) { + atapi_dataread(drv); + break; + } drv->sc = IDEINTR_IO | IDEINTR_CD; - drv->status &= ~(IDESTAT_BSY | IDESTAT_DRQ | IDESTAT_ERR); + drv->status &= ~(IDESTAT_BSY | IDESTAT_SERV | IDESTAT_CHK); drv->status |= IDESTAT_DRDY; drv->error = 0; setintr(drv); @@ -792,20 +920,100 @@ REG16 IOINPCALL ideio_r16(UINT port) { // ---- +#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->fname[0] != '\0')) { - drv->sxsidrv = 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 = 1; + 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; @@ -814,7 +1022,7 @@ static void devinit(IDEDRV drv, REG8 sxs } } -void ideio_reset(void) { +void ideio_reset(const NP2CFG *pConfig) { REG8 i; IDEDRV drv; @@ -825,36 +1033,18 @@ void ideio_reset(void) { devinit(drv, i); } -#if 0 // CD-ROM test - drv = ideio.dev[1].drv; - drv->hd = 0; - drv->sc = 1; - drv->sn = 1; - drv->cy = 0xeb14; - drv->status = 0; - drv->error = 0; - drv->device = IDETYPE_CDROM; -#endif - -#if 0 - ideio.dev[0].drv[0].status = IDE_READY | IDE_SEEKCOMPLETE; - ideio.dev[0].drv[0].error = 1; - ideio.dev[1].drv[0].status = IDE_READY | IDE_SEEKCOMPLETE; - ideio.dev[1].drv[0].error = 1; - - ideio.dev[0].drv[0].sxsidrv = 0x00; - ideio.dev[0].drv[1].sxsidrv = 0x01; - ideio.dev[1].drv[0].sxsidrv = 0x02; - ideio.dev[1].drv[1].sxsidrv = 0x03; -#endif - 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); @@ -881,4 +1071,42 @@ void ideio_bind(void) { } } +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 */ +