static int dracoromsize;
static uae_u8 draco_revision, draco_cias;
-static uae_u8 draco_intena, draco_intpen, draco_svga_irq_state;
+static uae_u8 draco_intena, draco_intpen, draco_intfrc, draco_svga_irq_state;
static uae_u16 draco_timer, draco_timer_latch;
static bool draco_timer_latched;
static bool draco_fdc_intpen;
irq |= 0x2000;
}
}
+ if (draco_intfrc & 1) {
+ irq |= 1; // software interrupt
+ }
if (draco_svga_irq_state) {
irq |= 0x0010; // INT3
}
static uae_u16 draco_kbd_in_buffer[16];
static int draco_kbd_in_buffer_len;
-#define DRACO_KBD_POLL_VAL 96
+#define DRACO_KBD_POLL_VAL 48
static void draco_keyboard_reset(void)
{
uae_u8 v = draco_reg[3];
if (draco_kbd_poll > 0) {
+ do_cycles(CYCLE_UNIT * 8);
draco_kbd_poll--;
if (draco_kbd_poll == 0) {
draco_reg[3] &= ~DRSTAT_KBDCLKIN;
}
if (draco_kbd_poll < 0) {
+ do_cycles(CYCLE_UNIT * 8);
draco_kbd_poll++;
if (draco_kbd_poll == 0) {
draco_kbd_poll = DRACO_KBD_POLL_VAL;
draco_1wire_rtc_count();
}
+uint8_t draco_1wire_crc8(uint8_t *addr, uint8_t len)
+{
+ uint8_t crc = 0;
+ for (uint8_t i = 0; i < len; i++)
+ {
+ uint8_t inbyte = addr[i];
+ for (uint8_t j = 0; j < 8; j++)
+ {
+ uint8_t mix = (crc ^ inbyte) & 0x01;
+ crc >>= 1;
+ if (mix)
+ crc ^= 0x8C;
+
+ inbyte >>= 1;
+ }
+ }
+ return crc;
+}
+
static void draco_1wire_set_bit(void)
{
uae_u8 *dptr = NULL;
} else if (draco_1wire_cmd == DS_READ_SCRATCHPAD) {
dptr = draco_1wire_scratchpad;
maxlen = sizeof(draco_1wire_scratchpad);
+ } else if (draco_1wire_cmd == DS_ROM_READ) {
+ dptr = draco_1wire_rom;
+ maxlen = sizeof(draco_1wire_rom);
}
- if (dptr && draco_1wire_sram_offset >= 0 && draco_1wire_dir) {
- if (draco_1wire_rom_offset >= 0) {
- draco_1wire_dat = draco_1wire_rom[draco_1wire_rom_offset];
- uae_u8 bit = (draco_1wire_rom[draco_1wire_rom_offset] >> draco_1wire_cnt) & 1;
- draco_1wire_bit = bit != 0;
- } else {
- if (draco_1wire_sram_offset >= maxlen) {
- draco_1wire_dat = 0xff;
- draco_1wire_bit = true;
+ if (dptr && draco_1wire_rom_offset >= 0 && draco_1wire_dir) {
+ uae_u8 bit = 1;
+ draco_1wire_dat = 0xff;
+ if (draco_1wire_rom_offset < sizeof(draco_1wire_rom)) {
+ if (draco_1wire_rom_offset == 7) {
+ draco_1wire_dat = draco_1wire_crc8(draco_1wire_rom, sizeof(draco_1wire_rom) - 1);
} else {
- if (draco_1wire_sram_offset >= 0) {
- draco_1wire_dat = dptr[draco_1wire_sram_offset];
- uae_u8 bit = (dptr[draco_1wire_sram_offset] >> draco_1wire_cnt) & 1;
- draco_1wire_bit = bit != 0;
- }
+ draco_1wire_dat = draco_1wire_rom[draco_1wire_rom_offset];
+ }
+ bit = (draco_1wire_dat >> draco_1wire_cnt) & 1;
+ }
+ draco_1wire_bit = bit != 0;
+ } else if (dptr && draco_1wire_sram_offset >= 0 && draco_1wire_dir) {
+ if (draco_1wire_sram_offset >= maxlen) {
+ draco_1wire_dat = 0xff;
+ draco_1wire_bit = true;
+ } else {
+ if (draco_1wire_sram_offset >= 0) {
+ draco_1wire_dat = dptr[draco_1wire_sram_offset];
+ uae_u8 bit = (dptr[draco_1wire_sram_offset] >> draco_1wire_cnt) & 1;
+ draco_1wire_bit = bit != 0;
}
}
}
draco_1wire_cnt = 0;
draco_1wire_bytes++;
if (draco_1wire_rom_offset >= 0) {
- if (draco_1wire_rom_offset == sizeof(draco_1wire_rom)) {
- draco_1wire_rom_offset = -1;
- }
+ draco_1wire_rom_offset++;
+// if (draco_1wire_rom_offset == 8)
+// activate_debugger();
} else if (draco_1wire_cmd == DS_READ_SCRATCHPAD) {
if (draco_1wire_sram_offset == 2) {
draco_1wire_sram_offset = (draco_1wire_sram_offset_copy & 31) + 3;
}
if (draco_1wire_cnt == 8 && !draco_1wire_dir) {
bool gotcmd = false;
+ draco_1wire_cnt = 0;
if (!draco_1wire_state) {
draco_1wire_cmd = draco_1wire_data[0];
- if (draco_1wire_cmd != DS_ROM_SKIP) {
+ if (draco_1wire_cmd == DS_ROM_READ) {
+ draco_1wire_rom_offset = 0;
+ draco_1wire_dir = 1;
+ draco_1wire_bytes = 0;
+ draco_1wire_set_bit();
+#if ONEWIRE_DEBUG
+ write_log("draco received 1-wire ROM read command\n");
+#endif
+ return;
+ } else if (draco_1wire_cmd != DS_ROM_SKIP) {
draco_1wire_state = 1;
gotcmd = true;
} else {
#if ONEWIRE_DEBUG > 1
write_log("draco received 1-wire byte %02x, cnt %02x\n", draco_1wire_data[0], draco_1wire_bytes);
#endif
- draco_1wire_cnt = 0;
draco_1wire_bytes++;
// read data command + 2 address bytes
if (draco_1wire_cmd == DS_READ_MEMORY && draco_1wire_data[3] == DS_READ_MEMORY) {
v = draco_intpen;
break;
case 0x800001:
- v = 0;
+ v = draco_intfrc;
break;
case 0xc0001:
v = 0;
draco_irq();
break;
case 0x800001:
- if (b)
- write_log("draco interrupt 0x800001 write %02x\n", b);
- draco_intpen |= b & 15;
+ draco_intfrc = b & 1;
draco_irq();
break;
case 0xc00001:
draco_1wire_rtc_validate();
draco_1wire_rom[0] = 0x04;
draco_1wire_rom[1] = 1;
- draco_1wire_rom[2] = 2;
- draco_1wire_rom[3] = 3;
- draco_1wire_rom[4] = 4;
- draco_1wire_rom[5] = 5;
- draco_1wire_rom[6] = 6;
- draco_1wire_rom[7] = 0xaa;
-
+ draco_1wire_rom[2] = 0;
+ draco_1wire_rom[3] = 0;
+ draco_1wire_rom[4] = 0;
+ draco_1wire_rom[5] = 0;
+ draco_1wire_rom[6] = 0;
+ draco_1wire_rom[7] = 0;
}
void draco_init(void)
static uae_u8 floppy_dpc;
static uae_s8 floppy_idx;
static uae_u8 floppy_dir;
-static uae_u8 floppy_cmd_len;
+static uae_s8 floppy_cmd_len;
static uae_u8 floppy_cmd[16];
static uae_u8 floppy_result[16];
static uae_u8 floppy_status[4];
static int floppy_delay_hsync;
static bool floppy_did_reset;
static bool floppy_irq;
+static bool floppy_specify_pio;
+static uae_u8 *floppy_pio_buffer;
+static int floppy_pio_len, floppy_pio_cnt;
static uae_s8 floppy_rate;
#define PC_SEEK_DELAY 50
floppy_idx = 0;
floppy_dir = 0;
floppy_did_reset = true;
+ floppy_specify_pio = false;
if (xb->type == TYPE_2286) {
// apparently A2286 BIOS AT driver assumes
// floppy reset also resets IDE.
valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
#if FLOPPY_DEBUG
- if (floppy_cmd_len) {
+ if (floppy_cmd_len > 0) {
write_log(_T("Command: "));
for (int i = 0; i < floppy_cmd_len; i++) {
write_log(_T("%02x "), floppy_cmd[i]);
write_log(_T("Floppy%d Specify SRT=%d HUT=%d HLT=%d ND=%d\n"), floppy_num, floppy_cmd[1] >> 4, floppy_cmd[1] & 0x0f, floppy_cmd[2] >> 1, floppy_cmd[2] & 1);
#endif
floppy_delay_hsync = -5;
+ floppy_specify_pio = (floppy_cmd[2] & 1) != 0;
+ if (floppy_specify_pio && !floppy_pio_buffer) {
+ floppy_pio_buffer = xcalloc(uae_u8, 512 * 36);
+ }
break;
case 4:
bool end = false;
pcf->sector = floppy_cmd[4] - 1;
pcf->head = (floppy_cmd[1] & 4) ? 1 : 0;
+ floppy_pio_len = 0;
+ floppy_pio_cnt = 0;
+ uae_u8 *pioptr = floppy_pio_buffer;
while (!end) {
int len = 128 << floppy_cmd[5];
uae_u8 buf[512];
zfile_fseek(fr.img, (pcf->cyl * fr.secs * fr.heads + pcf->head * fr.secs + pcf->sector) * 512, SEEK_SET);
zfile_fread(buf, 1, 512, fr.img);
- for (int i = 0; i < 512 && i < len; i++) {
- int v = dma_channel_write(2, buf[i]);
- if (v < 0 || v > 65535)
- end = true;
+ if (floppy_specify_pio) {
+ memcpy(pioptr, buf, 512);
+ pioptr += 512;
+ floppy_pio_len += 512;
+ } else {
+ for (int i = 0; i < 512 && i < len; i++) {
+ int v = dma_channel_write(2, buf[i]);
+ if (v < 0 || v > 65535)
+ end = true;
+ }
}
pcf->sector++;
if (pcf->sector == eot) {
pcf->cyl++;
pcf->head ^= 1;
} else {
- break;
+ end = true;
}
}
if (pcf->sector >= fr.secs) {
pcf->sector = 0;
pcf->head ^= 1;
- break;
+ end = true;
}
}
floppy_result[3] = cyl;
}
end:
- if (floppy_cmd_len) {
+ if (floppy_cmd_len > 0) {
floppy_idx = -1;
floppy_dir = 1;
#if FLOPPY_DEBUG
if (xb->type < 0) {
struct floppy_reserved fr = { 0 };
bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
- v |= floppy_irq ? 0x80 : 0x00;
- v |= 0x40;
- v |= fr.wrprot ? 0 : 2;
- v |= fr.cyl == 0 ? 0 : 16;
+ v |= floppy_irq ? 0x80 : 0x00; // INT PENDING
+ v |= 0x40; // nDRV2
+ v |= fr.wrprot ? 0 : 2; // nWP
+ v |= fr.cyl == 0 ? 0 : 16; // nTRK0
}
break;
case 0x3f1: // PS/2 status B (draco)
v = 0;
if (!floppy_delay_hsync && (floppy_dpc & 4))
v |= 0x80;
- if (floppy_idx || floppy_delay_hsync)
+ if (floppy_idx || floppy_delay_hsync || floppy_pio_len) {
v |= 0x10;
+ if (floppy_pio_len)
+ v |= 0x20;
+ }
if ((v & 0x80) && floppy_dir)
v |= 0x40;
for (int i = 0; i < 4; i++) {
}
break;
case 0x3f5: // data reg
- if (floppy_cmd_len && floppy_dir) {
+ if (floppy_pio_len > 0 && floppy_pio_cnt < floppy_pio_len) {
+ v = floppy_pio_buffer[floppy_pio_cnt++];
+ if (floppy_pio_cnt >= floppy_pio_len) {
+ floppy_pio_len = 0;
+ }
+ } else if (floppy_cmd_len && floppy_dir) {
int idx = (-floppy_idx) - 1;
if (idx < sizeof floppy_result) {
v = floppy_result[idx];
v = 0x00;
if (valid_floppy && fr.disk_changed)
v = 0x80;
+ } else if (xb->type < 0) {
+ struct floppy_reserved fr = { 0 };
+ bool valid_floppy = disk_reserved_getinfo(floppy_num, &fr);
+ v = 0x00;
+ if (fr.disk_changed)
+ v = 0x80;
}
break;
default: