+
+void sci_rx_int() {
+ char buf = _io_ports[M6811_SCDR];
+ if (sci_doing_xmodem) {
+ if ((sci_rx_buf_ptr+1)%BUFFER_LEN == sci_rx_buf_ptr_start) {
+ /* we drop following bytes :( */
+ return;
+ }
+ sci_rx_buf[sci_rx_buf_ptr] = buf;
+ sci_rx_buf_ptr++;
+ sci_rx_buf_ptr %= BUFFER_LEN;
+ return;
+ }
+ if (sci_echo) {
+ while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); /* wait for TX ready */
+ _io_ports[M6811_SCDR] = buf; /* send byte */
+ }
+
+ /* XXX FIXME we should do something about errors. nack? */
+ if (sci_have_packet) {
+ /* overrun :( */
+ return;
+ }
+ sci_rx_buf[sci_rx_buf_ptr] = buf;
+
+ if (buf == '\n' || buf == '\r') {
+ sci_rx_buf[sci_rx_buf_ptr] = '\0';
+ sci_have_packet = 1;
+ }
+
+ if (sci_rx_buf_ptr+1 < BUFFER_LEN)
+ sci_rx_buf_ptr++;
+ else {
+ sci_rx_buf[BUFFER_LEN-1] = '\0'; /* this is as much as we could fit */
+ }
+}
+
+void sci_interrupt_serial() {
+ if (_io_ports[M6811_SCSR] & M6811_RDRF) sci_rx_int();
+
+ if (_io_ports[M6811_SCSR] & M6811_OR)
+ _io_ports[M6811_SCDR]; /* declare it a lost cause */
+}
+
+void msg_clr() {
+ sci_have_packet = 0;
+ sci_rx_buf_ptr = 0;
+}
+
+void send_ack() {
+ send_string("!" CRLF);
+}
+
+void send_nack() {
+ send_string("?" CRLF);
+}
+
+u16 sci_timer;
+void serial_rti() { /* called every 6.6 ms */
+ if (sci_timer) sci_timer--;
+}
+
+/* for gdb compatibility */
+int serial_readchar(u8 timeout) {
+ int ret;
+ sci_timer = timeout * 152;
+ while (sci_timer && sci_rx_buf_ptr_start == sci_rx_buf_ptr); /* spin */
+ if (sci_timer == 0) return SERIAL_TIMEOUT;
+ ret = sci_rx_buf[sci_rx_buf_ptr_start];
+ sci_rx_buf_ptr_start++;
+ sci_rx_buf_ptr_start %= BUFFER_LEN;
+ return ret;
+}
+
+void serial_write(const char *str, int len) {
+ char *c, *end;
+ end = (char*)(str + len);
+ for (c = (char*)str; c < end; c++) {
+ while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); /* wait for TX ready */
+ _io_ports[M6811_SCDR] = *c; /* send byte */
+ }
+}
+