{
for (int i = 0; ide_boards[i]; i++) {
struct ide_board *board = ide_boards[i];
+ if (board->hsync_cnt > 0) {
+ board->hsync_cnt--;
+ if (!board->hsync_cnt && board->hsync_code)
+ board->hsync_code(board);
+ }
if (board->configured) {
for (int j = 0; j < MAX_IDE_PORTS_BOARD; j++) {
if (board->ide[j]) {
reg |= IDE_SECONDARY;
return reg;
}
+static void masoboshi_ide_dma(struct ide_board *board)
+{
+ board->state2[0] |= 0x80;
+}
static int get_adide_reg(uaecptr addr, struct ide_board *board)
{
v = board->rom[addr & board->rom_mask];
rom = true;
}
- } else if (addr >= 0xf000 && addr <= 0xf007) {
+ } else if ((addr >= 0xf000 && addr <= 0xf00f) || (addr >= 0xf100 && addr <= 0xf10f)) {
+ // scsi dma controller
if (board->subtype)
v = masoboshi_ncr9x_scsi_get(oaddr, getidenum(board, masoboshi_board));
} else if (addr == 0xf040) {
if (board->irq) {
v &= ~1;
}
- v |= masoboshi_ncr9x_scsi_get(oaddr, getidenum(board, masoboshi_board));
+ v |= board->state2[0] &0x80;
} else if (addr == 0xf047) {
v = board->state;
} else {
v = board->rom[addr & board->rom_mask] << 8;
v |= board->rom[(addr + 1) & board->rom_mask];
}
+ } else if (addr == 0xf04c || addr == 0xf14c) {
+ v = board->dma_ptr >> 16;
+ } else if (addr == 0xf04e || addr == 0xf14e) {
+ v = board->dma_ptr;
+ write_log(_T("MASOBOSHI IDE DMA PTR READ = %08x %08x\n"), board->dma_ptr, M68K_GETPC);
+ } else if (addr == 0xf04a || addr == 0xf14a) {
+ v = board->dma_cnt;
+ write_log(_T("MASOBOSHI IDE DMA LEN READ = %04x %08x\n"), board->dma_cnt, v, M68K_GETPC);
} else {
int regnum = get_masoboshi_reg(addr, board);
if (regnum == IDE_DATA) {
} else if ((addr >= 0xf000 && addr <= 0xf007)) {
if (board->subtype)
masoboshi_ncr9x_scsi_put(oaddr, v, getidenum(board, masoboshi_board));
- } else if (addr >= 0xf04a && addr <= 0xf04f) {
- // dma controller
+ } else if (addr >= 0xf00a && addr <= 0xf00f) {
+ // scsi dma controller
masoboshi_ncr9x_scsi_put(oaddr, v, getidenum(board, masoboshi_board));
- } else if (addr >= 0xf040 && addr < 0xf048) {
- masoboshi_ncr9x_scsi_put(oaddr, v, getidenum(board, masoboshi_board));
- if (addr == 0xf047) {
- board->state = v;
- board->intena = (v & 8) != 0;
- }
- if (addr == 0xf040) {
- board->irq = false;
+ } else if (addr >= 0xf040 && addr <= 0xf04f) {
+ // ide dma controller
+ if (addr >= 0xf04c && addr < 0xf050) {
+ int shift = (3 - (addr - 0xf04c)) * 8;
+ uae_u32 mask = 0xff << shift;
+ board->dma_ptr &= ~mask;
+ board->dma_ptr |= v << shift;
+ board->dma_ptr &= 0xffffff;
+ } else if (addr >= 0xf04a && addr < 0xf04c) {
+ if (addr == 0xf04a) {
+ board->dma_cnt &= 0x00ff;
+ board->dma_cnt |= v << 8;
+ } else {
+ board->dma_cnt &= 0xff00;
+ board->dma_cnt |= v;
+ }
+ } else if (addr >= 0xf040 && addr < 0xf048) {
+ board->state2[addr - 0xf040] = v;
+ board->state2[0] &= ~0x80;
+ if (addr == 0xf047) {
+ board->state = v;
+ board->intena = (v & 8) != 0;
+ // masoboshi ide dma
+ if (v & 0x80) {
+ board->hsync_code = masoboshi_ide_dma;
+ board->hsync_cnt = (board->dma_cnt / maxhpos) * 2 + 1;
+ write_log(_T("MASOBOSHI IDE DMA %s start %08x, %d\n"), (board->state2[5] & 0x80) ? _T("READ") : _T("WRITE"), board->dma_ptr, board->dma_cnt);
+ if (ide_drq_check(board->ide[0])) {
+ if (!(board->state2[5] & 0x80)) {
+ for (int i = 0; i < board->dma_cnt; i++) {
+ put_ide_reg(board, IDE_DATA, get_word(board->dma_ptr & ~1));
+ board->dma_ptr += 2;
+ }
+ } else {
+ for (int i = 0; i < board->dma_cnt; i++) {
+ put_word(board->dma_ptr & ~1, get_ide_reg(board, IDE_DATA));
+ board->dma_ptr += 2;
+ }
+ }
+ board->dma_cnt = 0;
+ }
+ }
+ }
+ if (addr == 0xf040) {
+ board->state2[0] &= ~0x80;
+ board->irq = false;
+ }
}
- write_log(_T("MASOBOSHI STATUS BYTE PUT %08x %02x %08x\n"), addr, v, M68K_GETPC);
}
} else if (board->type == APOLLO_IDE) {
s->current_req = scsiesp_req_new(current_lun, 0, lun, buf, s);
datalen = scsiesp_req_enqueue(s->current_req);
s->ti_size = datalen;
+ s->transfer_complete = 0;
if (datalen != 0) {
s->rregs[ESP_RSTAT] = 0;
if (s->dma) {
if (s->dma) {
s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
- s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
+ s->rregs[ESP_RINTR] = INTR_FC;
s->rregs[ESP_RSEQ] = SEQ_CD;
} else {
s->ti_size = 2;
s->ti_rptr = 0;
s->ti_wptr = 0;
- //s->rregs[ESP_RFLAGS] = 2;
+ s->rregs[ESP_RSTAT] |= STAT_MI;
+ s->rregs[ESP_RINTR] = INTR_FC;
}
esp_raise_irq(s);
}
static void esp_dma_done(ESPState *s)
{
+ s->transfer_complete = 1;
s->rregs[ESP_RSTAT] |= STAT_TC;
s->rregs[ESP_RINTR] = INTR_BS;
s->rregs[ESP_RSEQ] = 0;
- //s->rregs[ESP_RFLAGS] = 0;
s->rregs[ESP_TCLO] = 0;
s->rregs[ESP_TCMID] = 0;
s->rregs[ESP_TCHI] = 0;
len2 = len;
s->dma_pending = len2;
if (to_device) {
- len = s->dma_memory_read(s->dma_opaque, s->async_buf, len2);
+ len = s->dma_memory_read(s->dma_opaque, s->async_buf, len2);
+ // if dma counter is larger than transfer size, fill the FIFO
+ // Masoboshi needs this.
+ if (len < 0) {
+ int diff = s->dma_counter - (len2 + s->dma_len);
+ if (diff > TI_BUFSZ)
+ diff = TI_BUFSZ;
+ if (diff > 0) {
+ s->dma_memory_read(s->dma_opaque, s->ti_buf, diff);
+ s->ti_rptr = 0;
+ s->ti_size = diff;
+ s->ti_wptr = diff;
+ s->fifo_on = 3;
+ }
+ }
} else {
len = s->dma_memory_write(s->dma_opaque, s->async_buf, len2);
}
if (len < 0)
len = len2;
s->dma_left -= len;
+ s->dma_len += len;
s->async_buf += len;
s->async_len -= len;
if (to_device)
return 1;
}
+void esp_fake_dma_put(void *opaque, uint8_t v)
+{
+ ESPState *s = (ESPState*)opaque;
+ if (s->transfer_complete) {
+ if (!s->fifo_on) {
+ s->fifo_on = 1;
+ s->ti_rptr = s->ti_wptr = 0;
+ s->ti_size = 0;
+ }
+ esp_reg_write(opaque, ESP_FIFO, v);
+ } else {
+ esp_dma_enable(opaque, 1);
+ }
+}
+
void esp_fake_dma_done(void *opaque)
{
ESPState *s = (ESPState*)opaque;
s->dma_pending = 0;
s->dma_left -= len;
+ s->dma_len += len;
s->async_buf += len;
s->async_len -= len;
if (to_device)
size_t resid)
{
ESPState *s = (ESPState*)req->hba_private;
+ bool dma = s->dma != 0;
- s->fifo_on = 0;
- s->ti_size = 0;
+ if (s->fifo_on != 3) {
+ s->fifo_on = 0;
+ s->ti_size = 0;
+ }
s->dma_left = 0;
s->dma_pending = 0;
s->async_len = 0;
fas408_check(s);
s->rregs[ESP_RSTAT] = STAT_ST;
esp_dma_done(s);
+ // TC is not set if transfer stopped due to phase change, not counter becoming zero.
+ if (dma && s->dma_len < s->dma_counter)
+ s->rregs[ESP_RSTAT] &= ~STAT_TC;
if (s->current_req) {
scsiesp_req_unref(s->current_req);
s->current_req = NULL;
uint32_t dmalen, minlen;
s->fifo_on = 1;
+ s->transfer_complete = 0;
fas408_check(s);
else
minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
if (s->dma) {
- if (s->dma == 1)
+ if (s->dma == 1) {
s->dma_left = minlen;
+ s->dma_len = 0;
+ }
s->dma = 2;
s->rregs[ESP_RSTAT] &= ~STAT_TC;
if (!esp_do_dma(s)) {
else
v = s->ti_size;
}
- if (!s->dma && v > 1 && s->fifo_on != 2)
+ if (!s->dma && v > 1 && s->fifo_on < 2)
v = 1;
return v | (s->rregs[ESP_RSEQ] << 5);
}
break;
case ESP_FIFO:
if (s->do_cmd) {
+ if (s->cmdlen >= TI_BUFSZ)
+ return;
s->cmdbuf[s->cmdlen++] = val & 0xff;
- } else if (s->ti_size == TI_BUFSZ - 1) {
- ;
} else {
+ if (s->ti_wptr >= TI_BUFSZ)
+ return;
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
}
break;
case CMD_ICCS:
write_response(s);
- s->rregs[ESP_RINTR] = INTR_FC;
- s->rregs[ESP_RSTAT] |= STAT_MI;
break;
case CMD_MSGACC:
s->rregs[ESP_RINTR] = INTR_DC;