gno/kern/gno/pty.asm

1338 lines
21 KiB
NASM

* $Id: pty.asm,v 1.1 1998/02/02 08:19:40 taubert Exp $
****************************************************************
*
* Pseudo-TTY device drivers and line discipline
*
* Assumes 32 PTYs right now
*
****************************************************************
case on
mcopy m/pty.mac
copy inc/tty.inc
DebugNames gequ 1
ptyBufSize gequ 4096 !! MUST BE A POWER OF TWO !!
ptyDevStart gequ 6
IncBusy gequ $E10064
DecBusy gequ $E10068
ptyDPindex START KERN2
dc i2'ptyRecSize*0'
dc i2'ptyRecSize*0'
dc i2'ptyRecSize*1'
dc i2'ptyRecSize*1'
dc i2'ptyRecSize*2'
dc i2'ptyRecSize*2'
dc i2'ptyRecSize*3'
dc i2'ptyRecSize*3'
dc i2'ptyRecSize*4'
dc i2'ptyRecSize*4'
dc i2'ptyRecSize*5'
dc i2'ptyRecSize*5'
dc i2'ptyRecSize*6'
dc i2'ptyRecSize*6'
dc i2'ptyRecSize*7'
dc i2'ptyRecSize*7'
dc i2'ptyRecSize*8'
dc i2'ptyRecSize*8'
dc i2'ptyRecSize*9'
dc i2'ptyRecSize*9'
dc i2'ptyRecSize*10'
dc i2'ptyRecSize*10'
dc i2'ptyRecSize*11'
dc i2'ptyRecSize*11'
dc i2'ptyRecSize*12'
dc i2'ptyRecSize*12'
dc i2'ptyRecSize*13'
dc i2'ptyRecSize*14'
dc i2'ptyRecSize*14'
dc i2'ptyRecSize*15'
dc i2'ptyRecSize*15'
dc i2'ptyRecSize*16'
dc i2'ptyRecSize*16'
dc i2'ptyRecSize*17'
dc i2'ptyRecSize*17'
dc i2'ptyRecSize*18'
dc i2'ptyRecSize*18'
dc i2'ptyRecSize*19'
dc i2'ptyRecSize*19'
dc i2'ptyRecSize*20'
dc i2'ptyRecSize*20'
dc i2'ptyRecSize*21'
dc i2'ptyRecSize*21'
dc i2'ptyRecSize*22'
dc i2'ptyRecSize*22'
dc i2'ptyRecSize*23'
dc i2'ptyRecSize*23'
dc i2'ptyRecSize*24'
dc i2'ptyRecSize*24'
dc i2'ptyRecSize*25'
dc i2'ptyRecSize*25'
dc i2'ptyRecSize*26'
dc i2'ptyRecSize*26'
dc i2'ptyRecSize*27'
dc i2'ptyRecSize*27'
dc i2'ptyRecSize*28'
dc i2'ptyRecSize*28'
dc i2'ptyRecSize*29'
dc i2'ptyRecSize*29'
dc i2'ptyRecSize*30'
dc i2'ptyRecSize*30'
dc i2'ptyRecSize*31'
dc i2'ptyRecSize*31'
END
PTY_signalIO START KERN2
txa ; put devNum in acc
txy
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
tya
eor 6,s
bit #1
bne Bcheck4select
; check for select here.
Acheck4select anop
lda >PTYSlaveHeader+t_select_proc
cmp #$FFFF
beq Adone
* someone is selecting on us, so call selwakeup with the process ID
* and our collision flag
pha
lda >PTYSlaveHeader+privFlags
and #TS_RCOLL
pha
jsl >PTYSlaveHeader+t_selwakeup
lda >PTYSlaveHeader+privFlags
and #TS_RCOLL.EOR.$FFFF
sta >PTYSlaveHeader+privFlags
lda #$FFFF
sta >PTYSlaveHeader+t_select_proc
Adone anop
pei (p_bufAptr+2)
pei (p_bufAptr)
jsl k_wakeup
bra byebye
; check for select here.
Bcheck4select anop
lda >PTYMastHeader+t_select_proc
cmp #$FFFF
beq Bdone
* someone is selecting on us, so call selwakeup with the process ID
* and our collision flag
pha
lda >PTYMastHeader+privFlags
and #TS_RCOLL
pha
jsl >PTYMastHeader+t_selwakeup
lda >PTYMastHeader+privFlags
and #TS_RCOLL.EOR.$FFFF
sta >PTYMastHeader+privFlags
lda #$FFFF
sta >PTYMastHeader+t_select_proc
Bdone anop
pei (p_bufBptr+2)
pei (p_bufBptr)
jsl k_wakeup
byebye anop
pld
lda 2,s
sta 4,s
lda 1,s
sta 3,s
pla
rtl
END
A_sizeq START KERN2
_A_sizeq name
txa ; put devNum in acc
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
lda #4095
sec
sbc p_Aleft
pld
rtl
END
A_leftq START KERN2
_A_leftq name
txa ; put devNum in acc
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
lda p_Aleft
pld
rtl
END
B_sizeq START KERN2
_B_sizeq name
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
lda #4095
sec
sbc p_Bleft
pld
rtl
END
B_leftq START KERN2
_B_leftq name
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
lda p_Bleft
pld
rtl
END
pty_mutex START KERN2
_pty_mutex name
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
pei (p_sem)
jsl >IncBusy
jsl asmWait
pld
rtl
END
pty_demutex START KERN2
_pty_demutex name
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
pei (p_sem)
jsl asmSignal
jsl >DecBusy
pld
rtl
END
*
* ENQUEUE/DEQUEUE routines
*
A_deq START KERN2
using KernelStruct
_a_deq name
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
again ldx p_Aleft
cpx #4095
beq dowait
ldy p_Atail
lda [p_bufAptr],y
and #$00FF
pha
tya
inc a
and #ptyBufSize-1 ; wrap it around
sta p_Atail
inx
stx p_Aleft
pla
pld
rtl
dowait anop
* free access semaphore
pei (p_sem)
jsl asmSignal
* wait on vector of buffer A; the line discipline code calls a low level
* signal_operation(read|write) to indicate what happened. That way we
* don't vec_signal each and every time a character goes out.
lda >truepid
pha
pea 0
pei (p_bufAptr+2)
pei (p_bufAptr)
jsl k_sleep
pei (p_sem)
jsl asmWait
bra again
END
B_deq START KERN2
using KernelStruct
_b_deq name
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
again ldx p_Bleft
cpx #4095
beq dowait
ldy p_Btail
lda [p_bufBptr],y
and #$00FF
pha
tya
inc a
and #ptyBufSize-1 ; wrap it around
sta p_Btail
inx
stx p_Bleft
pla
pld
rtl
dowait anop
pei (p_sem)
jsl asmSignal
lda >truepid
pha
pea 0
pei (p_bufBptr+2)
pei (p_bufBptr)
jsl k_sleep
pei (p_sem)
jsl asmWait
bra again
END
A_enq START KERN2
using KernelStruct
char equ 6
_a_enq name
* subroutine (2:char),2
* 'char' is 6,7,S
* RTL address is 3,4,5,S
* dp is 1,2,S
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd ; 1,s
tcd
again ldx p_Aleft
cpx #0
beq dowait
ldy p_Ahead
short m
lda char,S
sta [p_bufAptr],y
long m
tya
inc a
and #ptyBufSize-1 ; wrap it around
sta p_Ahead
dex
stx p_Aleft
pld
lda 2,s
sta 4,s
lda 1,s
sta 3,s
pla
rtl
dowait anop
* free access semaphore
pei (p_sem)
jsl asmSignal
* wait on vector of buffer A; the line discipline code calls a low level
* signal_operation(read|write) to indicate what happened. That way we
* don't vec_signal each and every time a character goes out.
lda >truepid
pha
pea 0
pei (p_bufAptr+2)
pei (p_bufAptr)
jsl k_sleep
pei (p_sem)
jsl asmWait
bra again
END
B_enq START KERN2
using KernelStruct
char equ 6
_b_enq name
* subroutine (2:char),2
txa
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
phd
tcd
again ldx p_Bleft
cpx #0
beq dowait
ldy p_Bhead
short m
lda char,S
sta [p_bufBptr],y
long m
tya
inc a
and #ptyBufSize-1 ; wrap it around
sta p_Bhead
dex
stx p_Bleft
pld
lda 2,s
sta 4,s
lda 1,s
sta 3,s
pla
rtl
dowait anop
* free access semaphore
pei (p_sem)
jsl asmSignal
lda >truepid
pha
pea 0 ; wakeup priority
pei (p_bufBptr+2)
pei (p_bufBptr)
jsl k_sleep
pei (p_sem)
jsl asmWait
bra again
END
* 24 bytes each. 24*32 = 768 pages of direct page space
* Steal this from the kernel.
PTYSlaveHeader START KERN2
ds t_open
* Line Discipline entry points
dc i4'PTYOpen'
dc i4'PTYClose'
dc i4'PTYIOCTL'
dc i4'ttread'
dc i4'ttwrite'
dc i4'pty_mutex'
dc i4'pty_demutex'
dc i4'B_enq'
dc i4'A_enq'
dc i4'B_deq'
dc i4'A_deq'
dc i4'A_sizeq'
dc i4'B_sizeq'
ds t_signalIO-editInd
dc i4'PTY_signalIO'
dc i2'$FFFF' ; noone selecting
dc i4'PTYS_select'
jmp >selwakeup
END
PTYMastHeader START KERN2
ds t_open
* Line Discipline entry points
dc i4'PTYOpen'
dc i4'PTYClose'
dc i4'PTYIOCTL'
dc i4'ttread'
dc i4'ptwrite'
dc i4'pty_mutex'
dc i4'pty_demutex'
dc i4'A_enq'
dc i4'B_enq'
dc i4'A_deq'
dc i4'B_deq'
dc i4'B_sizeq'
dc i4'A_sizeq'
ds t_signalIO-editInd
dc i4'PTY_signalIO'
dc i2'$FFFF' ; noone selecting
dc i4'PTYM_select'
jmp >selwakeup
END
initPTY START KERN2
ptyhand equ 0
ptyptr equ 4
_init_pty name
subroutine (0:foo),8
pha
pha
pea 0
pea ptyRecSize*32
lda >~USER_ID
pha
pea $C015
pea 0
pea 0
_NewHandle
pl4 ptyhand
lda [ptyhand]
sta >PTYDP
sta ptyptr
ldy #2
lda [ptyhand],y
sta >PTYDP+2
sta ptyptr+2
ldy #0
next lda #0
sta [ptyptr],y
iny
iny
sta [ptyptr],y
tya
clc
adc #ptyRecSize-2
tay
cmp #ptyRecSize*32
bcc next
return
END
* If the devNum is even, this is the master we're opening.
* If the devNum is odd, this is the slave we're opening.
PTYOpen START KERN2
using KernelStruct
ptyDpPtr equ 0
bufA equ 4
bufB equ 8
dTermioPtr equ 12
result equ 16
masterTerm equ 18
slaveTerm equ 22
subroutine (2:devNum),26
stz result
lda devNum
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
sta ptyDpPtr
stz ptyDpPtr+2
ldy #p_bufAptr
lda [ptyDpPtr],y
ldy #p_bufAptr+2
ora [ptyDpPtr],y
beq notInit ; this pty was not yet initialized
* at this point, the pty structures are already allocated and initialized.
* So, we need to signal the process that opened the other end of the pty
* to continue.
; pei (ptyDpPtr+2)
; pei (ptyDpPtr)
; jsl k_wakeup
jmp finish
notInit anop
; if we're trying to open the Slave w/o the master being open, fail
; with an error $50.
lda devNum
bit #1
beq isMaster
lda #$50
sta result
jmp finish
; allocate master's and slave's TTY headers via malloc
isMaster ph4 #ttyRecSize
jsl malloc
stx masterTerm+2
sta masterTerm
ph4 #ttyRecSize
jsl malloc
stx slaveTerm+2
sta slaveTerm
; initialize them by copying data from the static copies here in KERN2
lda #ptwrite ; install custom write routine
ldy #t_write ; for the master
sta PTYMastHeader,y
lda #^ptwrite
sta PTYMastHeader+2,y
ph4 #ttyRecSize
ph4 #PTYMastHeader
pei (masterTerm+2)
pei (masterTerm)
jsl memcpy
ph4 #ttyRecSize
ph4 #PTYSlaveHeader
pei (slaveTerm+2)
pei (slaveTerm)
jsl memcpy
lda devNum
and #$FFFE ; clear the low bit
asl a
asl a
tax
lda masterTerm+2 ; init the header pointers
sta >DeviceBlock+2,x
lda masterTerm
sta >DeviceBlock,x
lda slaveTerm+2
sta >DeviceBlock+6,x
lda slaveTerm
sta >DeviceBlock+4,x
pea 0
pea ptyBufSize
jsl malloc ; alloc buffer A
stx bufA+2
sta bufA
ldy #p_bufAptr
sta [ptyDpPtr],y
txa
ldy #p_bufAptr+2
sta [ptyDpPtr],y
pea 0
pea ptyBufSize
jsl malloc ; alloc buffer B
stx bufB+2
sta bufB
ldy #p_bufBptr
sta [ptyDpPtr],y
txa
ldy #p_bufBptr+2
sta [ptyDpPtr],y
* For purposes of interrupt chars & whatnot, both devices use the slave's
* ioctl structure, so initialize that.
* Initialize default values for terminal settings
ldy #sg_flags
lda #CRMOD+ECHO
sta [slaveTerm],y
short m
lda #0
sta [slaveTerm] ; ispeed
ldy #sg_ospeed
sta [slaveTerm],y ; ospeed
ldy #t_intrc
lda #'C'-64
sta [slaveTerm],y ; t_intrc
ldy #t_suspc
lda #'Z'-64
sta [slaveTerm],y
ldy #t_quitc
lda #'\'-64
sta [slaveTerm],y
ldy #t_startc
lda #'Q'-64
sta [slaveTerm],y
ldy #t_stopc
lda #'S'-64
sta [slaveTerm],y
ldy #t_eofc
lda #'D'-64
sta [slaveTerm],y
ldy #t_brkc
lda #-1
sta [slaveTerm],y
ldy #t_dsuspc
lda #'Y'-64
sta [slaveTerm],y
ldy #t_rprntc
lda #'R'-64
sta [slaveTerm],y
ldy #sg_erase
lda #$7F
sta [slaveTerm],y
long m
ldy #privFlags
lda #0 ; master can only be opened once
sta [slaveTerm],y
lda #EXCL
sta [masterTerm],y
ldy #local
lda #LCRTERA+LCTLECH
sta [slaveTerm],y
ldy #ws_row
lda #24
sta [slaveTerm],y
ldy #ws_col
lda #80
sta [slaveTerm],y
ldy #ws_xpixel
lda #0
sta [slaveTerm],y
ldy #ws_ypixel
sta [slaveTerm],y
lda #RAW
ldy #sg_flags
sta [masterTerm],y
pea 1
jsl asmSemNew
ldy #p_sem
sta [ptyDpPtr],y
lda #0
ldy #p_Ahead
sta [ptyDpPtr],y
ldy #p_Atail
sta [ptyDpPtr],y
ldy #p_Bhead
sta [ptyDpPtr],y
ldy #p_Btail
sta [ptyDpPtr],y
lda #ptyBufSize-1
ldy #p_Aleft
sta [ptyDpPtr],y
ldy #p_Bleft
sta [ptyDpPtr],y
; jsl decBusy
; lda >truepid
; pha
; pea 0
; pei (ptyDpPtr+2)
; pei (ptyDpPtr)
; jsl k_sleep
; jsl incBusy
finish anop
return 2:result
PTYDP ENTRY
dc i4'0'
END
PTYClose START KERN2
ptyDpPtr equ 0
otherHeader equ 4
devIndex equ 8
subroutine (2:devNum),10
lda devNum
sec
sbc #ptyDevStart
asl a ; calculate index into table
tax
lda >ptyDPindex,x
clc ; clc$$
adc >PTYDP
sta ptyDpPtr
stz ptyDpPtr+2
* only deallocate PTY information if the both ends of the PTY have been
* closed (see if the other PTY has been closed)
lda devNum
asl a
asl a
sta devIndex
lda devNum
eor #1 ; the OTHER one, dork
asl a
asl a
tax
lda #^PTYMastHeader
cmp >DeviceBlock+2,x
bne notClosed
lda >DeviceBlock,x
cmp #PTYMastHeader
beq isClosed
cmp #PTYSlaveHeader
beq isClosed
* If we're closing the master, send a SIGHUP to the PTYs process group
* If the slave was already closed, we assume there are no processes
* to kill and thus we don't fall through
notClosed lda devNum
ror a
bcs notMaster
pea 1 ; push signal number
lda devNum
inc a
pha ; signal the TTY end
jsl PTYSlaveHeader+t_sendSignal
notMaster bra goaway
* Deallocate the pty buffers - only executed when both ends are
* closed
isClosed ldy #p_bufAptr+2
lda [ptyDpPtr],y
pha
ldy #p_bufAptr
lda [ptyDpPtr],y
pha
jsl nfree
ldy #p_bufBptr+2
lda [ptyDpPtr],y
pha
ldy #p_bufBptr
lda [ptyDpPtr],y
pha
jsl nfree
lda #0
ldy #p_bufAptr ; zero out this info
sta [ptyDpPtr],y
ldy #p_bufAptr+2
sta [ptyDpPtr],y
goaway anop
* Deallocate the PTYs header
ldx devIndex
lda >DeviceBlock+2,x
pha
lda >DeviceBlock,x
pha
jsl free
* Reset the tty header pointer so we know we're closed
ldx devIndex
lda devNum
ror a
bcs resetSlave
lda #^PTYMastHeader
sta >DeviceBlock+2,x
lda #PTYMastHeader
sta >DeviceBlock,x
bra byebye
resetSlave lda #^PTYSlaveHeader
sta >DeviceBlock+2,x
lda #PTYSlaveHeader
sta >DeviceBlock,x
byebye return
END
PTYIOCTL START KERN2
using KernelStruct
retval equ 0
subroutine (4:tioc,4:dataPtr,2:devNum),2
lda tioc
and #$FF00
xba
cmp #'f'
beq chkfile
cmp #'t'
beq tioctl
err lda #-1
sta retval
jmp goaway
chkfile lda tioc
and #$7F
cmp #127
bne err
ldx devNum
jsl pty_mutex
lda devNum
tax
bit #%00000001 ; ARGH! IMMEDIATE! IMMEDIATE!
beq isMaster
jsl A_sizeq
bra notMaster
isMaster jsl B_sizeq
notMaster anop
sta [dataPtr]
ldx devNum
jsl pty_demutex
stz retval
jmp goaway
tioctl anop
lda tioc
and #$7F
cmp #21
bcc okay2
eor #$7F
cmp #26
bcc okay1
jmp invalid
okay1 anop
asl a
asl a
inc a
inc a
tax
jmp (tNTable,x)
okay2 anop
asl a
asl a
inc a
inc a
tax
jmp (tPTable,x)
goaway return 2:retval
tPTable anop
dc i2'0',a2'TIOCGETD'
dc i2'1',a2'TIOCSETD'
dc i2'-1',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'-1',a2'invalid'
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'-1',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'16',a2'TIOCFLUSH'
dc i2'-1',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'19',a2'invalid'
dc i2'20',a2'invalid'
tNTable anop
dc i2'127',a2'invalid'
dc i2'126',a2'invalid'
dc i2'125',a2'invalid'
dc i2'124',a2'invalid'
dc i2'123',a2'invalid'
dc i2'122',a2'invalid'
dc i2'121',a2'invalid'
dc i2'120',a2'invalid'
dc i2'119',a2'invalid'
dc i2'118',a2'invalid'
dc i2'117',a2'invalid'
dc i2'116',a2'invalid'
dc i2'115',a2'TIOCOUTQ'
dc i2'114',a2'TIOCSTI'
dc i2'113',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'111',a2'TIOCSTOP'
dc i2'110',a2'TIOCSTART'
dc i2'109',a2'invalid'
dc i2'108',a2'invalid'
dc i2'107',a2'invalid'
dc i2'106',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'104',a2'invalid'
dc i2'103',a2'invalid'
invalid lda #-1
sta retval
jmp goaway
*****************************************************
dc i2'0',a2'TIOCGETD'
dc i2'1',a2'TIOCSETD'
dc i2'-1',a2'invalid'
dc i2'-1',a2'invalid'
dc i2'-1',a2'invalid'
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'
TIOCGETD anop
TIOCSETD anop
TIOCSETN anop
TIOCSETP anop
TIOCGETP stz retval
jmp goaway
TIOCOUTQ anop
TIOCSTOP anop
TIOCSTART anop
TIOCFLUSH anop
* simulate terminal input (this code is borrowed from INOUT.ASM/OurADB
TIOCSTI anop
stz retval
jmp goaway
END
ptwrite START KERN2
ttyPtr equ 0
c equ 4
xfer equ 6
retval equ 8
slavePtr equ 10
subroutine (2:length,4:buf,2:devNum),14
lda devNum
jsr fetchDevPtr
sta ttyPtr
stx ttyPtr+2
lda devNum
and #%11111110 clear lo bit
inc a
jsr fetchDevPtr
sta slavePtr
stx slavePtr+2
lda length
sta xfer
stz retval
ldx devNum
ldy #mutex
jsl ttyDispatch
px1 anop we were in raw or cbreak mode
lda length
jeq pw1
dea
sta length
lda [buf]
and #$00FF
sta c
inc buf
bne px2
inc buf+2
px2 anop
; check for special characters going to the slave, and process appropriately
lda c
jsr checkPtyIntr
bcs px1 ; don't write char if it was a signal
pei (c)
ldx devNum
ldy #out_enq
jsl ttyDispatch
jmp px1
pw1 ldx devNum
ldy #demutex
jsl ttyDispatch
pea 0 ; 0 means 'write occurred'
ldx devNum
ldy #t_signalIO
jsl ttyDispatch
return 4:xfer
checkPtyIntr anop
php
long ai
and #$7f
pha
short m
ldy #sg_flags
lda [slavePtr],y
bit #RAW ; RAW mode?
beq x9 ; yep, no character checking
brl notty
x9 ldy #t_quitc
lda [slavePtr],y
cmp #-1
beq x0
cmp 1,s
beq gotQQ
x0 ldy #t_suspc
lda [slavePtr],y
cmp #-1
beq x1
cmp 1,s
beq gotZ
x1 ldy #t_intrc
lda [slavePtr],y
cmp #-1
beq x2
cmp 1,s
beq gotC
bra notty
x2 anop
; lda >OutStopped
; bne x3
; ldy #t_stopc
; lda [slavePtr],y
; cmp #-1
; beq x3
; cmp 1,s
; beq gotS
x3 anop
; ldy #t_startc
; lda [slavePtr],y
; cmp #-1
; beq notty
; cmp 1,s
; beq gotQ
; bra notty
;gotS long m
; pla
; lda #1
; sta >OutStopped
; plp
; sec
; rts
;gotQ long m
; pla
; lda >OutStopped
; beq notQ
; lda #0
; sta >OutStopped
; plp
; sec
; rts
notQ anop ;oops!
plp
clc
rts
gotQQ long m
lda #3
bra gotSIG
gotZ long m
lda #18
bra gotSIG
gotC long m
lda #2
gotSIG anop
phx
phy
pha
pha ; push signal number
lda devNum
inc a ; push our device number
pha
jsl PTYSlaveHeader+t_sendSignal ; setup by InstallDriver
; flush internal editing buffers on interrupt character
lda #0
ldy #editInd
sta [slavePtr],y
ldy #editBegin
sta [slavePtr],y
ldy #st_flags
sta [slavePtr],y
pla ; prolly don't need to, but what
ply ; the hell...
plx
pla ; the character
plp ; ready? Let's go!
sec
rts
notty anop
long m
pla
plp
clc
rts
sigtosend dc i2'0'
END
; eeeeewwwww, just one t_select_proc for all the ptys?
; we should probably store that on a per-pty basis...
PTYS_select START KERN2
res equ 0
subroutine (2:ttyn,2:which,2:pid),2
lda #1
sta res
lda ttyn
tax ; *_sizeq needs devNum in X
lda which ; which I/O to check?
cmp #SEL_READ
bne trywrite
jsl A_sizeq ; # bytes in in q
cmp #0
bne done
willwait anop
* record that the process wants to do I/O
lda >PTYSlaveHeader+t_select_proc ; see if someone's here already
cmp #$FFFF ; nope
beq nocollision
cmp pid ; is it us?
beq nocollision
lda >PTYSlaveHeader+privFlags
ora #TS_RCOLL
sta >PTYSlaveHeader+privFlags
bra none
nocollision anop
lda pid ; set select_proc field to
sta >PTYSlaveHeader+t_select_proc ; current process ID
bra none
trywrite cmp #SEL_WRITE
bne doexcept
jsl B_leftq ; # bytes avail in out q
cmp #0
bne done
bra willwait
doexcept anop
; there are no exceptions on ptys - what about other side close?
none lda #0 ; no data, return 0
sta res
done anop
return 2:res
END
PTYM_select START KERN2
res equ 0
subroutine (2:ttyn,2:which,2:pid),2
lda #1
sta res
lda ttyn
tax ; *_sizeq needs devNum in X
lda which ; which I/O to check?
cmp #SEL_READ
bne trywrite
jsl B_sizeq ; # bytes in in q
cmp #0
bne done
willwait anop
* record that the process wants to do I/O
lda >PTYMastHeader+t_select_proc ; see if someone's here already
cmp #$FFFF ; nope
beq nocollision
cmp pid ; is it us?
beq nocollision
lda >PTYMastHeader+privFlags
ora #TS_RCOLL
sta >PTYMastHeader+privFlags
bra none
nocollision anop
lda pid ; set select_proc field to
sta >PTYMastHeader+t_select_proc ; current process ID
bra none
trywrite cmp #SEL_WRITE
bne doexcept
jsl A_leftq ; # bytes avail in out q
cmp #0
bne done
bra willwait
doexcept anop
; there are no exceptions on ptys - what about other side close?
none lda #0 ; no data, return 0
sta res
done anop
return 2:res
END