On 01/15/16 18:33, Ryan Harkin wrote: > On 15 January 2016 at 17:05, Laszlo Ersek <ler...@redhat.com> wrote: >> Hi, >> >> snipping context liberally... >> >>>>>>>>>>> Whilst simple text input seems to work ok, cursor support does not. >>>>>>>>>>> And we need cursor support for Intel BDS. >> >> (1) I think this is important. See below. >> >>> When trying to revert your patch on the latest trunk code, the build >>> fails because your patch is doing too many things in one step. It >>> should have been three (or more) patches, in my opinion. >> >> (2) >> >> (Caveat: what I'm about to say / reference here may not apply fully.) >> >> I just want to say that I followed / partially reviewed Star's patch series >> (earlier versions of it than v4), and I had the exact same impression (= >> "this is too big"), about the patch that did more or less the same for >> ArmVirtPkg. >> >> Surprisingly :), I was wrong. Please see the message of commit >> >> commit ad7f6bc2e1163125cdb26f6b0e6695554028626a >> Author: Star Zeng <star.z...@intel.com> >> Date: Thu Nov 26 08:52:12 2015 +0000 >> >> ArmVirtPkg: Use SerialDxe in MdeModulePkg instead of EmbeddedPkg >> >> Also, this sub-thread could be interesting: >> >> http://thread.gmane.org/gmane.comp.bios.edk2.devel/4582/focus=4593 >> > > I don't think this is the same as ARM platform support. I think there > could have been a single patch to move the code from ExtLib to Lib. > Another to remove ExtLib and another to change from to MdeModulePkg. > > >>> >>> Instead of reverting, I manually added back PL011SerialPortExtLib and >>> removed the code from PL011SerialPortLib at the same time. Then, the >>> code did not compile. >>> >>> So I changed my patch to also make PL011SerialPortLib return 0 instead >>> of calling the PL011 functions. And everything started to work. I >>> assumed this was because I added back the ExtLib, not because I >>> changed the added code. I was wrong. >>> >>> I've just pushed a new branch, serialdxe-fix-006, that only changes >>> PL011SerialPortLib.c to "return 0;" for all the new functions - and >>> that works also. >>> >>> So I don't need PL011SerialPortExtLib at all. I guess it was never >>> called from there? When you moved the code to PL011SerialPortLib, it >>> started getting called - and the code is causing problems. >>> >>> >>>> Could you check out to *SHA-1: 1b96428d92c01383dc437717db679f57cf70d980* >>>> that just before my SerialDxe series changes, and help to confirm if there >>>> is regression? >>>> >>> >>> I already checked out the commit before yours [1] and it works fine. >>> >>> [1] git checkout 921e987b2b26602dc85eaee856d494b97b6e02b0^ >> >> (3) Alright, so SVN r18974 (git 1bccab910700) is the commit that removes the >> old SerialDxe from EmbeddedPkg. At that stage, all client packages have been >> converted to the new driver in MdeModulePkg. Therefore, if we want to >> compare the two *drivers*, we have to check out the parent of this commit >> (that is, check out SVN r18973 == git 1bccab910700^ == git ad7f6bc2e1), and >> compare the following files: >> >> - EmbeddedPkg/SerialDxe/SerialIo.c >> - MdeModulePkg/Universal/SerialDxe/SerialIo.c >> >> I don't recommend to diff them -- instead, open them both side by side, and >> read them in parallel. >> >> This way I noticed the following difference: >> >> (a) In the EmbeddedPkg driver, we have the following *initial* values (not >> quoting everything, just what I think is relevant): >> >> EFI_SERIAL_IO_PROTOCOL.Mode->Timeout = 0 >> EFI_SERIAL_IO_PROTOCOL.Mode->ReceiveFifoDepth = 1 >> >> (see gSerialIoTemplate and gSerialIoMode), however the SerialReset() >> function (implementing the Reset protocol member) sets the following, >> different values: >> >> EFI_SERIAL_IO_PROTOCOL.Mode->Timeout = 1000000 >> EFI_SERIAL_IO_PROTOCOL.Mode->ReceiveFifoDepth = 0 >> >> Inconsistent, right? But that's not the difference I think is relevant: >> >> (b) The MdeModulePkg driver stores the following settings *both* at driver >> initialization and in SerialReset(): >> >> EFI_SERIAL_IO_PROTOCOL.Mode->Timeout = 0 >> EFI_SERIAL_IO_PROTOCOL.Mode->ReceiveFifoDepth = 1 >> >> (See mSerialIoTemplate and mSerialIoMode.) >> >> That is, the initial state for Mode is identical between the (a) old and (b) >> new drivers. However, these relevant-looking fields *differ* between old and >> new driver after a client calls EFI_SERIAL_IO_PROTOCOL.Reset(). Then the old >> driver sets a ReceiveFifoDepth of zero, while the new driver sets 1. (I'll >> ignore Timeout for now.) >> >> The UEFI spec says the following about ReceiveFifoDepth: >> >> ReceiveFifoDepth The number of characters the device will buffer on >> input. >> >> [...] >> >> The default attributes for all UART-style serial device interfaces >> are: 115,200 baud, a 1 byte receive FIFO, a 1,000,000 microsecond >> timeout per character, no parity, 8 data bits, and 1 stop bit. [...] >> >> Special care must be taken if a significant amount of data is going >> to be read from a serial device. Since UEFI drivers are polled mode >> drivers, characters received on a serial device might be missed. It >> is the responsibility of the software that uses the protocol to >> check for new data often enough to guarantee that no characters will >> be missed. The required polling frequency depends on the baud rate >> of the connection and the depth of the receive FIFO. >> >> Okay, thus far it seems that the *new* driver is the correct one; the old >> ReceiveFifoDepth=0 setting, after Reset() was incorrect. >> >> Let's see though if that zero value is special in some way. >> >> Both old and new drivers depend on SerialPortLib. If I understand correctly, >> this class is resolved in both cases to the >> ArmPlatformPkg/Library/PL011SerialPortLib instance. That instance in turn >> depends on PL011UartLib. >> >> PL011UartLib is resolved, by >> "ArmPlatformPkg/ArmVExpressPkg/ArmVExpress.dsc.inc", to >> "ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.inf". This DSC include file >> seems to be used by the Juno platform. So in the end we should look at how >> "ArmPlatformPkg/Drivers/PL011Uart" handles ReceiveFifoDepth. >> >> In PL011UartInitializePort(), we have: >> >> // The PL011 supports a buffer of 1, 16 or 32 chars. Therefore we can >> accept >> // 1 char buffer as the minimum fifo size. Because everything can be >> rounded down, >> // there is no maximum fifo size. >> if ((*ReceiveFifoDepth == 0) || (*ReceiveFifoDepth >= 32)) { >> LineControl |= PL011_UARTLCR_H_FEN; >> if (PL011_UARTPID2_VER (MmioRead32 (UartBase + UARTPID2)) > >> PL011_VER_R1P4) >> *ReceiveFifoDepth = 32; >> else >> *ReceiveFifoDepth = 16; >> } else { >> ASSERT (*ReceiveFifoDepth < 32); >> // Nothing else to do. 1 byte fifo is default. >> *ReceiveFifoDepth = 1; >> } >> >> Now, I didn't even *try* to trace the actual control flow, but, post-Reset(), >> - with the old driver we seem to have room for at least 16 characters in the >> receive FIFO, and the PL011_UARTLCR_H_FEN (== "FIFOs Enable") bit gets set, >> - whereas with the new driver, we end up with a single-byte buffer, and the >> "FIFOs Enable" bit is cleared in the line control register. >> >> I think this looks quite consistent with the facts that: >> - simple text input (= single byte "scan codes", with human-scale pauses >> between them) works, >> - but cursor movement (= multibyte escape sequences, produced in >> machine-scale bursts) breaks. >> >> (4) My opinion: >> >> - The new driver's ReceiveFifoDepth setting, on init and on Reset, is >> correct. (Conforms to the spec.) >> >> - The Timeout defaults seem wrong however: 1 million usecs should be set. >> >> - Whatever *uses* the Serial IO Protocol directly, should explicitly set >> some ReceiveFifoDepth (with the SetAttributes() member function), such that >> the depth accommodates the longest escape sequence that the client wishes to >> handle. I believe this requirement falls on the TerminalDxe driver, doesn't >> it? >> >> In any case, the explicitly configured FIFO depth can be "zero", apparently, >> for selecting the device's "default" FIFO depth. (See the documentation of >> SetAttributes()). >> >> (BTW, the SetAttributes() spec also explains the "everything can be rounded >> down" comment from PL011UartInitializePort(): "The nearest FIFO size >> supported by the serial device will be selected without exceeding the >> ReceiveFifoDepth parameter.") >> >> Ryan, can you please test the following patch? >> >>> diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c >>> b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c >>> index 6fde3b2..e1a6527 100644 >>> --- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c >>> +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c >>> @@ -806,7 +806,7 @@ TerminalDriverBindingStart ( >>> Status = TerminalDevice->SerialIo->SetAttributes ( >>> TerminalDevice->SerialIo, >>> Mode->BaudRate, >>> - Mode->ReceiveFifoDepth, >>> + 0, // device's default FIFO depth. >>> (UINT32) SerialInTimeOut, >>> (EFI_PARITY_TYPE) (Mode->Parity), >>> (UINT8) Mode->DataBits, >>> diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c >>> b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c >>> index 3be877b..ffdc8f2 100644 >>> --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c >>> +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c >>> @@ -547,7 +547,7 @@ TerminalConInTimerHandler ( >>> Status = SerialIo->SetAttributes ( >>> SerialIo, >>> Mode->BaudRate, >>> - Mode->ReceiveFifoDepth, >>> + 0, // device's default FIFO depth. >>> (UINT32) SerialInTimeOut, >>> (EFI_PARITY_TYPE) (Mode->Parity), >>> (UINT8) Mode->DataBits, >> > > Yes, this works for me.
Thanks for the testing (to Ard too)! > So what do you think the proper solution is? Is Ard's patch not what > you were thinking? I think the UEFI spec is clear enough on EFI_SERIAL_IO_PROTOCOL that we can derive what the right thing is: - SerialDxe needs a fix so that not only its ReceiveFifoDepth defaults are correct (beause they are correct now!), but also the Timeout defaults. - TerminalDxe needs a fix too: it should recognize the defaults set by SerialDxe (as per UEFI spec requirements), and set ReceiveFifoDepth explicitly, with a SetAttributes() call. A good value for that looks like zero (= device's default FIFO depth). I believe the value zero also happens to restore the previous behavior, in practice -- it's just not SerialDxe's responsibility. Thanks Laszlo > >> I expect the following call chain: >> >> TerminalDriverBindingStart() | TerminalConInTimerHandler() >> [MdeModulePkg/Universal/Console/TerminalDxe] >> SerialSetAttributes() >> [MdeModulePkg/Universal/SerialDxe/SerialIo.c] >> SerialPortSetAttributes() >> [ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.c] >> PL011UartInitializePort() >> [ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.c] >> >> Thanks! >> Laszlo _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel