]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Serial port fix
authorToni Wilen <twilen@winuae.net>
Mon, 11 May 2026 14:02:09 +0000 (17:02 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 11 May 2026 14:02:09 +0000 (17:02 +0300)
custom.cpp
od-win32/parser.cpp
od-win32/serial_win32.cpp

index 3292b2fc9a91304e39d7b92a39ac482ec62d3bf3..778ce4b38f493c86e82514885215259ca2cd7273 100644 (file)
@@ -3179,9 +3179,13 @@ static void rethink_intreq(void)
        devices_rethink();
 }
 
-static void intreq_checks(uae_u16 oldreq, uae_u16 newreq)
+static void intreq_checks(uae_u16 req)
 {
-       serial_rbf_change((newreq & 0x0800) ? 1 : 0);
+#ifdef SERIAL_PORT
+       if (req & 0x0800) {
+               serial_rbf_change((req & 0x8000) != 0);
+       }
+#endif
 }
 
 static void event_doint_delay_do_ext_old(uae_u32 v)
@@ -3290,7 +3294,7 @@ static void INTREQ_nodelay(uae_u16 v)
        uae_u16 old = intreq;
        setclr(&intreq, v);
        intreq2 = intreq;
-       intreq_checks(old, intreq);
+       intreq_checks(v);
        doint();
 }
 
@@ -3299,17 +3303,17 @@ void INTREQ_f(uae_u16 v)
        uae_u16 old = intreq;
        setclr(&intreq, v);
        intreq2 = intreq;
-       intreq_checks(old, intreq);
+       intreq_checks(v);
 }
 
 bool INTREQ_0(uae_u16 v)
 {
        uae_u16 old = intreq;
        setclr(&intreq, v);
+       intreq_checks(v);
 
        if (old != intreq) {
                doint_delay_intreq(v);
-               intreq_checks(old, intreq);
        }
        return true;
 }
index cb167703f9cb4c5f6a28fc29624316d85561c7a4..24a3366cc6a4d087f8b491a887d9245dba2551ad 100644 (file)
@@ -907,7 +907,8 @@ static uae_u8 inputbuffer[SERIAL_READ_BUFFER];
 static int datainoutput;
 static int dataininput, dataininputcnt;
 static OVERLAPPED writeol, readol;
-static int writepending;
+static bool writepending;
+static int writepending_size;
 static bool breakpending;
 
 static WSADATA wsadata;
@@ -1087,7 +1088,7 @@ int openser (const TCHAR *sername)
        }
 
        SetCommMask (hCom, EV_RXFLAG | EV_BREAK);
-       SetupComm (hCom, 65536, 128);
+       SetupComm (hCom, 128, 128);
        PurgeComm (hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
        CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
        CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
@@ -1168,22 +1169,67 @@ void closeser (void)
        uartbreak = 0;
 }
 
-static void outser (void)
+static void outser(void)
 {
-       if (datainoutput <= 0)
-               return;
-       DWORD v = WaitForSingleObject (writeevent, 0);
-       if (v == WAIT_OBJECT_0) {
+       if (writepending) {
+               DWORD actual;
+               writepending = false;
+               if (GetOverlappedResult(hCom, &writeol, &actual, FALSE)) {
+                       if (actual < writepending_size) {
+                               if (actual) {
+                                       memmove(outputbufferout, outputbufferout + actual, writepending_size - actual);
+                                       writepending_size -= actual;
+                               }
+                               if (!WriteFile(hCom, outputbufferout, writepending_size, NULL, &writeol)) {
+                                       if (GetLastError() == ERROR_IO_PENDING) {
+                                               writepending = true;
+                                       }
+                               } else {
+                                       DWORD err = GetLastError();
+                                       write_log(_T("SERIAL: WriteFile failed (remaining write), err=%d\n"), err);
+                                       writepending_size = 0;
+                               }
+                       }
+               } else {
+                       writepending = false;
+                       writepending_size = 0;
+               }
+       }
+       if (!writepending && datainoutput > 0) {
+               writepending_size = 0;
+               memcpy(outputbufferout, outputbuffer, datainoutput);
+               if (!WriteFile(hCom, outputbufferout, datainoutput, NULL, &writeol)) {
+                       DWORD err = GetLastError();
+                       if (err == ERROR_IO_PENDING) {
+                               writepending_size = datainoutput;
+                               writepending = true;
+                               datainoutput = 0;
+                       } else {
+                               write_log(_T("SERIAL: WriteFile failed, err=%d\n"), err);
+                               datainoutput = 0;
+                       }
+               } else {
+                       datainoutput = 0;
+               }
+       }
+}
+
+static void writeser_waitpending(void)
+{
+       if (writepending) {
                DWORD actual;
-               memcpy (outputbufferout, outputbuffer, datainoutput);
-               WriteFile (hCom, outputbufferout, datainoutput, &actual, &writeol);
+               GetOverlappedResult(hCom, &writeol, &actual, TRUE);
+               writepending_size = 0;
                datainoutput = 0;
+               writepending = false;
        }
 }
 
 void writeser_flush(void)
 {
+       writeser_waitpending();
        outser();
+       writeser_waitpending();
 }
 
 void writeser (int c)
index e1efa80e625938ce34a3ff2854ed6b7f5da85c22..a0e3ff05bc857fde8c35602ab1c24f1dc3fb8626 100644 (file)
@@ -284,7 +284,7 @@ void SERPER (uae_u16 w)
                serial_period_receive_ccks = maxhpos;
                safe_receive = true;
        }
-       if (sermap_enabled || serxdevice_enabled) {
+       if (sermap_enabled || serxdevice_enabled || currprefs.m68k_speed < 0) {
                safe_receive = true;
        }
 
@@ -477,8 +477,9 @@ static void checkreceive_serial (void)
        static int ninebitdata;
        int recdata;
 
-       if (!canreceive())
+       if (!canreceive()) {
                return;
+       }
 
        if (ninebit) {
                bool breakcond;
@@ -1047,8 +1048,9 @@ uae_u16 SERDATR(void)
        if (!data_in_serdatr) {
                // interrupt was previously cleared but SERDATR was not read.
                // Clear it now when SERDATR was read.
-               INTREQ_f(1 << 11);
+               INTREQ_INT(11, 0);
        }
+       serdatr_last_got = 0;
        return serdatr;
 }