[haiku-commits] haiku: hrev47763 - src/add-ons/kernel/drivers/ports/pc_serial

  • From: revol@xxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 29 Aug 2014 15:23:26 +0200 (CEST)

hrev47763 adds 5 changesets to branch 'master'
old head: 9bc823ff5c02e0b7c7d39e6347e6f9d1d42b60c1
new head: a9ccc3a5ec748d2dc296cadb376f54baa7272c3b
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=a9ccc3a+%5E9bc823f

----------------------------------------------------------------------------

9ab4970: pc_serial: apply lcr parameters even when unmasking latch reg
  
  No need to change line params even more if it was already the same before.

e9bbba8: pc_serial: cache IER and temporarily mask IRQs until dpc done
  
  No need to be flooded by IRQs while filling in the FIFO...

6e7189d: pc_serial: toggle THRE in IER to make VirtualBox happy
  
  Not sure it's needed on real hardware yet.

b6708d7: pc_serial: wait for writes to complete on a sem
  
  This avoids close being called too early and discarding output.

a9ccc3a: pc_serial: mask THRE again when we're out of data

                                          [ François Revol <revol@xxxxxxx> ]

----------------------------------------------------------------------------

2 files changed, 48 insertions(+), 9 deletions(-)
.../drivers/ports/pc_serial/SerialDevice.cpp     | 56 ++++++++++++++++----
.../drivers/ports/pc_serial/SerialDevice.h       |  1 +

############################################################################

Commit:      9ab497059d919d817f65dbcb881a72f99bcb1f41
URL:         http://cgit.haiku-os.org/haiku/commit/?id=9ab4970
Author:      François Revol <revol@xxxxxxx>
Date:        Fri Aug 29 10:48:03 2014 UTC

pc_serial: apply lcr parameters even when unmasking latch reg

No need to change line params even more if it was already the same before.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp 
b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
index ad83803..37e558a 100644
--- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
+++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
@@ -161,7 +161,7 @@ SerialDevice::SetModes(struct termios *tios)
                WriteReg8(FCR, fcr);
 
                // unmask the divisor latch regs
-               WriteReg8(LCR, LCR_DLAB);
+               WriteReg8(LCR, lcr | LCR_DLAB);
                // set divisor
                WriteReg8(DLLB, divisor & 0x00ff);
                WriteReg8(DLHB, divisor >> 8);

############################################################################

Commit:      e9bbba8b847ca4ca5d13493a08dad81c33b9d443
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e9bbba8
Author:      François Revol <revol@xxxxxxx>
Date:        Fri Aug 29 11:37:31 2014 UTC

pc_serial: cache IER and temporarily mask IRQs until dpc done

No need to be flooded by IRQs while filling in the FIFO...

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp 
b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
index 37e558a..5082d1b 100644
--- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
+++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
@@ -29,6 +29,7 @@ SerialDevice::SerialDevice(const struct 
serial_support_descriptor *device,
                fIOBase(ioBase),
                fIRQ(irq),
                fMaster(master),
+               fCachedIER(0x0),
                fCachedIIR(0x1),
                fPendingDPC(0),
                fReadBufferAvail(0),
@@ -89,6 +90,10 @@ SerialDevice::Init()
        fReadBufferSem = create_sem(0, "pc_serial:done_read");
        fWriteBufferSem = create_sem(0, "pc_serial:done_write");
 
+       // disable IRQ
+       fCachedIER = 0;
+       WriteReg8(IER, fCachedIER);
+
        // disable DLAB
        WriteReg8(LCR, 0);
 
@@ -264,7 +269,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void 
*buffer, size_t length)
                                // remove the handler
                                remove_io_interrupt_handler(IRQ(), 
pc_serial_interrupt, this);
                                // disable IRQ
-                               WriteReg8(IER, 0);
+                               fCachedIER = 0;
+                               WriteReg8(IER, fCachedIER);
                                WriteReg8(MCR, 0);
                        }
 
@@ -277,7 +283,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void 
*buffer, size_t length)
                                // 
                                WriteReg8(MCR, MCR_DTR | MCR_RTS | MCR_IRQ_EN 
/*| MCR_LOOP*//*XXXXXXX*/);
                                // enable irqs
-                               WriteReg8(IER, IER_RLS | IER_MS | IER_RDA);
+                               fCachedIER = IER_RLS | IER_MS | IER_RDA;
+                               WriteReg8(IER, fCachedIER);
                                //WriteReg8(IER, IER_RDA);
                        }
 
@@ -330,7 +337,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void 
*buffer, size_t length)
                case TTYOSTART:
                        TRACE("TTYOSTART\n");
                        // enable irqs
-                       WriteReg8(IER, IER_RLS | IER_MS | IER_RDA | IER_THRE);
+                       fCachedIER |= IER_THRE;
+                       WriteReg8(IER, fCachedIER);
                        return true;
                case TTYOSYNC:
                        TRACE("TTYOSYNC\n");
@@ -366,8 +374,14 @@ SerialDevice::IsInterruptPending()
 
        bool pending = (fCachedIIR & IIR_PENDING) == 0;
 
-       if (pending)
+       if (pending) {
+               // temporarily mask the IRQ
+               // else VirtualBox triggers one per every written byte it seems
+               // not sure it's required on real hardware
+               WriteReg8(IER, fCachedIER & ~(IER_RLS | IER_MS | IER_RDA | 
IER_THRE));
+
                atomic_add(&fPendingDPC, 1);
+       }
 
        return pending; // 0 means yes
 }
@@ -487,6 +501,9 @@ SerialDevice::InterruptHandler()
 
        atomic_add(&fPendingDPC, -1);
 
