hcj@lzaz.ATT.COM (HC Johnson) (01/04/89)
This is rs232.shar, the new rs232 files for adding rs232 and midi to
minix-st.
==============================================================
echo extracting 'README'
sed -e 's/^X//' >README <<'SHAR_EOF'
X
XNew files for rs232:
X
Xkernel/rstty.c
Xkernel/rs232.c
Xkernel/rs232s.s
Xkernel/ring.h
X
XChanged files for rs232
X
Xkernel/Makefile
Xkernel/stacia.h
Xkernel/stcon.c
Xkernel/stdmp.c
Xkernel/stmain.c
Xkernel/stvdu.c
Xkernel/table.c
Xkernel/tty.h
Xfs/table.c
Xh/com.h
Xh/const.h
Xh/sgtty.h
X
XNew files for Midi:
X
Xkernel/miditty.c
Xkernel/midi.c
Xkernel/midis.s
X
SHAR_EOF
echo extracting 'rstty.c'
sed -e 's/^X//' >rstty.c <<'SHAR_EOF'
X/*
X * This file contains the device-independent part of the terminal driver.
X * The device-independent part accepts characters to be printed from
X * programs and queues them in a standard way for device-dependent output.
X * It also accepts input and queues it for programs.
X * This file contains one entry point: rs232_task().
X * It accepts not only messages about typed input, but
X * also requests to read and write from terminals, etc.
X *
X * The valid messages and their parameters are:
X *
X * RS232_CHAR_INT: a character has been typed on a terminal (input interrupt)
X * RS232_O_DONE: a character has been output (output completed interrupt)
X * RS232_READ: a process wants to read from a terminal
X * RS232_WRITE: a process wants to write on a terminal
X * RS232_IOCTL: a process wants to change a terminal's parameters
X * RS232_SETPGRP: indicate a change in a control terminal
X * CANCEL: terminate a previous incomplete system call immediately
X *
X * m_type RS232_LINE PROC_NR COUNT RS232_SPEK RS232_FLAGS ADDRESS
X * ---------------------------------------------------------------------------
X * | RS232_CHAR_INT| | | | | |array ptr|
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | RS232_O_DONE |minor dev| | | | | |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | RS232_READ |minor dev| proc nr | count | | | buf ptr |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | RS232_WRITE |minor dev| proc nr | count | | | buf ptr |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | RS232_IOCTL |minor dev| proc nr |func code|erase etc| flags | |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | RS232_SETPGRP |minor dev| proc nr | | | | |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | CANCEL |minor dev| proc nr | | | | |
X * ---------------------------------------------------------------------------
X */
X
X#include "../h/const.h"
X#include "../h/type.h"
X#include "../h/callnr.h"
X#include "../h/com.h"
X#include "../h/error.h"
X#include "../h/sgtty.h"
X#include "../h/signal.h"
X#include "const.h"
X#include "type.h"
X#include "proc.h"
X#include "tty.h"
X#include "ring.h"
X
X/* IN_CANON will be dis-asserted when set, noop if == 0 */
X
XPRIVATE int Rs_blocked = 0;
XPUBLIC struct tty_struct rstty_struct[1];
X
X#define DBG(x) printf(x);
X
X
X/*===========================================================================*
X * rs232_task *
X *===========================================================================*/
XPUBLIC rs232_task()
X{
X/* Main routine of the terminal task. */
X
X message rstty_mess; /* buffer for all incoming messages */
X register struct tty_struct *tp;
X
X rstty_init(); /* initialize */
X while (TRUE) {
X receive(ANY, &rstty_mess);
X/* we would rather be general here, but not enough info is avail USE 0 */
X tp = &rstty_struct[0];
X if(tp->tty_incount == 0 && Rs_blocked) {
X do_charint(&rstty_mess);
X if(rstty_mess.m_type == RS232_CHAR_INT) /* might be fake */
X continue;
X }
X#ifdef CANT_BE
X tp = &rstty_struct[rstty_mess.TTY_LINE];
X#endif
X if(rstty_mess.m_type != RS232_CHAR_INT && rstty_mess.TTY_LINE != 0) {
X printf("\r\nInvalid rs232 minor:type=%d LINE=%d PROCNR=%d ADDRESS=%lx COUNT=%d\n\r",
X rstty_mess.m_type,
X rstty_mess.TTY_LINE,
X rstty_mess.PROC_NR,
X rstty_mess.ADDRESS,
X rstty_mess.COUNT,
X rstty_mess.m_source);
X continue; /* ignore or do something ?? */
X }
X
X switch(rstty_mess.m_type) {
X case RS232_CHAR_INT: do_charint(&rstty_mess); break;
X case RS232_READ: do_read(tp, &rstty_mess); break;
X case RS232_WRITE: do_write(tp, &rstty_mess); break;
X case RS232_IOCTL: do_ioctl(tp, &rstty_mess); break;
X case RS232_SETPGRP: do_setpgrp(tp, &rstty_mess); break;
X case RS232_OPEN: do_open(tp, &rstty_mess); break;
X case RS232_CLOSE: do_close(tp, &rstty_mess); break;
X case CANCEL : do_cancel(tp, &rstty_mess); break;
X case RS232_O_DONE: break; /* reserved for future use (RS-232 terminals)*/
X default: tty_reply(TASK_REPLY, rstty_mess.m_source,
X rstty_mess.PROC_NR, EINVAL, 0L, 0L);
X }
X }
X}
X
X
X/*===========================================================================*
X * do_close *
X *===========================================================================*/
XPRIVATE do_close(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xmessage *m_ptr; /* message containing pointer to char(s) */
X{
X int minor;
X minor = m_ptr->DEVICE;
X (*tp->tty_close)(tp);
X tty_reply(TASK_REPLY, m_ptr->m_source,
X m_ptr->PROC_NR, OK, 0L, 0L);
X}
X
X/*===========================================================================*
X * do_open *
X *===========================================================================*/
XPRIVATE do_open(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xmessage *m_ptr; /* message containing pointer to char(s) */
X{
X int minor;
X return; /* we do not know how to handle this and set pgrp also */
X}
X
X/*===========================================================================*
X * do_odone *
X *===========================================================================*/
XPUBLIC int Rs232_wempty = 0;
XPRIVATE do_odone(tp)
Xstruct tty_struct *tp;
X{
X unsigned char *ptr;
X
X Rs232_wempty = 0;
X/* there may be more to send */
X if ((*tp->tty_start)(tp)) /* copy data to queue and start I/O */
X finish(tp, tp->tty_cum);
X}
X
X/*===========================================================================*
X * do_charint *
X *===========================================================================*/
Xstatic cnt_max = 0;
XPRIVATE do_charint(m_ptr)
Xmessage *m_ptr; /* message containing pointer to char(s) */
X{
X/* A character has been typed. If a character is typed and the tty task is
X * not able to service it immediately, the character is accumulated within
X * the tty driver. Thus multiple chars may be accumulated. A single message
X * to the tty task may have to process several characters.
X */
X
X int m, n, count, replyee, caller, s;
X char ch;
X struct tty_struct *tp;
X struct ring *ptr;
X
X if(Rs232_wempty)
X do_odone(rstty_struct);
X Rs_blocked = 0;
X for( ;; ) {
X
X tp = &rstty_struct[0]; /* pointer to struct for this character */
X if (tp->tty_incount >= TTY_IN_BYTES-4) {
X Rs_blocked |= 1;
X break;
X }
X
X m = rs232get();
X if((m & 0x100))
X break;
X ch = m ;
X n = COM0; /* get the line number it came in on */
X
X m= in_char(n, ch&0377); /* queue the char and echo it */
X
X /* See if a previously blocked reader can now be satisfied. */
X if (tp->tty_inleft > 0 ) { /* does anybody want input? */
X m = tp->tty_mode & (CBREAK | RAW);
X if (tp->tty_lfct > 0 ||
X (m != 0 && tp->tty_incount > 0) ||
X (((tp->tty_mode & IN_CANON) ) &&
X tp->tty_incount >= tp->tty_eof)
X ) {
X
X
X m = rd_chars(tp);
X
X /* Tell hanging reader that chars have arrived. */
X replyee = (int) tp->tty_incaller;
X caller = (int) tp->tty_inproc;
X tty_reply(REVIVE, replyee, caller, m, 0L, 0L);
X }
X }
X }
X}
X
X
X/*===========================================================================*
X * in_char *
X *===========================================================================*/
XPRIVATE in_char(line, ch)
Xint line; /* line number on which char arrived */
Xint ch; /* code for character that arrived */
X{
X/* A character has just been typed in. Process, save, and echo it. */
X
X register struct tty_struct *tp;
X int mode;
X
X tp = &rstty_struct[line]; /* set 'tp' to point to proper struct */
X if (tp->tty_incount >= TTY_IN_BYTES) {
X return(0); /* no room, discard char */
X}
X mode = tp->tty_mode & (RAW | CBREAK);
X if (mode != RAW) ch &= 0177; /* 7-bit chars except in raw mode */
X
Xif((tp->tty_mode & IN_CANON) == 0) { /* bit set means not CANON */
X /* Processing for COOKED and CBREAK mode contains special checks. */
X if (mode == COOKED || mode == CBREAK) {
X /* Handle erase, kill and escape processing. */
X if (mode == COOKED) {
X /* First erase processing (rub out of last character). */
X if (ch == tp->tty_erase && tp->tty_escaped == NOT_ESCAPED) {
X if (chuck(tp) != -1) { /* remove last char entered */
X echo(tp, '\b'); /* remove it from the screen */
X echo(tp, ' ');
X echo(tp, '\b');
X }
X return(1);
X }
X
X /* Now do kill processing (remove current line). */
X if (ch == tp->tty_kill && tp->tty_escaped == NOT_ESCAPED) {
X while ( chuck(tp) == OK) /* keep looping */ ;
X echo(tp, tp->tty_kill);
X echo (tp, '\n');
X return(1);
X }
X
X /* Handle EOT and the escape symbol (backslash). */
X if (tp->tty_escaped == NOT_ESCAPED) {
X /* Normal case: previous char was not backslash. */
X if (ch == '\\') {
X /* An escaped symbol has just been typed. */
X tp->tty_escaped = ESCAPED;
X echo(tp, ch);
X return(1); /* do not store the '\' */
X }
X /* CTRL-D means end-of-file, unless it is escaped. It
X * is stored in the text as MARKER, and counts as a
X * line feed in terms of knowing whether a full line
X * has been typed already.
X */
X if (ch == tp->tty_eof) ch = MARKER;
X } else {
X /* Previous character was backslash. */
X tp->tty_escaped = NOT_ESCAPED; /* turn escaping off */
X if (ch != tp->tty_erase && ch != tp->tty_kill &&
X ch != tp->tty_eof) {
X /* Store the escape previously skipped over */
X *tp->tty_inhead++ = '\\';
X tp->tty_incount++;
X if (tp->tty_inhead ==
X &tp->tty_inqueue[TTY_IN_BYTES])
X tp->tty_inhead = tp->tty_inqueue;
X }
X }
X }
X /* Both COOKED and CBREAK modes come here; first map CR to LF. */
X if (ch == '\r' && (tp->tty_mode & CRMOD)) ch = '\n';
X
X /* Check for interrupt and quit characters. */
X if (ch == tp->tty_intr) {
X sigchar(tp, SIGINT);
X return(1);
X }
X if (ch == tp->tty_quit) {
X sigchar(tp, SIGQUIT);
X return(1);
X }
X
X /* Check for and process CTRL-S (terminal stop). */
X if (ch == tp->tty_xoff) {
X tp->tty_inhibited |= STOPPED;
X return(1);
X }
X
X /* Check for stopped output (any key including CTRL-Q) */
X if (tp->tty_inhibited & STOPPED) {
X tp->tty_inhibited &= ~STOPPED;
X if ((*tp->tty_start)(tp)) /* resume output */
X finish(tp, tp->tty_cum);
X return(1);
X }
X }
X
X /* All 3 modes come here. */
X if (ch == '\n' || ch == MARKER) tp->tty_lfct++; /* count line feeds */
X } else {
X/* AT LEAST WE CAN USE THE RETURN KEY */
X if (ch == '\n' || ch == '\r') tp->tty_lfct++;
X }
X *tp->tty_inhead++ = ch; /* save the character in the input queue */
X if (tp->tty_inhead == &tp->tty_inqueue[TTY_IN_BYTES])
X tp->tty_inhead = tp->tty_inqueue; /* handle wraparound */
X tp->tty_incount++;
X echo(tp, ch);
X return(1);
X}
X
X
X/*===========================================================================*
X * echo *
X *===========================================================================*/
XPRIVATE echo(tp, c)
Xregister struct tty_struct *tp; /* terminal on which to echo */
Xregister char c; /* character to echo */
X{
X/* Echo a character on the terminal. */
X
X if ( (tp->tty_mode & ECHO) == 0) return; /* if no echoing, don't echo */
X if ((c != MARKER) || (tp->tty_mode & RAW))
X (*tp->tty_echo)(tp, c);
X}
X
X
X/*===========================================================================*
X * chuck *
X *===========================================================================*/
XPRIVATE int chuck(tp)
Xregister struct tty_struct *tp; /* from which tty should chars be removed */
X{
X/* Delete one character from the input queue. Used for erase and kill. */
X
X char *prev;
X
X /* If input queue is empty, don't delete anything. */
X if (tp->tty_incount == 0) return(-1);
X
X /* Don't delete '\n' or '\r'. */
X prev = (tp->tty_inhead != tp->tty_inqueue ? tp->tty_inhead - 1 :
X &tp->tty_inqueue[TTY_IN_BYTES-1]);
X if (*prev == '\n' || *prev == '\r') return(-1);
X tp->tty_inhead = prev;
X tp->tty_incount--;
X return(OK); /* char erasure was possible */
X}
X
X
X/*===========================================================================*
X * do_read *
X *===========================================================================*/
XPRIVATE do_read(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xmessage *m_ptr; /* pointer to message sent to the task */
X{
X/* A process wants to read from a terminal. */
X
X int code, caller;
X
X if (tp->tty_inleft > 0) { /* if someone else is hanging, give up */
X tty_reply(TASK_REPLY,m_ptr->m_source,m_ptr->PROC_NR, E_TRY_AGAIN,0L,0L);
X return;
X }
X
X /* Copy information from the message to the tty struct. */
X tp->tty_incaller = m_ptr->m_source;
X tp->tty_inproc = m_ptr->PROC_NR;
X tp->tty_in_vir = m_ptr->ADDRESS;
X tp->tty_inleft = m_ptr->COUNT;
X
X /* Try to get chars. This call either gets enough, or gets nothing. */
X code = rd_chars(tp);
X
X caller = (int) tp->tty_inproc;
X tty_reply(TASK_REPLY, m_ptr->m_source, caller, code, 0L, 0L);
X}
X
X
X/*===========================================================================*
X * rd_chars *
X *===========================================================================*/
X
XPRIVATE int rd_chars(tp)
Xregister struct tty_struct *tp; /* pointer to terminal to read from */
X{
X/* A process wants to read from a terminal. First check if enough data is
X * available. If so, pass it to the user. If not, send FS a message telling
X * it to suspend the user. When enough data arrives later, the tty driver
X * copies it to the user space directly and notifies FS with a message.
X */
X
X int cooked, ct, user_ct, buf_ct, cum, enough, eot_seen;
X vir_bytes in_vir, left;
X phys_bytes user_phys, tty_phys;
X char ch, *tty_ptr;
X struct proc *rp;
X extern phys_bytes umap();
X static char tty_buf[256]; /* scratch buffer to/from user space */
X
X message rstty_mess;
X
X/* for midi and rs232, call a get routine to fill the tty queue */
X cooked = ( (tp->tty_mode & (RAW | CBREAK)) ? 0 : 1); /* 1 iff COOKED mode */
X if (tp->tty_incount == 0 || (cooked && tp->tty_lfct == 0)) return(SUSPEND);
X rp = proc_addr(tp->tty_inproc);
X in_vir = (vir_bytes) tp-> tty_in_vir;
X left = (vir_bytes) tp->tty_inleft;
X if ( (user_phys = umap(rp, D, in_vir, left)) == 0) return(E_BAD_ADDR);
X tty_phys = umap(proc_addr(TTY), D, (vir_bytes) tty_buf, (vir_bytes) sizeof(tty_buf));
X cum = 0;
X enough = 0;
X eot_seen = 0;
X
X /* The outer loop iterates on buffers, one buffer load per iteration. */
X while (tp->tty_inleft > 0) {
X buf_ct = MIN(tp->tty_inleft, tp->tty_incount);
X buf_ct = MIN(buf_ct, sizeof(tty_buf));
X ct = 0;
X tty_ptr = tty_buf;
X
X /* The inner loop fills one buffer. */
X while(buf_ct-- > 0) {
X ch = *tp->tty_intail++;
X if (tp->tty_intail == &tp->tty_inqueue[TTY_IN_BYTES])
X tp->tty_intail = tp->tty_inqueue;
X *tty_ptr++ = ch;
X ct++;
X if (ch == '\n' || ch == MARKER) {
X tp->tty_lfct--;
X if (cooked && ch == MARKER) eot_seen++;
X enough++; /* exit loop */
X if (cooked) break; /* only provide 1 line */
X }
X }
X
X /* Copy one buffer to user space. Be careful about CTRL-D. In cooked
X * mode it is not transmitted to user programs, and is not counted as
X * a character as far as the count goes, but it does occupy space in
X * the driver's tables and must be counted there.
X */
X user_ct = (eot_seen ? ct - 1 : ct); /* bytes to copy to user */
X phys_copy(tty_phys, user_phys, (phys_bytes) user_ct);
X user_phys += user_ct;
X cum += user_ct;
X tp->tty_inleft -= ct;
X tp->tty_incount -= ct;
X if (tp->tty_incount == 0 || enough) break;
X }
X if(tp->tty_incount == 0 && tp->tty_inleft && !enough && Rs_blocked) {
X ct = lock();
X rstty_mess.m_type = TTY_CHAR_INT;
X rstty_mess.ADDRESS = (char *)0 ;
X interrupt(RS232, &rstty_mess); /* send message to tty task */
X restore(ct);
X }
X
X tp->tty_inleft = 0;
X return(cum);
X}
X
X
X/*===========================================================================*
X * finish *
X *===========================================================================*/
XPRIVATE finish(tp, code)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xint code; /* reply code */
X{
X/* A command has terminated (possibly due to DEL). Tell caller. */
X
X int replyee, caller;
X
X tp->tty_outleft = 0;
X#ifdef ATARI_ST
X (proc_addr(tp->tty_outproc))->p_physio = 0; /* enable (un)shadowing */
X#endif
X if (tp->tty_waiting == NOT_WAITING) return;
X replyee = (int) tp->tty_otcaller;
X caller = (int) tp->tty_outproc;
X tty_reply(TASK_REPLY, replyee, caller, code, 0L, 0L);
X tp->tty_waiting = NOT_WAITING;
X}
X
X
X/*===========================================================================*
X * do_write *
X *===========================================================================*/
XPRIVATE do_write(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xmessage *m_ptr; /* pointer to message sent to the task */
X{
X/* A process wants to write on a terminal. */
X
X vir_bytes out_vir, out_left;
X struct proc *rp;
X extern phys_bytes umap();
X
X /* Copy message parameters to the tty structure. */
X tp->tty_otcaller = m_ptr->m_source;
X tp->tty_outproc = m_ptr->PROC_NR;
X tp->tty_out_vir = m_ptr->ADDRESS;
X tp->tty_outleft = m_ptr->COUNT;
X tp->tty_waiting = WAITING;
X tp->tty_cum = 0;
X
X /* Compute the physical address where the data is in user space. */
X rp = proc_addr(tp->tty_outproc);
X out_vir = (vir_bytes) tp->tty_out_vir;
X out_left = (vir_bytes) tp->tty_outleft;
X if ( (tp->tty_phys = umap(rp, D, out_vir, out_left)) == 0) {
X /* Buffer address provided by user is outside its address space. */
X tp->tty_cum = E_BAD_ADDR;
X tp->tty_outleft = 0;
X }
X#ifdef ATARI_ST
X rp->p_physio = 1; /* disable (un)shadowing */
X#endif
X
X /* Copy characters from the user process to the terminal. */
X if ((*tp->tty_start)(tp)) /* copy data to queue and start I/O */
X finish(tp, tp->tty_cum);
X}
X
X
X/*===========================================================================*
X * do_ioctl *
X *===========================================================================*/
XPRIVATE do_ioctl(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty_struct */
Xmessage *m_ptr; /* pointer to message sent to task */
X{
X/* Perform IOCTL on this terminal. */
X
X long flags, erki, erase, kill, intr, quit, xon, xoff, eof, baud;
X int r;
X
X r = OK;
X flags = 0;
X erki = 0;
X switch(m_ptr->TTY_REQUEST) {
X case TIOCSETP:
X /* Set erase, kill, and flags. */
X baud = (char) ((m_ptr->TTY_SPEK >> 16) & BYTE); /* ispeed */
X tp->tty_baud = (char) ((m_ptr->TTY_SPEK >> 16) & BYTE); /* ispeed */
X tp->tty_erase = (char) ((m_ptr->TTY_SPEK >> 8) & BYTE); /* erase */
X tp->tty_kill = (char) ((m_ptr->TTY_SPEK >> 0) & BYTE); /* kill */
X tp->tty_mode = (int) m_ptr->TTY_FLAGS; /* mode word */
X if(baud != tp->tty_baud)
X r = (*tp->tty_ioctl)(tp, m_ptr);
X break;
X
X case TIOCSETC:
X /* Set intr, quit, xon, xoff, eof (brk not used). */
X
X tp->tty_intr = (char) ((m_ptr->TTY_SPEK >> 24) & BYTE); /* interrupt */
X tp->tty_quit = (char) ((m_ptr->TTY_SPEK >> 16) & BYTE); /* quit */
X tp->tty_xon = (char) ((m_ptr->TTY_SPEK >> 8) & BYTE); /* CTRL-S */
X tp->tty_xoff = (char) ((m_ptr->TTY_SPEK >> 0) & BYTE); /* CTRL-Q */
X tp->tty_eof = (char) ((m_ptr->TTY_FLAGS >> 8) & BYTE); /* CTRL-D */
X break;
X
X case TIOCGETP:
X /* Get erase, kill, and flags. */
X erase = ((long) tp->tty_erase) & BYTE;
X kill = ((long) tp->tty_kill) & BYTE;
X baud = ((long) tp->tty_baud) & BYTE;
X erki = (baud << 16) | (erase << 8) | kill;
X flags = (long) tp->tty_mode;
X break;
X
X case TIOCGETC:
X /* Get intr, quit, xon, xoff, eof. */
X intr = ((long) tp->tty_intr) & BYTE;
X quit = ((long) tp->tty_quit) & BYTE;
X xon = ((long) tp->tty_xon) & BYTE;
X xoff = ((long) tp->tty_xoff) & BYTE;
X eof = ((long) tp->tty_eof) & BYTE;
X erki = (intr << 24) | (quit << 16) | (xon << 8) | (xoff << 0);
X flags = (eof <<8);
X break;
X
X case TIOCSTART:
X case TIOCSTOP:
X rstty_init();
X r = (*tp->tty_ioctl)(tp, m_ptr);
X break;
X case TCSETAW: /* wait for output to drain */
X r = (*tp->tty_ioctl)(tp, m_ptr);
X /* Set erase, kill, and flags. */
X tp->tty_baud = (char) ((m_ptr->TTY_SPEK >> 16) & BYTE); /* ispeed */
X tp->tty_erase = (char) ((m_ptr->TTY_SPEK >> 8) & BYTE); /* erase */
X tp->tty_kill = (char) ((m_ptr->TTY_SPEK >> 0) & BYTE); /* kill */
X tp->tty_mode = (int) m_ptr->TTY_FLAGS; /* mode word */
X break;
X case TCSETAF: /* wait for output to drain, then flush input */
X r = (*tp->tty_ioctl)(tp, m_ptr);
X /* Set erase, kill, and flags. */
X tp->tty_baud = (char) ((m_ptr->TTY_SPEK >> 16) & BYTE); /* ispeed */
X tp->tty_erase = (char) ((m_ptr->TTY_SPEK >> 8) & BYTE); /* erase */
X tp->tty_kill = (char) ((m_ptr->TTY_SPEK >> 0) & BYTE); /* kill */
X tp->tty_mode = (int) m_ptr->TTY_FLAGS; /* mode word */
X break;
X case TCSBRK: /* drain output, send a break */
X r = (*tp->tty_ioctl)(tp, m_ptr);
X break;
X case TCXONC: /* start/stop output arg ==0 stop, ==1 start */
X r = (*tp->tty_ioctl)(tp, m_ptr);
X break;
X case TCFLSH: /* flush: 0==input 1==output 2=both */
X r = (*tp->tty_ioctl)(tp, m_ptr);
X break;
X
X default:
X r = EINVAL;
X }
X
X /* Send the reply. */
X tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r, flags, erki);
X}
X
X
X/*===========================================================================*
X * do_setpgrp *
X *===========================================================================*/
XPRIVATE do_setpgrp(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty struct */
Xmessage *m_ptr; /* pointer to message sent to task */
X{
X/* A control process group has changed */
X
X if((tp->tty_pgrp = m_ptr->TTY_PGRP) )
X (*tp->tty_open)(tp); /* do a device open to force midi/rs232 startup */
X tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, OK, 0L, 0L);
X}
X
X
X/*===========================================================================*
X * do_cancel *
X *===========================================================================*/
XPRIVATE do_cancel(tp, m_ptr)
Xregister struct tty_struct *tp; /* pointer to tty_struct */
Xmessage *m_ptr; /* pointer to message sent to task */
X{
X/* A signal has been sent to a process that is hanging trying to read or write.
X * The pending read or write must be finished off immediately.
X */
X
X /* First check to see if the process is indeed hanging. If it is not, don't
X * reply (to avoid race conditions).
X */
X if (tp->tty_inleft == 0 && tp->tty_outleft == 0) return;
X
X /* Kill off input and output. */
X tp->tty_inhead = tp->tty_inqueue; /* discard all input */
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_incount = 0;
X tp->tty_lfct = 0;
X tp->tty_inleft = 0;
X tp->tty_outleft = 0;
X tp->tty_waiting = NOT_WAITING; /* don't send reply */
X tp->tty_inhibited = RUNNING;
X tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EINTR, 0L, 0L);
X}
X
X
X/*===========================================================================*
X * tty_reply *
X *===========================================================================*/
XPRIVATE tty_reply(code, replyee, proc_nr, status, extra, other)
Xint code; /* TASK_REPLY or REVIVE */
Xint replyee; /* destination address for the reply */
Xint proc_nr; /* to whom should the reply go? */
Xint status; /* reply code */
Xlong extra; /* extra value */
Xlong other; /* used for IOCTL replies */
X{
X/* Send a reply to a process that wanted to read or write data. */
X
X message rstty_mess;
X
X rstty_mess.m_type = code;
X rstty_mess.REP_PROC_NR = proc_nr;
X rstty_mess.REP_STATUS = status;
X rstty_mess.TTY_FLAGS = extra; /* used by IOCTL for flags (mode) */
X rstty_mess.TTY_SPEK = other; /* used by IOCTL for erase and kill chars */
X send(replyee, &rstty_mess);
X}
X
X/*===========================================================================*
X * sigchar *
X *===========================================================================*/
XPRIVATE sigchar(tp, sig)
Xregister struct tty_struct *tp; /* pointer to tty_struct */
Xint sig; /* SIGINT, SIGQUIT, or SIGKILL */
X{
X/* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard */
X
X tp->tty_inhibited = RUNNING; /* do implied CRTL-Q */
X finish(tp, EINTR); /* send reply */
X tp->tty_inhead = tp->tty_inqueue; /* discard input */
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_incount = 0;
X tp->tty_lfct = 0;
X if (tp->tty_pgrp)
X cause_sig(tp->tty_pgrp, sig);
X}
X
X
X/*===========================================================================*
X * rstty_init *
X *===========================================================================*/
XPRIVATE rstty_init()
X{
X/* Initialize the tty tables. */
X
X register struct tty_struct *tp;
X int i;
X
X for (i = 0; i < NR_RS232; i++) {
X tp = &rstty_struct[i];
X tp->tty_inhead = tp->tty_inqueue; /* discard all input */
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_incount = 0;
X tp->tty_lfct = 0;
X tp->tty_inleft = 0;
X tp->tty_outleft = 0;
X tp->tty_waiting = NOT_WAITING; /* don't send reply */
X tp->tty_inhibited = RUNNING;
X tp->tty_mode = CRMOD | XTABS | ECHO ;
X
X tp->tty_erase = ERASE_CHAR;
X tp->tty_kill = KILL_CHAR;
X tp->tty_intr = INTR_CHAR;
X tp->tty_quit = QUIT_CHAR;
X tp->tty_xon = XON_CHAR;
X tp->tty_xoff = XOFF_CHAR;
X tp->tty_eof = EOT_CHAR;
X Rs232_wempty = 0;
X rs232init(tp);
X }
X}
X
Xrstty_dmp()
X{
X struct tty_struct *tp;
X
X tp = &rstty_struct[0];
X
Xprintf("\rTTY for RS232: cnt_max=%d\n\
X\r\tinhead=%lx intail=%lx inqueue=%lx mode=%x\n\
X\r\terase=%x kill=%x intr=%x quit=%x xon=%x xoff=%x eof=%x\n\
X\r\tincount=%d lfct=%d escaped=%x inhibited=%x waiting=%x\n\
X\r\tincaller=%d inproc=%d in_vir=%lx inleft=%d otcaller=%d outproc=%d\n\
X\r\t out_vir=%lx phys=%lx outleft=%d cum=%d pgrp=%d baud=%x\n\r",
Xcnt_max,
X tp->tty_inhead ,
X tp->tty_intail , tp->tty_inqueue,
X tp->tty_mode ,
X
X tp->tty_erase ,
X tp->tty_kill ,
X tp->tty_intr ,
X tp->tty_quit ,
X tp->tty_xon ,
X tp->tty_xoff ,
X tp->tty_eof ,
X tp->tty_incount, tp->tty_lfct, tp->tty_escaped, tp->tty_inhibited,
X tp->tty_waiting,
X tp->tty_incaller, /* process that made the call (usually FS) */
X tp->tty_inproc, /* process that wants to read from tty */
X tp->tty_in_vir, /* virtual address where data is to go */
X tp->tty_inleft, /* how many chars are still needed */
X tp->tty_otcaller, /* process that made the call (usually FS) */
X tp->tty_outproc, /* process that wants to write to tty */
X tp->tty_out_vir, /* virtual address where data comes from */
X tp->tty_phys, /* physical address where data comes from */
X tp->tty_outleft, /* # chars yet to be copied to tty_outqueue */
X tp->tty_cum, /* # chars copied to tty_outqueue so far */
X tp->tty_pgrp, /* Slot number of controlling process */
X tp->tty_baud /* index of baud (rs232) */
X );
X}
SHAR_EOF
echo extracting 'rs232.c'
sed -e 's/^X//' >rs232.c <<'SHAR_EOF'
X/* RS232 driver */
X#include "../h/const.h"
X#include "../h/type.h"
X#include "../h/callnr.h"
X#include "../h/com.h"
X#include "../h/error.h"
X#include "../h/sgtty.h"
X#include "../h/signal.h"
X#include "const.h"
X#include "type.h"
X#include "proc.h"
X#include "tty.h"
X#include "stacia.h"
X#include "stmfp.h"
X#include "stsound.h"
X#include "staddr.h"
X#include "glo.h"
X#include "ring.h"
X
XPRIVATE dbg_flag = 0;
XPRIVATE message commes; /* message used for console input chars */
X
XPUBLIC struct ring rs232ring;
X#define COM_OUT_SIZE 512
XPRIVATE char com_out_buffer[COM_OUT_SIZE];
X
X#define COM_IN_SIZE 512
XPRIVATE char com_in_buffer[COM_IN_SIZE];
X
XPRIVATE int rs232_o_flag = 0;
XPRIVATE int Xmit_on = 0;
X
Xextern struct tty_struct rstty_struct[];
X
X#define T_BITS IA_TRDY
X#define R_BITS IA_RRDY
X#define RENABLE() MFP->mf_imra |= (R_BITS)
X#define RDISABLE() MFP->mf_imra &= ~(R_BITS)
X#define TENABLE() MFP->mf_imra |= (T_BITS)
X#define TDISABLE() MFP->mf_imra &= ~(IA_TERR | T_BITS)
X
Xint set_timer();
X
X/*
X * This file contains the device_dependent part of the rs232 driver.
X *
X */
X
X/*===========================================================================*
X * open *
X *===========================================================================*/
XPRIVATE int open(tp)
Xregister struct tty_struct *tp;
X{
X int s;
X int i;
X
X if(rs232_o_flag ==0) {
X rs232_o_flag = 1;
X s = lock();
X rs232init(tp); /* will turn off all interrupts */
X restore(s);
X }
X}
X
X
X/*===========================================================================*
X * close *
X *===========================================================================*/
XPRIVATE int close(tp)
Xregister struct tty_struct *tp;
X{
X MFP->mf_imra &= ~( IA_RRDY | IA_TRDY | IA_TERR | IA_RERR);
X rs232_o_flag = 0;
X Xmit_on = 0;
X}
X/*===========================================================================*
X * ioctl *
X *===========================================================================*/
X
XPRIVATE int ioctl(tp,m_ptr)
Xregister struct tty_struct *tp;
Xmessage *m_ptr;
X{
X long i;
X
X switch(m_ptr->TTY_REQUEST) {
X case TIOCSTART:
X open(tp);
X return(OK);
X case TIOCSTOP:
X close(tp);
X return(OK);
X case TIOCSETP:
X set_timer(tp->tty_baud);
X case TCSETAW: /* wait for output to drain */
X while(rs232ring.o_head != rs232ring.o_tail);
X return(OK);
X case TCSETAF: /* wait for output to drain, then flush input */
X while(rs232ring.o_head != rs232ring.o_tail);
X rs232ring.i_head = rs232ring.i_tail = 0;
X tp->tty_inhead = tp->tty_inqueue;
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_incount = 0;
X tp->tty_lfct = 0;
X tp->tty_inleft = 0;
X tp->tty_outleft = 0;
X return(OK);
X case TCSBRK: /* drain output, send a break */
X while(rs232ring.o_head != rs232ring.o_tail);
X MFP->mf_tsr = T_BREAK | T_ENA;
X for(i=0;i<30000;i++) ;
X MFP->mf_tsr = T_ENA;
X return(OK);
X case TCXONC: /* start/stop output arg ==0 stop, ==1 start */
X switch((int)m_ptr->TTY_SPEK) {
X case 0:
X break;
X case 1:
X break;
X }
X return(OK);
X case TCFLSH: /* flush: 0==input 1==output 2=both */
X switch((int)m_ptr->TTY_SPEK) {
X case 0:
X rs232ring.i_head = rs232ring.i_tail;
X tp->tty_inhead = tp->tty_inqueue;
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_incount = 0;
X tp->tty_lfct = 0;
X tp->tty_inleft = 0;
X tp->tty_outleft = 0;
X break;
X case 1:
X rs232ring.o_head = rs232ring.o_tail;
X break;
X case 2:
X rs232ring.i_head = rs232ring.i_tail;
X rs232ring.o_head = rs232ring.o_tail;
X break;
X }
X return(OK);
X }
X}
X
XPUBLIC rs232charint()
X{
X /* Build and send the interrupt message. */
Xif(dbg_flag)
Xprintf("sia_rrdy charint msg n=%d\n\r",rs232ring.i_head - rs232ring.i_tail);
X commes.m_type = TTY_CHAR_INT;
X commes.ADDRESS = (char *)0 ;
X interrupt(RS232, &commes); /* send message to tty task */
X}
X
X
X/*===========================================================================*
X * start *
X *===========================================================================*/
X
XPRIVATE int start(tp)
Xregister struct tty_struct *tp;
X{
X int r;
X int i;
X register int k;
X
X if(rs232_o_flag == 0) {
X rs232_o_flag++;
X r = lock();
X rs232init();
X
X
X restore(r);
X }
X
X if (tp->tty_outleft == 0)
X return(1);
Xif(dbg_flag)
Xprintf("Start left=%d\n\r",tp->tty_outleft);
X do {
X if((r = rs232put( *(char*)tp->tty_phys)) == 0)
X break;
X tp->tty_phys++;
X tp->tty_cum++; /* number of characters printed */
X } while ( --tp->tty_outleft != 0 );
X return(r);
X}
X/*===========================================================================*
X * echo *
X *===========================================================================*/
XPRIVATE echo(tp, c)
Xregister struct tty_struct *tp;
X{
X rs232put(c);
X}
X/*
X * This file contains the device_dependent part of the rs232 driver.
X *
X */
X
X/*===========================================================================*
X * siaint *
X *===========================================================================*/
X
XPUBLIC siaint(which)
Xint which; /* 0=rrdy, 1=rerr, 2=trdy, 3=terr */
X{
X switch(which) {
X case 1: /* rerr */
X printf("sia_rerr\n\r");
X break;
X case 3: /* terr */
X printf("sia_terr\n\r");
X break;
X case 0: /* rrdy */
X sia_rrdy();
X break;
X case 2: /* trdy */
X sia_trdy();
X break;
X }
X}
X
X/*===========================================================================*
X * sia_rrdy *
X *===========================================================================*/
X
XPRIVATE sia_rrdy()
X{
X rs232rrdy();
X}
X/*===========================================================================*
X * sia_trdy *
X *===========================================================================*/
X
XPRIVATE sia_trdy()
X{
X rs232trdy();
X}
X
X
X/*===========================================================================*
X * rs232_init *
X *===========================================================================*/
XPUBLIC rs232init(tp)
Xregister struct tty_struct *tp;
X{
X int i;
X struct ring *rp = &rs232ring;
X
X
X rs232_o_flag = 1;
X rp->i_buffer = com_in_buffer;
X rp->i_length = COM_IN_SIZE;
X rp->i_head = 0;
X rp->i_tail = 0;
X rp->i_lo_water = (TTY_IN_BYTES / 16); /* restart at this level */
X rp->i_hi_water = (TTY_IN_BYTES / 4); /* send xoff function at this level */
X rp->i_lo_water = (16); /* restart at this level */
X rp->i_hi_water = (64); /* send xoff function at this level */
X
X rp->o_buffer = com_out_buffer;
X rp->o_length = COM_OUT_SIZE;
X rp->o_head = 0;
X rp->o_tail = 0;
X rp->o_lo_water = COM_OUT_SIZE / 4;
X rp->o_hi_water = 3 * COM_OUT_SIZE / 4;
X
X rp->rx_stat = 0;
X rp->tx_stat = 0;
X rp->xoff_flag = 0;
X rp->xon_flag = 0;
X rp->rtscts = 1;
X rp->xoff_char = XOFF_CHAR;
X rp->xon_char = XON_CHAR;
X
X tp->tty_start = start;
X tp->tty_echo = echo;
X tp->tty_open = open;
X tp->tty_close = close;
X tp->tty_ioctl = ioctl;
X MFP->mf_imra &= ~( IA_RRDY | IA_TRDY | IA_TERR | IA_RERR);
X MFP->mf_tsr = 0;
X tp->tty_inhead = tp->tty_inqueue;
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_mode = CRMOD | XTABS | ECHO;
X tp->tty_erase = ERASE_CHAR;
X tp->tty_kill = KILL_CHAR;
X tp->tty_intr = INTR_CHAR;
X tp->tty_quit = QUIT_CHAR;
X tp->tty_xon = XON_CHAR;
X tp->tty_xoff = XOFF_CHAR;
X tp->tty_eof = EOT_CHAR;
X tp->tty_baud = B2400;
X Xmit_on = 0;
X tp->tty_inhibited = 0;
X MFP->mf_rsr = 0;
X MFP->mf_tsr = T_HIGH;
X set_timer(tp->tty_baud);
X MFP->mf_ucr = U_Q16 | U_ST2;
X MFP->mf_rsr = R_ENA;
X MFP->mf_tsr |= T_ENA;
X MFP->mf_ierb &= ~(IB_SCTS | IB_SDCD);
X MFP->mf_iera |= ( R_BITS | T_BITS); /* start receive */
X MFP->mf_imra |= (T_BITS | R_BITS);
X
X dtr_on();
X rts_on();
X
X}
X/*===========================================================================*
X * set_timer *
X *===========================================================================*/
XPRIVATE struct baud {
X unsigned char prescale;
X unsigned char scale;
X} baud[] = {
X T_Q004, 1, /* 0 19200 divided by 1 */
X T_Q004, 2, /* 1 9600 */
X T_Q004, 4, /* 2 4800 */
X T_Q004, 5, /* 3 3600 */
X T_Q004, 8, /* 4 2400 */
X T_Q004, 10, /* 5 2000 */
X T_Q004, 11, /* 6 1800 */
X T_Q004, 16, /* 7 1200 */
X T_Q004, 32, /* 8 600 */
X T_Q004, 64, /* 9 300 */
X T_Q004, 96, /* a 200 */
X T_Q004, 128, /* b 150 */
X T_Q004, 143, /* c 134 */
X T_Q004, 175, /* d 110 */
X T_Q016, 64, /* e 75 */
X T_Q016, 96, /* f 50 */
X};
X
XPRIVATE set_timer(index)
X{
X/*
X * Initialize the timer D in the MFP 68901.
X */
X int clock;
X int clocka;
X
X clock = MFP->mf_tcdcr & 0x70;
X for(;;) {
X clocka = MFP->mf_tcdcr & 0x70;
X if(clock != clocka) {
X clock = clocka;
X continue;
X }
X break;
X }
X do
X MFP->mf_tddr = baud[index].scale;
X while ((MFP->mf_tddr & 0xFF) != baud[index].scale);
X MFP->mf_tcdcr = clock | baud[index].prescale;
X}
Xrs232_dmp()
X{
X dbg_flag ^=1;
X printf("DMP:ohead=%d otail=%d ihead=%d itail=%d iera=%x imra=%x\n\r",
X rs232ring.o_head, rs232ring.o_tail,
X rs232ring.i_head, rs232ring.i_tail,
X MFP->mf_iera, MFP->mf_imra);
X printf("\tdbgflg=%d Xmit_on=%d tsr=%x rsr=%x\n\r",
X dbg_flag,Xmit_on,MFP->mf_tsr,MFP->mf_rsr);
X printf("\tring flgs: tx=%x rx=%x xoff=%x on=%x dtrcts=%x\n\r",
X rs232ring.rx_stat, rs232ring.tx_stat,
X rs232ring.xoff_flag, rs232ring.xon_flag,
X rs232ring.rtscts);
X}
XRsdebuger(x)
X{
X printf("Rsdebuger(%x)\n",x);
X}
SHAR_EOF
echo extracting 'rs232s.s'
sed -e 's/^X//' >rs232s.s <<'SHAR_EOF'
X
X! entry points
X .define _rs232get !get chars from input ring
X .define _rs232put !put chars to output ring
X .define _rs232rrdy !process rec char interrupt
X .define _rs232trdy !process xmit char interrupt
X .define _rs232cts !process cts interrupt
X .define _dtr_on !turn on dtr
X .define _rts_on !turn on cts
X .define _dtr_off !turn off dtr
X .define _rts_off !turn off cts
X
X .extern _rs232ring !input and output rings
X .extern _rs232charint !sends a charint message
X .extern _Rs232_wempty !a flag cleared in do_odone
X
X .extern _Rsdebuger
X
X .sect .text
X .sect .rom
X .sect .data
X .sect .bss
X
X .sect .text
X_setjmp:
X!
X! ring buffer offsets locked to ring.h
X!
Xi_buffer = 0
Xi_length = 4
Xi_head = 6
Xi_tail = 8
Xi_lo_wat = 0xa
Xi_hi_wat = 0xc
Xo_buffer = 0xe
Xo_length = 0x12
Xo_head = 0x14
Xo_tail = 0x16
Xo_low_wat = 0x18
Xo_hi_wat = 0x1a
Xrs_data = 0x1c
Xts_data = 0x1d
Xxoff_flag = 0x1e
Xxon_flag = 0x1f
Xrtscts_flag = 0x20
Xxoff_char = 0x21
Xxon_char = 0x22
X
X .sect .text
X! setup a0, a1 for routines
Xrs232ptr:
X lea _rs232ring,a0 ! pointer to rs232 iorec
X lea 0xfffffa01,a1 ! pointer to mfp
X rts ! 4e75
X
X! compute actual size of input ring in use (tail - head)
Xrs232ibuf:
X move i_tail(a0),d2 ! tail index
X move i_head(a0),d3 ! head index
X cmp.w d3,d2 ! head > tail ?
X bhi L1 ! no
X add.w i_length(a0),d2 ! add buffer size
XL1:
X sub.w d3,d2 ! tail - head
X rts ! 4e75
Xrtschk:
X btst #0x1,rtscts_flag(a0) ! RTS/CTS mode
X beq L2 ! no
X bsr rts_on ! rts on
XL2:
X rts ! 4e75
X
X_rs232put:
X move.w 4(a7), d1
Xcomput:
X movem.l d2-d3,-(a7) ! save regs
X move.w sr,-(a7) ! save status
X or.w #0x700,sr ! IPL 7, disable interrupts
X bsr rs232ptr ! get buffer pointer
X btst #0x0,rtscts_flag(a0) ! XON/XOFF mode?
X beq L4 ! no
X tst.b xoff_flag(a0) ! XON active?
X bne L5 ! yes
XL4:
X btst #0x7,0x2c(a1) ! is MFP still sending?
X beq L5 ! yes
X move.w o_head(a0),d2 ! head index
X cmp.w o_tail(a0),d2 ! tail index
X bne L5 ! still chars in buffer?
X move.b d1,0x2e(a1) ! no, pass_data to mfp
X bra L6 !.data has been sent
X!queue the.data
XL5:
X move.w o_tail(a0),d2 ! tail index
X bsr wrapout ! test for wrap around
X cmp.w o_head(a0),d2 ! compare with head index
X!if buffer is full, just dump the char, boo!
X beq L7 ! same, buffer is full
X move.l o_buffer(a0),a1 ! get current buffer address
X move.b d1,0x0(a1,d2.w) ! write char in buffer
X move.w d2,o_tail(a0) ! save new tail index
XL6:
X bsr rtschk ! rschk, set RTS?
X move (a7)+,sr ! restore status
X move.l #1,d0 ! char sent
X movem.l (a7)+,d2-d3 ! restore regs
X rts ! 4e75
XL7:
X bsr rtschk ! rschk, set RTS?
X move (a7)+,sr ! restore status
X move.l #0,d0 ! char not sent
X movem.l (a7)+,d2-d3 ! restore regs
X rts ! 4e75
X
X_rs232get: !rs232 input
X movem.l d2-d3,-(a7) ! save regs
X move sr,-(a7) ! save status
X or.w #0x700,sr ! IPL 7, disable interrupts
X bsr rs232ptr ! get rs232 pointer
X move i_head(a0),d1 ! head index
X cmp.w i_tail(a0),d1 ! tail index
X beq L10 ! no char in buffer ?
X bsr wrapin ! test for wrap arround
X move.l i_buffer(a0),a1 ! get buffer address
X move.l #0x0,d0 ! 7000
X move.b 0x0(a1,d1.w),d0 ! get char from the buffer
X move d1,i_head(a0) ! set new head index
X!move (a7)+,sr ! restore status
X!and.b #0xfe,ccr ! clear carry flag, OK
X bra L9 ! 6006
XL10:
Xmove.w #0x100,d0 !1xx if no char
X
X!move (a7)+,sr ! restore status
X!or.b #0x1,ccr ! set carry flag, no chars in buffer
X
XL9:
Xmove.w d0,-(a7)
X btst #0x0,rtscts_flag(a0) ! XON/XOFF mode ?
X beq L11 ! no
X tst.b xon_flag(a0) ! XON active ?
X beq L11 ! no
X bsr rs232ibuf ! get input buffer, and length
X cmp.w i_lo_wat(a0),d2 ! equal low water mark?
X bne L11 ! no
X move.b xon_char(a0),d1 ! this is XON
X bsr comput ! send it
X!movem.l d0-d1/a0-a1,-(a7) ! save regs
X!move d1,-(a7)
X!jsr _Rsdebuger
X!add.l #2,a7
X!movem.l (a7)+,d0-d1/a0-a1 ! restore regs
X clr.b xon_flag(a0) ! clear the XON flag
XL11:
X move (a7)+,d0 ! return value
X move (a7)+,sr ! restore status
X movem.l (a7)+,d2-d3 ! restore regs
X rts ! 4e75
X
X!rs232 receiver interrupt routine
X! called as a C program
X_rs232rrdy:
Xrcvint:
X movem.l d2-d3/a2,-(a7) ! save regs
X bsr rs232ptr ! get rs232 pointer
X move.b 0x2a(a1),rs_data(a0) ! read receiver status reg
X btst #0x7,rs_data(a0) ! interrupt through receiver buffer full
X beq R2 ! no
X btst #0x1,rtscts_flag(a0) ! RTS/CTS mode?
X beq R1 ! no
X bsr rts_off ! rts off
XR1:
X move.b 0x2e(a1),d0 ! read data from rec. register
X btst #0x1,rtscts_flag(a0) ! RTS/CTS mode?
X bne R3 ! yes
X btst #0x0,rtscts_flag(a0) ! XON/XOFF mode?
X beq R3 ! no
X cmp.b xon_char(a0),d0 ! XON received?
X bne R4 ! no
X move.b #0x0,xoff_flag(a0) ! clear XOFF flag
X move o_head(a0),d2 ! get head index
X cmp.w o_tail(a0),d2 ! == to tail?
X beq R2 ! yes
X bsr wrapout ! wrap the pointer
X move.l o_buffer(a0),a2 ! get the output buffer
X move.b 0x0(a2,d2.w),0x2e(a1) ! 1372 2000 002e
X move d2,o_head(a0) ! 3142 0014
X bra R2 ! 6062
XR4:
X cmp.b xoff_char(a0),d0 ! receive XOFF?
X bne R3 ! no
X move.b #0xff,xoff_flag(a0) ! save flag
X bra R2 ! char not in buffer
XR3:
X move i_tail(a0),d1 ! 3228 0008
X bsr wrapin ! 6100 01f8
X cmp.w i_head(a0),d1 ! b268 0006
X beq R2 ! yes, head == tail
X move.l i_buffer(a0),a2 ! get buffer address
X move.b d0,0x0(a2,d1.w) ! put.data in the buffer
X move d1,i_tail(a0) ! save new tail index
X bsr rs232ibuf ! get input length
X cmp.w i_hi_wat(a0),d2 ! == high water?
X bne L12 ! no
X btst #0x1,rtscts_flag(a0) ! tst if rts/cts mode
X bne R2 ! yes
X btst #0x0,rtscts_flag(a0) ! xon/xoff mode
X beq L12 ! no
X tst.b xon_flag(a0) ! xoff sent already?
X bne L12 ! yes
X move.b #0xff,xon_flag(a0) ! set flag for xoff
X move.b xoff_char(a0),d1 ! get an xoff
X bsr comput ! send it
X
XL12:
X btst #0x1,rtscts_flag(a0) ! rtscts mode
X beq R2 ! no
X bsr rts_on ! rtson
XR2:
X jsr _rs232charint
X movem.l (a7)+,d2-d3/a2 ! restore regs
X rts
X
X_rs232trdy:
Xtxrint:
X movem.l d2/a2,-(a7) ! save registers
X bsr rs232ptr ! get rs232 pointer
X btst #0x1,rtscts_flag(a0) ! rtscts mode?
X bne T1 ! yes, then use this interrupt
X btst #0x0,rtscts_flag(a0) ! xonxoff mode?
X beq T2 ! no
X tst.b xoff_flag(a0) ! xoff active ?
X bne T1 ! yes
XT2:
X move.b 0x2c(a1),ts_data(a0) ! save transmit status reg
X move o_head(a0),d2 ! head index
X cmp.w o_tail(a0),d2 ! compare with tail
X beq T1A ! send buffer is empty
X!look, if buffer empty, dont change mfp, as only the TXRDY transition
X!causes the interrupt. NEAT
X!
X!but for minix, we will set a tx_empty flag, and send a charint message
X!charint will see and clear the flag, and call do_odone
X bsr wrapout ! test for wrap arround
X move.l o_buffer(a0),a2 ! pointer to send buffer
X move.b 0x0(a2,d2.w),0x2e(a1) ! pass_data to mfp
X move d2,o_head(a0) ! save new head
XT1:
X movem.l (a7)+,d2/a2 ! restore regs
X rts ! 4e73
XT1A:
X move.w #1, _Rs232_wempty
X jsr _rs232charint
X bra T1
X
X_rs232cts:
Xctsint: !cts interrupt routine
X movem.l d2/a2,-(a7) ! save regs
X bsr rs232ptr ! get rs232 pointer
X btst #0x1,rtscts_flag(a0) ! rtscts mode?
X beq T4 ! no, then ignore interrupt
X move.b 0x2c(a1),ts_data(a0) ! save xmit status
XT6:
X btst #0x7,ts_data(a0) ! trans buffer empty?
X beq T6 ! no, wait
X move o_head(a0),d2 ! get head index
X cmp.w o_tail(a0),d2 ! compare wiht tail index
X beq T5 ! transmit buffer empty
X bsr wrapout ! test for wrap
X move.l o_buffer(a0),a2 ! pointer to transmit buffer
X move.b 0x0(a2,d2.w),0x2e(a1) ! pass_data to mfp for sending
X move d2,o_head(a0) ! save new head index
XT4:
X bclr #0x2,0x10(a1) ! clear interrupt service bit
X movem.l (a7)+,d2/a2 ! restore regs
X rts ! 4e73
XT5:
X bra T4 ! transmit buffer empty
X
Xrxerror: !receive error
X movem.l d0/a0-a1,-(a7) ! save regs
X bsr rs232ptr ! get rs232 pointer
X move.b 0x2a(a1),rs_data(a0) ! save receiver status
X move.b 0x2e(a1),d0 ! read data register (to clear status)
X movem.l (a7)+,d0/a0-a1 ! restore regs
X rte ! 4e73
X
Xtxerror: !receive error
X movem.l a0-a1,-(a7) ! save regs
X bsr rs232ptr ! get rs232 pointer
X move.b 0x2c(a1),ts_data(a0) ! save transmitter status
X movem.l (a7)+,a0-a1 ! restore regs
X rte ! 4e73
X
X
Xwrapin: !test for wrap arround
X add.w #1,d1 ! head index + 1
X cmp.w i_length(a0),d1 ! equal to buffer size ?
X bcs W1 ! no
X move.l #0x0,d1 ! else start with zero again
XW1:
X rts ! 4e75
Xwrapout: !test for wrap arround
X add.w #1,d2 ! tail index +1
X cmp.w o_length(a0),d2 ! equal to buffer size?
X bcs W2 ! no
X move.l #0x0,d2 ! else start with zero again
XW2:
X rts ! 4e75
X!
X!change cts dtr bits in sound reg
X!only called at spl7
X!
Xsound_bits:
X movem.l d1-d2/a0,-(a7) ! save regs
X lea 0xffff8800,a0 ! 41f9 ffff 8800
X move.b d1,d2 ! 1401
X and.w #0xf,d1 ! 0201 000f
X move.b d1,(a0) ! 1081
X asl.b #1,d2 ! e302
X bcc L3 ! 6404
X move.b d0,0x2(a0) ! 1140 0002
XL3:
X move.w #0x0,d0 ! 7000
X move.b (a0),d0 ! 1010
X movem.l (a7)+,d1-d2/a0 ! restore regs
X rts ! 4e75
X
X_rts_off:
Xrts_off:
X move.w #0x8,d2 ! 7408
X bra do_off ! 6012
X_rts_on:
Xrts_on:
X move.w #0xf7,d2 ! 74f7
X bra do_on ! 6034
X_dtr_off:
Xdtr_off:
X move.w #0x10,d2 ! 7410
X bra do_off ! 600a
X_dtr_on:
Xdtr_on:
X move.w #0xef,d2 ! 74ef
X bra do_on ! 602c
X
X! turn off a bit input 8=cts 10=dtr
X_dtrctsoff:
X move.l #0x0,d2 ! 7400
X move 0x4(a7),d2 ! 342f 0004
X neg d2
Xdo_off:
X movem.l d0-d2,-(a7) ! save regs
X move.w sr,-(a7) ! 40e7
X or.w #0x700,sr ! 007c 0700
X move.w #0xe,d1 ! 720e
X move.l d2,-(a7) ! 2f02
X bsr sound_bits ! 61ae
X move.l (a7)+,d2 ! 241f
X or.b d2,d0 ! 8002
X move.w #0x8e,d1 ! 728e
X bsr sound_bits ! 61a6
X move.w (a7)+,sr ! 46df
X movem.l (a7)+,d0-d2 ! restore regs
X rts ! 4e75
X!
X! entry to turn on dtr bits
X_dtrctson:
X move.l #0x0,d2 ! 7400
X move 0x4(a7),d2 ! 342f 0004
Xdo_on:
X movem.l d0-d2,-(a7) ! save regs
X move.w sr,-(a7) ! 40e7
X or.w #0x700,sr ! 007c 0700
X move.w #0xe,d1 ! 720e
X move.l d2,-(a7) ! 2f02
X bsr sound_bits ! 6188
X move.l (a7)+,d2 ! 241f
X and.b d2,d0 ! c002
X move.w #0x8e,d1 ! 728e
X bsr sound_bits ! 6180
X move.w (a7)+,sr ! 46df
X movem.l (a7)+,d0-d2 ! restore regs
X rts ! 4e75
X
SHAR_EOF
echo extracting 'ring.h'
sed -e 's/^X//' >ring.h <<'SHAR_EOF'
X
Xstruct ring {
X char *i_buffer;
X int i_length;
X int i_head;
X int i_tail;
X int i_lo_water;
X int i_hi_water;
X
X char *o_buffer;
X int o_length;
X int o_head;
X int o_tail;
X int o_lo_water;
X int o_hi_water;
X
X char rx_stat;
X char tx_stat;
X char xoff_flag;
X char xon_flag;
X char rtscts;
X char xoff_char;
X char xon_char;
X};
SHAR_EOF