IDE DMA: Properly handle partial transfers, fixes ATAPI DMA in Windows 98 SE.
This commit is contained in:
@@ -117,7 +117,7 @@
|
||||
#define ROM_PATH_MCIDE "roms/hdd/xtide/ide_ps2 R1.1.bin"
|
||||
|
||||
typedef struct ide_bm_t {
|
||||
int (*dma)(uint8_t *data, int transfer_length, int out, void *priv);
|
||||
int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv);
|
||||
void (*set_irq)(uint8_t status, void *priv);
|
||||
void *priv;
|
||||
} ide_bm_t;
|
||||
@@ -1094,7 +1094,7 @@ ide_atapi_callback(ide_t *ide)
|
||||
if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 &&
|
||||
(bm != NULL) && bm->dma) {
|
||||
if (ide->sc->block_len == 0) {
|
||||
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, bm->priv);
|
||||
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, 0, bm->priv);
|
||||
|
||||
/* Underrun. */
|
||||
if (ret == 1)
|
||||
@@ -1102,6 +1102,7 @@ ide_atapi_callback(ide_t *ide)
|
||||
} else {
|
||||
ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos -
|
||||
ide->sc->block_len, ide->sc->block_len,
|
||||
ide->sc->sector_len * ide->sc->block_len,
|
||||
0, bm->priv);
|
||||
|
||||
if (ret == 1) {
|
||||
@@ -1144,14 +1145,16 @@ ide_atapi_callback(ide_t *ide)
|
||||
if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 &&
|
||||
(bm != NULL) && bm->dma) {
|
||||
if (ide->sc->block_len == 0) {
|
||||
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 1, bm->priv);
|
||||
ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, 0, 1, bm->priv);
|
||||
|
||||
/* Underrun. */
|
||||
if (ret == 1)
|
||||
ret = 3;
|
||||
} else {
|
||||
ret = bm->dma(ide->sc->temp_buffer + ide->sc->buffer_pos,
|
||||
ide->sc->block_len, 1, bm->priv);
|
||||
ide->sc->block_len,
|
||||
ide->sc->sector_len * ide->sc->block_len,
|
||||
1, bm->priv);
|
||||
|
||||
if (ret & 1) {
|
||||
if (ide->write != NULL)
|
||||
@@ -2392,7 +2395,7 @@ ide_callback(void *priv)
|
||||
err = UNC_ERR;
|
||||
} else if (!ide_boards[ide->board]->force_ata3 && bm->dma) {
|
||||
/* We should not abort - we should simply wait for the host to start DMA. */
|
||||
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, bm->priv);
|
||||
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, 0, bm->priv);
|
||||
if (ret == 2) {
|
||||
/* Bus master DMA disabled, simply wait for the host to enable DMA. */
|
||||
ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT;
|
||||
@@ -2500,7 +2503,7 @@ ide_callback(void *priv)
|
||||
else
|
||||
ide->sector_pos = 256;
|
||||
|
||||
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 1, bm->priv);
|
||||
ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, 1, bm->priv);
|
||||
|
||||
if (ret == 2) {
|
||||
/* Bus master DMA disabled, simply wait for the host to enable DMA. */
|
||||
@@ -3127,7 +3130,7 @@ ide_xtide_close(void)
|
||||
|
||||
void
|
||||
ide_set_bus_master(int board,
|
||||
int (*dma)(uint8_t *data, int transfer_length, int out, void *priv),
|
||||
int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv),
|
||||
void (*set_irq)(uint8_t status, void *priv), void *priv)
|
||||
{
|
||||
ide_bm_t *bm;
|
||||
|
||||
@@ -95,19 +95,19 @@ cmd646_set_irq_1(uint8_t status, void *priv)
|
||||
}
|
||||
|
||||
static int
|
||||
cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int out, void *priv)
|
||||
cmd646_bus_master_dma_0(uint8_t *data, int transfer_length, int total_length, int out, void *priv)
|
||||
{
|
||||
const cmd646_t *dev = (cmd646_t *) priv;
|
||||
|
||||
return sff_bus_master_dma(data, transfer_length, out, dev->bm[0]);
|
||||
return sff_bus_master_dma(data, transfer_length, total_length, out, dev->bm[0]);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int out, void *priv)
|
||||
cmd646_bus_master_dma_1(uint8_t *data, int transfer_length, int total_length, int out, void *priv)
|
||||
{
|
||||
const cmd646_t *dev = (cmd646_t *) priv;
|
||||
|
||||
return sff_bus_master_dma(data, transfer_length, out, dev->bm[1]);
|
||||
return sff_bus_master_dma(data, transfer_length, total_length, out, dev->bm[1]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -316,14 +316,14 @@ sff_bus_master_readl(uint16_t port, void *priv)
|
||||
}
|
||||
|
||||
int
|
||||
sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv)
|
||||
sff_bus_master_dma(uint8_t *data, int transfer_length, int total_length, int out, void *priv)
|
||||
{
|
||||
sff8038i_t *dev = (sff8038i_t *) priv;
|
||||
#ifdef ENABLE_SFF_LOG
|
||||
char *sop;
|
||||
#endif
|
||||
|
||||
int force_end = 0;
|
||||
int force_end = 0;
|
||||
int buffer_pos = 0;
|
||||
|
||||
#ifdef ENABLE_SFF_LOG
|
||||
@@ -365,9 +365,15 @@ sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv)
|
||||
return 1; /* This block has exhausted the data to transfer and it was smaller than the count, break. */
|
||||
} else {
|
||||
if (!transfer_length && !dev->eot) {
|
||||
sff_log("Total transfer length smaller than sum of all blocks, full block\n");
|
||||
dev->status &= ~2;
|
||||
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
|
||||
if (total_length) {
|
||||
sff_log("Total transfer length smaller than sum of all blocks, partial transfer\n");
|
||||
sff_bus_master_next_addr(dev);
|
||||
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
|
||||
} else {
|
||||
sff_log("Total transfer length smaller than sum of all blocks, full block\n");
|
||||
dev->status &= ~2;
|
||||
return 1; /* We have exhausted the data to transfer but there's more blocks left, break. */
|
||||
}
|
||||
} else if (transfer_length && dev->eot) {
|
||||
sff_log("Total transfer length greater than sum of all blocks\n");
|
||||
dev->status |= 2;
|
||||
|
||||
@@ -201,7 +201,7 @@ extern uint8_t ide_read_alt_status(uint16_t addr, void *priv);
|
||||
extern uint16_t ide_readw(uint16_t addr, void *priv);
|
||||
|
||||
extern void ide_set_bus_master(int board,
|
||||
int (*dma)(uint8_t *data, int transfer_length, int out, void *priv),
|
||||
int (*dma)(uint8_t *data, int transfer_length, int total_length, int out, void *priv),
|
||||
void (*set_irq)(uint8_t status, void *priv), void *priv);
|
||||
|
||||
extern void win_cdrom_eject(uint8_t id);
|
||||
|
||||
@@ -63,7 +63,7 @@ extern const device_t sff8038i_device;
|
||||
extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base);
|
||||
|
||||
extern void sff_bus_master_set_irq(uint8_t status, void *priv);
|
||||
extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int out, void *priv);
|
||||
extern int sff_bus_master_dma(uint8_t *data, int transfer_length, int total_length, int out, void *priv);
|
||||
|
||||
extern void sff_bus_master_write(uint16_t port, uint8_t val, void *priv);
|
||||
extern uint8_t sff_bus_master_read(uint16_t port, void *priv);
|
||||
|
||||
@@ -1096,6 +1096,8 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev)
|
||||
int msf = 0;
|
||||
int type = dev->sector_type;
|
||||
int flags = dev->sector_flags;
|
||||
int num = (dev->drv->bus_type == CDROM_BUS_SCSI) ?
|
||||
dev->requested_blocks : 1;
|
||||
|
||||
switch (dev->current_cdb[0]) {
|
||||
case GPCMD_READ_CD_MSF_OLD:
|
||||
@@ -1128,7 +1130,7 @@ scsi_cdrom_read_blocks(scsi_cdrom_t *dev)
|
||||
}
|
||||
|
||||
scsi_cdrom_log(dev->log, "Reading %i blocks starting from %i...\n",
|
||||
dev->requested_blocks, dev->sector_pos);
|
||||
num, dev->sector_pos);
|
||||
|
||||
ret = scsi_cdrom_read_data(dev, msf, type, flags, dev->vendor_type);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user