[kernel] Let endpoints get interrupt notifications
- Add a tag field to all endpoint messages, which doubles as a notification field - Add a endpoint_bind_irq syscall to enable an endpoint to listen for interrupt notifications. This mechanism needs to change. - Add a temporary copy of the serial port code to nulldrv, and let it take responsibility for COM2
This commit is contained in:
22
src/drivers/nulldrv/io.cpp
Normal file
22
src/drivers/nulldrv/io.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "io.h"
|
||||
|
||||
uint8_t
|
||||
inb(uint16_t port)
|
||||
{
|
||||
uint8_t val;
|
||||
__asm__ __volatile__ ( "inb %1, %0" : "=a"(val) : "Nd"(port) );
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
__asm__ __volatile__ ( "outb %0, %1" :: "a"(val), "Nd"(port) );
|
||||
}
|
||||
|
||||
void
|
||||
io_wait(unsigned times)
|
||||
{
|
||||
for (unsigned i = 0; i < times; ++i)
|
||||
outb(0x80, 0);
|
||||
}
|
||||
24
src/drivers/nulldrv/io.h
Normal file
24
src/drivers/nulldrv/io.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
/// Read a byte from an IO port.
|
||||
/// \arg port The address of the IO port
|
||||
/// \returns One byte read from the port
|
||||
uint8_t inb(uint16_t port);
|
||||
|
||||
/// Write a byte to an IO port.
|
||||
/// \arg port The addres of the IO port
|
||||
/// \arg val The byte to write
|
||||
void outb(uint16_t port, uint8_t val);
|
||||
|
||||
/// Pause briefly by doing IO to port 0x80
|
||||
/// \arg times Number of times to delay by writing
|
||||
void io_wait(unsigned times = 1);
|
||||
|
||||
}
|
||||
|
||||
constexpr uint16_t COM1 = 0x03f8;
|
||||
constexpr uint16_t COM2 = 0x02f8;
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#include <j6libc/syscalls.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "serial.h"
|
||||
|
||||
char inbuf[1024];
|
||||
j6_handle_t endp = j6_handle_invalid;
|
||||
|
||||
@@ -24,7 +27,8 @@ thread_proc()
|
||||
|
||||
char buffer[512];
|
||||
size_t len = sizeof(buffer);
|
||||
j6_status_t result = _syscall_endpoint_receive(endp, &len, (void*)buffer);
|
||||
j6_tag_t tag = 0;
|
||||
j6_status_t result = _syscall_endpoint_receive(endp, &tag, &len, (void*)buffer);
|
||||
if (result != j6_status_ok)
|
||||
_syscall_thread_exit(result);
|
||||
|
||||
@@ -34,7 +38,8 @@ thread_proc()
|
||||
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
|
||||
buffer[i] += 0x20;
|
||||
|
||||
result = _syscall_endpoint_send(endp, len, (void*)buffer);
|
||||
tag++;
|
||||
result = _syscall_endpoint_send(endp, tag, len, (void*)buffer);
|
||||
if (result != j6_status_ok)
|
||||
_syscall_thread_exit(result);
|
||||
|
||||
@@ -66,8 +71,8 @@ main(int argc, const char **argv)
|
||||
return 1;
|
||||
|
||||
uint64_t *vma_ptr = reinterpret_cast<uint64_t*>(base);
|
||||
for (int i = 0; i < 300; ++i)
|
||||
vma_ptr[i] = uint64_t(i);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
vma_ptr[i*100] = uint64_t(i);
|
||||
|
||||
_syscall_system_log("main thread wrote to memory area");
|
||||
|
||||
@@ -85,10 +90,14 @@ main(int argc, const char **argv)
|
||||
|
||||
char message[] = "MAIN THREAD SUCCESSFULLY CALLED SENDRECV IF THIS IS LOWERCASE";
|
||||
size_t size = sizeof(message);
|
||||
result = _syscall_endpoint_sendrecv(endp, &size, (void*)message);
|
||||
j6_tag_t tag = 16;
|
||||
result = _syscall_endpoint_sendrecv(endp, &tag, &size, (void*)message);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
if (tag != 17)
|
||||
_syscall_system_log("GOT WRONG TAG FROM SENDRECV");
|
||||
|
||||
_syscall_system_log(message);
|
||||
|
||||
_syscall_system_log("main thread waiting on child");
|
||||
@@ -97,6 +106,29 @@ main(int argc, const char **argv)
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
_syscall_system_log("main testing irqs");
|
||||
|
||||
_syscall_endpoint_bind_irq(endp, 3);
|
||||
|
||||
serial_port com2(COM2);
|
||||
|
||||
const char *fgseq = "\x1b[2J";
|
||||
while (*fgseq)
|
||||
com2.write(*fgseq++);
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
com2.write('%');
|
||||
|
||||
size_t len = 0;
|
||||
while (true) {
|
||||
result = _syscall_endpoint_receive(endp, &tag, &len, nullptr);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
if (j6_tag_is_irq(tag))
|
||||
_syscall_system_log("main thread got irq!");
|
||||
}
|
||||
|
||||
_syscall_system_log("main thread closing endpoint");
|
||||
|
||||
result = _syscall_endpoint_close(endp);
|
||||
|
||||
41
src/drivers/nulldrv/serial.cpp
Normal file
41
src/drivers/nulldrv/serial.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "io.h"
|
||||
#include "serial.h"
|
||||
|
||||
|
||||
serial_port::serial_port() :
|
||||
m_port(0)
|
||||
{
|
||||
}
|
||||
|
||||
serial_port::serial_port(uint16_t port) :
|
||||
m_port(port)
|
||||
{
|
||||
outb(port + 1, 0x00); // Disable all interrupts
|
||||
outb(port + 3, 0x80); // Enable the Divisor Latch Access Bit
|
||||
outb(port + 0, 0x01); // Divisor low bit: 1 (115200 baud)
|
||||
outb(port + 1, 0x00); // Divisor high bit
|
||||
outb(port + 3, 0x03); // 8-N-1
|
||||
outb(port + 2, 0xe7); // Clear and enable FIFO, enable 64 byte, 56 byte trigger
|
||||
outb(port + 4, 0x0b); // Data terminal ready, Request to send, aux output 2 (irq enable)
|
||||
outb(port + 1, 0x03); // Enable interrupts
|
||||
}
|
||||
|
||||
bool serial_port::read_ready() { return (inb(m_port + 5) & 0x01) != 0; }
|
||||
|
||||
bool serial_port::write_ready() {
|
||||
uint8_t lsr = inb(m_port + 5);
|
||||
return (lsr & 0x20) != 0;
|
||||
}
|
||||
|
||||
char
|
||||
serial_port::read() {
|
||||
while (!read_ready());
|
||||
return inb(m_port);
|
||||
}
|
||||
|
||||
void
|
||||
serial_port::write(char c) {
|
||||
while (!write_ready());
|
||||
outb(m_port, c);
|
||||
}
|
||||
|
||||
26
src/drivers/nulldrv/serial.h
Normal file
26
src/drivers/nulldrv/serial.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
/// \file serial.h
|
||||
/// Declarations related to serial ports.
|
||||
#include <stdint.h>
|
||||
|
||||
#define serial_port nulldrv_serial_port
|
||||
|
||||
class serial_port
|
||||
{
|
||||
public:
|
||||
/// Constructor.
|
||||
/// \arg port The IO address of the serial port
|
||||
serial_port(uint16_t port);
|
||||
|
||||
serial_port();
|
||||
|
||||
void write(char c);
|
||||
char read();
|
||||
|
||||
private:
|
||||
uint16_t m_port;
|
||||
|
||||
bool read_ready();
|
||||
bool write_ready();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user