From 8314fb8819edf29b5fa3c7a450f3384600dd999d Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 6 Jan 2024 17:44:25 +0200 Subject: [PATCH] DraCo updates, floppy, unique ID, software interrupt support. --- draco.cpp | 103 +++++++++++++++++++++++++++++++++++++----------------- x86.cpp | 61 ++++++++++++++++++++++++-------- 2 files changed, 117 insertions(+), 47 deletions(-) diff --git a/draco.cpp b/draco.cpp index f5175c7f..2166ee66 100644 --- a/draco.cpp +++ b/draco.cpp @@ -152,7 +152,7 @@ static uae_u8 *dracorom; 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; @@ -186,6 +186,9 @@ static void draco_irq(void) irq |= 0x2000; } } + if (draco_intfrc & 1) { + irq |= 1; // software interrupt + } if (draco_svga_irq_state) { irq |= 0x0010; // INT3 } @@ -222,7 +225,7 @@ static uae_s8 draco_kdb_params; 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) { @@ -240,6 +243,7 @@ static void draco_keyboard_read(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; @@ -251,6 +255,7 @@ static void draco_keyboard_read(void) } 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; @@ -384,6 +389,25 @@ static void draco_1wire_rtc_validate(void) 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; @@ -394,22 +418,31 @@ static void draco_1wire_set_bit(void) } 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; } } } @@ -432,9 +465,9 @@ static void draco_1wire_read(void) 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; @@ -484,9 +517,19 @@ static void draco_1wire_send(int bit) } 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 { @@ -499,7 +542,6 @@ static void draco_1wire_send(int bit) #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) { @@ -761,7 +803,7 @@ static uae_u32 REGPARAM2 draco_bget(uaecptr addr) v = draco_intpen; break; case 0x800001: - v = 0; + v = draco_intfrc; break; case 0xc0001: v = 0; @@ -1011,9 +1053,7 @@ static void REGPARAM2 draco_bput(uaecptr addr, uae_u32 b) 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: @@ -1189,13 +1229,12 @@ void draco_reset(int hardreset) 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) diff --git a/x86.cpp b/x86.cpp index a25232be..dcbf3dc8 100644 --- a/x86.cpp +++ b/x86.cpp @@ -560,7 +560,7 @@ static struct pc_floppy floppy_pc[4]; 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]; @@ -570,6 +570,9 @@ static uae_u8 floppy_seekcyl[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 @@ -584,6 +587,7 @@ static void floppy_reset(void) 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. @@ -732,7 +736,7 @@ static void floppy_do_cmd(struct x86_bridge *xb) 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]); @@ -790,6 +794,10 @@ static void floppy_do_cmd(struct x86_bridge *xb) 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: @@ -910,15 +918,24 @@ static void floppy_do_cmd(struct x86_bridge *xb) 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) { @@ -928,13 +945,13 @@ static void floppy_do_cmd(struct x86_bridge *xb) 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; @@ -1070,7 +1087,7 @@ static void floppy_do_cmd(struct x86_bridge *xb) } end: - if (floppy_cmd_len) { + if (floppy_cmd_len > 0) { floppy_idx = -1; floppy_dir = 1; #if FLOPPY_DEBUG @@ -1207,10 +1224,10 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum) 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) @@ -1231,8 +1248,11 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum) 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++) { @@ -1241,7 +1261,12 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum) } 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]; @@ -1262,6 +1287,12 @@ static uae_u8 infloppy(struct x86_bridge *xb, int portnum) 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: -- 2.47.3