#include <hal/term.h>
#include <lunaix/clock.h>
-#include <lunaix/sched.h>
+#include <lunaix/kpreempt.h>
#include <usr/lunaix/term.h>
-#define ONBREAK (LSTATE_EOF | LSTATE_SIGRAISE)
-#define ONSTOP (LSTATE_SIGRAISE | LSTATE_EOL | LSTATE_EOF)
+#define ONBREAK (LEVT_EOF | LEVT_SIGRAISE)
+#define ONSTOP (LEVT_SIGRAISE | LEVT_EOL | LEVT_EOF)
static int
do_read_raw(struct term* tdev)
{
- struct device* chdev = tdev->chdev;
-
- struct linebuffer* line_in = &tdev->line_in;
- size_t max_lb_sz = line_in->sz_hlf;
-
- line_flip(line_in);
-
- char* inbuffer = line_in->current->buffer;
- size_t min = tdev->cc[_VMIN] - 1;
- size_t sz = chdev->ops.read_async(chdev, inbuffer, 0, max_lb_sz);
- time_t t = clock_systime(), dt = 0;
- time_t expr = (tdev->cc[_VTIME] * 100) - 1;
-
+ struct linebuffer* line_in;
+ lbuf_ref_t current_buf;
+ size_t min, sz = 0;
+ time_t t, expr, dt = 0;
+
+ line_in = &tdev->line_in;
+ current_buf = ref_current(line_in);
+
+ min = tdev->cc[_VMIN] - 1;
+ t = clock_systime();
+ expr = (tdev->cc[_VTIME] * 100) - 1;
+
+ min = MIN(min, (size_t)line_in->sz_hlf);
while (sz <= min && dt <= expr) {
// XXX should we held the device lock while we are waiting?
- sched_yieldk();
+ yield_current();
dt = clock_systime() - t;
t += dt;
- max_lb_sz -= sz;
-
- // TODO pass a flags to read to indicate it is non blocking ops
- sz += chdev->ops.read_async(chdev, &inbuffer[sz], 0, max_lb_sz);
+ sz = deref(current_buf)->len;
}
- rbuffer_puts(line_in->next, inbuffer, sz);
- line_flip(line_in);
-
return 0;
}
-static int
-do_read_raw_canno(struct term* tdev)
-{
- struct device* chdev = tdev->chdev;
- struct linebuffer* line_in = &tdev->line_in;
- struct rbuffer* current_buf = line_in->current;
- int sz = chdev->ops.read(chdev, current_buf->buffer, 0, line_in->sz_hlf);
-
- current_buf->ptr = sz;
- current_buf->len = sz;
-
- return sz;
-}
-
-static int
-term_read_noncano(struct term* tdev)
-{
- struct device* chdev = tdev->chdev;
- return do_read_raw(tdev);
-}
-
-static int
+static inline int
term_read_cano(struct term* tdev)
{
- struct device* chdev = tdev->chdev;
- struct linebuffer* line_in = &tdev->line_in;
- int size = 0;
+ struct linebuffer* line_in;
+ line_in = &tdev->line_in;
while (!(line_in->sflags & ONSTOP)) {
- // move all hold-out content to 'next' buffer
- line_flip(line_in);
-
- size += do_read_raw_canno(tdev);
- lcntl_transform_inseq(tdev);
+ pwait(&tdev->line_in_event);
}
return 0;
if ((tdev->lflags & _ICANON)) {
return term_read_cano(tdev);
}
- return term_read_noncano(tdev);
+
+ return do_read_raw(tdev);
}
int
term_flush(struct term* tdev)
{
- if ((tdev->oflags & _OPOST)) {
- lcntl_transform_outseq(tdev);
- }
-
+ struct device* chardev;
struct linebuffer* line_out = &tdev->line_out;
- size_t xmit_len = line_out->current->len;
- char* xmit_buf = line_out->next->buffer;
+ char* xmit_buf = tdev->scratch_pad;
+ lbuf_ref_t current_ref = ref_current(line_out);
+
+ int count = 0;
+
+ chardev = tdev->chdev;
+
+ while (!rbuffer_empty(deref(current_ref))) {
+ if ((tdev->oflags & _OPOST)) {
+ lcntl_transform_outseq(tdev);
+ }
+
+ size_t xmit_len = line_out->current->len;
- rbuffer_gets(line_out->current, xmit_buf, xmit_len);
+ rbuffer_gets(line_out->current, xmit_buf, xmit_len);
- off_t off = 0;
- int ret = 0;
- while (xmit_len && ret >= 0) {
- ret = tdev->chdev->ops.write(tdev->chdev, &xmit_buf[off], 0, xmit_len);
- xmit_len -= ret;
- off += ret;
+ off_t off = 0;
+ int ret = 0;
+ while (xmit_len && ret >= 0) {
+ ret = chardev->ops.write(chardev, &xmit_buf[off], 0, xmit_len);
+ xmit_len -= ret;
+ off += ret;
+ count += ret;
+ }
+
+ // put back the left over if transmittion went south
+ rbuffer_puts(line_out->current, xmit_buf, xmit_len);
+
+ line_flip(line_out);
}
- // put back the left over if transmittion went south
- rbuffer_puts(line_out->current, xmit_buf, xmit_len);
+ return count;
+}
+
+void
+term_notify_data_avaliable(struct termport_capability* cap)
+{
+ struct term* term;
+ struct device* term_chrdev;
+ struct linebuffer* line_in;
+ lbuf_ref_t current_ref;
+ char* buf;
+ int sz;
+
+ term = cap->term;
+ term_chrdev = term->chdev;
+ line_in = &term->line_in;
+ current_ref = ref_current(line_in);
+
+ // make room for current buf
+ line_flip(line_in);
+ buf = deref(current_ref)->buffer;
+
+ sz = term_chrdev->ops.read_async(term_chrdev, buf, 0, line_in->sz_hlf);
+ rbuffer_setcontent(deref(current_ref), sz);
+
+ if ((term->lflags & _ICANON)) {
+ lcntl_transform_inseq(term);
+ // write all processed to next, and flip back to current
+ }
- return off;
+ pwake_all(&term->line_in_event);
}
\ No newline at end of file