* Cleanup, no functional change.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34142 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2009-11-19 22:00:24 +00:00
parent a9591c50fd
commit a8b3406203

View File

@ -1,14 +1,17 @@
/* /*
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
// This file could be moved into a generic tty module. // This file could be moved into a generic tty module.
// The whole hardware signaling stuff is missing, though - it's currently // The whole hardware signaling stuff is missing, though - it's currently
// tailored for pseudo-TTYs. Have a look at Be's TTY includes (drivers/tty/*) // tailored for pseudo-TTYs. Have a look at Be's TTY includes (drivers/tty/*)
#include "tty_private.h"
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
@ -24,8 +27,6 @@
#include <tty.h> #include <tty.h>
#include "tty_private.h"
//#define TTY_TRACE //#define TTY_TRACE
#ifdef TTY_TRACE #ifdef TTY_TRACE
@ -96,13 +97,21 @@ static void tty_notify_if_available(struct tty *tty, struct tty *otherTTY,
class AbstractLocker { class AbstractLocker {
public: public:
AbstractLocker(tty_cookie *cookie) : fCookie(cookie), fBytes(0) {} AbstractLocker(tty_cookie* cookie)
:
fCookie(cookie),
fBytes(0)
{
}
size_t AvailableBytes() const { return fBytes; } size_t AvailableBytes() const
{ return fBytes; }
protected: protected:
void Lock() { mutex_lock(fCookie->tty->lock); } void Lock()
void Unlock() { mutex_unlock(fCookie->tty->lock); } { mutex_lock(fCookie->tty->lock); }
void Unlock()
{ mutex_unlock(fCookie->tty->lock); }
tty_cookie* fCookie; tty_cookie* fCookie;
size_t fBytes; size_t fBytes;
@ -114,7 +123,8 @@ class WriterLocker : public AbstractLocker {
WriterLocker(tty_cookie* sourceCookie); WriterLocker(tty_cookie* sourceCookie);
~WriterLocker(); ~WriterLocker();
status_t AcquireWriter(bool dontBlock, size_t bytesNeeded); status_t AcquireWriter(bool dontBlock,
size_t bytesNeeded);
private: private:
size_t _CheckAvailableBytes() const; size_t _CheckAvailableBytes() const;
@ -132,7 +142,8 @@ class ReaderLocker : public AbstractLocker {
ReaderLocker(tty_cookie* cookie); ReaderLocker(tty_cookie* cookie);
~ReaderLocker(); ~ReaderLocker();
status_t AcquireReader(bigtime_t timeout, size_t minBytes); status_t AcquireReader(bigtime_t timeout,
size_t minBytes);
status_t AcquireReader(bool dontBlock); status_t AcquireReader(bool dontBlock);
private: private:
@ -329,8 +340,7 @@ RequestOwner::RequestOwner()
} }
/** /*! The caller must already hold the request lock.
* The caller must already hold the request lock.
*/ */
void void
RequestOwner::Enqueue(tty_cookie* cookie, RequestQueue* queue1, RequestOwner::Enqueue(tty_cookie* cookie, RequestQueue* queue1,
@ -358,8 +368,7 @@ RequestOwner::Enqueue(tty_cookie *cookie, RequestQueue *queue1,
} }
/** /*! The caller must already hold the request lock.
* The caller must already hold the request lock.
*/ */
void void
RequestOwner::Dequeue() RequestOwner::Dequeue()
@ -387,8 +396,7 @@ RequestOwner::SetBytesNeeded(size_t bytesNeeded)
} }
/** /*! The request lock MUST NOT be held!
* The request lock MUST NOT be held!
*/ */
status_t status_t
RequestOwner::Wait(bool interruptable, bigtime_t timeout) RequestOwner::Wait(bool interruptable, bigtime_t timeout)
@ -495,7 +503,8 @@ RequestOwner::NotifyError(Request *request, status_t error)
WriterLocker::WriterLocker(tty_cookie* sourceCookie) WriterLocker::WriterLocker(tty_cookie* sourceCookie)
: AbstractLocker(sourceCookie), :
AbstractLocker(sourceCookie),
fSource(fCookie->tty), fSource(fCookie->tty),
fTarget(fCookie->other_tty), fTarget(fCookie->other_tty),
fRequestOwner(), fRequestOwner(),
@ -646,7 +655,8 @@ WriterLocker::_CheckBackgroundWrite() const
ReaderLocker::ReaderLocker(tty_cookie* cookie) ReaderLocker::ReaderLocker(tty_cookie* cookie)
: AbstractLocker(cookie), :
AbstractLocker(cookie),
fTTY(cookie->tty), fTTY(cookie->tty),
fRequestOwner() fRequestOwner()
{ {
@ -837,9 +847,9 @@ tty_output_getc(struct tty *tty, int *_c)
} }
/** Processes the input character and puts it into the TTY's input buffer. /*! Processes the input character and puts it into the TTY's input buffer.
* Depending on the termios flags set, signals may be sent, the input Depending on the termios flags set, signals may be sent, the input
* character changed or removed, etc. character changed or removed, etc.
*/ */
static void static void
tty_input_putc_locked(struct tty* tty, int c) tty_input_putc_locked(struct tty* tty, int c)
@ -984,8 +994,7 @@ uninit_tty_cookie(tty_cookie *cookie)
} }
/** /*! The global lock must be held.
* The global lock must be held.
*/ */
void void
add_tty_cookie(tty_cookie* cookie) add_tty_cookie(tty_cookie* cookie)
@ -998,8 +1007,7 @@ add_tty_cookie(tty_cookie *cookie)
} }
/** /*! The global lock must be held.
* The global lock must be held.
*/ */
void void
tty_close_cookie(struct tty_cookie* cookie) tty_close_cookie(struct tty_cookie* cookie)
@ -1128,15 +1136,15 @@ tty_notify_select_event(struct tty *tty, uint8 event)
} }
/** \brief Checks whether bytes can be read from/written to the line buffer of /*! \brief Checks whether bytes can be read from/written to the line buffer of
* the given TTY and notifies the respective queues. the given TTY and notifies the respective queues.
*
* Also sends out \c B_SELECT_READ and \c B_SELECT_WRITE events as needed. Also sends out \c B_SELECT_READ and \c B_SELECT_WRITE events as needed.
*
* The TTY and the request lock must be held. The TTY and the request lock must be held.
*
* \param tty The TTY. \param tty The TTY.
* \param otherTTY The connected TTY. \param otherTTY The connected TTY.
*/ */
static void static void
tty_notify_if_available(struct tty* tty, struct tty* otherTTY, tty_notify_if_available(struct tty* tty, struct tty* otherTTY,
@ -1169,8 +1177,7 @@ tty_notify_if_available(struct tty *tty, struct tty *otherTTY,
} }
/*! /*! \brief Performs input character conversion and writes the result to
\brief Performs input character conversion and writes the result to
\a buffer. \a buffer.
\param tty The master tty. \param tty The master tty.
\param c The input character. \param c The input character.
@ -1216,7 +1223,7 @@ process_input_char(struct tty* tty, char c, char* buffer,
} else if (c == '\n') { } else if (c == '\n') {
if (flags & INLCR) // NL -> CR if (flags & INLCR) // NL -> CR
c = '\r'; c = '\r';
} else if (flags & ISTRIP) // strip of eighth bit } else if ((flags & ISTRIP) != 0) // strip off eighth bit
c &= 0x7f; c &= 0x7f;
*buffer = c; *buffer = c;
@ -1224,8 +1231,8 @@ process_input_char(struct tty* tty, char c, char* buffer,
return true; return true;
} }
/*!
\brief Performs output character conversion and writes the result to /*! \brief Performs output character conversion and writes the result to
\a buffer. \a buffer.
\param tty The master tty. \param tty The master tty.
\param c The output character. \param c The output character.
@ -1293,8 +1300,269 @@ process_output_char(struct tty* tty, char c, char* buffer,
} }
// #pragma mark - static status_t
// device functions tty_write_to_tty_master_unsafe(tty_cookie* sourceCookie, const char* data,
size_t* _length)
{
struct tty* source = sourceCookie->tty;
struct tty* target = sourceCookie->other_tty;
size_t length = *_length;
size_t bytesWritten = 0;
uint32 mode = sourceCookie->open_mode;
bool dontBlock = (mode & O_NONBLOCK) != 0;
// bail out, if source is already closed
TTYReference sourceTTYReference(sourceCookie);
if (!sourceTTYReference.IsLocked())
return B_FILE_ERROR;
if (length == 0)
return B_OK;
WriterLocker locker(sourceCookie);
// if the target is not open, fail now
if (target->open_count <= 0)
return B_FILE_ERROR;
bool echo = (source->settings->termios.c_lflag & ECHO) != 0;
TRACE(("tty_write_to_tty_master(source = %p, target = %p, "
"length = %lu%s)\n", source, target, length,
(echo ? ", echo mode" : "")));
// Make sure we are first in the writer queue(s) and AvailableBytes() is
// initialized.
status_t status = locker.AcquireWriter(dontBlock, 0);
if (status != B_OK) {
*_length = 0;
return status;
}
size_t writable = locker.AvailableBytes();
size_t writtenSinceLastNotify = 0;
while (bytesWritten < length) {
// fetch next char and do input processing
char c;
size_t bytesNeeded;
if (!process_input_char(source, *data, &c, &bytesNeeded)) {
// input char shall be skipped
data++;
bytesWritten++;
continue;
}
// If in echo mode, we do the output conversion and need to update
// the needed bytes count.
char echoBuffer[3];
size_t echoBytes;
if (echo) {
process_output_char(source, c, echoBuffer, &echoBytes, true);
if (echoBytes > bytesNeeded)
bytesNeeded = echoBytes;
}
// If there's not enough space to write what we have, we need to wait
// until it is available.
if (writable < bytesNeeded) {
if (writtenSinceLastNotify > 0) {
tty_notify_if_available(target, source, true);
if (echo)
tty_notify_if_available(source, target, true);
writtenSinceLastNotify = 0;
}
status = locker.AcquireWriter(dontBlock, bytesNeeded);
if (status != B_OK) {
*_length = bytesWritten;
return status;
}
writable = locker.AvailableBytes();
// XXX: do we need to support VMIN & VTIME for write() ?
// We need to restart the loop, since the termios flags might have
// changed in the meantime (while we've unlocked the tty). Note,
// that we don't re-get "echo" -- maybe we should.
continue;
}
// write the bytes
tty_input_putc_locked(target, c);
if (echo) {
for (size_t i = 0; i < echoBytes; i++)
line_buffer_putc(source->input_buffer, echoBuffer[i]);
}
writable -= bytesNeeded;
data++;
bytesWritten++;
writtenSinceLastNotify++;
}
return B_OK;
}
static status_t
tty_write_to_tty_slave_unsafe(tty_cookie* sourceCookie, const char* data,
size_t* _length)
{
struct tty* target = sourceCookie->other_tty;
size_t length = *_length;
size_t bytesWritten = 0;
uint32 mode = sourceCookie->open_mode;
bool dontBlock = (mode & O_NONBLOCK) != 0;
// bail out, if source is already closed
TTYReference sourceTTYReference(sourceCookie);
if (!sourceTTYReference.IsLocked())
return B_FILE_ERROR;
if (length == 0)
return B_OK;
WriterLocker locker(sourceCookie);
// if the target is not open, fail now
if (target->open_count <= 0)
return B_FILE_ERROR;
TRACE(("tty_write_to_tty_slave(source = %p, target = %p, length = %lu)\n",
sourceCookie->tty, target, length));
// Make sure we are first in the writer queue(s) and AvailableBytes() is
// initialized.
status_t status = locker.AcquireWriter(dontBlock, 0);
if (status != B_OK) {
*_length = 0;
return status;
}
size_t writable = locker.AvailableBytes();
size_t writtenSinceLastNotify = 0;
while (bytesWritten < length) {
// fetch next char and do output processing
char buffer[3];
size_t bytesNeeded;
process_output_char(target, *data, buffer, &bytesNeeded, false);
// If there's not enough space to write what we have, we need to wait
// until it is available.
if (writable < bytesNeeded) {
if (writtenSinceLastNotify > 0) {
tty_notify_if_available(target, sourceCookie->tty, true);
writtenSinceLastNotify = 0;
}
status = locker.AcquireWriter(dontBlock, bytesNeeded);
if (status != B_OK) {
*_length = bytesWritten;
return status;
}
writable = locker.AvailableBytes();
// We need to restart the loop, since the termios flags might have
// changed in the meantime (while we've unlocked the tty).
continue;
}
// write the bytes
for (size_t i = 0; i < bytesNeeded; i++)
line_buffer_putc(target->input_buffer, buffer[i]);
writable -= bytesNeeded;
data++;
bytesWritten++;
writtenSinceLastNotify++;
}
return B_OK;
}
static void
dump_tty_settings(struct tty_settings& settings)
{
kprintf(" pgrp_id: %ld\n", settings.pgrp_id);
kprintf(" session_id: %ld\n", settings.session_id);
kprintf(" termios:\n");
kprintf(" c_iflag: 0x%08lx\n", settings.termios.c_iflag);
kprintf(" c_oflag: 0x%08lx\n", settings.termios.c_oflag);
kprintf(" c_cflag: 0x%08lx\n", settings.termios.c_cflag);
kprintf(" c_lflag: 0x%08lx\n", settings.termios.c_lflag);
kprintf(" c_line: %d\n", settings.termios.c_line);
kprintf(" c_ispeed: %u\n", settings.termios.c_ispeed);
kprintf(" c_ospeed: %u\n", settings.termios.c_ospeed);
for (int i = 0; i < NCCS; i++)
kprintf(" c_cc[%02d]: %d\n", i, settings.termios.c_cc[i]);
kprintf(" wsize: %u x %u c, %u x %u pxl\n",
settings.window_size.ws_row, settings.window_size.ws_col,
settings.window_size.ws_xpixel, settings.window_size.ws_ypixel);
}
static void
dump_tty_struct(struct tty& tty)
{
kprintf(" tty @: %p\n", &tty);
kprintf(" index: %ld\n", tty.index);
kprintf(" is_master: %s\n", tty.is_master ? "true" : "false");
kprintf(" open_count: %ld\n", tty.open_count);
kprintf(" select_pool: %p\n", tty.select_pool);
kprintf(" pending_eof: %lu\n", tty.pending_eof);
kprintf(" lock: %p\n", tty.lock);
kprintf(" input_buffer:\n");
kprintf(" first: %ld\n", tty.input_buffer.first);
kprintf(" in: %lu\n", tty.input_buffer.in);
kprintf(" size: %lu\n", tty.input_buffer.size);
kprintf(" buffer: %p\n", tty.input_buffer.buffer);
kprintf(" reader queue:\n");
tty.reader_queue.Dump(" ");
kprintf(" writer queue:\n");
tty.writer_queue.Dump(" ");
kprintf(" cookies: ");
TTYCookieList::Iterator it = tty.cookies.GetIterator();
while (tty_cookie* cookie = it.Next())
kprintf(" %p", cookie);
kprintf("\n");
}
static int
dump_tty(int argc, char** argv)
{
if (argc < 2) {
kprintf("Usage: %s <tty index>\n", argv[0]);
return 0;
}
int32 index = atol(argv[1]);
if (index < 0 || index >= (int32)kNumTTYs) {
kprintf("Invalid tty index.\n");
return 0;
}
kprintf("master:\n");
dump_tty_struct(gMasterTTYs[index]);
kprintf("slave:\n");
dump_tty_struct(gSlaveTTYs[index]);
kprintf("settings:\n");
dump_tty_settings(gTTYSettings[index]);
return 0;
}
// #pragma mark - device functions
status_t status_t
@ -1343,7 +1611,7 @@ tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer, size_t length)
// values marked BeOS are non-standard codes we support for legacy apps // values marked BeOS are non-standard codes we support for legacy apps
switch (op) { switch (op) {
/* blocking/non-blocking mode */ // blocking/non-blocking mode
case B_SET_BLOCKING_IO: case B_SET_BLOCKING_IO:
cookie->open_mode &= ~O_NONBLOCK; cookie->open_mode &= ~O_NONBLOCK;
@ -1352,7 +1620,7 @@ tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer, size_t length)
cookie->open_mode |= O_NONBLOCK; cookie->open_mode |= O_NONBLOCK;
return B_OK; return B_OK;
/* get and set TTY attributes */ // get and set TTY attributes
case TCGETA: case TCGETA:
TRACE(("tty: get attributes\n")); TRACE(("tty: get attributes\n"));
@ -1370,7 +1638,7 @@ tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer, size_t length)
return user_memcpy(&tty->settings->termios, buffer, return user_memcpy(&tty->settings->termios, buffer,
sizeof(struct termios)); sizeof(struct termios));
/* get and set process group ID */ // get and set process group ID
case TIOCGPGRP: case TIOCGPGRP:
TRACE(("tty: get pgrp_id\n")); TRACE(("tty: get pgrp_id\n"));
@ -1392,7 +1660,7 @@ tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer, size_t length)
return error; return error;
} }
/* get and set window size */ // get and set window size
case TIOCGWINSZ: case TIOCGWINSZ:
TRACE(("tty: set window size\n")); TRACE(("tty: set window size\n"));
@ -1601,112 +1869,6 @@ tty_input_read(tty_cookie *cookie, void *buffer, size_t *_length)
} }
static status_t
tty_write_to_tty_master_unsafe(tty_cookie *sourceCookie, const char *data,
size_t *_length)
{
struct tty *source = sourceCookie->tty;
struct tty *target = sourceCookie->other_tty;
size_t length = *_length;
size_t bytesWritten = 0;
uint32 mode = sourceCookie->open_mode;
bool dontBlock = (mode & O_NONBLOCK) != 0;
// bail out, if source is already closed
TTYReference sourceTTYReference(sourceCookie);
if (!sourceTTYReference.IsLocked())
return B_FILE_ERROR;
if (length == 0)
return B_OK;
WriterLocker locker(sourceCookie);
// if the target is not open, fail now
if (target->open_count <= 0)
return B_FILE_ERROR;
bool echo = (source->settings->termios.c_lflag & ECHO) != 0;
TRACE(("tty_write_to_tty_master(source = %p, target = %p, "
"length = %lu%s)\n", source, target, length,
(echo ? ", echo mode" : "")));
// Make sure we are first in the writer queue(s) and AvailableBytes() is
// initialized.
status_t status = locker.AcquireWriter(dontBlock, 0);
if (status != B_OK) {
*_length = 0;
return status;
}
size_t writable = locker.AvailableBytes();
size_t writtenSinceLastNotify = 0;
while (bytesWritten < length) {
// fetch next char and do input processing
char c;
size_t bytesNeeded;
if (!process_input_char(source, *data, &c, &bytesNeeded)) {
// input char shall be skipped
data++;
bytesWritten++;
continue;
}
// If in echo mode, we do the output conversion and need to update
// the needed bytes count.
char echoBuffer[3];
size_t echoBytes;
if (echo) {
process_output_char(source, c, echoBuffer, &echoBytes, true);
if (echoBytes > bytesNeeded)
bytesNeeded = echoBytes;
}
// If there's not enough space to write what we have, we need to wait
// until it is available.
if (writable < bytesNeeded) {
if (writtenSinceLastNotify > 0) {
tty_notify_if_available(target, source, true);
if (echo)
tty_notify_if_available(source, target, true);
writtenSinceLastNotify = 0;
}
status = locker.AcquireWriter(dontBlock, bytesNeeded);
if (status != B_OK) {
*_length = bytesWritten;
return status;
}
writable = locker.AvailableBytes();
// XXX: do we need to support VMIN & VTIME for write() ?
// We need to restart the loop, since the termios flags might have
// changed in the meantime (while we've unlocked the tty). Note,
// that we don't re-get "echo" -- maybe we should.
continue;
}
// write the bytes
tty_input_putc_locked(target, c);
if (echo) {
for (size_t i = 0; i < echoBytes; i++)
line_buffer_putc(source->input_buffer, echoBuffer[i]);
}
writable -= bytesNeeded;
data++;
bytesWritten++;
writtenSinceLastNotify++;
}
return B_OK;
}
status_t status_t
tty_write_to_tty_master(tty_cookie* sourceCookie, const void* _buffer, tty_write_to_tty_master(tty_cookie* sourceCookie, const void* _buffer,
size_t* _length) size_t* _length)
@ -1742,84 +1904,6 @@ tty_write_to_tty_master(tty_cookie *sourceCookie, const void *_buffer,
} }
static status_t
tty_write_to_tty_slave_unsafe(tty_cookie *sourceCookie, const char *data,
size_t *_length)
{
struct tty *target = sourceCookie->other_tty;
size_t length = *_length;
size_t bytesWritten = 0;
uint32 mode = sourceCookie->open_mode;
bool dontBlock = (mode & O_NONBLOCK) != 0;
// bail out, if source is already closed
TTYReference sourceTTYReference(sourceCookie);
if (!sourceTTYReference.IsLocked())
return B_FILE_ERROR;
if (length == 0)
return B_OK;
WriterLocker locker(sourceCookie);
// if the target is not open, fail now
if (target->open_count <= 0)
return B_FILE_ERROR;
TRACE(("tty_write_to_tty_slave(source = %p, target = %p, length = %lu)\n",
sourceCookie->tty, target, length));
// Make sure we are first in the writer queue(s) and AvailableBytes() is
// initialized.
status_t status = locker.AcquireWriter(dontBlock, 0);
if (status != B_OK) {
*_length = 0;
return status;
}
size_t writable = locker.AvailableBytes();
size_t writtenSinceLastNotify = 0;
while (bytesWritten < length) {
// fetch next char and do output processing
char buffer[3];
size_t bytesNeeded;
process_output_char(target, *data, buffer, &bytesNeeded, false);
// If there's not enough space to write what we have, we need to wait
// until it is available.
if (writable < bytesNeeded) {
if (writtenSinceLastNotify > 0) {
tty_notify_if_available(target, sourceCookie->tty, true);
writtenSinceLastNotify = 0;
}
status = locker.AcquireWriter(dontBlock, bytesNeeded);
if (status != B_OK) {
*_length = bytesWritten;
return status;
}
writable = locker.AvailableBytes();
// We need to restart the loop, since the termios flags might have
// changed in the meantime (while we've unlocked the tty).
continue;
}
// write the bytes
for (size_t i = 0; i < bytesNeeded; i++)
line_buffer_putc(target->input_buffer, buffer[i]);
writable -= bytesNeeded;
data++;
bytesWritten++;
writtenSinceLastNotify++;
}
return B_OK;
}
status_t status_t
tty_write_to_tty_slave(tty_cookie* sourceCookie, const void* _buffer, tty_write_to_tty_slave(tty_cookie* sourceCookie, const void* _buffer,
size_t* _length) size_t* _length)
@ -1957,83 +2041,6 @@ tty_deselect(tty_cookie *cookie, uint8 event, selectsync *sync)
} }
static void
dump_tty_settings(struct tty_settings& settings)
{
kprintf(" pgrp_id: %ld\n", settings.pgrp_id);
kprintf(" session_id: %ld\n", settings.session_id);
kprintf(" termios:\n");
kprintf(" c_iflag: 0x%08lx\n", settings.termios.c_iflag);
kprintf(" c_oflag: 0x%08lx\n", settings.termios.c_oflag);
kprintf(" c_cflag: 0x%08lx\n", settings.termios.c_cflag);
kprintf(" c_lflag: 0x%08lx\n", settings.termios.c_lflag);
kprintf(" c_line: %d\n", settings.termios.c_line);
kprintf(" c_ispeed: %u\n", settings.termios.c_ispeed);
kprintf(" c_ospeed: %u\n", settings.termios.c_ospeed);
for (int i = 0; i < NCCS; i++)
kprintf(" c_cc[%02d]: %d\n", i, settings.termios.c_cc[i]);
kprintf(" wsize: %u x %u c, %u x %u pxl\n",
settings.window_size.ws_row, settings.window_size.ws_col,
settings.window_size.ws_xpixel, settings.window_size.ws_ypixel);
}
static void
dump_tty_struct(struct tty& tty)
{
kprintf(" tty @: %p\n", &tty);
kprintf(" index: %ld\n", tty.index);
kprintf(" is_master: %s\n", tty.is_master ? "true" : "false");
kprintf(" open_count: %ld\n", tty.open_count);
kprintf(" select_pool: %p\n", tty.select_pool);
kprintf(" pending_eof: %lu\n", tty.pending_eof);
kprintf(" lock: %p\n", tty.lock);
kprintf(" input_buffer:\n");
kprintf(" first: %ld\n", tty.input_buffer.first);
kprintf(" in: %lu\n", tty.input_buffer.in);
kprintf(" size: %lu\n", tty.input_buffer.size);
kprintf(" buffer: %p\n", tty.input_buffer.buffer);
kprintf(" reader queue:\n");
tty.reader_queue.Dump(" ");
kprintf(" writer queue:\n");
tty.writer_queue.Dump(" ");
kprintf(" cookies: ");
TTYCookieList::Iterator it = tty.cookies.GetIterator();
while (tty_cookie* cookie = it.Next())
kprintf(" %p", cookie);
kprintf("\n");
}
static int
dump_tty(int argc, char** argv)
{
if (argc < 2) {
kprintf("Usage: %s <tty index>\n", argv[0]);
return 0;
}
int32 index = atol(argv[1]);
if (index < 0 || index >= (int32)kNumTTYs) {
kprintf("Invalid tty index.\n");
return 0;
}
kprintf("master:\n");
dump_tty_struct(gMasterTTYs[index]);
kprintf("slave:\n");
dump_tty_struct(gSlaveTTYs[index]);
kprintf("settings:\n");
dump_tty_settings(gTTYSettings[index]);
return 0;
}
void void
tty_add_debugger_commands() tty_add_debugger_commands()
{ {