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