openfirmware: Refactor console implementation following bootloader changes.

Confirmed working on sparc

Change-Id: I60bf82978ccf967e7e10611f6360cadccf22d15d
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4667
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Augustin Cavalier
2021-10-28 20:06:38 +00:00
committed by waddlesplash
parent 9aba9395e7
commit 7d41530f62
3 changed files with 76 additions and 97 deletions
@@ -9,9 +9,7 @@
#include <boot/vfs.h> #include <boot/vfs.h>
#ifdef __cplusplus class Handle : public Node {
class Handle : public ConsoleNode {
public: public:
Handle(intptr_t handle, bool takeOwnership = true); Handle(intptr_t handle, bool takeOwnership = true);
Handle(); Handle();
@@ -29,6 +27,4 @@ class Handle : public ConsoleNode {
bool fOwnHandle; bool fOwnHandle;
}; };
#endif /* __cplusplus */
#endif /* HANDLE_H */ #endif /* HANDLE_H */
@@ -18,59 +18,86 @@
#include "Handle.h" #include "Handle.h"
class ConsoleHandle : public Handle { class Console : public ConsoleNode {
public: public:
ConsoleHandle(); Console();
void SetHandles(intptr_t readHandle, intptr_t writeHandle, bool takeOwnership = true);
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
size_t bufferSize); size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
size_t bufferSize); size_t bufferSize);
};
class InputConsoleHandle : public ConsoleHandle { virtual void ClearScreen();
public: virtual int32 Width();
InputConsoleHandle(); virtual int32 Height();
virtual void SetCursor(int32 x, int32 y);
virtual void SetCursorVisible(bool visible);
virtual void SetColors(int32 foreground, int32 background);
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, void PutBackChar(char c);
size_t bufferSize); void PutBackChars(const char *buffer, int count);
void PutChar(char c);
void PutChars(const char *buffer, int count);
char GetChar(); char GetChar();
private: private:
enum { BUFFER_SIZE = 32 }; Handle fReadHandle, fWriteHandle;
char fBuffer[BUFFER_SIZE]; enum { BUFFER_SIZE = 32 };
char fReadBuffer[BUFFER_SIZE];
int fStart; int fStart;
int fCount; int fCount;
}; };
static InputConsoleHandle sInput; extern ConsoleNode* gConsoleNode;
static ConsoleHandle sOutput; static Console sConsole;
FILE *stdin, *stdout, *stderr; FILE *stdin, *stdout, *stderr;
ConsoleHandle::ConsoleHandle() Console::Console()
: :
Handle() ConsoleNode()
{ {
} }
void
Console::SetHandles(intptr_t readHandle, intptr_t writeHandle, bool takeOwnership)
{
fReadHandle.SetHandle(readHandle, takeOwnership);
fWriteHandle.SetHandle(readHandle, takeOwnership);
}
ssize_t ssize_t
ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer, Console::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
size_t bufferSize) size_t bufferSize)
{ {
// don't seek in character devices char *buffer = (char*)_buffer;
return of_read(fHandle, buffer, bufferSize);
// copy buffered bytes first
int bytesTotal = 0;
while (bufferSize > 0 && fCount > 0) {
*buffer++ = GetChar();
bytesTotal++;
bufferSize--;
}
// read from console
if (bufferSize > 0) {
ssize_t bytesRead = fReadHandle.ReadAt(NULL, -1, buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
bytesTotal += bytesRead;
}
return bytesTotal;
} }
ssize_t ssize_t
ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer, Console::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
size_t bufferSize) size_t bufferSize)
{ {
const char *string = (const char *)buffer; const char *string = (const char *)buffer;
@@ -96,7 +123,7 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
} }
if (length > 0) { if (length > 0) {
of_write(fHandle, string, length); fWriteHandle.WriteAt(NULL, -1, string, length);
string += length; string += length;
bufferSize -= length; bufferSize -= length;
} }
@@ -104,7 +131,7 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
if (newLine) { if (newLine) {
// this code replaces a single '\n' with '\r\n', so it // this code replaces a single '\n' with '\r\n', so it
// bumps the string/bufferSize only a single character // bumps the string/bufferSize only a single character
of_write(fHandle, "\r\n", 2); fWriteHandle.WriteAt(NULL, -1, "\r\n", 2);
string++; string++;
bufferSize--; bufferSize--;
} }
@@ -114,72 +141,34 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
} }
// #pragma mark -
InputConsoleHandle::InputConsoleHandle()
:
ConsoleHandle(),
fStart(0),
fCount(0)
{
}
ssize_t
InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
size_t bufferSize)
{
char *buffer = (char*)_buffer;
// copy buffered bytes first
int bytesTotal = 0;
while (bufferSize > 0 && fCount > 0) {
*buffer++ = GetChar();
bytesTotal++;
bufferSize--;
}
// read from console
if (bufferSize > 0) {
ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
bytesTotal += bytesRead;
}
return bytesTotal;
}
void void
InputConsoleHandle::PutChar(char c) Console::PutBackChar(char c)
{ {
if (fCount >= BUFFER_SIZE) if (fCount >= BUFFER_SIZE)
return; return;
int pos = (fStart + fCount) % BUFFER_SIZE; int pos = (fStart + fCount) % BUFFER_SIZE;
fBuffer[pos] = c; fReadBuffer[pos] = c;
fCount++; fCount++;
} }
void void
InputConsoleHandle::PutChars(const char *buffer, int count) Console::PutBackChars(const char *buffer, int count)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
PutChar(buffer[i]); PutBackChar(buffer[i]);
} }
char char
InputConsoleHandle::GetChar() Console::GetChar()
{ {
if (fCount == 0) if (fCount == 0)
return 0; return 0;
fCount--; fCount--;
char c = fBuffer[fStart]; char c = fReadBuffer[fStart];
fStart = (fStart + 1) % BUFFER_SIZE; fStart = (fStart + 1) % BUFFER_SIZE;
return c; return c;
} }
@@ -199,12 +188,12 @@ console_init(void)
return B_ERROR; return B_ERROR;
} }
sInput.SetHandle(input); sConsole.SetHandles(input, output);
sOutput.SetHandle(output); gConsoleNode = &sConsole;
// now that we're initialized, enable stdio functionality // now that we're initialized, enable stdio functionality
stdin = (FILE *)&sInput; stdin = (FILE *)gConsoleNode;
stdout = stderr = (FILE *)&sOutput; stdout = stderr = (FILE *)gConsoleNode;
return B_OK; return B_OK;
} }
@@ -214,12 +203,12 @@ console_init(void)
void void
console_clear_screen(void) Console::ClearScreen()
{ {
#ifdef __sparc__ #ifdef __sparc__
// Send both a clear screen (for serial terminal) and a vertical form // Send both a clear screen (for serial terminal) and a vertical form
// feed for on-screen console // feed for on-screen console
sOutput.Write("\014\033[2J", 5); Write("\014\033[2J", 5);
#else #else
of_interpret("erase-screen", 0, 0); of_interpret("erase-screen", 0, 0);
#endif #endif
@@ -227,7 +216,7 @@ console_clear_screen(void)
int32 int32
console_width(void) Console::Width()
{ {
intptr_t columnCount; intptr_t columnCount;
#ifdef __sparc__ #ifdef __sparc__
@@ -241,7 +230,7 @@ console_width(void)
int32 int32
console_height(void) Console::Height()
{ {
intptr_t lineCount; intptr_t lineCount;
#ifdef __sparc__ #ifdef __sparc__
@@ -255,13 +244,13 @@ console_height(void)
void void
console_set_cursor(int32 x, int32 y) Console::SetCursor(int32 x, int32 y)
{ {
#ifdef __sparc__ #ifdef __sparc__
char buffer[11]; char buffer[11];
int len = snprintf(buffer, sizeof(buffer), int len = snprintf(buffer, sizeof(buffer),
"\033[%" B_PRId32 ";%" B_PRId32 "H", y, x); "\033[%" B_PRId32 ";%" B_PRId32 "H", y, x);
sOutput.Write(buffer, len); Write(buffer, len);
#else #else
// Note: We toggle the cursor temporarily to prevent a cursor artifact at // Note: We toggle the cursor temporarily to prevent a cursor artifact at
// at the old location. // at the old location.
@@ -275,13 +264,7 @@ console_set_cursor(int32 x, int32 y)
void void
console_show_cursor(void) Console::SetCursorVisible(bool visible)
{
}
void
console_hide_cursor(void)
{ {
} }
@@ -317,14 +300,14 @@ translate_color(int32 color)
void void
console_set_color(int32 foreground, int32 background) Console::SetColors(int32 foreground, int32 background)
{ {
#ifdef __sparc__ #ifdef __sparc__
// Sadly it seems we can only get inverse video, nothing else seems to work // Sadly it seems we can only get inverse video, nothing else seems to work
if (background != 0) if (background != 0)
sOutput.Write("\033[7m", 4); Write("\033[7m", 4);
else else
sOutput.Write("\033[0m", 4); Write("\033[0m", 4);
#else #else
// Note: Toggling the cursor doesn't seem to help. We still get cursor // Note: Toggling the cursor doesn't seem to help. We still get cursor
// artifacts. // artifacts.
@@ -369,7 +352,7 @@ console_wait_for_key(void)
char buffer[3]; char buffer[3];
ssize_t bytesRead; ssize_t bytesRead;
do { do {
bytesRead = sInput.ReadAt(NULL, 0, buffer, 3); bytesRead = sConsole.ReadAt(NULL, 0, buffer, 3);
if (bytesRead < 0) if (bytesRead < 0)
return 0; return 0;
} while (bytesRead == 0); } while (bytesRead == 0);
@@ -383,7 +366,7 @@ console_wait_for_key(void)
// put back unread chars // put back unread chars
if (bytesRead > 1) if (bytesRead > 1)
sInput.PutChars(buffer + 1, bytesRead - 1); sConsole.PutBackChars(buffer + 1, bytesRead - 1);
return buffer[0]; return buffer[0];
} }
@@ -393,7 +376,7 @@ int
console_check_for_key(void) console_check_for_key(void)
{ {
char buffer[3]; char buffer[3];
ssize_t bytesRead = sInput.ReadAt(NULL, 0, buffer, 3); ssize_t bytesRead = sConsole.ReadAt(NULL, 0, buffer, 3);
if (bytesRead <= 0) if (bytesRead <= 0)
return 0; return 0;
@@ -406,7 +389,7 @@ console_check_for_key(void)
// put back unread chars // put back unread chars
if (bytesRead > 1) if (bytesRead > 1)
sInput.PutChars(buffer + 1, bytesRead - 1); sConsole.PutBackChars(buffer + 1, bytesRead - 1);
return buffer[0]; return buffer[0];
} }