hcj@lzaz.ATT.COM (HC Johnson) (01/04/89)
This is midi.shar, the new midi files for adding rs232 and midi to
minix-st.
==============================================================
echo extracting 'midi.c'
sed -e 's/^X//' >midi.c <<'SHAR_EOF'
X/* MIDI 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 "staddr.h"
X#include "glo.h"
X#include "ring.h"
X
XPRIVATE dbg_flag = 0;
XPRIVATE Tx_active = 0;
XPRIVATE Tx_int = 0;
XPRIVATE message commes; /* message used for console input chars */
X
XPUBLIC struct ring midiring;
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 midi_o_flag = 0;
X
Xextern int Midi_wempty ;
X
X/*
X * This file contains the device_dependent part of the midi 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 int midiinit();
X
X midi_o_flag = 1;
X s = lock();
X midiinit(tp); /* will turn off all interrupts */
X tp->tty_inhead = tp->tty_inqueue;
X tp->tty_intail = tp->tty_inqueue;
X tp->tty_mode = RAW;
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 = 0;
X
X tp->tty_inhibited = 0;
X
X
X restore(s);
X MDI->ac_cs = MDI_INIT | A_RXINT;
X}
X
X
X/*===========================================================================*
X * close *
X *===========================================================================*/
XPRIVATE int close(tp)
Xregister struct tty_struct *tp;
X{
X midi_o_flag = 0;
X MDI->ac_cs = A_RESET;
X MDI->ac_cs = MDI_INIT ;
X}
X/*===========================================================================*
X * ioctl *
X *===========================================================================*/
X
XPRIVATE int ioctl(tp,m_ptr)
Xregister struct tty_struct *tp;
Xmessage *m_ptr;
X{
X int 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 default:
X return(EINVAL);
X }
X}
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
Xmidi_o_flag = 1;;
X if(midi_o_flag == 0) {
X midi_o_flag++;
X r = lock();
X open();
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 = midienque( *(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 midiqstart();
X return(r);
X}
X/*===========================================================================*
X * echo *
X *===========================================================================*/
XPRIVATE echo(tp, c)
Xregister struct tty_struct *tp;
X{
X midienque(c);
X midiqstart();
X}
X/*
X * This file contains the device_dependent part of the midi driver.
X *
X */
X
XPRIVATE midiput(c)
X{
Xif(dbg_flag)
Xprintf("midiput(%x)\n",c);
X while(( MDI->ac_cs & A_TXRDY) == 0) ;
X MDI->ac_cs = MDI_INIT | A_RXINT;
X MDI->ac_da = c;
X return(1);
X}
X
X/*===========================================================================*
X * mdiint *
X *===========================================================================*/
X
XPUBLIC mdiint()
X{
X int i,s;
X register k;
X
Xif(dbg_flag)
Xprintf("mdiint()\n\r");
X k = midiring.i_tail;
X/* we want to lock up here looking for an input burst */
X for (s=0; s<10000; s++) {
X for (;((i = MDI->ac_cs) & A_IRQ) ; ) {
X if( i & A_RXRDY) {
X midirrdy();
X s = 0;
X continue;
X }
X if(Tx_int && (i & A_TXRDY)) {
X Tx_int = 0;
X midiqstart();
X }
X }
X }
X if ( k != midiring.i_tail) {
X midicharint();
X }
X}
X
Xmidiqstart()
X{
X int n,s;
X
X if(Tx_int) { /* its active */
X return;
X }
X if(Tx_active) { /* send in progress */
X while(( MDI->ac_cs & A_TXRDY) == 0) ;
X MDI->ac_cs = MDI_INIT | A_RXINT;
X }
X if((n = midiring.o_tail - midiring.o_head) < 0)
X n += midiring.o_length;
X
X if(n == 0) {
X restore(s);
X return;
X } else if (n == 1) {
X Tx_active = 1;
X Tx_int = 0;
X MDI->ac_cs = MDI_INIT | A_RXINT;
X MDI->ac_da = midideque();
X Midi_wempty = 1;
X midicharint();
X } else {
X Tx_active = 0;
X Tx_int = 1;
X MDI->ac_cs = MDI_INIT | A_RXINT | A_TXINT;
X MDI->ac_da = midideque();
X }
X}
X
X
XPUBLIC midicharint()
X{
X /* Build and send the interrupt message. */
Xif(dbg_flag)
Xprintf("mdi_rrdy charint msg n=%d\n\r",midiring.i_tail - midiring.i_head);
X commes.m_type = TTY_CHAR_INT;
X commes.ADDRESS = (char *)&midiring ;
X interrupt(MIDI, &commes); /* send message to tty task */
X}
X
X
X/*===========================================================================*
X * midi_init *
X *===========================================================================*/
XPUBLIC midiinit(tp)
Xregister struct tty_struct *tp;
X{
X int i;
X struct ring *rp = &midiring;
X
X
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 MDI->ac_cs = A_RESET;
X MDI->ac_cs = MDI_INIT ;
X}
X/*===========================================================================*
X * midi_dmp *
X *===========================================================================*/
Xmidi_dmp()
X{
X dbg_flag ^=1;
X printf("DMP:dbg_flag=%d ohead=%d otail=%d ihead=%d itail=%d \n\r",
X dbg_flag,
X midiring.o_head, midiring.o_tail,
X midiring.i_head, midiring.i_tail
X );
X printf("\tring flgs: tx=%x rx=%x xoff=%x on=%x dtrcts=%x\n\r",
X midiring.rx_stat, midiring.tx_stat,
X midiring.xoff_flag, midiring.xon_flag,
X midiring.rtscts);
X}
XMddeguger(x)
X{
X printf("Mddeguger(%x)\n",x);
X}
SHAR_EOF
echo extracting 'midis.s'
sed -e 's/^X//' >midis.s <<'SHAR_EOF'
X#define MIDI_RING
X#ifdef MIDI_RING
X
X! entry points
X .define _midiget !get chars from input ring
X .define _midienque !put chars to output ring
X .define _midideque !take chars from output ring
X .define _midirrdy !process rec char interrupt
X
X .extern _midiring !input and output rings
X .extern _Midi_wempty !a flag cleared in do_odone
X .extern _midicharint
X
X .extern _Mddeguger
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
Xac_cs = 0
Xac_da = 2
X
X .sect .text
X! setup a0, a1 for routines
Xmidiptr:
X lea _midiring,a0 ! pointer to midi iorec
X lea 0xfffffc04,a1 ! pointer to mfp
X rts ! 4e75
X
X_midienque:
X move.w 4(a7), d1
X movem.l d2,-(a7) ! save regs
X move.w sr,-(a7) ! save status
X or.w #0x700,sr ! IPL 7, disable interrupts
X bsr midiptr ! get buffer pointer
X
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 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
X
X move.l #1,d0 ! char sent
XL6:
X move (a7)+,sr ! restore status
X movem.l (a7)+,d2 ! restore regs
X rts ! 4e75
XL7:
X move.l #0,d0 ! char not sent
X bra L6
X
X
X_midideque: !midi input
X movem.l d2,-(a7) ! save regs
X move sr,-(a7) ! save status
X or.w #0x700,sr ! IPG 7, disable interrupts
X bsr midiptr ! get midi pointer
X move o_head(a0),d1 ! head index
X cmp.w o_tail(a0),d1 ! tail index
X beq G10 ! no char in buffer ?
X bsr wrapin ! test for wrap arround
X move.l o_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,o_head(a0) ! set new head index
X bra G9 ! 6006
XG10:
X move.w #0x100,d0 !1xx if no char
X
XG9:
X move (a7)+,sr ! restore status
X movem.l (a7)+,d2 ! restore regs
X rts ! 4e75
X
X_midiget: !midi 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 midiptr ! get midi 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 bra L9 ! 6006
XL10:
Xmove.w #0x100,d0 !1xx if no char
X
XL9:
X move (a7)+,sr ! restore status
X movem.l (a7)+,d2-d3 ! restore regs
X rts ! 4e75
X
X!midi receiver interrupt routine
X! called as a C program
X_midirrdy:
Xrcvint:
X movem.l d2-d3/a2,-(a7) ! save regs
X bsr midiptr ! get midi pointer
X move.b ac_da(a1),d0 ! read data from rec. register
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
XR2:
X movem.l (a7)+,d2-d3/a2 ! restore regs
X rts
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
X
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
X#endif ATARI_ST
SHAR_EOF
echo extracting 'miditty.c'
sed -e 's/^X//' >miditty.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: midi_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 * MIDI_CHAR_INT: a character has been typed on a terminal (input interrupt)
X * MIDI_O_DONE: a character has been output (output completed interrupt)
X * MIDI_READ: a process wants to read from a terminal
X * MIDI_WRITE: a process wants to write on a terminal
X * MIDI_IOCTL: a process wants to change a terminal's parameters
X * MIDI_SETPGRP: indicate a change in a control terminal
X * CANCEL: terminate a previous incomplete system call immediately
X *
X * m_type MIDI_LINE PROC_NR COUNT MIDI_SPEK MIDI_FLAGS ADDRESS
X * ---------------------------------------------------------------------------
X * | MIDI_CHAR_INT| | | | | |array ptr|
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | MIDI_O_DONE |minor dev| | | | | |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | MIDI_READ |minor dev| proc nr | count | | | buf ptr |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | MIDI_WRITE |minor dev| proc nr | count | | | buf ptr |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | MIDI_IOCTL |minor dev| proc nr |func code|erase etc| flags | |
X * |-------------+---------+---------+---------+---------+---------+---------|
X * | MIDI_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 miditty_struct[1];
X
X#define DBG(x) printf(x);
X
X
X/*===========================================================================*
X * midi_task *
X *===========================================================================*/
XPUBLIC midi_task()
X{
X/* Main routine of the terminal task. */
X
X message miditty_mess; /* buffer for all incoming messages */
X register struct tty_struct *tp;
X
X miditty_init(); /* initialize */
X while (TRUE) {
X receive(ANY, &miditty_mess);
X tp = &miditty_struct[miditty_mess.TTY_LINE];
X if(tp->tty_incount == 0 && Rs_blocked)
X do_charint(&miditty_mess);
X switch(miditty_mess.m_type) {
X case MIDI_CHAR_INT: do_charint(&miditty_mess); break;
X case MIDI_READ: do_read(tp, &miditty_mess); break;
X case MIDI_WRITE: do_write(tp, &miditty_mess); break;
X case MIDI_IOCTL: do_ioctl(tp, &miditty_mess); break;
X case MIDI_SETPGRP: do_setpgrp(tp, &miditty_mess); break;
X case MIDI_OPEN: do_open(tp, &miditty_mess); break;
X case MIDI_CLOSE: do_close(tp, &miditty_mess); break;
X case CANCEL : do_cancel(tp, &miditty_mess); break;
X case MIDI_O_DONE: break; /* reserved for future use (RS-232 terminals)*/
X default: tty_reply(TASK_REPLY, miditty_mess.m_source,
X miditty_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 Midi_wempty = 0;
XPRIVATE do_odone(tp)
Xstruct tty_struct *tp;
X{
X unsigned char *ptr;
X
X Midi_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(Midi_wempty)
X do_odone(miditty_struct);
X Rs_blocked = 0;
X ptr = (struct ring*)m_ptr->ADDRESS; /* pointer to accumulated char array */
X while(ptr->i_head != ptr->i_tail) {
X
X tp = &miditty_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 = midiget();
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,m_ptr);
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 = &miditty_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,m_ptr);
X
Xif(code == SUSPEND && (tp->tty_inhibited & 2)) {
Xprintf("midi restarted sent <%x>\n\r",tp->tty_xon);
X echo (tp->tty_xon);
X tp->tty_inhibited &= ~2;
X}
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,m_ptr)
Xregister struct tty_struct *tp; /* pointer to terminal to read from */
Xmessage *m_ptr;
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 miditty_mess;
X
X/* for midi and midi, 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 = tty_reply(TTY_CHAR_INT, MIDI, m_ptr->PROC_NR, OK, 0L, 0L);
X if(ct)
Xprintf("requeuing CHARINT, error = %d\n\r",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 miditty_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/midi 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 miditty_mess;
X
X miditty_mess.m_type = code;
X miditty_mess.REP_PROC_NR = proc_nr;
X miditty_mess.REP_STATUS = status;
X miditty_mess.TTY_FLAGS = extra; /* used by IOCTL for flags (mode) */
X miditty_mess.TTY_SPEK = other; /* used by IOCTL for erase and kill chars */
X send(replyee, &miditty_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 * miditty_init *
X *===========================================================================*/
XPRIVATE miditty_init()
X{
X/* Initialize the tty tables. */
X
X register struct tty_struct *tp;
X int i;
X
X for (i = 0; i < NR_MIDI; i++) {
X tp = &miditty_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 = RAW;
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 Midi_wempty = 0;
X midiinit(tp);
X }
X}
X
Xmiditty_dmp()
X{
X struct tty_struct *tp;
X
X tp = &miditty_struct[0];
X
Xprintf("\rTTY for MIDI: 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 (midi) */
X );
X}
SHAR_EOF