mirror of https://github.com/GnoConsortium/gno.git
1980 lines
32 KiB
NASM
1980 lines
32 KiB
NASM
* $Id: tty.asm,v 1.1 1998/02/02 08:19:54 taubert Exp $
|
|
*
|
|
* tty.asm
|
|
* New generic standard UNIX Line Discipline
|
|
*
|
|
mcopy m/tty.mac
|
|
case on
|
|
copy inc/tty.inc
|
|
copy inc/gsos.inc
|
|
copy inc/kern.inc
|
|
|
|
udispatch gequ $E10008
|
|
IncBusyFlag gequ $E10064
|
|
DecBusyFlag gequ $E10068
|
|
|
|
DebugNames gequ 1
|
|
|
|
;#include <gno/gno.h>
|
|
;#include <types.h>
|
|
;#include <sgtty.h>
|
|
;#include <string.h>
|
|
;#include <texttool.h>
|
|
;#include <ctype.h>
|
|
;#include <signal.h>
|
|
|
|
;#define MIN(x,y) (x > y ? y : x)
|
|
;#define CTRL(x) (x-'@')
|
|
;#define DEV 0
|
|
|
|
* device control subsystem (ioctl & friends)
|
|
|
|
SIGTSTP gequ 18
|
|
|
|
; Control character definitions
|
|
BS gequ 8 ; ^H
|
|
LF gequ 10 ; ^J
|
|
NL gequ 10 ; ^J
|
|
CR gequ 13 ; ^M
|
|
|
|
|
|
; NOTE: Whenever we're not in RAW mode and we get a signal character
|
|
; (^Z ^C ^\ ^Y) we must clear all pending input/output on the terminal
|
|
; with the equivalent of a TIOCFLUSH. In addition to clearing the
|
|
; actual interrupt queues, we need to set editInd = editBegin = 0
|
|
|
|
|
|
* dispatches to a vectored TTY function handling routine. Various
|
|
* data is implicit : the pointer to the tty structure (location 0 on
|
|
* the DP) and thus the device number).
|
|
|
|
ttyDispatch START KERN2
|
|
ttyDispatch name
|
|
ttyPtr equ 0
|
|
|
|
short m
|
|
iny
|
|
iny
|
|
lda [ttyPtr],y
|
|
pha
|
|
long m
|
|
dey
|
|
dey
|
|
lda [ttyPtr],y
|
|
dec a
|
|
pha
|
|
rtl
|
|
END
|
|
|
|
ttwrite START KERN2
|
|
ttwrite name
|
|
ttyPtr equ 0
|
|
c equ 4
|
|
xfer equ 6
|
|
retval equ 8
|
|
|
|
subroutine (2:length,4:buf,2:devNum),10
|
|
|
|
lda devNum
|
|
jsr fetchDevPtr
|
|
sta ttyPtr
|
|
stx ttyPtr+2
|
|
|
|
lda length
|
|
sta xfer
|
|
stz retval
|
|
ldx devNum
|
|
ldy #mutex
|
|
jsl ttyDispatch
|
|
|
|
* if we're clobbering an input line, set the retype flag
|
|
ldy #sg_flags See what mode we're in. If not in
|
|
lda [ttyPtr],y cooked mode, then we don't need
|
|
bit #CBREAK+RAW to do this check (no editing)
|
|
bne x1
|
|
ldy #st_flags
|
|
lda [ttyPtr],y
|
|
beq x1
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
ora #LPENDIN
|
|
sta [ttyPtr],y
|
|
|
|
x1 anop we were in raw or cbreak mode
|
|
|
|
lda length
|
|
jeq w1
|
|
dea
|
|
sta length
|
|
lda [buf]
|
|
and #$00FF
|
|
sta c
|
|
inc buf
|
|
bne x2
|
|
inc buf+2
|
|
x2 anop
|
|
ldy #sg_flags if RAW mode do no output processing
|
|
lda [ttyPtr],y
|
|
bit #RAW
|
|
bne x4
|
|
|
|
ldy #sg_flags if (tty->sg_flags & CRMOD) {
|
|
lda [ttyPtr],y
|
|
bit #CRMOD
|
|
beq x3
|
|
lda c if (c == LF) {
|
|
cmp #CR
|
|
bne x3
|
|
|
|
pea CR (*tty->out_enq)(DEV,CR);
|
|
ldx devNum
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea LF (*tty->out_enq)(DEV,LF);
|
|
ldx devNum
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
bra x1 continue
|
|
x3 anop
|
|
ldy #local if (tty->local & LTILDE)
|
|
lda [ttyPtr],y
|
|
bit #LTILDE
|
|
beq x4
|
|
lda c
|
|
cmp #'~'
|
|
bne x4
|
|
lda #'`'
|
|
sta c
|
|
x4 anop
|
|
pei (c)
|
|
ldx devNum
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
jmp x1
|
|
w1 ldx devNum
|
|
ldy #demutex
|
|
jsl ttyDispatch
|
|
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx devNum
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
|
|
return 4:xfer
|
|
END
|
|
|
|
;char editbuf[256];
|
|
|
|
;void echoCtlChar(char c)
|
|
;{
|
|
; if (tty->local & LCTLECH) {
|
|
; if (c < 32) {
|
|
; if ((c != CR) && (c != LF)) {
|
|
; (*tty->out_enq)(DEV,'^');
|
|
; (*tty->out_enq)(DEV,c+64);
|
|
; return;
|
|
; }
|
|
;x2: } else if (c == 0x7f) {
|
|
; (*tty->out_enq)(DEV,'^');
|
|
; (*tty->out_enq)(DEV,'?');
|
|
; return;
|
|
; }
|
|
; }
|
|
;x1:
|
|
; (*tty->out_enq)(DEV,c);
|
|
;x3:
|
|
;}
|
|
* Remember, DP is set to ttwrite/ttread local vars
|
|
|
|
echoCtlChar START KERN2
|
|
echoCtlChar name
|
|
ttyPtr equ 0
|
|
tmpC equ 6
|
|
loc_dev equ 30
|
|
|
|
sta tmpC
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
bit #LCTLECH
|
|
jeq x1
|
|
lda tmpC
|
|
cmp #' '
|
|
bcs x2
|
|
cmp #CR
|
|
beq x3
|
|
cmp #LF
|
|
beq x1
|
|
pea '^'
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
lda tmpC
|
|
clc
|
|
adc #'@'
|
|
pha
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
x1 pei (tmpC)
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
x3 ldy #sg_flags ; it's a CR. Check to see if the
|
|
lda [ttyPtr],y
|
|
bit #CRMOD ; CRMOD flag is set. If it is, we
|
|
beq x1 ; need to do a CR->CRLF translation
|
|
pea CR
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea LF
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
x2 cmp #$007F ; DELETE?
|
|
bne x1
|
|
pea '^'
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea '?'
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
END
|
|
|
|
;echoCtlErase(char c)
|
|
;{
|
|
; if (tty->local & LCRTBS)
|
|
; (*tty->out_enq)(DEV,BS);
|
|
;x1:
|
|
; else if (tty->local & LCRTERA) {
|
|
; (*tty->out_enq)(DEV,BS);
|
|
; (*tty->out_enq)(DEV,' ');
|
|
; (*tty->out_enq)(DEV,BS);
|
|
; }
|
|
;x2:
|
|
; else (*tty->out_enq)(DEV,c);
|
|
;}
|
|
echoCtlErase START KERN2
|
|
echoCtlErase name
|
|
ttyPtr equ 0
|
|
tmpC equ 6
|
|
loc_dev equ 30
|
|
|
|
sta tmpC
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
bit #LCRTBS
|
|
beq x1
|
|
pea BS
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
x1 bit #LCRTERA
|
|
beq x2
|
|
pea BS
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea ' '
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea BS
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
x2 pei (tmpC)
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
rts
|
|
END
|
|
|
|
;void retype(int _index)
|
|
;{
|
|
;int x;
|
|
; ttwrite("\r#",2);
|
|
; for (x = 0; x < _index; x++) echoCtlChar(editbuf[x]);
|
|
; tty->local &= ~LPENDIN; /* clear the flag */
|
|
;}
|
|
|
|
; retypes the current input buffer onto the screen (happens when
|
|
; user hits ^R or input is overwritten with asynchronous output)
|
|
|
|
retype START KERN2
|
|
retype name
|
|
ttyPtr equ 0
|
|
tmpC equ 6
|
|
_editBuf equ 24
|
|
|
|
pha
|
|
lda #CR
|
|
jsr echoCtlChar
|
|
|
|
pea 0
|
|
|
|
x1 lda 1,s
|
|
cmp 3,s
|
|
bcs x2
|
|
tay
|
|
lda [_editBuf],y ; local copy of the pointer
|
|
jsr echoCtlChar
|
|
lda 1,s
|
|
inc a
|
|
sta 1,s
|
|
bra x1
|
|
x2 anop
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
; damned ORCA doesn't work right
|
|
; and #(LPENDIN.EOR.$FFFF)
|
|
and #%1101111111111111
|
|
sta [ttyPtr],y
|
|
pla
|
|
pla
|
|
rts
|
|
END
|
|
|
|
fetchDevPtr START KERN2
|
|
fetchDevPtr name
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda >DeviceBlock+2,x
|
|
tay
|
|
lda >DeviceBlock,x
|
|
tyx
|
|
rts
|
|
END
|
|
|
|
ttread START KERN2
|
|
ttread name
|
|
ttyPtr equ 0
|
|
c equ 4
|
|
tmpC equ 6
|
|
origLength equ 8
|
|
tmp equ 10
|
|
xfer equ 12
|
|
retval equ 14
|
|
inQueue equ 16
|
|
_flags equ 18
|
|
_index equ 20
|
|
_begin equ 22
|
|
_editBuf equ 24
|
|
_x equ 28
|
|
_zero equ 28
|
|
loc_dev equ 30
|
|
|
|
subroutine (2:length,4:buf,2:devNum),32
|
|
* zero byte transfer? return immediately
|
|
lda devNum
|
|
sta loc_dev
|
|
|
|
stz xfer
|
|
stz retval
|
|
lda devNum
|
|
jsr fetchDevPtr
|
|
sta ttyPtr
|
|
stx ttyPtr+2
|
|
lda length
|
|
jeq x1
|
|
|
|
dobgcheck anop
|
|
ldx devNum ; get the driver's number
|
|
lda #21
|
|
jsl BGCheck
|
|
cmp #0
|
|
beq isfg
|
|
cmp #1
|
|
beq dobgcheck ; we were suspended, try again
|
|
|
|
lda #$0027 ; the signal was blocked, so return
|
|
sta retval ; an I/O error
|
|
jmp doReturn
|
|
|
|
isfg ldy #editBuf
|
|
lda [ttyPtr],y
|
|
sta _editBuf
|
|
ldy #editBuf+2
|
|
lda [ttyPtr],y
|
|
sta _editBuf+2
|
|
|
|
lda #0
|
|
ldy #st_flags
|
|
sta [ttyPtr],y
|
|
|
|
ldy #sg_flags
|
|
lda [ttyPtr],y
|
|
sta _flags
|
|
ldy #editInd
|
|
lda [ttyPtr],y
|
|
sta _index
|
|
ldy #editBegin
|
|
lda [ttyPtr],y
|
|
sta _begin
|
|
|
|
; (*tty->mutex)(DEV);
|
|
ldx devNum
|
|
ldy #mutex
|
|
jsl ttyDispatch
|
|
|
|
; if (_begin != 0) { /* if there is data still in the edit buffer */
|
|
lda _begin
|
|
beq x2
|
|
|
|
* number of unread bytes in the edit buffer. These should
|
|
* be read out whether we're in RAW/CBREAK or COOKED mode.
|
|
; int x;
|
|
; x = _index - _begin;
|
|
lda _index
|
|
sec
|
|
sbc _begin
|
|
sta _x
|
|
|
|
; /* see how many we should transfer */
|
|
; tmp = MIN(x,length);
|
|
|
|
cmp length
|
|
bcc x3
|
|
lda length
|
|
x3 sta tmp
|
|
|
|
; /* copy them */
|
|
; memcpy(buf,editbuf+_begin,(size_t)tmp);
|
|
pea 0
|
|
pha
|
|
ldx _editBuf+2
|
|
lda _editBuf
|
|
clc
|
|
adc _begin
|
|
bcc x4
|
|
inx
|
|
x4 phx
|
|
pha
|
|
pei (buf+2)
|
|
pei (buf)
|
|
jsl memcpy
|
|
|
|
; /* if we got all the data the caller wanted then update our
|
|
; counts and return */
|
|
; if (tmp == length) {
|
|
lda tmp
|
|
cmp length
|
|
bne x5
|
|
|
|
; _begin += tmp;
|
|
clc
|
|
adc _begin
|
|
sta _begin
|
|
|
|
; if (_begin == _index) _begin = 0;
|
|
cmp _index
|
|
bne x6
|
|
stz _begin
|
|
;x6 xfer = tmp;
|
|
x6 lda tmp
|
|
sta xfer
|
|
; goto doReturn;
|
|
jmp doReturn
|
|
; }
|
|
;x5:
|
|
; /* Otherwise, we've returned what we had in the buffer, and
|
|
; we return to the caller (i.e., always return at a NL) */
|
|
; _begin = _index = 0;
|
|
x5 stz _begin
|
|
stz _index
|
|
lda tmp
|
|
sta xfer
|
|
jmp doReturn
|
|
; xfer = tmp;
|
|
; goto doReturn;
|
|
; }
|
|
|
|
x2 anop
|
|
; _index = 0;
|
|
stz _index
|
|
; origLength = length;
|
|
lda length
|
|
sta origLength
|
|
; inQueue = (*tty->size_inq)(DEV);
|
|
ldx loc_dev
|
|
ldy #size_inq
|
|
jsl ttyDispatch
|
|
sta inQueue
|
|
|
|
; /* The next statement is reponsible for choosing between EWOULDBLOCK
|
|
; for the fcntl nonblocking I/O mode and sleeping anyway. */
|
|
; if (!inQueue) inQueue = 1; /* no data? read at least one! */
|
|
cmp #0
|
|
bne y1
|
|
lda #1
|
|
sta inQueue
|
|
ldy #_flags
|
|
bit #RAW+CBREAK
|
|
beq y1
|
|
; after the read, check to see if we got more data than just one in
|
|
; to improve performance
|
|
lda #1
|
|
sta length
|
|
sta origLength
|
|
|
|
;y1: while (1) { /* pretty much an infinite loop, bub! */
|
|
y1 anop
|
|
|
|
; if (tty->local & LPENDIN) retype(_index);
|
|
; tty->editInd = _index;
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
bit #LPENDIN
|
|
beq y2
|
|
lda _index
|
|
jsr retype
|
|
|
|
;y2: c = (*tty->in_deq)(DEV);
|
|
y2 anop
|
|
ldy #editInd
|
|
lda _index
|
|
sta [ttyPtr],y
|
|
ldy #editBegin
|
|
lda _begin
|
|
sta [ttyPtr],y
|
|
|
|
ldx devNum
|
|
ldy #in_deq
|
|
jsl ttyDispatch
|
|
; /* if C is a value that indicates we were sleeping and interrupted,
|
|
; then restart the read operation, return an error, or other
|
|
; stuff, depending on fcntl settings */
|
|
cmp #$7E43
|
|
bne strip_mod
|
|
lda #$430e ; EINTR
|
|
sta retval
|
|
jmp doReturn
|
|
strip_mod anop
|
|
and #$00FF ; strip out modifier flags
|
|
sta c
|
|
|
|
; /* we skip _all_ processing in RAW mode */
|
|
; if (_flags & RAW) {
|
|
_checkRaw name
|
|
lda _flags
|
|
bit #RAW
|
|
beq y3
|
|
|
|
; *buf++ = c; xfer++;
|
|
short m
|
|
lda c
|
|
sta [buf]
|
|
long m
|
|
inc buf
|
|
bne y4
|
|
inc buf+2
|
|
y4 inc xfer
|
|
; if ((--inQueue == 0) || (--length == 0)) break;
|
|
dec inQueue
|
|
jeq doReturn
|
|
dec length
|
|
jeq doReturn
|
|
; continue;
|
|
bra y1
|
|
|
|
; }
|
|
; recache this because it can be changed by an interrupt routine
|
|
;y3: /* Check for dsuspc in CBREAK & COOKED modes */
|
|
; if (c == tty->t_dsuspc) {
|
|
|
|
y3 anop
|
|
; _index = tty->editInd; _begin = tty->editBegin;
|
|
ldy #editInd
|
|
lda [ttyPtr],y
|
|
sta _index
|
|
ldy #editBegin
|
|
lda [ttyPtr],y
|
|
sta _begin
|
|
|
|
ldy #t_dsuspc
|
|
lda [ttyPtr],y
|
|
and #$00FF
|
|
cmp c
|
|
bne z1
|
|
|
|
; int zero = 0;
|
|
stz _zero
|
|
|
|
; if (_flags & ECHO) echoCtlChar(c);
|
|
lda _flags
|
|
bit #ECHO
|
|
beq z77
|
|
lda c
|
|
jsr echoCtlChar
|
|
|
|
;z77 if (!(tty->local & LNOFLSH)) {
|
|
z77 ldy #local
|
|
lda [ttyPtr],y
|
|
bit #LNOFLSH
|
|
bne z3
|
|
|
|
; _index = _begin = 0;
|
|
lda #0
|
|
sta _index
|
|
sta _begin
|
|
ldy #editBegin
|
|
sta [ttyPtr],y
|
|
ldy #editInd
|
|
sta [ttyPtr],y
|
|
ldy #st_flags
|
|
sta [ttyPtr],y
|
|
|
|
; ioctl(1,TIOCFLUSH,(ampersand)zero);
|
|
; }
|
|
;z3 kill(getpid(),SIGTSTP);
|
|
z3 anop
|
|
pha
|
|
pha
|
|
jsl KERNgetpid ; this is #pragma toolparms 1
|
|
pea SIGTSTP
|
|
ph4 #errno
|
|
jsl KERNkill ; this is #pragma toolparms 1
|
|
pla
|
|
; continue; /* restart the read operation */
|
|
jmp x2 ; reset & restart the read
|
|
; }
|
|
|
|
;z1: if (_flags & CRMOD)
|
|
z1 lda _flags
|
|
bit #CRMOD
|
|
beq z2
|
|
|
|
; if (c == LF) c = CR;
|
|
lda c
|
|
cmp #LF
|
|
bne z2
|
|
lda #CR
|
|
sta c
|
|
; /* did we receive an ERASE character? */
|
|
; if (!(_flags & CBREAK))
|
|
z2 lda _flags
|
|
bit #CBREAK
|
|
jne w1
|
|
|
|
; tty->st_flags = 1; /* we're in the middle of an input edit */
|
|
lda #1
|
|
ldy #st_flags
|
|
sta [ttyPtr],y
|
|
|
|
; if (c == tty->sg_erase) {
|
|
ldy #sg_erase
|
|
lda [ttyPtr],y
|
|
and #$00FF
|
|
cmp c
|
|
bne w1
|
|
|
|
; if (_index) {
|
|
lda _index
|
|
beq w2
|
|
|
|
; _index--;
|
|
dea
|
|
sta _index
|
|
|
|
; c = editbuf[_index];
|
|
tay
|
|
lda [_editBuf],y
|
|
and #$00FF
|
|
sta c
|
|
; if (tty->local & LPRTERA) {
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
bit #LPRTERA
|
|
beq z9
|
|
|
|
; (*tty->out_enq)(DEV,'\\');
|
|
; (*tty->out_enq)(DEV,c);
|
|
pea '\'
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pei (c)
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea '/'
|
|
ldx loc_dev
|
|
ldy #out_enq
|
|
jsl ttyDispatch
|
|
pea 0 ; 0 means 'write occurred'
|
|
ldx loc_dev
|
|
ldy #t_signalIO
|
|
jsl ttyDispatch
|
|
bra w1
|
|
;z9: } else {
|
|
; if ((tty->local & LCTLECH) && (iscntrl(c)))
|
|
z9 anop
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
bit #LCTLECH
|
|
beq z7
|
|
lda c
|
|
cmp #$7F
|
|
beq z8
|
|
cmp #' '
|
|
bcs z7
|
|
;z8 echoCtlErase(c);
|
|
z8 lda c
|
|
jsr echoCtlErase
|
|
|
|
;z7 echoCtlErase(c);
|
|
z7 lda c
|
|
jsr echoCtlErase
|
|
; }
|
|
; continue;
|
|
; }
|
|
jmp y1
|
|
;w2: else { /* nothing to erase! */
|
|
; tty->st_flags = 0;
|
|
|
|
w2 lda #0
|
|
ldy #st_flags
|
|
sta [ttyPtr],y
|
|
; continue; /* ignore the backspace */
|
|
jmp y1
|
|
; }
|
|
; }
|
|
|
|
;w1: /* Echo input characters? */
|
|
; if (_flags & ECHO)
|
|
w1 lda _flags
|
|
bit #ECHO
|
|
beq v1
|
|
; echoCtlChar(c);
|
|
lda c
|
|
jsr echoCtlChar
|
|
|
|
;v1 /* Check for and handle the Reprint character */
|
|
; if ((c == tty->t_rprntc) && (_flags & ECHO)) {
|
|
v1 ldy #t_rprntc
|
|
lda [ttyPtr],y
|
|
and #$00FF
|
|
cmp c
|
|
bne v2
|
|
lda _flags
|
|
bit #ECHO
|
|
beq v2
|
|
; tty->local |= LPENDIN;
|
|
ldy #local
|
|
lda [ttyPtr],y
|
|
ora #LPENDIN
|
|
sta [ttyPtr],y
|
|
; continue;
|
|
jmp y1
|
|
; }
|
|
|
|
;v2 /* Put character into COOKED mode buffer & return if we got CR */
|
|
; if (!(_flags & CBREAK)) {
|
|
v2 lda _flags
|
|
bit #CBREAK
|
|
bne u2
|
|
|
|
; if (c != tty->t_eofc)
|
|
ldy #t_eofc
|
|
lda [ttyPtr],y
|
|
and #$00FF
|
|
cmp c
|
|
beq v3
|
|
; editbuf[_index++] = c;
|
|
ldy _index
|
|
short m
|
|
lda c
|
|
sta [_editBuf],y
|
|
long m
|
|
iny
|
|
sty _index
|
|
|
|
;v3 /* end of line? */
|
|
; if ((c == NL) || (c == CR) || (c == tty->t_eofc)) {
|
|
v3 anop
|
|
lda c
|
|
cmp #NL
|
|
beq v4
|
|
cmp #CR
|
|
beq v4
|
|
ldy #t_eofc
|
|
lda [ttyPtr],y
|
|
and #$00FF
|
|
cmp c
|
|
bne u1
|
|
|
|
;v4 tty->st_flags = 0; /* done editing this line */
|
|
v4 anop
|
|
lda #0
|
|
ldy #st_flags
|
|
sta [ttyPtr],y
|
|
|
|
; tmp = MIN(_index,origLength);
|
|
lda _index
|
|
cmp origLength
|
|
bcc v5
|
|
lda origLength
|
|
|
|
; memcpy(buf,editbuf,(size_t)tmp);
|
|
v5 sta tmp
|
|
pea 0
|
|
pha
|
|
pei (_editBuf+2)
|
|
pei (_editBuf)
|
|
pei (buf+2)
|
|
pei (buf)
|
|
jsl memcpy
|
|
|
|
; /* insert code to set up state for a partial read _here_ */
|
|
; _begin += tmp;
|
|
lda tmp
|
|
clc
|
|
adc _begin
|
|
sta _begin
|
|
|
|
; if (_begin == _index) _begin = 0;
|
|
cmp _index
|
|
bne v6
|
|
stz _begin
|
|
;v6 xfer += tmp;
|
|
v6 lda tmp
|
|
clc
|
|
adc xfer
|
|
sta xfer
|
|
; if (c == tty->t_eofc) { retval = 0x4C; goto doReturn; }
|
|
ldy #t_eofc
|
|
lda [ttyPtr],y
|
|
and #$00FF
|
|
cmp c
|
|
bne doReturn
|
|
lda #$4C
|
|
sta retval
|
|
bra doReturn
|
|
; break;
|
|
; goto doReturn
|
|
; }
|
|
; }
|
|
u1 jmp y1
|
|
; }
|
|
u2 anop
|
|
; if (flags & Cbreak)
|
|
lda _flags
|
|
bit #CBREAK
|
|
beq u1
|
|
short m
|
|
lda c
|
|
sta [buf]
|
|
long m
|
|
inc buf
|
|
bne yy4
|
|
inc buf+2
|
|
yy4 inc xfer
|
|
; if ((--inQueue == 0) || (--length == 0)) break;
|
|
dec inQueue
|
|
beq doReturn
|
|
dec length
|
|
beq doReturn
|
|
; continue;
|
|
bra u1
|
|
|
|
doReturn anop
|
|
; (*tty->demutex)();
|
|
ldx devNum
|
|
ldy #demutex
|
|
jsl ttyDispatch
|
|
; tty->editInd = _index;
|
|
lda _index
|
|
ldy #editInd
|
|
sta [ttyPtr],y
|
|
; tty->editBegin = _begin;
|
|
lda _begin
|
|
ldy #editBegin
|
|
sta [ttyPtr],y
|
|
; (*tty->t_signalIO)(1); /* signal a read operation occurred */
|
|
pea 1
|
|
ldy #t_signalIO
|
|
ldx devNum
|
|
jsl ttyDispatch
|
|
|
|
; return xfer;
|
|
x1 anop
|
|
return 4:xfer
|
|
;}
|
|
END
|
|
|
|
* An array of 38 pointers to device entry blocks. A NULL pointer
|
|
* indicates that no device is active in that slot.
|
|
|
|
DeviceBlock START KERN2
|
|
dc 38i4'0'
|
|
END
|
|
|
|
* Dispatches to one of the line discipline routines (open,close,r/w,ioctl)
|
|
* A is the device number, Y is the index of the routine to call
|
|
|
|
LineDiscDispatch START KERN2
|
|
LineDiscDispatch name
|
|
rtlAdr equ 7
|
|
headerPtr equ 1
|
|
|
|
tax
|
|
phb ; 1 +
|
|
pha ; 2 = 3 byte for fake rtl
|
|
phd
|
|
pha ; some dp space
|
|
pha
|
|
tsc
|
|
tcd
|
|
txa
|
|
asl a ; calculate index into table
|
|
asl a
|
|
tax
|
|
lda >DeviceBlock,x
|
|
sta headerPtr
|
|
lda >DeviceBlock+2,x
|
|
sta headerPtr+2
|
|
lda [headerPtr],y
|
|
dec a
|
|
sta rtlAdr
|
|
iny
|
|
iny
|
|
short m
|
|
lda [headerPtr],y
|
|
sta rtlAdr+2
|
|
long m
|
|
pla
|
|
pla
|
|
pld
|
|
rtl
|
|
END
|
|
|
|
;Device Information
|
|
;
|
|
;o Device Name
|
|
;o Device Number
|
|
;o Device pointer points to:
|
|
; - tty linedisc info
|
|
; - misc, device-dependent info (Q pointers, semaphores, etc)
|
|
|
|
|
|
* ioctl(int fd, longword tioc, void *dataptr)
|
|
* ioctl's are encoded in the following format
|
|
* 33222222 22221111 11111100 00000000
|
|
* 10987654 32109876 54321098 76543210
|
|
* ii sssssss tttttttt nnnnnnnn
|
|
|
|
* ii = in/out (01 = copy out, 10 = copy in)
|
|
* s = size of parameter to copy in/out
|
|
* t = 't' : tty, 's' : socket, 'i' : inet
|
|
* n = base ioctl code
|
|
|
|
TIioctl START KERN2
|
|
TIioctl name
|
|
using pipeRecord
|
|
using KernelStruct
|
|
|
|
space equ 16
|
|
|
|
retval equ 24+space
|
|
fd equ 22+space
|
|
tioc equ 18+space
|
|
dataPtr equ 14+space
|
|
ERRNOptr equ 10+space
|
|
|
|
rtl1 equ 7+space
|
|
rtl2 equ 4+space
|
|
dsp equ 2+space
|
|
bsp equ 1+space
|
|
|
|
bitTmp equ 13
|
|
tInd equ 15
|
|
dInd equ 13
|
|
ttyPtr equ 9
|
|
fdPtr equ 5
|
|
tmpPtr equ 1
|
|
|
|
phd
|
|
phb
|
|
|
|
phk
|
|
plb
|
|
tsc
|
|
sec
|
|
sbc #space
|
|
tcd
|
|
tcs
|
|
|
|
stz retval
|
|
ph2 fd
|
|
jsl getFDptr
|
|
sta fdPtr
|
|
stx fdPtr+2
|
|
ora fdPtr+2
|
|
beq refIsBad
|
|
|
|
ldy #FDrefNum
|
|
lda [fdPtr],y
|
|
bne validFD
|
|
refIsBad lda #EBADF
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sta retval
|
|
jmp byeIoctl
|
|
|
|
* the file descriptor is valid, if it is a socket then re-route control to
|
|
* network software
|
|
|
|
validFD anop
|
|
ldy #FDrefType
|
|
lda [fdPtr],y
|
|
cmp #FDsocket
|
|
bne notsocket
|
|
ldy #FDrefNum
|
|
lda [fdPtr],y
|
|
pha
|
|
ph4 tioc
|
|
ph4 dataPtr
|
|
jsl SOCKioctl
|
|
beq sockgroovy
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sockgroovy anop
|
|
sta retval
|
|
jmp byeIoctl
|
|
|
|
* here we should check to see what type
|
|
* of operation the user wants to perform (file or tty).
|
|
|
|
notsocket anop
|
|
lda tioc
|
|
and #$FF00
|
|
xba
|
|
cmp #'t' ; tty style?
|
|
beq doTTYioctl
|
|
cmp #'f'
|
|
beq doFioctl
|
|
jmp invalid
|
|
|
|
doTTYioctl anop
|
|
ldy #FDrefType
|
|
lda [fdPtr],y
|
|
cmp #FDtty
|
|
beq isatty
|
|
lda #ENOTTY
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sta retval
|
|
jmp byeIoctl
|
|
|
|
isatty anop
|
|
lda [fdPtr]
|
|
dec a
|
|
sta bitTmp ; driver number, for null hack
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda >DeviceBlock,x
|
|
sta ttyPtr
|
|
lda >DeviceBlock+2,x
|
|
sta ttyPtr+2
|
|
|
|
lda tioc
|
|
and #$7F
|
|
cmp #25
|
|
bcs jmpNew
|
|
asl a
|
|
asl a
|
|
inc a
|
|
inc a
|
|
tax
|
|
jmp (tOTable,X)
|
|
jmpNew eor #$7F
|
|
cmp #32
|
|
bcs invalid
|
|
asl a
|
|
asl a
|
|
inc a
|
|
inc a
|
|
tax
|
|
jmp (tNTable,X)
|
|
|
|
doFioctl lda tioc
|
|
and #$7F
|
|
eor #$7F
|
|
cmp #1
|
|
bcs invalid
|
|
asl a
|
|
asl a
|
|
inc a
|
|
inc a
|
|
tax
|
|
jmp (fTable,X)
|
|
* Table for OLD ioctls
|
|
|
|
invalid anop
|
|
lda #EINVAL
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sta retval
|
|
jmp byeIoctl
|
|
|
|
tOTable anop
|
|
dc i2'0',a2'TIOCGETD'
|
|
dc i2'1',a2'TIOCSETD'
|
|
dc i2'2',a2'TIOCHPCL'
|
|
dc i2'3',a2'TIOCMODG'
|
|
dc i2'4',a2'TIOCMODS'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'8',a2'TIOCGETP'
|
|
dc i2'9',a2'TIOCSETP'
|
|
dc i2'10',a2'TIOCSETN'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'13',a2'TIOCEXCL'
|
|
dc i2'14',a2'TIOCNXCL'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'16',a2'TIOCFLUSH'
|
|
dc i2'17',a2'TIOCSETC'
|
|
dc i2'18',a2'TIOCGETC'
|
|
dc i2'19',a2'TIOCSETK'
|
|
dc i2'20',a2'TIOCGETK'
|
|
dc i2'21',a2'TIOCSHUP'
|
|
dc i2'22',a2'TIOCGHUP'
|
|
dc i2'23',a2'TIOCSVECT'
|
|
dc i2'24',a2'TIOCGVECT'
|
|
|
|
* Table for new ioctls
|
|
tNTable anop
|
|
dc i2'127',a2'TIOCLBIS'
|
|
dc i2'126',a2'TIOCLBIC'
|
|
dc i2'125',a2'TIOCLSET'
|
|
dc i2'124',a2'TIOCLGET'
|
|
|
|
dc i2'123',a2'TIOCSBRK'
|
|
dc i2'122',a2'TIOCCBRK'
|
|
dc i2'121',a2'TIOCSDTR'
|
|
dc i2'120',a2'TIOCCDTR'
|
|
|
|
dc i2'119',a2'TIOCGPGRP'
|
|
dc i2'118',a2'TIOCSPGRP'
|
|
dc i2'117',a2'TIOCSLTC'
|
|
dc i2'116',a2'TIOCGLTC'
|
|
dc i2'115',a2'TIOCOUTQ'
|
|
dc i2'114',a2'TIOCSTI'
|
|
dc i2'113',a2'TIOCNOTTY'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'111',a2'TIOCSTOP'
|
|
dc i2'110',a2'TIOCSTART'
|
|
|
|
dc i2'109',a2'TIOCMSET'
|
|
dc i2'108',a2'TIOCMBIS'
|
|
dc i2'107',a2'TIOCMBIC'
|
|
dc i2'106',a2'TIOCMGET'
|
|
dc i2'-1',a2'invalid'
|
|
dc i2'104',a2'TIOCGWINSZ'
|
|
dc i2'103',a2'TIOCSWINSZ'
|
|
dc i2'-1',a2'invalid' 102
|
|
dc i2'-1',a2'invalid' 101
|
|
dc i2'-1',a2'invalid' 100
|
|
dc i2'-1',a2'invalid' 99
|
|
dc i2'-1',a2'invalid' 98
|
|
dc i2'97',a2'TIOCSCTTY' 97
|
|
|
|
fTable anop
|
|
dc i2'127',a2'FIONREAD'
|
|
|
|
FIONREAD anop
|
|
* check to see what type of FD this is, files aren't supported yet
|
|
ldy #FDrefType
|
|
lda [fdPtr],y
|
|
cmp #FDtty
|
|
beq frTTY
|
|
cmp #FDpipe
|
|
beq frPIPE
|
|
lda #ENOTTY
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sta retval
|
|
jmp byeIoctl
|
|
frTTY anop
|
|
ph4 tioc
|
|
ph4 dataPtr
|
|
lda [fdPtr]
|
|
dec a
|
|
pha
|
|
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda >DeviceBlock,x
|
|
sta ttyPtr
|
|
lda >DeviceBlock+2,x
|
|
sta ttyPtr+2
|
|
|
|
jsl DoIoctl ; let the device know what happened
|
|
jmp byeIoctl
|
|
* another last minute addition/hack
|
|
frPIPE anop
|
|
ldy #FDrefNum
|
|
lda [fdPtr],y ; get the pipe ID code
|
|
jsl calcPipeInd ; get index
|
|
sta tInd
|
|
tax
|
|
lda >accessSem,x
|
|
pha
|
|
jsl asmWait
|
|
ldx tInd
|
|
lda >readLeft,x
|
|
sta [dataPtr]
|
|
lda >accessSem,x
|
|
pha
|
|
jsl asmSignal
|
|
jmp byeIoctl
|
|
|
|
********************************************************
|
|
* Set a process' controlling TTY to the input FD
|
|
* We've already been validated as a TTY file descriptor
|
|
TIOCSCTTY anop
|
|
lda >curProcInd
|
|
tax
|
|
lda [fdPtr]
|
|
dec a
|
|
sta >ttyID,x
|
|
jmp byeIoctl
|
|
|
|
********************************************************
|
|
TIOCGPGRP anop
|
|
TIOCSPGRP anop
|
|
jmp invalid
|
|
|
|
* remove process' associate with controlling terminal
|
|
* may need to futz with process groups too, maybe not
|
|
* Currently sets controlling terminal to .NULL
|
|
TIOCNOTTY anop
|
|
lda >curProcInd
|
|
tax
|
|
lda #0
|
|
sta >ttyID,x
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCGETD ldy #t_linedisc
|
|
lda [ttyPtr],y
|
|
sta [dataPtr]
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCSETD lda [dataPtr]
|
|
beq okaySETD
|
|
cmp #2
|
|
beq okaySETD
|
|
lda #EINVAL
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sta retval
|
|
jmp byeIoctl
|
|
okaySETD ldy #t_linedisc
|
|
sta [ttyPtr],y
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCHPCL ldy #privFlags
|
|
lda [ttyPtr],y
|
|
ora #HUPCL
|
|
sta [ttyPtr],y
|
|
jmp byeIoctl
|
|
********************************************************
|
|
* These Ioctl's must be handled by the driver
|
|
TIOCSVECT anop
|
|
TIOCGVECT anop
|
|
TIOCSHUP anop
|
|
TIOCGHUP anop
|
|
TIOCMODG anop
|
|
TIOCMODS anop
|
|
TIOCFLUSH anop
|
|
ph4 tioc
|
|
ph4 dataPtr
|
|
lda [fdPtr]
|
|
dec a
|
|
tax
|
|
pha
|
|
jsl DoIoctl ; let the device know what happened
|
|
|
|
********************************************************
|
|
* SETP should wait for output buffer to empty before copying info
|
|
* that's a device IOCTL call
|
|
|
|
TIOCSETP anop
|
|
* wait for output to drain
|
|
* Flush input buffer
|
|
|
|
TIOCSETN anop ; same as SETP, but no flush
|
|
TIOCGETP ldy #sg_ispeed
|
|
jsr CopyInfo
|
|
ph4 tioc
|
|
ph4 dataPtr
|
|
lda [fdPtr]
|
|
dec a
|
|
pha
|
|
jsl DoIoctl ; let the device know what happened
|
|
cmp #0
|
|
beq okayETP
|
|
sta [ERRNOptr]
|
|
lda #-1
|
|
sta retval
|
|
okayETP jmp byeIoctl
|
|
********************************************************
|
|
TIOCEXCL lda bitTmp ; don't allow exclusive acess of .null
|
|
beq isNullDev
|
|
ldy #privFlags
|
|
lda [ttyPtr],y
|
|
ora #EXCL
|
|
sta [ttyPtr],y
|
|
isNullDev jmp byeIoctl
|
|
TIOCNXCL ldy #privFlags
|
|
lda [ttyPtr],y
|
|
and #EXCL.EOR.$FFFF
|
|
sta [ttyPtr],y
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCSETC anop
|
|
TIOCGETC anop
|
|
ldy #t_intrc
|
|
jsr CopyInfo
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCSETK anop
|
|
TIOCGETK anop
|
|
ph4 tioc
|
|
ph4 dataPtr
|
|
lda [fdPtr]
|
|
dec a
|
|
pha
|
|
jsl DoIoctl
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCLGET ldy #local
|
|
lda [ttyPtr],y
|
|
sta [dataPtr]
|
|
jmp byeIoctl
|
|
TIOCLSET ldy #local
|
|
lda [dataPtr]
|
|
sta [ttyPtr],y
|
|
jmp byeIoctl
|
|
TIOCLBIS ldy #local
|
|
lda [ttyPtr],y
|
|
ora [dataPtr]
|
|
sta [ttyPtr],y
|
|
jmp byeIoctl
|
|
TIOCLBIC ldy #local
|
|
lda [ttyPtr],y
|
|
sta bitTmp
|
|
lda [dataPtr]
|
|
trb bitTmp
|
|
sta [ttyPtr],y
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCSBRK anop
|
|
TIOCCBRK anop
|
|
TIOCSDTR anop
|
|
TIOCCDTR anop
|
|
TIOCOUTQ anop
|
|
TIOCSTI anop
|
|
TIOCSTOP anop
|
|
TIOCSTART anop
|
|
TIOCMSET anop
|
|
TIOCMBIS anop
|
|
TIOCMBIC anop
|
|
TIOCMGET anop
|
|
ph4 tioc
|
|
ph4 dataPtr
|
|
lda [fdPtr]
|
|
dec a
|
|
pha
|
|
jsl DoIoctl
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCSLTC anop
|
|
TIOCGLTC anop
|
|
ldy #t_suspc
|
|
jsr CopyInfo
|
|
jmp byeIoctl
|
|
********************************************************
|
|
TIOCGWINSZ anop
|
|
* for SWINSZ, if new information is different from old,
|
|
* send a SIGWINCH signal to the members of the TTY's process group
|
|
|
|
TIOCSWINSZ anop
|
|
ldy #ws_row
|
|
jsr CopyInfo
|
|
jmp byeIoctl
|
|
********************************************************
|
|
|
|
byeIoctl tsc
|
|
clc
|
|
adc #space
|
|
tcs
|
|
plb
|
|
pld
|
|
ldx #0
|
|
ldy #14
|
|
jmp >tool_exit
|
|
|
|
* This does the work for many of the IOCTLs, which mainly copy data
|
|
* in and out.
|
|
* The in mode copies data TO the tty record (dataPtr -> ttyPtr)
|
|
* The out mode copies data FROM the tty record (ttyPtr -> dataPtr)
|
|
* no registers are valid after the call.
|
|
* Provide in Y the position in ttyPtr to start the transfer
|
|
|
|
CopyInfo anop
|
|
lda tioc+2
|
|
and #%01111111
|
|
tax
|
|
|
|
sty tInd ; save it on the stack 3,s
|
|
stz dInd ; the other index 1,s
|
|
lda tioc+2 ; get the type of transfer
|
|
and #%1100000000000000 ; mask out in/out flags
|
|
cmp #$8000 ; copy 'in'
|
|
beq copyIn
|
|
short m
|
|
outLoop cpx #0
|
|
beq doneCopy
|
|
ldy tInd
|
|
lda [ttyPtr],y
|
|
iny
|
|
sty tInd
|
|
ldy dInd
|
|
sta [dataPtr],y
|
|
iny
|
|
sty dInd
|
|
dex
|
|
bra outLoop
|
|
copyIn short m
|
|
inLoop cpx #0
|
|
beq doneCopy
|
|
ldy dInd
|
|
lda [dataPtr],y
|
|
iny
|
|
sty dInd
|
|
ldy tInd
|
|
sta [ttyPtr],y
|
|
iny
|
|
sty tInd
|
|
dex
|
|
bra inLoop
|
|
doneCopy long m
|
|
rts
|
|
|
|
; vector to the TTY's ioctl handler
|
|
DoIoctl anop
|
|
ldy #t_ioctl+2
|
|
short m
|
|
lda [ttyPtr],y
|
|
pha
|
|
long m
|
|
ldy #t_ioctl
|
|
lda [ttyPtr],y
|
|
dea
|
|
pha
|
|
rtl
|
|
END
|
|
|
|
* Must be in same data segment main() is expecting, or we have to
|
|
* use pointers to access these variables.
|
|
|
|
vecs START
|
|
OldGetNextEvent ENTRY
|
|
jmp >$000000
|
|
OldOSEventAvail ENTRY
|
|
jmp >$000000
|
|
OldGetOSEvent ENTRY
|
|
jmp >$000000
|
|
OldEventAvail ENTRY
|
|
jmp >$000000
|
|
|
|
mouseMode ENTRY
|
|
dc i1'0'
|
|
dc i1'0'
|
|
dc i2'0'
|
|
dc i2'0'
|
|
END
|
|
|
|
GetDaMouseMod START
|
|
GetDaMouseMod name
|
|
|
|
pha
|
|
pha
|
|
pha
|
|
_ReadMouse
|
|
pla
|
|
and #$000F
|
|
sta >mouseMode
|
|
pla
|
|
pla
|
|
rtl
|
|
END
|
|
|
|
toolOffset gequ 8
|
|
|
|
NewEMStartUp START KERN2
|
|
NewEMStartUp name
|
|
userID equ 0+toolOffset
|
|
ymax equ userID+2
|
|
ymin equ ymax+2
|
|
xmax equ ymin+2
|
|
xmin equ xmax+2
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
pei (xmin)
|
|
lda xmax
|
|
dec a
|
|
pha
|
|
pei (ymin)
|
|
lda ymax
|
|
dec a
|
|
pha
|
|
_ClampMouse
|
|
|
|
pei (xmin)
|
|
lda xmax
|
|
dec a
|
|
pha
|
|
pei (ymin)
|
|
lda ymax
|
|
dec a
|
|
pha
|
|
_SetAbsClamp
|
|
|
|
ph4 #bufr
|
|
ph4 #$40067408
|
|
pea 1
|
|
jsl ioctl
|
|
lda #$20
|
|
tsb bufr+4
|
|
ph4 #bufr
|
|
ph4 #$80067409
|
|
pea 1
|
|
jsl ioctl
|
|
|
|
lda >mouseMode
|
|
pha
|
|
_SetMouse
|
|
|
|
_HomeMouse
|
|
|
|
pld
|
|
plb
|
|
|
|
ldx #0
|
|
ldy #14
|
|
jmp >tool_exit
|
|
|
|
NewEMShutDown ENTRY
|
|
|
|
phb
|
|
phk
|
|
plb
|
|
ph4 #bufr
|
|
ph4 #$40067408
|
|
pea 1
|
|
jsl ioctl
|
|
lda #$20
|
|
trb bufr+4
|
|
ph4 #bufr
|
|
ph4 #$80067409
|
|
pea 1
|
|
jsl ioctl
|
|
|
|
plb
|
|
|
|
ldx #0
|
|
ldy #0
|
|
jmp >tool_exit
|
|
bufr ds 6
|
|
END
|
|
|
|
NewGetNextEvent START
|
|
NewGetNextEvent name
|
|
|
|
phy
|
|
phx
|
|
pha
|
|
phb
|
|
phk
|
|
plb
|
|
jsr CheckGNOCON
|
|
plb
|
|
pla
|
|
plx
|
|
ply
|
|
jmp >OldGetNextEvent
|
|
END
|
|
|
|
NewEventAvail START
|
|
NewEventAvail name
|
|
|
|
phy
|
|
phx
|
|
pha
|
|
phb
|
|
phk
|
|
plb
|
|
jsr CheckGNOCON
|
|
plb
|
|
pla
|
|
plx
|
|
ply
|
|
jmp >OldEventAvail
|
|
END
|
|
|
|
NewOSEventAvail START
|
|
NewOSEventAvail name
|
|
|
|
phy
|
|
phx
|
|
pha
|
|
phb
|
|
phk
|
|
plb
|
|
jsr CheckGNOCON
|
|
plb
|
|
pla
|
|
plx
|
|
ply
|
|
jmp >OldOSEventAvail
|
|
END
|
|
|
|
NewGetOSEvent START
|
|
NewGetOSEvent name
|
|
|
|
phy
|
|
phx
|
|
pha
|
|
phb
|
|
phk
|
|
plb
|
|
jsr CheckGNOCON
|
|
plb
|
|
pla
|
|
plx
|
|
ply
|
|
jmp >OldGetOSEvent
|
|
END
|
|
|
|
CheckGNOCON START
|
|
CheckGNOCON name
|
|
using InOutData
|
|
using ADBData
|
|
|
|
* If this is the actual nullProcess, don't fetch keyboard input. If this
|
|
* is, however, the CDA panel, let events get caught. Then check for
|
|
* a process in the background (and ignore if so).
|
|
* We check for nullprocess by a bogus event mask because we can't
|
|
* simply check the PID - it could be the CDA panel running as the
|
|
* nullprocess (or init or something wierd like that).
|
|
|
|
lda 20,s
|
|
cmp #$0400
|
|
bne notNullProc
|
|
inbg rts don't go away eventless, just go away
|
|
|
|
notNullProc anop
|
|
lda >bufState
|
|
bne doGetKey we're in the CDA panel
|
|
|
|
jsr isBGProcess
|
|
bcc doGetKey
|
|
rts
|
|
|
|
doGetKey php
|
|
sei ; temporarily shut off interrupts
|
|
again lda >bufState
|
|
bne bufferOff
|
|
|
|
lda >head ; if head == tail then there
|
|
cmp >tail ; is no data in the input buffer
|
|
beq noKeyWaiting
|
|
|
|
lda >tail ; get the character & modifiers
|
|
tax ; from the buffer, indexed by
|
|
lda >keybuf,x
|
|
and #$00FF ; tail.
|
|
tay
|
|
|
|
phy ; preserve the Y register thru this, moron
|
|
lda >modbuf,x ; portions out
|
|
and #$00FF
|
|
jsl ConvKMR2EM
|
|
pha
|
|
short m remove the keystroke from the
|
|
lda >tail key buffer
|
|
inc a
|
|
sta >tail
|
|
long m
|
|
pla
|
|
ply
|
|
|
|
doThePost pha
|
|
bit #$08
|
|
bne autoKeyIt
|
|
pea 3
|
|
bra noak
|
|
autoKeyIt pea 5
|
|
noak pha
|
|
phy
|
|
jsr DoKeyTranslation
|
|
bcs noPostEvent
|
|
_PostEvent
|
|
pla
|
|
bra again
|
|
|
|
noKeyWaiting plp ; restore interrupts
|
|
rts
|
|
noPostEvent pla
|
|
pla
|
|
pla
|
|
pla
|
|
bra noKeyWaiting go ahead and zap the keypress
|
|
|
|
bufferOff short m
|
|
lda >$E0C000 key available?
|
|
bpl noKeyWaiting
|
|
tay
|
|
lda >$E0C025
|
|
sta >$E0C010
|
|
long m
|
|
and #$00FF map the modifiers
|
|
phy preserve the Y register thru this
|
|
jsl ConvKMR2EM
|
|
ply
|
|
pha
|
|
tya
|
|
and #$7F
|
|
tay
|
|
pla
|
|
bra doThePost
|
|
|
|
DoKeyTranslation anop
|
|
phd
|
|
lda >$E103CA Get the WAP for the Event Manager
|
|
pha
|
|
lda >$E103C8
|
|
pha
|
|
tsc
|
|
tcd And set the DP to it
|
|
ldy #$0018 Tool set 6 * 4 bytes each
|
|
lda [$01],y
|
|
ply
|
|
ply
|
|
cmp #$0000
|
|
beq doNothing Event Manager not started??!?!!
|
|
tcd
|
|
lda $68 Translation table loaded?
|
|
bne okay yes
|
|
clc no, so don't translate the keypress
|
|
bra doNothing
|
|
okay pei $68 Save the translation handle on the stack
|
|
pei $66
|
|
ldy #$0002
|
|
lda [$66],y
|
|
tax
|
|
lda [$66] Deref the key translation
|
|
sta $66 table handle directly into
|
|
stx $68 the same pointer
|
|
lda $0B,s
|
|
and #$0800 option Key pressed?
|
|
beq noOption
|
|
bra OptionKey
|
|
doneXlate pla
|
|
sta $66
|
|
pla
|
|
sta $68
|
|
doNothing pld
|
|
rts
|
|
OptionKey lda $09,s set the hi bit of
|
|
ora #$0080 the character if
|
|
bra yucky1 option was pressed
|
|
noOption lda $09,s
|
|
yucky1 tay
|
|
lda [$66],y
|
|
and #$00FF
|
|
cmp #$00FF if the entry is FF
|
|
bne l1A79 $$$
|
|
tya set the hi bit
|
|
ora #$0080
|
|
tay
|
|
lda [$66],y and load in the
|
|
and #$00FF option-key version
|
|
l1A79 tax and stuff in X
|
|
lda $6A last keystroke a dead key?
|
|
bne validateDead if so, go to 'validate'
|
|
tya
|
|
and #$0080
|
|
beq notDead
|
|
stx $6A set the dead key
|
|
ldy #$0100
|
|
scanDeadKey lda [$66],y
|
|
and #$00FF
|
|
beq notDead last entry in array?
|
|
cmp $6A
|
|
beq isDeadKey dead key found?
|
|
iny
|
|
iny
|
|
bra scanDeadKey
|
|
notDead txa
|
|
stz $6A clear dead key flag/value
|
|
sta $09,s
|
|
clc
|
|
bra doneXlate
|
|
isDeadKey sec
|
|
bra doneXlate
|
|
validateDead ldy #$0100
|
|
lp2 lda [$66],y scan the dead key
|
|
and #$00FF table for the offset
|
|
beq noDeadMatch in the replacement
|
|
cmp $6A table
|
|
beq gotIt got it
|
|
iny
|
|
iny
|
|
bra lp2
|
|
gotIt lda [$66],y
|
|
and #$FF00
|
|
xba
|
|
asl a
|
|
clc
|
|
adc #$0100 deadKey+replaceTab
|
|
tay is 256 bytes at most
|
|
phx
|
|
scanReplace lda [$66],y now find the keycode
|
|
and #$00FF they just hit
|
|
beq noReplMatch end of list, no match
|
|
cmp $01,s
|
|
beq matched matched a key
|
|
iny
|
|
iny
|
|
bra scanReplace
|
|
noDeadMatch txa
|
|
sta $09,s
|
|
stz $6A
|
|
clc
|
|
bra l1234
|
|
matched plx
|
|
lda [$66],y
|
|
and #$FF00
|
|
xba
|
|
tax
|
|
bra noDeadMatch replaced, clc means
|
|
noReplMatch pla regular key
|
|
sta $09,s
|
|
lda $0B,s
|
|
pha
|
|
pea $0003
|
|
ora #$0800
|
|
pha
|
|
lda $6A
|
|
pha
|
|
_PostEvent
|
|
pla
|
|
stz $6A
|
|
clc
|
|
l1234 brl doneXlate
|
|
END
|
|
|
|
checkExclTTY START KERN2
|
|
checkExclTTY name
|
|
ttyPtr equ 1
|
|
|
|
tay
|
|
pha
|
|
pha
|
|
tsc
|
|
phd
|
|
tcd
|
|
|
|
dey
|
|
tya
|
|
asl a
|
|
asl a
|
|
tax
|
|
lda >DeviceBlock,x
|
|
sta ttyPtr
|
|
lda >DeviceBlock+2,x
|
|
sta ttyPtr+2
|
|
|
|
ldy #privFlags
|
|
lda [ttyPtr],y
|
|
ldy #0
|
|
bit #EXCL
|
|
beq not_excl
|
|
ldy #1
|
|
not_excl anop
|
|
pld
|
|
pla
|
|
pla
|
|
rtl
|
|
END
|
|
|
|
* FIXME: change calls that use this to call TIioctl directly
|
|
* int ioctl (int fd, unsigned long request, void *argp);
|
|
ioctl START KERN2
|
|
ioctl name
|
|
retval equ 1
|
|
sub (4:argp,4:request,2:d),2
|
|
|
|
pha
|
|
ph2 d
|
|
ph4 request
|
|
ph4 argp
|
|
ph4 #errno
|
|
ldx #$2603
|
|
jsl udispatch
|
|
pla
|
|
sta retval
|
|
ret 2:retval
|
|
END
|
|
|