+       // unmask IRQ
+       WriteReg8(IER, fCachedIER);
+
        TRACE_FUNCRET("< IRQ:%d\n", ret);
        return ret;
 }
diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h 
b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h
index 38fca92..3f9daf8 100644
--- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h
+++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.h
@@ -116,6 +116,7 @@ static      void                                    
InterruptCallbackFunction(void *cookie,
                //usb_serial_line_coding        fLineCoding;
 
                /* deferred interrupt */
+               uint8                                   fCachedIER;     // last 
value written to IER
                uint8                                   fCachedIIR;     // 
cached IRQ condition
                int32                                   fPendingDPC; // some 
IRQ still
 

############################################################################

Commit:      6e7189d9b2b41e673c79e0fe9056543ded7c3c82
URL:         http://cgit.haiku-os.org/haiku/commit/?id=6e7189d
Author:      François Revol <revol@xxxxxxx>
Date:        Fri Aug 29 11:43:20 2014 UTC

pc_serial: toggle THRE in IER to make VirtualBox happy

Not sure it's needed on real hardware yet.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp 
b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
index 5082d1b..883a0bb 100644
--- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
+++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
@@ -338,6 +338,8 @@ SerialDevice::Service(struct tty *tty, uint32 op, void 
*buffer, size_t length)
                        TRACE("TTYOSTART\n");
                        // enable irqs
                        fCachedIER |= IER_THRE;
+                       // XXX: toggle the bit to make VirtualBox happy !?
+                       WriteReg8(IER, fCachedIER & ~IER_THRE);
                        WriteReg8(IER, fCachedIER);
                        return true;
                case TTYOSYNC:

############################################################################

Commit:      b6708d7c47109f3e03d80211cdba141c43b95b43
URL:         http://cgit.haiku-os.org/haiku/commit/?id=b6708d7
Author:      François Revol <revol@xxxxxxx>
Date:        Fri Aug 29 13:00:57 2014 UTC

pc_serial: wait for writes to complete on a sem

This avoids close being called too early and discarding output.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp 
b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
index 883a0bb..e02917f 100644
--- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
+++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
@@ -62,6 +62,8 @@ SerialDevice::~SerialDevice()
 {
        Removed();
 
+       if (fDoneWrite >= B_OK)
+               delete_sem(fDoneWrite);
        if (fReadBufferSem >= B_OK)
                delete_sem(fReadBufferSem);
        if (fWriteBufferSem >= B_OK)
@@ -87,6 +89,7 @@ SerialDevice::Probe()
 status_t
 SerialDevice::Init()
 {
+       fDoneWrite = create_sem(0, "pc_serial:done_write");
        fReadBufferSem = create_sem(0, "pc_serial:done_read");
        fWriteBufferSem = create_sem(0, "pc_serial:done_write");
 
@@ -429,6 +432,11 @@ SerialDevice::InterruptHandler()
                                sizeof(readable));
                        TRACE("%s: FIONREAD: %d\n", __FUNCTION__, readable);
 
+                       if (readable == 0) {
+                               release_sem_etc(fDoneWrite, 1, 
B_DO_NOT_RESCHEDULE);
+                               break;
+                       }
+
                        bytesLeft = MIN(fifoavail, sizeof(buffer));
                        bytesLeft = MIN(bytesLeft, readable);
                        TRACE("%s: left %d\n", __FUNCTION__, bytesLeft);
@@ -619,6 +627,7 @@ SerialDevice::Write(const char *buffer, size_t *numBytes)
                return B_DEV_NOT_READY;
        }
 
+       status_t status;
        size_t bytesLeft = *numBytes;
        *numBytes = 0;
 
@@ -629,11 +638,11 @@ SerialDevice::Write(const char *buffer, size_t *numBytes)
                        // that isn't a problem, we shouldn't just hardcode the 
value here.
 
                TRACE("%s: tty_write(,&%d)\n", __FUNCTION__, length);
-               status_t result = gTTYModule->tty_write(fSystemTTYCookie, 
buffer,
+               status = gTTYModule->tty_write(fSystemTTYCookie, buffer,
                        &length);
-               if (result != B_OK) {
-                       TRACE_ALWAYS("failed to write to tty: %s\n", 
strerror(result));
-                       return result;
+               if (status != B_OK) {
+                       TRACE_ALWAYS("failed to write to tty: %s\n", 
strerror(status));
+                       return status;
                }
 
                buffer += length;
@@ -645,6 +654,14 @@ SerialDevice::Write(const char *buffer, size_t *numBytes)
                Service(fMasterTTY, TTYOSTART, NULL, 0);
        }
 
+       status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0);
+       if (status != B_OK) {
+               TRACE_ALWAYS("write: failed to get write done sem "
+                               "0x%08x\n", status);
+               return status;
+       }
+
+
        if (*numBytes > 0)
                return B_OK;
 

############################################################################

Revision:    hrev47763
Commit:      a9ccc3a5ec748d2dc296cadb376f54baa7272c3b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a9ccc3a
Author:      François Revol <revol@xxxxxxx>
Date:        Fri Aug 29 13:05:03 2014 UTC

pc_serial: mask THRE again when we're out of data

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp 
b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
index e02917f..7e482db 100644
--- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
+++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp
@@ -434,6 +434,8 @@ SerialDevice::InterruptHandler()
 
                        if (readable == 0) {
                                release_sem_etc(fDoneWrite, 1, 
B_DO_NOT_RESCHEDULE);
+                               // mask it until there's data again
+                               fCachedIER &= ~IER_THRE;
                                break;
                        }
 


Other related posts:

  • » [haiku-commits] haiku: hrev47763 - src/add-ons/kernel/drivers/ports/pc_serial - revol