Going back to letting mailboxes use variable-length data. Note that this requires extra copies, so shared memory channels should be used for anything in the hot path. But this allows better RPC over mailboxes and other flexibility. Other changes: - added a j6::proto::sl::client class to act as a service locator client, instead of duplicating that code in every program. - moved protocol ids into j6/tables/protocols.inc so that C++ clients can easily have their own API
127 lines
3.3 KiB
C++
127 lines
3.3 KiB
C++
#include <new>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <j6/cap_flags.h>
|
|
#include <j6/channel.hh>
|
|
#include <j6/errors.h>
|
|
#include <j6/flags.h>
|
|
#include <j6/init.h>
|
|
#include <j6/protocols/service_locator.hh>
|
|
#include <j6/syscalls.h>
|
|
#include <j6/sysconf.h>
|
|
#include <j6/syslog.hh>
|
|
#include <j6/types.h>
|
|
#include <util/hash.h>
|
|
|
|
#include "io.h"
|
|
#include "serial.h"
|
|
|
|
extern "C" {
|
|
int main(int, const char **);
|
|
}
|
|
|
|
j6_handle_t g_handle_sys = j6_handle_invalid;
|
|
|
|
constexpr size_t in_buf_size = 512;
|
|
constexpr size_t out_buf_size = 128 * 1024;
|
|
|
|
uint8_t com1_in[in_buf_size];
|
|
uint8_t com2_in[in_buf_size];
|
|
uint8_t com1_out[out_buf_size];
|
|
uint8_t com2_out[out_buf_size];
|
|
|
|
constexpr uintptr_t stack_top = 0xf80000000;
|
|
|
|
int
|
|
main(int argc, const char **argv)
|
|
{
|
|
j6_log("uart driver starting");
|
|
|
|
j6_handle_t event = j6_handle_invalid;
|
|
j6_status_t result = j6_status_ok;
|
|
|
|
g_handle_sys = j6_find_first_handle(j6_object_type_system);
|
|
if (g_handle_sys == j6_handle_invalid)
|
|
return 1;
|
|
|
|
result = j6_system_request_iopl(g_handle_sys, 3);
|
|
if (result != j6_status_ok)
|
|
return result;
|
|
|
|
result = j6_event_create(&event);
|
|
if (result != j6_status_ok)
|
|
return result;
|
|
|
|
result = j6_system_bind_irq(g_handle_sys, event, 3, 0);
|
|
if (result != j6_status_ok)
|
|
return result;
|
|
|
|
result = j6_system_bind_irq(g_handle_sys, event, 4, 1);
|
|
if (result != j6_status_ok)
|
|
return result;
|
|
|
|
serial_port com1 {COM1, in_buf_size, com1_in, out_buf_size, com1_out};
|
|
serial_port com2 {COM2, in_buf_size, com2_in, out_buf_size, com2_out};
|
|
|
|
static constexpr size_t buffer_size = 512;
|
|
char buffer[buffer_size];
|
|
|
|
j6_handle_t slp = j6_find_first_handle(j6_object_type_mailbox);
|
|
if (slp == j6_handle_invalid)
|
|
return 1;
|
|
|
|
j6::channel *cout = j6::channel::create(0x2000);
|
|
if (!cout)
|
|
return 2;
|
|
|
|
uint64_t proto_id = "jsix.protocol.stream.ouput"_id;
|
|
uint64_t handle = cout->handle();
|
|
j6::proto::sl::client slp_client {slp};
|
|
result = slp_client.register_service(proto_id, handle);
|
|
if (result != j6_status_ok)
|
|
return 4;
|
|
|
|
result = j6_system_request_iopl(g_handle_sys, 3);
|
|
if (result != j6_status_ok)
|
|
return 6;
|
|
|
|
while (true) {
|
|
size_t size = buffer_size;
|
|
while (true) {
|
|
result = cout->receive(buffer, &size, 0);
|
|
if (result != j6_status_ok)
|
|
break;
|
|
|
|
//j6::syslog("uart driver: got %d bytes from channel", size);
|
|
com1.write(buffer, size);
|
|
}
|
|
if (result != j6_status_would_block)
|
|
j6::syslog("uart driver: error %lx receiving from channel", result);
|
|
|
|
uint64_t signals = 0;
|
|
result = j6_event_wait(event, &signals, 500);
|
|
if (result == j6_err_timed_out) {
|
|
com1.do_write();
|
|
continue;
|
|
}
|
|
|
|
if (result != j6_status_ok) {
|
|
j6::syslog("uart driver: error %lx waiting for irq", result);
|
|
continue;
|
|
} else {
|
|
j6::syslog("uart driver: irq signals: %lx", signals);
|
|
}
|
|
|
|
if (signals & (1<<0))
|
|
com2.handle_interrupt();
|
|
if (signals & (1<<1))
|
|
com1.handle_interrupt();
|
|
}
|
|
|
|
j6_log("uart driver somehow got to the end of main");
|
|
return 0;
|
|
}
|
|
|