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