| Age | Commit message (Collapse) | Author |
|
Removed the rsputs() function in favour of calls to tty_write().
Corrected a bug in the serial driver and TTY subsystem where a full
buffer wouldn't be detected. This was caused by a missing set of
brackets on several operations involving the modulus operator.
Added the ability for the serial driver to automatically take data from
the TTY device's write buffer and push it to the serial port. This can
happen in one of two ways; 1) the TTY subsystem notifies the serial
driver of new data by calling the write() function pointer in the
tty_struct or, 2) the serial port issues an interrupt signalling that it
has finished sending data prompting the driver to check the buffers for
any more pending data.
|
|
the project.
Added the system call 'sys_panic' as well as the corresponding library
function panic() whose prototype is defined in unistd.h. This is to
allow userspace programs to deliberately crash the kernel for the
purpose of debugging.
Added the element 'write' as a function pointer in the tty_struct
structure. The purpose of this function pointer is to provide a means
for the TTY subsystem to notify the device driver of any newly added
data to the write queue.
Added the tty_write() function to the TTY subsystem. This function will
copy data provided by the user into the specified TTY device's write
queue, blocking if the queue's buffer is full. tty_write() will then
call the driver's write() function to notify it of new data.
Added the rsint_tx() function to the serial driver to handle transmit
interrupts by re-supplying the UART's transmit FIFO.
|
|
SSIZE_MAX which is needed to limit the number of bytes read() will
transfer.
Laid the foundation for a TTY subsystem. This works by taking the
previously used buffer and r/w pointers concept and implements it as a
'tty_queue' struct. The struct 'tty_struct' is used to represent a TTY
device. This struct currently contains three elements; a read queue for
data flowing from the device to the user, a write queue for data flowing
from the user to the device and a function pointer to an init function.
The latter element will reduce complexity by allowing the TTY subsystem
to initialize each TTY device driver (when it's ready), rather than each
driver having to be initialized during bootup. Each TTY device is
implemented as a pointer to a tty_struct. The structures are defined
separately by each driver as well as tracked and maintained by pointers
in the table 'ttys' in tty.c.
Modified the RS232 serial driver to make use of the new TTY subsystem
for transferring data to the user. Currently, write calls are still
handled manually through the rsputs() function though this will change
in future.
Modified the read() system call to direct read calls to the TTY
subsystem which will further direct the call to the appropriate TTY
device driver.
The serial driver's interrupt routine now uses the wake_up() function to
wake processes blocking for serial data. This is to ensure the scheduler
is notified of the wakeup. This function is the preferred method for
waking processes since accessing the task state field directly may not
be possible in the future and is discouraged. The reason for this is
that the scheduler's behaviour may change to require being notified of
task wakeup events in the future.
|
|
interrupts respectively.
Added the scheduling primatives sleep_on() and interruptible_sleep_on()
to sched.c. sleep_on() adds the current task to the specified wait queue
then puts it into an uninterruptible sleep. Wait queues are formed by
having each waiting task holding a pointer to the waiting task that
preceeded it, then placing a pointer to it's own task struct into the
queue's head pointer. When the first task in the queue is awoken, it
wakes the preceeding task prior to returning from sleep_on(). The
function interruptible_sleep_on() works in a similar manner, however
when a task is awoken from interruptible_sleep_on(), it wakes up the
first task in it's wait queue, then puts itself back to sleep. The
purpose of this, is to automatically dissolve and reform the wait queue.
As each task in the queue is a awakened, tasks that need to handle
signals will do so whilst tasks that have no pending signals and are
still waiting will place themselves back into the wait queue by calling
interruptible_sleep_on() again. Whilst this method isn't the most
effiecient due to waking every task in a wait queue because one received
a signal, it does avoid the mess and complications involved in
maintaining the queue as an array or linked list.
Added prototypes for the scheduling primatives wake_up(), sleep_on() and
interruptible_sleep_on() to kernel/sched.h so that these functions may
be used throughout the kernel.
Added code to temporaily re-enable interrupts in reschedule() so that
the idle loop may continue to function even if interrupts were disabled
prior to calling the function.
|
|
printk() to notify the user of the kernel panic. This resulted in a
system call being made to the kernel itself and the machine not fully
halting.
Fixed an issue with the serial driver in which the functions rsputs()
and rsread() will still attempt a data transfer even if serial_init()
failed to detect and initialize a serial port.
Added the ability for tasks to be interrupted whilst reading from the
serial port. This was done by putting the task into TSTATE_INTERRUPTIBLE
instead of TSTATE_UNINTERRUPTIBLE when waiting for data in the serial
buffer. Furthermore, a check was introduced after the task wakes up to
see if any data was put in the buffer, or if the task was awoken by
another source.
Changed the type pid_t from an unsigned 16-bit integer to a signed
16-bit integer. This was done to make passing PID's to certain functions
easier.
Added the new system call sys_kill which will allow one process to send
a signal to another.
Added the kill_proc() function to sched.c to kill a process. Currently,
this works by nullifying the PID field in the process' task structure,
marking all the pages mapped to it's address space as free for use, then
calling the scheduler to switch to another runnable task (or to idle).
Modified the default signal handler within the kernel to now handle the
SIGKILL signal by calling kill_proc().
|
|
Added the _syscall2 macro to unistd.h to facilitate system calls that
require two arguments to be passed.
Modified the ATA driver to simply abort initialisation if a drive is not
found, or cannot be configured. This will allow the kernel to function
on a diskless system without invoking panic() unnecessarily.
Added the functions irq_enable() and irq_disable() to asm/interrupt.h to
make it easier for C code to mask and unmask IRQ's on each PIC.
Moved the declaration for rsputs() from kernel/con.h to the new
kernel/serial.h file since this is a function provided by the serial
driver.
Implemented a basic I/O input framework. This involves the new system
call sys_read, which takes an I/O read request and directs it to the
appropriate kernel handler function depending on the calling process'
ctty value. This mechanism is identical to the sys_puts system call.
Added the rsread() function to service sys_read calls from processes
whose ctty value is equal to 1. This function will continually copy data
from the serial buffer to the location specified. If there is not a
sufficient amount of new data in the buffer to satisfy the request, the
process is put into the TSTATE_UNINTERRUPTIBLE state and the scheduler
is called to switch tasks. Prior to calling the scheduler, the function
will set the waiting_task pointer to the calling process. This pointer
will later be used by the interrupt handler to wake the process when new
data arrives.
Added an interrupt handler to service the IRQ4 (UART) interrupt. This
subroutine is a stub which will save the machine's state then transfer
control to rs_handler() in serial.c which will read bytes from the
serial port and place them in a buffer. Before returning, rs_handler()
checks the waiting_task pointer to see if a task is waiting for the
newly received data and if so, it sets the task's state to
TSTATE_RUNNING before resetting the pointer to NULL and returning.
Ideally, the scheduler should be invoked at this point to select another
task but since our basic round-robin scheduler currently has no concept
of task priorities (and for the sake of simplicity), we will avoid
invoking the scheduler in response to interrupts for now.
|
|
Implemented the sprintf() library function in lib/stdio.c which uses the
vsprintf() function.
Implemented a very primative controlling TTY for each process. This is
achieved by a switch in the sys_puts system call which uses the 'ctty'
element of the process' task structure to determine an appropriate I/O
channel. A negative ctty value doesn't equate to any I/O channel
effectively disabling the process' output.
Added the sys_ctty system call which allows a process to set it's own
ctty value.
Removed the sys_rsputs system call. Output to serial is now performed by
the process first setting it's ctty value to 1, then invoking sys_puts.
|
|
Implemented a basic serial interface using COM0 which can be accessed
with the system call sys_puts as well as the library functions rsputs()
and rsprintf().
Renamed puts() in con.c to con_puts() and made the function static to
avoid interference with the library function puts().
|