]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
DraCo updates, floppy, unique ID, software interrupt support.
authorToni Wilen <twilen@winuae.net>
Sat, 6 Jan 2024 15:44:25 +0000 (17:44 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 6 Jan 2024 15:44:25 +0000 (17:44 +0200)
draco.cpp
x86.cpp

index f5175c7f22da520f8a74fdc138ad3448d1ac1710..2166ee663726c7b06e2cc37f596e27ddef166865 100644 (file)
--- 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 a25232be33d2b66d2978e5d823bc782cc78fdef2..dcbf3dc876624022faf445573e362340d2df7bee 100644 (file)
--- 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: