diff --git a/kern/drivers/Makefile b/kern/drivers/Makefile new file mode 100644 index 0000000..9fc2f42 --- /dev/null +++ b/kern/drivers/Makefile @@ -0,0 +1,35 @@ +# $Id: Makefile,v 1.1 1998/02/02 08:17:50 taubert Exp $ + +.INCLUDE: /src/gno/paths.mk + +all: modem printer null + +modem: port.o msccf.o + $(LD) $(LDFLAGS) -l libsim -o $@ $< + chtyp -t 187 -a 32257 $@ +modem: libsim + +printer: port.o psccf.o + $(LD) $(LDFLAGS) -l libsim -o $@ $< + chtyp -t 187 -a 32257 $@ +printer: libsim + +null: null.o + $(LD) $(LDFLAGS) -o $@ $< + chtyp -t 187 -a 32257 $@ + +console: console.o inout.o box.root conpatch.o + $(LD) $(LDFLAGS) -o $@ $< + chtyp -t 187 -a 32257 $@ + +### Dependencies ### + +box.root: box.mac console.equates +conpatch.asm: conpatch.mac +console.root: port.mac console.equates kern.equates ../gno/inc/tty.inc +inout.root: inout.mac console.equates kern.equates ../gno/inc/tty.inc +msccf.root: sccf.mac equates md.equates sccf.asm ../gno/inc/tty.inc +null.root: port.mac ../gno/inc/tty.inc +port.root: port.mac equates ../gno/inc/tty.inc +psccf.root: sccf.mac equates pr.equates sccf.asm ../gno/inc/tty.inc + diff --git a/kern/drivers/box.asm b/kern/drivers/box.asm new file mode 100644 index 0000000..063ab3e --- /dev/null +++ b/kern/drivers/box.asm @@ -0,0 +1,73 @@ +* $Id: box.asm,v 1.1 1998/02/02 08:17:52 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* BOX.ASM +* By Jawaid Bazyar +* +* Contains routines for drawing boxes using MouseText +* +************************************************************************** + + case on + mcopy ../drivers/box.mac + copy ../drivers/console.equates + +* EraseBox takes the same parameters as DrawBox, except the Accum +* is the character to fill the box with. + +EraseBox START + + sta EraseChar + lda 0,.a +&BL SETA L:&SYSOPR+1 +.a +&REST AMID "&SYSOPR",2,&BL-2 + dc I1'$F4',I2'&REST' + MEND + MACRO +&lab _SysFailMgr +&lab ldx #$1503 + jsl $E10000 + MEND + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/drivers/conpatch.asm b/kern/drivers/conpatch.asm new file mode 100644 index 0000000..22bfc78 --- /dev/null +++ b/kern/drivers/conpatch.asm @@ -0,0 +1,81 @@ +* $Id: conpatch.asm,v 1.1 1998/02/02 08:17:53 taubert Exp $ + + case on + mcopy ../drivers/conpatch.mac + +PatchDeskManager START + phd + pha + pha + pea $0000 ; system tool set + pea $0005 ; Desk Manager + _GetTSPtr + tsc + tcd + + ldy #$002d ; ($b * 4) + 1 + lda [$1],y + sta >CONOLDSAVEALL+1 + dey + lda [$1],y + inc A + sta >CONOLDSAVEALL + iny + lda #>ConSaveAllPatch ; -1 + sta [$1],y + dey + lda #ConSaveAllPatch-1 + sta [$1],y + + ldy #$0031 ; ($c * 4) + 1 + lda [$1],y + sta >CONOLDRESTALL+1 + dey + lda [$1],y + inc A + sta >CONOLDRESTALL + iny + lda #>ConRestAllPatch ; -1 + sta [$1],y + dey + lda #ConRestAllPatch-1 + sta [$1],y + + pla + pla + pld + rtl + END + +UnpatchDeskManager START + phd + pha + pha + pea $0000 ; system tool set + pea $0005 ; Desk Manager + _GetTSPtr + tsc + tcd + + ldy #$002d ; ($b * 4) + 1 + lda >CONOLDSAVEALL+1 + sta [$1],y + dey + lda >CONOLDSAVEALL + dec A + sta [$1],y + + ldy #$0031 ; ($c * 4) + 1 + lda >CONOLDRESTALL+1 + sta [$1],y + dey + lda >CONOLDRESTALL + dec A + sta [$1],y + + pla + pla + pld + rtl + END + diff --git a/kern/drivers/conpatch.mac b/kern/drivers/conpatch.mac new file mode 100644 index 0000000..833629b --- /dev/null +++ b/kern/drivers/conpatch.mac @@ -0,0 +1,6 @@ + MACRO +&lab _GetTSPtr +&lab ldx #$0901 + jsl $E10000 + MEND + diff --git a/kern/drivers/console.asm b/kern/drivers/console.asm new file mode 100644 index 0000000..014c340 --- /dev/null +++ b/kern/drivers/console.asm @@ -0,0 +1,505 @@ +* $Id: console.asm,v 1.1 1998/02/02 08:17:54 taubert Exp $ +************************************************************ +* +* CONSOLE device driver +* +************************************************************ + + case on + mcopy ../drivers/port.mac + copy ../gno/inc/tty.inc + copy ../drivers/console.equates + copy ../drivers/kern.equates + +************************************************************************** +consoleSem gequ $3C ; output code semaphore + +ConsoleHeader START +contty ENTRY + ds t_open +* Line Discipline entry points + dc i4'ConInit' + dc i4'ConDeInit' + dc i4'ConIOCTL' + dc i4'0' ; ttread and ttwrite must be + dc i4'0' ; set up by InstallDriver + dc i4'CON_mutex' + dc i4'CON_demutex' + dc i4'CON_out_enq' + dc i4'CON_in_enq' + dc i4'CON_out_deq' + dc i4'CON_in_deq' + dc i4'CON_size_inq' + dc i4'CON_size_outq' + ds t_signalIO-editInd + dc i4'CON_signalIO' + dc i2'$FFFF' ; noone selecting + dc i4'CON_select' + dc i4'0' ; t_selwakeup set during install + END + +CON_mutex START KERN2 +CON_demutex ENTRY +CON_in_enq ENTRY +CON_out_deq ENTRY + rtl + END + +CON_in_deq START KERN2 +; using InOutData +; phd +; lda >InOutDP +; tcd + jsl KEYIN +; pld + rtl + END + +CON_select START KERN2 +res equ 0 + subroutine (2:ttyn,2:which,2:pid),2 + + lda #1 + sta res + lda which ; which I/O to check? + cmp #SEL_READ + bne trywrite + jsl CON_size_inq ; # bytes in in q + cmp #0 + bne done + +willwait anop +* record that the process wants to do I/O + lda >contty+t_select_proc ; see if someone's here already + cmp #$FFFF ; nope + beq nocollision + cmp pid ; is it us? + beq nocollision + lda >contty+privFlags + ora #TS_RCOLL + sta >contty+privFlags + bra none +nocollision anop + lda pid ; set select_proc field to + sta >contty+t_select_proc ; current process ID + bra none + +trywrite cmp #SEL_WRITE + bne doexcept + bra done ; we can always write to console + +doexcept anop ; there are no exceptions on console +none lda #0 ; no data, return 0 + sta res +done anop + + return 2:res + END + +CON_size_inq START KERN2 + using ADBData + + php + sei + short m + lda >head + sec + sbc >tail + long m + and #$00FF + plp + rtl + END + +CON_size_outq START KERN2 + lda #0 + rtl + END +CON_out_enq START KERN2 +; using InOutData +; phd +; lda >InOutDP +; tcd +; lda 6,s + lda 4,s + jsl COUT +; pld + lda 2,s + sta 4,s + lda 1,s + sta 3,s + pla + rtl + END + +* This function does nothing in the console driver +CON_signalIO START KERN2 + lda 2,s + sta 4,s + lda 1,s + sta 3,s + pla + rtl + END + +ConInit START +dTermioPtr equ 0 +result equ 4 + subroutine (2:devNum),6 + + ld4 contty,dTermioPtr + + stz result + +* Initialize default values for terminal settings + ldy #sg_flags + lda #CRMOD+ECHO + sta [dTermioPtr],y + short m + lda #0 + sta [dTermioPtr] ; ispeed + ldy #sg_ospeed + sta [dTermioPtr],y ; ospeed + ldy #t_intrc + lda #'C'-64 + sta [dTermioPtr],y ; t_intrc + ldy #t_suspc + lda #'Z'-64 + sta [dTermioPtr],y + ldy #t_quitc + lda #'\'-64 + sta [dTermioPtr],y + ldy #t_startc + lda #'Q'-64 + sta [dTermioPtr],y + ldy #t_stopc + lda #'S'-64 + sta [dTermioPtr],y + ldy #t_eofc + lda #'D'-64 + sta [dTermioPtr],y + ldy #t_brkc + lda #-1 + sta [dTermioPtr],y + ldy #t_dsuspc + lda #'Y'-64 + sta [dTermioPtr],y + ldy #t_rprntc + lda #'R'-64 + sta [dTermioPtr],y + ldy #sg_erase + lda #$7F + sta [dTermioPtr],y + long m + + ldy #local + lda #LCRTERA+LCTLECH + sta [dTermioPtr],y + + ldy #ws_row + lda #24 + sta [dTermioPtr],y + ldy #ws_col + lda #80 + sta [dTermioPtr],y + ldy #ws_xpixel + lda #0 + sta [dTermioPtr],y + ldy #ws_ypixel + sta [dTermioPtr],y + + return 2:result + END + +ConDeInit START + subroutine (2:devNum),0 + + return + END + +* Character translation & such is handled here, to keep it out +* of TextTool's silly assumptions. Fortunately, pipes donna have this +* prollem. + +ConIOCTL START KERN2 + using ADBData + using InOutData +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 + php + sei + short m + lda >head + sec + sbc >tail + long m + and #$00FF +* bpl okey +* eor #$FFFF +* inc a +*okey anop + sta [dataPtr] + plp + stz retval + jmp goaway +tioctl anop + lda tioc + and #$7F + cmp #25 + 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'TIOCSETK' + dc i2'20',a2'TIOCGETK' + dc i2'-1',a2'invalid' + dc i2'-1',a2'invalid' + dc i2'23',a2'TIOCSVECT' + dc i2'24',a2'TIOCGVECT' + +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 + +TIOCGVECT anop + php + sei + lda >COUT+1 + sta [dataPtr] + ldy #2 + lda >COUT+3 + and #$00FF + sta [dataPtr],y + + ldy #4 + lda >KEYIN+1 + sta [dataPtr],y + ldy #6 + lda >KEYIN+3 + and #$00FF + sta [dataPtr],y + plp + stz retval + jmp goaway + +TIOCSVECT anop + php + sei + lda [dataPtr] + sta >COUT+1 + ldy #1 + lda [dataPtr],y + sta >COUT+2 + + ldy #4 + lda [dataPtr],y + sta >KEYIN+1 + iny + lda [dataPtr],y + sta >KEYIN+2 + plp + stz retval + jmp goaway + +TIOCOUTQ lda #0 + sta [dataPtr] + stz retval + jmp goaway +TIOCSTOP lda >OutStopped + bne isStopped + lda #1 + sta >OutStopped +isStopped stz retval + jmp goaway +TIOCSTART lda >OutStopped + beq isStopped + lda #0 + sta >OutStopped + bra isStopped + +TIOCFLUSH php + sei + short m + lda >tail + sta >head + long m + plp + stz retval + jmp goaway + +* simulate terminal input (this code is borrowed from INOUT.ASM/OurADB +TIOCSTI anop + php + sei + phd + lda >InOutDP + tcd + short m + lda >head + tax + lda [dataPtr] + sta >keybuf,x + ldy #1 + lda [dataPtr],y + sta >modbuf,x + inx + txa + sta >head + +; this chunk unblocks any process that was waiting on keyboard input + + long ai + lda >blockCP + cmp #$FFFF + beq check4select + + ldy #2 + lda [IODP_procPtr],y + cmp #pBlocked ; is it still blocked? + bne done ; nope, leave it alone + lda #pReady + sta [IODP_procPtr],y ; restart the process + + lda #$FFFF + sta >blockCP + +; check for select here. + +check4select lda >contty+t_select_proc + cmp #$FFFF + beq done + +* someone is selecting on us, so call selwakeup with the process ID +* and our collision flag + pha + + lda >contty+privFlags + and #TS_RCOLL + pha + jsl contty+t_selwakeup + lda >contty+privFlags + and #TS_RCOLL.EOR.$FFFF + sta >contty+privFlags + lda #$FFFF + sta >contty+t_select_proc + +done anop + pld + plp + stz retval + jmp goaway + +TIOCSETK anop + lda [dataPtr] + sta >keyMaps + stz retval + jmp goaway +TIOCGETK anop + lda >keyMaps + sta [dataPtr] + stz retval + jmp goaway + END + diff --git a/kern/drivers/console.equates b/kern/drivers/console.equates new file mode 100644 index 0000000..12402ed --- /dev/null +++ b/kern/drivers/console.equates @@ -0,0 +1,38 @@ +* $Id: console.equates,v 1.1 1998/02/02 08:18:11 taubert Exp $ +********************************************************************* +* +* TEXT TOOL DP LOCATIONS +* +********************************************************************* + +IODP_CH gequ $00 +IODP_CV gequ $02 +IODP_BASL gequ $04 ;thru $07 +IODP_BASH gequ $05 +IODP_InvFlag gequ $08 +IODP_gInsertFlag gequ $0A ; insert or replace cursor? +IODP_LongTemp gequ $0C ; temporary dereferencing pointer +IODP_LongTemp2 gequ $10 +IODP_BLTop gequ $14 ; Pointer to bottom of TOP block +IODP_BLBot gequ $16 ; Pointer to top of bottom block +IODP_TopLine gequ $18 ; Top line displayed on screen +IODP_CurLine gequ $1A ; line the cursor is on +IODP_CurCol gequ $1C ; column the cursor is in +IODP_LeftCol gequ $1E ; Leftmost column displayed (sideways scrolling) +IODP_BufBank gequ $20 ; Bank number of 64K memory buffer +IODP_LeftMar gequ $22 +IODP_RightMar gequ $24 +IODP_TopMar gequ $26 +IODP_BotMar gequ $28 +IODP_Scroll gequ $2A +IODP_ScrollFlag gequ $2A +IODP_GlobalCoords gequ $2C +IODP_AutowrapFlag gequ $2E +IODP_GotoFlag gequ $30 ; state of goto x,y +IODP_CurChar gequ $32 ; current character under the cursor +IODP_CurFlag gequ $34 ; =1 if cursor on +IODP_CurState gequ $36 ; =1 if curchar, = 0 if screen char +IODP_dTermioPtr gequ $38 +IODP_procPtr gequ $3C +IODP_TextDPSize gequ $40 + diff --git a/kern/drivers/equates b/kern/drivers/equates new file mode 100644 index 0000000..5384d45 --- /dev/null +++ b/kern/drivers/equates @@ -0,0 +1,70 @@ +* $Id: equates,v 1.1 1998/02/02 08:18:13 taubert Exp $ + +* The size in bytes of the input and output buffers (each is BUF_SIZE bytes) +BUF_SIZE gequ 4096 + +IncBusyFlag gequ $E10064 +DecBusyFlag gequ $E10068 + +* Direct-page equates +ibuf_hand gequ 0 +obuf_hand gequ 4 +in_buf gequ 8 +out_buf gequ 12 +ibuf_head gequ 16 ; * +ibuf_tail gequ 18 ; * +ibuf_mark gequ 20 ; * +ibuf_size gequ 22 ; * +obuf_head gequ 24 ; * +obuf_tail gequ 26 ; * +obuf_mark gequ 28 ; * +obuf_size gequ 30 ; * +ibuf_fcon gequ 32 +obuf_fcon gequ 34 ; * +fcon_type gequ 36 ; * +fcon_status gequ 38 ; * initialize to non-zero +dTermioPtr gequ 40 +blockProc gequ 44 +procPtr gequ 46 +tmpProcID gequ 50 +lastChar gequ 52 ; * +lastInt gequ 54 ; * +reg5Status gequ 56 ; * +tx_in_progress gequ 58 ; * + +UDISPATCH2 gequ $E1000C user tool locator entry type 2 +INTMGRV gequ $E10010 system Interrupt Manager + +pReady gequ $02 +pBlocked gequ $03 + +* Port-independent hardware/firmware equates and parameters + +v_Main gequ $E10010 +v_AppleTalk gequ $E10020 +v_Serial gequ $E10024 + +TheVect gequ v_Serial + +SccControl gequ $E0C038 +SccControlB gequ $E0C038 +SccControlA gequ $E0C039 +SccData gequ $E0C03A +SccDataB gequ $E0C03A +SccDataA gequ $E0C03B +*DTR gequ $EA +DTR gequ $6A ; for channel 2 +SerFlag gequ $E10104 + +* 100 - read +* 010 - write +* 001 - exceptional + +Tx_empty gequ %00000100 +Rx_empty gequ %00000001 + +* fcon_type values +FCON_NONE gequ 0 no flowcontrol +FCON_XON gequ 1 XON/XOFF flowcontrol +FCON_RTS gequ 2 rts/cts flowcontrol + diff --git a/kern/drivers/inout.asm b/kern/drivers/inout.asm new file mode 100644 index 0000000..e3d0b2c --- /dev/null +++ b/kern/drivers/inout.asm @@ -0,0 +1,1887 @@ +* $Id: inout.asm,v 1.1 1998/02/02 08:17:56 taubert Exp $ +************************************************************************** +* +* GNO Multitasking Environment +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* INOUT.ASM +* By Jawaid Bazyar & Tim Meekins +* +* GNO console driver for text display +* +************************************************************************** + +* x PRINT - print a cstring of text at current cursor +* x COUT - print a character at current cursor & increment cursor +* x STORCHAR - stuff a character at current cursor (but don't increment) +* x PickChar - get a character from current cursor +* x KEYIN - wait for a keystroke with the current cursor (ins/rpl) +* x VTAB - calculates position of current line and stores in BASL + + case on + mcopy ../drivers/inout.mac + copy ../gno/inc/tty.inc + copy ../drivers/console.equates + copy ../drivers/kern.equates + +consoleSem gequ $3C ; output code semaphore + +InOutData DATA +InOutDP dc i2'0' +blockCP dc i2'$FFFF' ; curProcInd of process blocked on input +; (or -1 if none) +blinkRate dc i2'0' + +; ACK! These are hideous- but if they work... +bufState dc i2'1' +OutStopped dc i2'0' +;ignSetInDev dc i2'0' +;ignSetInGlo dc i2'0' +;ignSetOutDev dc i2'0' +;ignSetOutGlo dc i2'0' +;ignSetErrDev dc i2'0' +;ignSetErrGlo dc i2'0' + +inCOUT dc i2'0' +keyMaps dc i2'0' +OldFlushVect dc i4'0' + END + +InOutStart START + using InOutData + using ADBData + +TempHandle equ 1 + + jsl PatchDeskManager + phb + phk + plb + phd + ph4 #0 + ph4 #IODP_TextDPSize + lda contty+t_userid + ora #$0100 + pha + ph2 #%1100000000000101 + ph4 #0 + _NewHandle + + tsc + tcd + lda [TempHandle] + sta InOutDP + tcd + pla + pla + +; pea 1 +; jsl asmSemNew +; sta consoleSem + + lda #$0000 ; >0 = inverse, 0 = normal + sta IODP_InvFlag + stz IODP_gInsertFlag + + stz IODP_LeftMar + stz IODP_TopMar + lda #79 + sta IODP_RightMar + lda #23 + sta IODP_BotMar + lda #1 + sta IODP_Scroll ; scroll automatically at end-of-page + sta IODP_AutowrapFlag ; automatically wrap to next line + stz IODP_GlobalCoords + stz IODP_GotoFlag + lda #contty + sta IODP_dTermioPtr + lda #^contty + sta IODP_dTermioPtr+2 + + stz IODP_CH ;[-TM 5/29/91] + stz IODP_CV + lda #0 + short a + sta >$57B + sta >$25 + long a + + jsr VTAB + + stz head + stz tail + SetVector (#$F,#OurADB) + IntSource #0 + lda #0 + sta bufState ; make sure key buffer is ON + + stz IODP_CurFlag + stz IODP_CurState + jsr cursOn + pushlong #cursorHB + _SetHeartBeat + + pha + pea $2F + _ReadBParam + pla + sta >blinkRate + + short m + lda >$E0C035 + and #%11111110 + sta >$E0C035 + long m + + pha + pha + pea $13 + _GetVector + + pl4 OldFlushVect + pea $13 + ph4 #NewFlush + _SetVector + + pld + plb + rtl + END + +InOutEnd START + using InOutData + + phb + phk + plb + IntSource #1 + pushlong #cursorHB + _DelHeartBeat +; phd +; lda >InOutDP +; tcd +; lda consoleSem +; pha +; jsl asmSemDispose +; pld + +; WriteChar #12 + + ph4 OldFlushVect + pea $13 + _SetVector + + plb + jsl UnpatchDeskManager + rtl + + END + +ClipH START + lda IODP_CH + cmp #80 + bcc bye + lda #0 + sta IODP_CH +bye rts +ClipV ENTRY + lda IODP_CV + cmp #24 + bcc later + lda #23 + sta IODP_CV +later rts + END + +COUT START + jmp >COUT_CODE + END +KEYIN START + jmp >KEYIN_CODE + END + +* Name > COUT +* Input > A = Char to print, x & y don't care +* > Inp/Out Globals +* Output > char on screen, cursor position updated, A & X & Y unchanged[!!] + +COUT_CODE START + using InOutData + + phx + phd + pha + lda >InOutDP + tcd + phb + phk + plb + +stopChk anop + lda >OutStopped + beq notStopped + cop $7F + bra stopChk + +notStopped anop +; pei (consoleSem) +; jsl asmWait + jsl >$E10064 ; incBusy + inc inCOUT + lda IODP_CurFlag + sta oldCur ; save the state! + jsr cursOff + + lda >$57B ; 80 column ch + and #$00FF + cmp IODP_CH + beq checkCV + sta IODP_CH + jsr ClipH +checkCV anop + lda >$25 + and #$00FF + cmp IODP_CV + beq humph + sta IODP_CV + jsr ClipV + jsr VTAB +humph anop + + lda 2,s + and #$007F ; strip hi bit + cmp #$20 + bcs notControl + lda 2,s + and #$007F + jmp controlChar +notControl anop + lda IODP_GotoFlag +; +; Do a mini state graph for goto xy. +; + jeq out + cmp #3 + bcs dosetport + + cmp #1 + bne goto2 + inc IODP_GotoFlag + lda 2,s + and #$7F + sec + sbc #32 + sta IODP_CH + jsr ClipH + jmp COUTxit +goto2 stz IODP_GotoFlag + lda 2,s + and #$7F + sec + sbc #32 + sta IODP_CV + jsr ClipV + jsr VTAB + jmp COUTxit + +* The GotoFlag equals these values during a setport operation: +* 3 = looking for '[' +* 4 = LeftMar +* 5 = RightMar +* 6 = TopMar +* 7 = BotMar +* 8 = done + +dosetport cmp #8 + bcs donesetport + cmp #3 + bne step2 + lda 2,s + and #$7F + cmp #'[' + beq step3 + stz IODP_GotoFlag ; not found, terminate the setport + jmp COUTxit +step2 sec + sbc #4 + asl a + tax + lda 2,s + and #$7F + sec + sbc #32 + sta IODP_LeftMar,x +step3 inc IODP_GotoFlag + jmp COUTxit +donesetport stz IODP_GotoFlag +* 'clip' the new port dimensions to ensure that they won't confuse the +* code into a crash. When in doubt, reset the default port parameters. + lda IODP_LeftMar + cmp IODP_RightMar + bcc ok_1 + stz IODP_LeftMar + lda #79 + sta IODP_RightMar +ok_1 lda IODP_TopMar + cmp IODP_BotMar + bcc ok_2 + stz IODP_TopMar + lda #23 + sta IODP_BotMar +ok_2 lda IODP_RightMar + cmp #80 + bcc ok_3 + lda #79 + sta IODP_RightMar +ok_3 lda IODP_BotMar + cmp #24 + bcc out + lda #23 + sta IODP_BotMar + +* we have a 'printable' character, so find out what's up with the cursor + +out lda IODP_AutowrapFlag ; do we autowrap + beq NoWrap + jsr FSpace + bra OutPut +NoWrap lda IODP_CH + cmp IODP_RightMar + bcc OutPut + lda IODP_RightMar + sta IODP_CH + +* we modded the cursor and screen appropriately, so do it! + +OutPut lda 2,s + and #$007F ; only the low stuff, please + bit IODP_InvFlag ; normal or inverse? + bpl Norm ; bit 15 clear means normal text + bvs NoAnd ; i.e. don't fix it cause its mousetext + cmp #$60 ; inverse! + bcs NoAnd + cmp #$40 ; special characters? + bcc NoAnd + sbc #$40 ; if it's an uppercase + bra NoAnd +Norm ora #$80 ; har har har +NoAnd jsr StorChar + inc IODP_CH +COUTxit anop + short m + lda IODP_CH + sta >$57B + lda IODP_CV + sta >$25 + long a + lda oldCur + beq norestore + jsr cursOn + bra gohome +norestore anop + jsr PickChar + sta IODP_CurChar +gohome anop +; pei (consoleSem) +; jsl asmSignal + dec inCOUT + jsl >$E10068 ; decBusy + plb + pla + pld + plx + rtl +oldCur dc i2'0' + +controlChar anop + asl a + tax + jmp (controlTable,x) + +ctl0D lda IODP_LeftMar + sta IODP_CH + jmp COUTxit + +ctl0A jsr FSpace2 + jmp COUTxit + +; cmp #8 ; backspace? +ctl08 lda IODP_CH + cmp IODP_LeftMar + beq ctl08a + dec IODP_CH + jmp COUTxit +ctl08a lda IODP_RightMar + sta IODP_CH + bra ctl1F + +; cmp #21 ; right arrow +ctl15 jsr FSpace ; if we're already in never-neverland, move to col0 + inc IODP_CH ; and increment the CH + jsr FSpace ; if we weren't, see if we are now, and fix it too + jmp COUTxit + +; cmp #"_"-64 ; Move up +ctl1F lda IODP_CV + cmp IODP_TopMar + beq ctl4b ; can't go any further up + dec IODP_CV + jsr VTAB +; lda IODP_RightMar +; sta IODP_CH +ctl4b jmp COUTxit + +; cmp #"N"-64 ; normal text mode? +; cmp #"X"-64 ; fake normal +ctl0E anop + lda IODP_InvFlag + and #%0111111111111111 + sta IODP_InvFlag + jmp COUTxit + +ctl18 lda IODP_InvFlag + and #%1011111111111111 + sta IODP_InvFlag + jmp COUTxit + +; cmp #"O"-64 ; inverse text +ctl0F lda IODP_InvFlag + ora #$8000 + sta IODP_InvFlag + jmp COUTxit + +; cmp #"["-64 ; mousetext +ctl1B lda IODP_InvFlag + ora #%0100000000000000 + sta IODP_InvFlag + jmp COUTxit +;im000000 +;i = inverse text? +;m = mouse text? + +; cmp #"L"-64 ; form feed = clear screen +ctl0C jsr HOME + jmp COUTxit + +; cmp #"Y"-64 ; move cursor home +ctl19 stz IODP_CH + stz IODP_CV + jsr VTAB + jmp COUTxit + +; cmp #"]"-64 ; clear EOL +ctl1D jsr CLREoln + jmp COUTxit + +; cmp #"K"-64 ; clear EOP +ctl0B jsr CLREop + jmp COUTxit + +; cmp #"^"-64 ; goto xy +ctl1E lda #1 + sta IODP_GotoFlag + jmp COUTxit + +; cmp #"Z"-64 ; clear line +ctl1A lda IODP_CH + pha + lda IODP_LeftMar + sta IODP_CH + jsr CLREoln + pla + sta IODP_CH + jmp COUTxit + +; cmp #"I"-64 ; tab +ctl09 lda IODP_CH + lsr3 a + inc a + asl3 a + sta IODP_CH + jsr FSpace + jmp COUTxit + +; cmp #"G"-64 ; beep +ctl07 ldx #$40 +tone ldy #$80 + lda $E0C030 ;speaker! +ll dey + bne ll + dex + bne tone + jmp COUTxit + +; cmp #"F"-64 ; turn off cursor +ctl06 stz oldCur ; cursor is already off! (see above) + jmp COUTxit + +; cmp #"E"-64 ; turn on cursor +ctl05 lda #1 + sta oldCur ; make sure it comes back on + jmp COUTxit + +; cmp #"V"-64 ; scroll down one line +ctl16 jsr ScrollWindowDn + jmp COUTxit + +; cmp #"W"-64 ; scroll up one line +ctl17 jsr ScrollWindowUp + jmp COUTxit + +; cmp #"\"-64 +ctl1C inc IODP_CH + jmp COUTxit + +; cmp #'Q'-64 +ctl11 ldx #1 + jsr InsLine + jmp COUTxit + +; cmp #'R'-64 +ctl12 ldx #1 + jsr DelLine + jmp COUTxit + +ctlout anop + jsr StorChar + inc IODP_CH + jmp COUTxit +setOver anop + stz IODP_gInsertFlag + jmp COUTxit +setInsert anop + lda #1 + sta IODP_gInsertFlag + jmp COUTxit +ctlsetport anop + lda #3 + sta IODP_GotoFlag + jmp COUTxit +controlTable anop + dc i2'ctlout' + dc i2'setOver' ; set cursor to overstrike mode + dc i2'setInsert' ; set cursor to insert mode +* dc i2'ctlout' + dc i2'ctlsetport' + dc i2'ctlout' + dc i2'ctl05' ; + dc i2'ctl06' ; + dc i2'ctl07' ; + dc i2'ctl08' ; + dc i2'ctl09' ; + dc i2'ctl0A' ; + dc i2'ctl0B' ; + dc i2'ctl0C' ; + dc i2'ctl0D' ; + dc i2'ctl0E' ; + dc i2'ctl0F' ; + dc i2'ctlout' + dc i2'ctl11' + dc i2'ctl12' + dc i2'ctlout' + dc i2'ctlout' + dc i2'ctl15' ; + dc i2'ctl16' ; + dc i2'ctl17' ; + dc i2'ctl18' ; + dc i2'ctl19' ; + dc i2'ctl1A' ; + dc i2'ctl1B' ; + dc i2'ctl1C' + dc i2'ctl1D' ; + dc i2'ctl1E' ; + dc i2'ctl1F' ; + +FSpace anop + lda IODP_CH + cmp IODP_RightMar + beq Bye + bcc Bye + lda IODP_LeftMar + sta IODP_CH +FSpace2 lda IODP_CV + cmp IODP_BotMar + bcs CheckScroll + inc IODP_CV + jmp VTAB +CheckScroll lda IODP_Scroll ; do they want us to scroll? + beq Bye ; nope, har har + jmp ScrollWindowUp +Bye rts + END + +cursOff START + lda IODP_CurFlag + beq ctl16a ; already turned off + lda IODP_CurState ; are currently in the 'invert' + beq ctl16a ; phase of cursor blink? + jsr normalCurs ; yeah, so turn it off +ctl16a stz IODP_CurFlag + rts + END + +cursOn START + lda IODP_CurFlag + bne ctl17a ; already turned on + lda IODP_CurState ; are we currently in the 'normal' + bne ctl17a ; phase of cursor blink? + jsr invertCurs ; yeah, so turn it on +ctl17a lda #1 + sta IODP_CurFlag + rts + END + +* +* Get character under cursor, save it, then invert it +* +invertCurs START + phy +ok jsr PickChar + sta IODP_CurChar + lda #"_"+128 ; insert cursor, which do we want? + ldy IODP_gInsertFlag ; ins = 1, rpl = 0 + bne done + lda IODP_CurChar + short a + eor #$80 + bmi done + cmp #$60 + bcs done + cmp #$40 + bcc done + sbc #$40 +done long a + jsr StorChar + lda #1 + sta IODP_CurState + ply + rts + END + +normalCurs START + stz IODP_CurState + lda IODP_CurChar + jmp StorChar + END + + +* Name > KEYIN +* Input > x,y,a don't care, keyboard input +* Output > flashing cursor, A = char typed & X & Y unchanged + +KEYIN_CODE START + using ADBData + using InOutData + + phb + phk + plb + phd + lda >InOutDP + tcd + + jsl >$E10064 ; incBusy + short a + lda >$57B ; 80 column ch + sta IODP_CH + lda >$25 + cmp IODP_CV + beq restart + sta IODP_CV + long a + jsr VTAB +restart long a + lda >bufState + beq gotBuffer + brl noBuffer +gotBuffer anop + short ai + lda tail + cmp head + bne GotKey + long ai +; lda >curProcInd + lda #1 ; this is how port.asm took care of this + sta >blockCP + jsl contty+t_GetProcInd ; get pointer to process entry + sta IODP_procPtr + stx IODP_procPtr+2 + ldy #2 ; set it to blocked state + lda #pBlocked + sta [IODP_procPtr],y + jsl >$E10068 ; decBusy + ldy #84 ; index of waitDone field + lda #0 + sta [IODP_procPtr],y ; set to zero, moron + + cop $7f ; wait for data to come in + jsl >$E10064 ; incBusy + ldy #84 + lda [IODP_procPtr],y + beq restart + cmp #1 + beq restart ; if waitdone 0|1 restart the call + lda #$FFFF ; waitdone was -1, so + sta >blockCP ; reset this to keep things clean + lda #$7E43 ; signal + bra doneread +GotKey anop + long ai + lda #$FFFF + sta >blockCP ; reset this to keep things clean + ldx tail + lda keybuf,x + and #$00FF ; don't clear this here + sta tmp1 + short i + ldx tail + lda modbuf,x + inx + stx tail + long i + xba + and #$FF00 ; save only that + ora tmp1 ; add key modifiers to character input +doneread anop + jsl >$E10068 ; decBusy + pld + plb + rtl +tmp1 dc i2'0' +noBuffer anop + jsl >$E10068 ; decBusy + short a +loop anop + lda >$E0C000 + bpl loop + and #$7F + sta >tmp1 + lda >$E0C025 + sta >tmp1+1 + sta >$E0C010 + long a + lda >tmp1 + pld + plb + rtl + END + +* Name > Delay/Private +* Input > none +* Output > Delay of about 1/2 second,X & Y unchanged, A = ?? + +*Delay PRIVATE +* +* using ADBData +* using InOutData +* +* lda >blinkRate ;Flash rate +* and #$FF +* asl a +* asl a +* sta count +* +*elayLoop1 lda tail +* cmp head +* bne DelayOut +* lda $E1C019 +* and #$80 +* beq DelayLoop1 +* +*elayLoop2 lda tail +* cmp head +* bne DelayOut +* lda $E1C019 +* and #$80 +* bne DelayLoop2 +* +* dec count +* bne DelayLoop1 +* +*elayOut rts +* +*ount dc i2'0' +* END + +* +* ADB interrupt handler (only if keyboard) +* +OurADB START KERN2 + + using ADBData + using InOutData + + php + phd + long m + lda >InOutDP + tcd + + lda >bufState ; whether the buffer is on or off + jne done2 + short ai + lda >$E0C000 + and #$7f ; turn off that stupid bit + pha + jsr checkIntr + bcc notatty ; c=1 means intr char was found + sta >$E0C010 + jmp done3 +notatty anop + lda >$E0C025 ; we'll look at this, first + pha +* now char/mods are on stack + lda >keyMaps + bit #%1000 ; vt100 arrows on? + beq notVT100 + + lda 1,s ; check for the control key + bit #%0010 + jne notVT100 ; they hit control-something + + lda 2,s + cmp #$A + beq isArrow + cmp #$B + beq isArrow + cmp #$8 + beq isArrow + cmp #$15 + jne notVT100 ; not one of the arrows +isArrow anop + lda >keyMaps ; is OA mapping set? if so, we + bit #%0011 ; should not map to vt100 arrows + beq notMetaMap ; then map as an OA-ascii + lda 1,s + bit #$80 + bne doMetaMap + +notMetaMap ldy #0 + lda #27 + jsr add2q + lda #'O' + jsr add2q + pla + pla ; the character + ldx #'A' + cmp #$B + beq doit1 + ldx #'B' + cmp #$A + beq doit1 + ldx #'C' + cmp #$15 + beq doit1 + ldx #'D' +doit1 txa + jsr add2q + jmp doUnblock + +notVT100 anop + lda >keyMaps + bit #%0001 + beq doNormal + bit #%0110 + beq doNormal ; neither bit is set. Goofup! + bit #%0100 + bne doHiBitMap +doMetaMap anop + lda 1,s + bit #$80 ; oa? + beq doNormal + ldy #0 + lda #27 ; the META character (ESC) + jsr add2q ; y is the modifier flag + pla + pla + jsr add2q + bra doUnblock +doHiBitMap pla + tay + bit #$80 + beq doNormal1 ; it's not set!!!! + and #$7F + tay ; okay now + pla ; grab the character + ora #$80 + jsr add2q + bra doUnblock + +doNormal ply +doNormal1 anop + pla + jsr add2q +; this chunk unblocks any process that was waiting on keyboard input + +doUnblock php + sta >$E0C010 + long ai + + lda >$E100B8 ; this is going to GSBug via EM, not + bit #1 ; a process + bne GSBugActive + + lda >blockCP + cmp #$FFFF + beq check4select + ldy #2 + lda [IODP_procPtr],y + cmp #pBlocked ; is it still blocked? + bne done ; nope, leave it alone + lda #pReady + sta [IODP_procPtr],y ; restart the process + lda #$FFFF + sta >blockCP + +; check for select here. + +check4select lda >contty+t_select_proc + cmp #$FFFF + beq done + +* someone is selecting on us, so call selwakeup with the process ID +* and our collision flag + pha + + lda >contty+privFlags + and #TS_RCOLL + pha + jsl contty+t_selwakeup + lda >contty+privFlags + and #TS_RCOLL.EOR.$FFFF + sta >contty+privFlags + lda #$FFFF + sta >contty+t_select_proc + +GSBugActive anop +done anop + plp +done2 anop + pld + plp + clc + rtl +done3 anop + pla + pld + plp + clc + rtl + +add2q pha + lda >head + inc a + cmp >tail ; buffer overflow? + beq done2 ; yes, ignore this key + lda >head + tax + pla + sta >keybuf,x + tya + sta >modbuf,x + inx + txa + sta >head + rts + + longi on + longa on + + END + +* Handles Control-OA-Delete, and flushes the GNO keyboard buffer + +NewFlush START + using ADBData + php + long ai + lda #0 + sta >head + sta >tail + plp + clc + rtl + longa on + longi on + END + +checkIntr START KERN2 + using InOutData + + php + long ai + and #$7f + pha + short m + + ldy #sg_flags + lda [IODP_dTermioPtr],y + bit #RAW ; RAW mode? + beq x9 ; yep, no character checking + brl notty +x9 ldy #t_quitc + lda [IODP_dTermioPtr],y + cmp #-1 + beq x0 + cmp 1,s + beq gotQQ +x0 ldy #t_suspc + lda [IODP_dTermioPtr],y + cmp #-1 + beq x1 + cmp 1,s + beq gotZ +x1 ldy #t_intrc + lda [IODP_dTermioPtr],y + cmp #-1 + beq x2 + cmp 1,s + beq gotC +x2 lda >OutStopped + bne x3 + ldy #t_stopc + lda [IODP_dTermioPtr],y + cmp #-1 + beq x3 + cmp 1,s + beq gotS +x3 ldy #t_startc + lda [IODP_dTermioPtr],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 + ph2 >contty+t_devNum ; push our device number + jsl contty+t_sendSignal + +; flush internal editing buffers on interrupt character + lda #0 + sta >contty+editInd + sta >contty+editBegin + sta >contty+st_flags + + ph4 #$80027410 + ph4 #0 + lda >contty+t_devNum + pha + jsl ConIOCTL ; flush the raw input queue + + 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 + +ADBData DATA + +head ds 2 +tail ds 2 +keybuf ds 256 +modbuf ds 256 + + END + +* Name > CalcBankCH/Private +* Input > CH = cursor horizontal position +* Output > Bank number of col in CH stored in BASL+2, y = a = 40col offset + longa off +CalcBankCH PRIVATE + + lda #0 ;TM 5/18/91 + xba ;---------- + lda IODP_CH + cmp IODP_RightMar + bcc Calc2 + beq Calc2 + lda IODP_RightMar +Calc2 lsr a + tay ; column number + lda #0 ; c = 1 if main mem, 0 if auxmem + rol a + eor #%00000001 ; not quite as fast as before, but hey... + sta IODP_BASL+2 + rts + + END + longa on + +* Name > STORCHAR +* Input > A is Char to poke, x & y don't care +* > cursor stored in CH,CV,BASL +* > A must NOT be greater than $00FF +* Output > A,X,Y unchanged, char in banks $E0 or $E1 + +StorChar START + + phy + short a + pha + jsr CalcBankCH + pla + sta [IODP_BASL],y + long a + ply + rts + + END + +* Name > PickChar +* Input > x & y don't care +* > cursor stored in CH,CV,BASL +* Output > A = char, X,Y unchanged + +PickChar START + + phy + short a + jsr CalcBankCH + lda [IODP_BASL],y + long a + ply + and #$00FF ; strip garbage off + rts + + END + +* Name > VTAB,VTABZ +* Input > CV for VTAB; A for VTABZ (both contain line to calculate base for) +* Output > Base screen address for line, A = BASE. + +VTAB START + using TextTable + + lda IODP_CV +VTABZ ENTRY + phy + asl a + tay + lda TextRowAddr,y + sta IODP_BASL + ply + rts + END + +TextTable DATA +TextRowAddr dc i2'$0400' + dc i2'$0480' + dc i2'$0500' + dc i2'$0580' + dc i2'$0600' + dc i2'$0680' + dc i2'$0700' + dc i2'$0780' + dc i2'$0428' + dc i2'$04A8' + dc i2'$0528' + dc i2'$05A8' + dc i2'$0628' + dc i2'$06A8' + dc i2'$0728' + dc i2'$07A8' + dc i2'$0450' + dc i2'$04D0' + dc i2'$0550' + dc i2'$05D0' + dc i2'$0650' + dc i2'$06D0' + dc i2'$0750' + dc i2'$07D0' + END + +HOME START + using InOutData + + phx + phy + lda IODP_LeftMar + bne DoFillBox + lda IODP_RightMar + cmp #79 + bne DoFillBox + lda IODP_TopMar + sta IODP_CV +Loop jsr VTAB ; set the line + ldx IODP_BASL + ldy #20 ; only 40 per bank, and 2 bytes/pass + lda #$A0A0 ; har har +Loop1 anop + sta >$000000,x + sta >$010000,x + inx + inx + dey + bne Loop1 + + lda IODP_CV + cmp IODP_BotMar + bcs urgh + + inc a + sta IODP_CV + bra Loop + +urgh stz IODP_CH + stz IODP_CV + ply + plx + jmp VTAB + +DoFillBox lda IODP_Scroll + pha + stz IODP_Scroll + + lda #" " + jsr EraseBox + + pla + sta IODP_Scroll + lda IODP_LeftMar + sta IODP_CH + lda IODP_TopMar + sta IODP_CV + ply + plx + jmp VTAB + + END + +* Name > PrintXChars +* Input > x = number of chars to print +* > a = character to print +* Output > x = 0, a = char + +PrintXChars START KERN2 + cpx #0 + beq DonePXC +PrintEm jsl COUT + dex + bne PrintEm +DonePXC rts + END + +CLREoln START + + lda IODP_CH + pha ;save it to restore later + +Loop lda #" "+128 + jsr StorChar + inc IODP_CH + lda IODP_CH + cmp IODP_RightMar + bcc Loop + beq Loop + + pla + sta IODP_CH + rts + + END + +CLREop START + + lda IODP_CH + pha + lda IODP_CV + pha + +Loop jsr CLREoln ; do the end of This line + inc IODP_CV + jsr VTAB + lda IODP_LeftMar + sta IODP_CH + lda IODP_CV + cmp IODP_BotMar + bcc Loop + beq Loop + + pla + sta IODP_CV + jsr VTAB + pla + sta IODP_CH + rts + END + + +CLRSop START + + lda IODP_CH + sta curh + lda IODP_CV + sta curv + + lda IODP_LeftMar + sta IODP_CH +FirstLoop lda #' '+128 + jsr StorChar + inc IODP_CH + lda IODP_CH + cmp curh + beq FirstLoop + bcc FirstLoop + lda #0 + sta IODP_CV + lda IODP_LeftMar + sta IODP_CH +Loop jsr VTAB + jsr CLREoln ; do the end of This line + inc IODP_CV + jsr VTAB + lda IODP_LeftMar + sta IODP_CH + lda IODP_CV + cmp curv + bcc Loop + + lda curh ; already vtabbed to that line + sta IODP_CH + rts +curh dc i2'0' +curv dc i2'0' + END + +ScrollWindowUp START + using InOutData + +* bra QuickScroll ;TM + +Okay lda IODP_LeftMar + bne SlowScroll + lda IODP_RightMar + cmp #79 + beq QuickScroll + +SlowScroll lda IODP_CV + pha + lda IODP_CH + pha + phx ;TM 5/17/91 + + lda IODP_TopMar + sta IODP_CV + jsr VTAB + ldx IODP_BASL + stx DstLine +LineLoop inc IODP_CV + jsr VTAB + ldx IODP_BASL + stx SrcLine + +* copy a line using PickChar and storchar + + lda IODP_LeftMar + sta IODP_CH + +InLineLoop ldx SrcLine + stx IODP_BASL + + jsr PickChar + ldx DstLine + stx IODP_BASL + jsr StorChar ; this should work, but I dunno how fast + inc IODP_CH + lda IODP_CH + cmp IODP_RightMar + bcc InLineLoop + beq InLineLoop + + ldx SrcLine + stx DstLine + lda IODP_CV + cmp IODP_BotMar + bcc LineLoop + + ldx SrcLine + stx IODP_BASL + lda IODP_LeftMar + sta IODP_CH +ClrLineLoop lda #$A0 ;this better work + jsr StorChar + inc IODP_CH + lda IODP_CH + cmp IODP_RightMar + bcc ClrLineLoop + beq ClrLineLoop + + plx ;TM 5/17/91 + pla + sta IODP_CH + pla + sta IODP_CV + jmp VTAB + +GoAway rts +SrcLine dc i2'0' +DstLine dc i2'0' + +* QuickScroll uses self-modifying code to kick ass + +QuickScroll lda IODP_CV + pha + lda IODP_CH + pha + phx ;TM 5/17/91 + phy + + lda IODP_TopMar + sta IODP_CV + jsr VTAB + lda IODP_BASL + sta CopyTwo0+1 + sta CopyTwo1+1 + ldx IODP_CV + cpx IODP_BotMar ; if there's only one line, just clear it + bne QSNextLine + tax ; we wanna clear this line and not scroll + bra clearline +QSNextLine inc IODP_CV + jsr VTAB + lda IODP_BASL + sta CopyOne0+1 + sta CopyOne1+1 + + ldx #38 ; yeah, oh yeah +CopyOne0 lda >$000000,x +CopyTwo0 sta >$000000,x +CopyOne1 lda >$010000,x +CopyTwo1 sta >$010000,x + dex + dex + bpl CopyOne0 + + lda CopyOne0+1 + sta CopyTwo0+1 + sta CopyTwo1+1 + + lda IODP_CV + cmp IODP_BotMar + bcc QSNextLine + + ldx CopyOne1+1 +clearline lda #$A0A0 ; spaces out the ass + ldy #10 ;TM +clrloop sta >$010000,x + sta >$000000,x + inx + inx + sta >$010000,x ;TM + sta >$000000,x ; + inx ; + inx ; + dey + bne clrloop + + ply + plx ;TM 5/17/91 + pla + sta IODP_CH + pla + sta IODP_CV + jmp VTAB + + END + +ScrollWindowDn START + using InOutData + +* bra QuickScroll ;TM + +Okay lda IODP_LeftMar + bne SlowScroll + lda IODP_RightMar + cmp #79 + beq QuickScroll + +SlowScroll lda IODP_CV + pha + lda IODP_CH + pha + phx ;TM 5/17/91 + + lda IODP_BotMar + sta IODP_CV + jsr VTAB + ldx IODP_BASL + stx DstLine +LineLoop dec IODP_CV + jsr VTAB + ldx IODP_BASL + stx SrcLine + +* copy a line using PickChar and storchar + + lda IODP_LeftMar + sta IODP_CH + +InLineLoop ldx SrcLine + stx IODP_BASL + + jsr PickChar + ldx DstLine + stx IODP_BASL + jsr StorChar ; this should work, but I dunno how fast + inc IODP_CH + lda IODP_CH + cmp IODP_RightMar + bcc InLineLoop + beq InLineLoop + + ldx SrcLine + stx DstLine + lda IODP_TopMar + cmp IODP_CV + bcc LineLoop + + ldx SrcLine + stx IODP_BASL + lda IODP_LeftMar + sta IODP_CH +ClrLineLoop lda #$A0 ;this better work + jsr StorChar + inc IODP_CH + lda IODP_CH + cmp IODP_RightMar + bcc ClrLineLoop + beq ClrLineLoop + + plx ;TM 5/17/91 + pla + sta IODP_CH + pla + sta IODP_CV + jmp VTAB + +GoAway rts +SrcLine dc i2'0' +DstLine dc i2'0' + +* QuickScroll uses self-modifying code to kick ass +QuickScroll lda IODP_CV + pha + lda IODP_CH + pha + phx ;TM 5/17/91 + phy + + lda IODP_BotMar + sta IODP_CV + jsr VTAB + lda IODP_BASL + sta CopyTwo0+1 + sta CopyTwo1+1 + ldx IODP_CV + cpx IODP_TopMar ; if there's only one line, just clear it + bne QSNextLine + tax ; we wanna clear this line and not scroll + bra clearline +QSNextLine dec IODP_CV + jsr VTAB + lda IODP_BASL + sta CopyOne0+1 + sta CopyOne1+1 + + ldx #38 ; yeah, oh yeah +CopyOne0 lda >$000000,x +CopyTwo0 sta >$000000,x +CopyOne1 lda >$010000,x +CopyTwo1 sta >$010000,x + dex + dex + bpl CopyOne0 + + lda CopyOne0+1 + sta CopyTwo0+1 + sta CopyTwo1+1 + + lda IODP_CV + cmp IODP_TopMar + bne QSNextLine + + ldx CopyOne1+1 +clearline lda #$A0A0 ; spaces out the ass + ldy #10 ; TM +clrloop sta >$010000,x + sta >$000000,x + inx + inx + sta >$010000,x ;TM + sta >$000000,x ; + inx ; + inx ; + dey + bne clrloop + + ply + plx ;TM 5/16/91 + pla + sta IODP_CH + pla + sta IODP_CV + jmp VTAB + + END + +* Insert Xreg lines at the current cursor location, using some of the +* text screen attributes + +InsLine START + stx temp + lda IODP_TopMar + pha + lda IODP_CV + sta IODP_TopMar +loop ldx temp + beq nomoreins + jsr ScrollWindowDn + dec temp + bra loop +nomoreins pla + sta IODP_TopMar + rts +temp dc i2'0' + END + +DelLine START + stx temp + lda IODP_TopMar + pha + lda IODP_CV + sta IODP_TopMar +loop ldx temp + beq nomoredel + jsr ScrollWindowUp + dec temp + bra loop +nomoredel pla + sta IODP_TopMar + rts +temp dc i2'0' + END + + longa off +cursorHB DATA + dc i4'0' +count dc i2'30' + dc h'5AA5' + END +cursorRout START + using InOutData + using cursorHB + phb + + phk + plb + + php + phd + long ai + lda >InOutDP + tcd + lda >inCOUT + bne rInCout ; if inside COUT, ignore this HB + lda >blinkRate ;Flash rate + and #$FF + cmp #0 + bne flashing ; is the rate 0? + lda #10 + sta count + lda IODP_CurState ; basically, force the cursor on + bne nocurs ; it's on, so leave it alone + lda #1 + sta IODP_CurState + lda IODP_CurFlag + beq nocurs + jsr invertCurs + bra nocurs +flashing anop + asl a + tax + lda tickTbl-2,x + sta count + lda IODP_CurState + eor #1 ; flip the cursor state we're + sta IODP_CurState + lda IODP_CurFlag + beq nocurs + lda IODP_CurState + beq norm + jsr invertCurs + bra nocurs +norm jsr normalCurs +nocurs pld + plp + clc + plb + rtl + +* don't change the cursor state while we're inside COUT... it's a +* race condition + +rInCout lda >blinkRate ;Flash rate + and #$FF + cmp #0 + bne isflash ; is the rate 0? + lda #10 + bra storeit +isflash asl a + tax + lda tickTbl-2,x +storeit sta count + bra nocurs + +tickTbl dc i2'60' + dc i2'30' + dc i2'15' + dc i2'10' + END + +FlexBeep START KERN2 + phx + phy + pha + + ldx #$40 +tone ldy #$80 + lda $E0C030 ;speaker! +ll dey + bne ll + dex + bne tone + + pla + ply + plx + rts + END + +* Special support for CDA keyboard input +* Save some state so we can restore it when we leave +ConSaveAllPatch START + using cursorHB + using InOutData + + php + sei + long ai + phb + phk + plb + pha + phx + phy + + lda blockCP + sta tblockCP + lda count + sta tcount + lda #0 + sta count + lda bufState + sta tbufState + inc a + sta bufState + + ply + plx + pla + plb + plp + dc i1'$5C' +CONOLDSAVEALL ENTRY + dc i4'0' + +ConRestAllPatch ENTRY + php + sei + long ai + phb + phk + plb + pha + phx + phy + phd + + lda tblockCP + sta blockCP + lda tcount + sta count + lda tbufState + sta bufState + + pha ; re-read the blink rate + pea $2F ; in case they changed it + _ReadBParam + pla + sta >blinkRate + + pld + ply + plx + pla + plb + plp +gooldRest dc i1'$5C' +CONOLDRESTALL ENTRY + dc i4'0' + +tblockCP dc i2'0' +tcount dc i2'0' +tbufState dc i2'0' + END + diff --git a/kern/drivers/inout.mac b/kern/drivers/inout.mac new file mode 100644 index 0000000..6231d40 --- /dev/null +++ b/kern/drivers/inout.mac @@ -0,0 +1,337 @@ + MACRO +&lab _DelHeartBeat +&lab ldx #$1303 + jsl $E10000 + MEND + MACRO +&lab _ReadBParam +&lab ldx #$0C03 + jsl $E10000 + MEND + MACRO +&lab _SetHeartBeat +&lab ldx #$1203 + jsl $E10000 + MEND + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab lsr3 &a +&lab lsr &a + lsr &a + lsr &a + mend + MACRO +&lab asl3 &a +&lab asl &a + asl &a + asl &a + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk1 + rep #%00100000 +.chk1 + aif "&char"<>"{",.chk2 +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + ldy #2 + lda (&parm),y + pha + lda (&parm) + pha + ago .shorten +.chk2 + aif "&char"<>"[",.absolute + ldy #2 + lda &parm,y + pha + lda &parm + pha + ago .shorten +.absolute + lda &parm+2 + pha + lda &parm + pha + ago .shorten +.at +&char1 amid &parm,2,1 +&char2 setc &char1 + ph&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + ph&char2 + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea +(&parm)|-16 + pea &parm + ago .done +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab SetVector &a1 +&lab ph2 &a1(1) + ph4 &a1(2) + tool $1003 + mend + MACRO +&lab IntSource &a1 +&lab ph2 &a1 + tool $2303 + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab pushlong &addr,&offset +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 + AIF "&C"="#",.immediate + AIF "&C"="[",.zeropage + AIF C:&offset=0,.nooffset + AIF "&offset"="s",.stack + pushword &addr+2,&offset + pushword &addr,&offset + MEXIT +.nooffset + pushword &addr+2 + pushword &addr + MEXIT +.immediate +&REST AMID &addr,2,L:&addr-1 + dc I1'$F4',I2'(&REST)|-16' + dc I1'$F4',I2'&REST' + MEXIT +.stack + pushword &addr+2,s + pushword &addr+2,s + MEXIT +.zeropage + ldy #&offset+2 + pushword &addr,y + ldy #&offset + pushword &addr,y + MEND + MACRO +&lab pushword &SYSOPR +&lab ANOP + AIF c:&SYSOPR=0,.b + LCLC &C +&C AMID "&SYSOPR",1,1 + AIF ("&C"="#").AND.(S:LONGA),.immediate + lda &SYSOPR + pha + MEXIT +.b + pha + MEXIT +.immediate + LCLC &REST + LCLA &BL +&BL ASEARCH "&SYSOPR"," ",1 + AIF &BL>0,.a +&BL SETA L:&SYSOPR+1 +.a +&REST AMID "&SYSOPR",2,&BL-2 + dc I1'$F4',I2'&REST' + MEND + MACRO +&lab _NewHandle +&lab ldx #$0902 + jsl $E10000 + MEND + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _GetVector +&lab ldx #$1103 + jsl $E10000 + MEND + MACRO +&lab _SetVector +&lab ldx #$1003 + jsl $E10000 + MEND + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/drivers/kern.equates b/kern/drivers/kern.equates new file mode 100644 index 0000000..dd70a13 --- /dev/null +++ b/kern/drivers/kern.equates @@ -0,0 +1,17 @@ +* $Id: kern.equates,v 1.1 1998/02/02 08:18:14 taubert Exp $ +********************************************************************* +* +* Kernel process state IDs +* +********************************************************************* + +NPROC gequ 32 +pUnused gequ $00 +pRunning gequ $01 +pReady gequ $02 +pBlocked gequ $03 +pNew gequ $04 ; ready, but no int info +pSuspended gequ $05 +pWait gequ $06 +pWaitSigCH gequ $07 +pPaused gequ $08 diff --git a/kern/drivers/md.equates b/kern/drivers/md.equates new file mode 100644 index 0000000..47b69b9 --- /dev/null +++ b/kern/drivers/md.equates @@ -0,0 +1,11 @@ +* $Id: md.equates,v 1.1 1998/02/02 08:18:15 taubert Exp $ +* Specific equates for the modem port version of the driver + +CtlPanBaud gequ $12 +PortControl gequ $E0C038 +PortData gequ $E0C03A +PortNum gequ 2 SIM modem port number +Channel_Rx gequ %00000100 +Channel_Tx gequ %00000010 +Reg11 gequ %01010000 modem +PortReset gequ %01000000 diff --git a/kern/drivers/msccf.asm b/kern/drivers/msccf.asm new file mode 100644 index 0000000..2df44f0 --- /dev/null +++ b/kern/drivers/msccf.asm @@ -0,0 +1,10 @@ +* $Id: msccf.asm,v 1.1 1998/02/02 08:17:58 taubert Exp $ +* Note that there's not much in this file- just a copy for macros, +* a copy for defining the port memory locations & values, and +* a copy for the generic low level port driver code itself + + mcopy sccf.mac + copy equates + copy ../gno/inc/tty.inc + copy md.equates + copy sccf.asm diff --git a/kern/drivers/null.asm b/kern/drivers/null.asm new file mode 100644 index 0000000..b944d70 --- /dev/null +++ b/kern/drivers/null.asm @@ -0,0 +1,85 @@ +* $Id: null.asm,v 1.1 1998/02/02 08:18:00 taubert Exp $ +************************************************************ +* +* NULL device driver +* +************************************************************ + + case on + mcopy port.mac + copy ../gno/inc/tty.inc + +NullHeader START + + ds t_open +* For speed/simplicity we use a non-standard, non-documented line +* discipline for the .null device + dc i4'NullInit2' + dc i4'NullDeInit' + dc i4'NullIOCTL' + dc i4'NullRead' + dc i4'NullWrite' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + dc i4'NullNoFunc' + ds t_signalIO-editInd + dc i4'NullNoFunc' ; t_signalIO + dc i2'$FFFF' ; t_select_proc + dc i4'NullSelect' ; t_select + dc i4'0' ; t_selwakeup jmp set during install + +NullNoFunc anop + rtl + END + +NullInit2 START +result equ 0 + subroutine (2:devNum),2 + stz result + return 2:result + END + +NullDeInit START + subroutine (2:devNum),0 + return + END + +NullWrite START +count equ 0 +retval equ 2 + subroutine (2:reqCount,4:dataPtr,2:devNum),4 + stz retval + lda reqCount + sta count + return 4:count + END + +NullRead START +count equ 0 +retval equ 2 + subroutine (2:reqCount,4:dataPtr,2:devNum),4 + stz count + lda #$4C + sta retval + return 4:count + END + +NullIOCTL START +retval equ 0 + subroutine (4:tioc,4:dataPtr,2:devNum),2 + stz retval + return 2:retval + END + +NullSelect START +res equ 0 + subroutine (2:ttyn,2:which,2:pid),2 + lda #1 + sta res + return 2:res + END diff --git a/kern/drivers/port.asm b/kern/drivers/port.asm new file mode 100644 index 0000000..447824e --- /dev/null +++ b/kern/drivers/port.asm @@ -0,0 +1,840 @@ +* $Id: port.asm,v 1.1 1998/02/02 08:18:01 taubert Exp $ +* +* 12/15/94 - select code added - Derek Taubert +* + case on + mcopy port.mac + copy ../gno/inc/tty.inc + copy equates + +SerialHeader START + +dtty ENTRY + ds t_open +* Line Discipline entry points + dc i4'DInit' + dc i4'DDeInit' + dc i4'DIOCTL' + dc i4'0' ; ttread and ttwrite must be + dc i4'0' ; set up by InstallDriver + dc i4'D_mutex' + dc i4'D_demutex' + dc i4'D_out_enq' + dc i4'D_in_enq' + dc i4'D_out_deq' + dc i4'D_in_deq' + dc i4'D_size_inq' + dc i4'D_size_outq' + ds t_signalIO-editInd + dc i4'nullfunc' ; t_signalIO + dc i2'$FFFF' ; t_select_proc + dc i4'D_select' ; t_select + dc i4'0' ; t_selwakeup jmp set up during install + END +D_in_enq START + rtl + END +D_mutex START + rtl + END +D_demutex START + rtl + END + +D_select START +res equ 0 + subroutine (2:ttyn,2:which,2:pid),2 + + jsl IncBusyFlag + + lda #1 + sta res + lda which ; which I/O to check? + cmp #SEL_READ + bne trywrite + jsl D_size_inq ; # bytes in in q + cmp #0 + bne done + +willwait anop +* record that the process wants to do I/O + lda >dtty+t_select_proc ; see if someone's here already + cmp #$FFFF ; nope + beq nocollision + cmp pid ; is it us? + beq nocollision + lda >dtty+privFlags + ora #TS_RCOLL + sta >dtty+privFlags + bra none +nocollision anop + lda pid ; set select_proc field to + sta >dtty+t_select_proc ; current process ID + bra none + +trywrite cmp #SEL_WRITE + bne doexcept + bra done ; we can always write +; jsl D_left_outq ; # bytes avail in out q +; cmp #0 +; bne done +; bra willwait + +doexcept anop ; there are no exceptions +none lda #0 ; no data, return 0 + sta res + +done jsl DecBusyFlag + return 2:res + END + +D_in_deq START + using SerialData + + phb + phk + plb + phd + lda >SerialDP + tcd + jsr lowRead + pld + plb + rtl + END +D_out_deq START + rtl + END + +nullfunc START + lda 2,s + sta 4,s + lda 1,s + sta 3,s + pla + rtl + END + +D_size_inq START + using SerialData + + phd + lda >SerialDP + tcd + lda SerialDP + tcd + lda SerialDP +; tcd +; lda SerialDP + tcd + lda 7,s + jsr WriteBuffer + pld + plb + lda 2,s + sta 4,s + lda 1,s + sta 3,s + pla + rtl + END + +lowRead START + +; php need to turn off interrupts to +; sei prevent the driver from hanging + +WaitMore anop +* Check for data in the buffer + lda DPHandle + _DisposeHandle + bra memErr + +didAlloc lda [bufHand] + tax + ldy #2 + lda [bufHand],y + sta bufHand+2 + stx bufHand + +; lda #$20 ; use CTS sighupping by default + lda #$00 ; use no sighupping by default + sta >DHUP + + lda SerialDP + phd + tcd +; mv4 >dtermioPtr,dTermioPtr + ld4 dtty,dTermioPtr +* Initialize default values for terminal settings + ldy #4 + + lda #CRMOD+ECHO + sta [dTermioPtr],y + + lda #0 + short m +* default baud rate either comes from the Control panel, or +* from a previous stty command. doing stty 0 on the port +* will force a reset to the control panel next time the port is opened + +* sta [dTermioPtr] ; ispeed +* ldy #1 +* sta [dTermioPtr],y ; ospeed + ldy #t_intrc + lda #3 + sta [dTermioPtr],y ; t_intrc + ldy #t_suspc + lda #'Z'-64 + sta [dTermioPtr],y + ldy #t_quitc + lda #'\'-64 + sta [dTermioPtr],y + ldy #t_startc + lda #'Q'-64 + sta [dTermioPtr],y + ldy #t_stopc + lda #'S'-64 + sta [dTermioPtr],y + ldy #t_eofc + lda #'D'-64 + sta [dTermioPtr],y + ldy #t_brkc + lda #-1 + sta [dTermioPtr],y +* lda #11 +* ldy #t_ispeed +* sta [dTermioPtr],y + long m +* Initialize the port and parameters + ldy #privFlags + lda #0 + sta [dTermioPtr],y + ldy #ws_row + sta [dTermioPtr],y + iny2 + sta [dTermioPtr],y + iny2 + sta [dTermioPtr],y + iny2 + sta [dTermioPtr],y + jsr ComInit set the initial baud rate + + pld + + pea 0 + pei (ptr) + pei (bufHand+2) + pei (bufHand) + lda bufHand + clc + adc #BUF_SIZE + tax + lda bufHand+2 + adc #0 + pha + phx + jsl StartSerial + sta result + cmp #0 error in startup? + beq goaway Nope + cmp #7 + bcs unknownErr + asl a map SIM error to a reasonable + tax GS/OS driver error code + lda ErrorMap,x + sta result + + ph4 >DPHandle + _DisposeHandle + ph4 >bufHandle + _DisposeHandle + +goaway return 2:result +unknownErr sta result assume some other error + bra goaway +nhErr str 'Modem:NewHandle failed' +nhInit str 'Modem:Init' + +ErrorMap anop + dc i2'0' + dc i2'$29' SIMAlreadyInst + dc i2'$27' SIMInvalidAddr + dc i2'$29' SIMATalkActive + dc i2'$27' SIMNotInstalled + dc i2'$22' SIMInvalidPort + dc i2'$26' SIMNotFound + + END + +DDeInit START + using SerialData + subroutine (2:devNum),0 + +* ph4 #detxt +* _ErrWriteString + + jsl EndSerial + + ph4 >DPHandle + _DisposeHandle + ph4 >bufHandle + _DisposeHandle + + return +detxt str 'DeInit Modem' + END + +DIOCTL START + using SerialData +retval equ 0 +dpPtr equ 2 + subroutine (4:tioc,4:dataPtr,2:devNum),6 + + lda SerialDP + sta dpPtr + stz dpPtr+2 + lda tioc + and #$FF00 + xba + cmp #'f' + beq chkfile + cmp #'t' + beq tioctl +err lda #-1 + sta retval + bra goaway +* FIONREAD +chkfile lda tioc + and #$7F + cmp #127 + bne err + + ldy #ibuf_mark + lda [dpPtr],y how many bytes in input buffer? + sta [dataPtr] lda is an atomic operation :-) + + stz retval + bra goaway +tioctl anop + lda tioc + and #$7F + cmp #23 + bcc okay2 + and #$7F + 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'2',a2'invalid' + dc i2'3',a2'invalid' + dc i2'4',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'-1',a2'invalid' + dc i2'-1',a2'invalid' + dc i2'21',a2'TIOCSHUP' + dc i2'22',a2'TIOCGHUP' + +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'TIOCSBRK' + dc i2'122',a2'TIOCCBRK' + dc i2'121',a2'TIOCSDTR' + dc i2'120',a2'TIOCCDTR' + + 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 +***************************************************** +TIOCSHUP anop + lda [dataPtr] + sta >DHUP +; jsr InstComplete + stz retval + jmp goaway +TIOCGHUP anop + lda >DHUP + sta [dataPtr] + stz retval + jmp goaway + +TIOCGETD anop +TIOCSETD anop +TIOCSETN anop +TIOCGETP stz retval + jmp goaway + +TIOCSETP anop + phd + lda >SerialDP + tcd + jsr SetWord $$$ SETWORD SET BAUD RATE + pld + stz retval + jmp goaway + +TIOCFLUSH anop + php + sei + lda dataPtr + ora dataPtr+2 + bne notNull + ldx #0 +notNull lda [dataPtr] get the type of operation + tax + cpx #2 + beq clrOutQ + lda #0 zero out the buffer information + ldy #ibuf_head + sta [dpPtr],y + ldy #ibuf_tail + sta [dpPtr],y + ldy #ibuf_mark + sta [dpPtr],y + +clrOutQ cpx #1 + beq doneFLUSH + lda #0 zero out the buffer information + ldy #obuf_head + sta [dpPtr],y + ldy #obuf_tail + sta [dpPtr],y + ldy #obuf_mark + sta [dpPtr],y + +doneFLUSH plp + stz retval + jmp goaway + +TIOCOUTQ ldy #obuf_mark + lda [dpPtr],y + sta [dataPtr] + stz retval + jmp goaway + +TIOCSTOP anop +TIOCSTART anop + lda #-1 + sta retval + jmp goaway ; we don't support these + +TIOCSDTR jsr DTRON ; these don't need DP + jmp goaway + +TIOCCDTR jsr DTROFF + jmp goaway + +TIOCSBRK jsr BRKON + stz retval + jmp goaway +TIOCCBRK jsr BRKOFF + stz retval + jmp goaway + +* simulate terminal input (this code is borrowed from INOUT.ASM/OurADB +TIOCSTI anop +; this chunk stores the byte in the buffer + lda [dataPtr] + tax + php + sei + phd + lda >SerialDP + tcd + ldy dtty+t_select_proc + cmp #$FFFF + beq done + +* someone is selecting on us, so call selwakeup with the process ID +* and our collision flag + pha + + lda >dtty+privFlags + and #TS_RCOLL + pha + jsl dtty+t_selwakeup + lda >dtty+privFlags + and #TS_RCOLL.EOR.$FFFF + sta >dtty+privFlags + lda #$FFFF + sta >dtty+t_select_proc + +done anop + pld + plp + stz retval + jmp goaway + END + +checkIntr START + using SerialData + + php + long ai + and #$7f + pha + short m + + ldy #sg_flags + lda [dTermioPtr],y + bit #$20 ; RAW mode? + beq x9 ; yep, no character checking + brl notty +x9 ldy #t_quitc + lda [dTermioPtr],y + cmp #-1 + beq x0 + cmp 1,s + beq gotQQ +x0 ldy #t_suspc + lda [dTermioPtr],y + cmp #-1 + beq x1 + cmp 1,s + beq gotZ +x1 ldy #t_intrc + lda [dTermioPtr],y + cmp #-1 + beq notty + cmp 1,s + beq gotC +*x2 lda >OutStopped +* bne x3 +* ldy #t_stopc +* lda [dTermioPtr],y +* cmp #-1 +* beq x3 +* cmp 1,s +* beq gotS +*x3 ldy #t_startc +* lda [dTermioPtr],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 + + lda dtty+t_devNum ; push our device number + jsl dtty+t_sendSignal + + 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 + END + + +SerialData DATA +SerialDP dc i2'0' +DPHandle dc i4'0' +bufHandle dc i4'0' +DHUP dc i2'$00' +ourSerFlag dc i2'0' +CurBaud dc i2'0' + +baudTbl dc i2'0' 0 - no baud! (hangup) + dc i2'$08FE' 1 - 50 baud + dc i2'$05FE' 2 - 75 baud + dc i2'$0415' 3 - 110 baud + dc i2'$035B' 4 - 134.5 baud + dc i2'$02FE' 5 - 150 baud + dc i2'$0000' 6 - 200 baud ($23E) or 57600 + dc i2'$017E' 7 - 300 baud + dc i2'$00BE' 8 - 600 baud + dc i2'$005E' 9 - 1200 baud + dc i2'$003E' 10 - 1800 baud + dc i2'$002E' 11 - 2400 baud + dc i2'$0016' 12 - 4800 baud + dc i2'$000A' 13 - 9600 baud + dc i2'$0004' 14 - 19200 baud + dc i2'$0001' 15 - 38400 baud + +* Firmware to UNIX baud-rate number conversion + +RevBDTab dc i2'1' 50 + dc i2'2' 75 + dc i2'3' 110 + dc i2'4' 134.5 + dc i2'5' 150 + dc i2'7' 300 + dc i2'8' 600 + dc i2'9' 1200 + dc i2'10' 1800 + dc i2'11' 2400 + dc i2'0' 3600 + dc i2'12' 4800 + dc i2'0' 7200 + dc i2'13' 9600 + dc i2'14' 19200 + + END diff --git a/kern/drivers/port.mac b/kern/drivers/port.mac new file mode 100644 index 0000000..8799caf --- /dev/null +++ b/kern/drivers/port.mac @@ -0,0 +1,303 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab _NewHandle +&lab ldx #$0902 + jsl $E10000 + MEND + MACRO +&lab _DisposeHandle +&lab ldx #$1002 + jsl $E10000 + MEND + MACRO +&lab str &string +&lab dc i1'l:&string',c'&string' + MEND + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab LD4 &val,&adr +&lab lcla &count + lda #<&val +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda #+(&val)|-16 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend diff --git a/kern/drivers/pr.equates b/kern/drivers/pr.equates new file mode 100644 index 0000000..b7bf2e5 --- /dev/null +++ b/kern/drivers/pr.equates @@ -0,0 +1,11 @@ +* $Id: pr.equates,v 1.1 1998/02/02 08:18:16 taubert Exp $ +* Specific equates for the modem port version of the driver + +CtlPanBaud gequ $6 +PortControl gequ $E0C039 +PortData gequ $E0C03B +PortNum gequ 1 SIM modem port number +Channel_Rx gequ %00100000 +Channel_Tx gequ %00010000 +Reg11 gequ %11010000 printer +PortReset gequ %10000000 diff --git a/kern/drivers/psccf.asm b/kern/drivers/psccf.asm new file mode 100644 index 0000000..374f85c --- /dev/null +++ b/kern/drivers/psccf.asm @@ -0,0 +1,10 @@ +* $Id: psccf.asm,v 1.1 1998/02/02 08:18:03 taubert Exp $ +* Note that there's not much in this file- just a copy for macros, +* a copy for defining the port memory locations & values, and +* a copy for the generic low level port driver code itself + + mcopy sccf.mac + copy equates + copy ../gno/inc/tty.inc + copy pr.equates + copy sccf.asm diff --git a/kern/drivers/sccf.asm b/kern/drivers/sccf.asm new file mode 100644 index 0000000..8872f95 --- /dev/null +++ b/kern/drivers/sccf.asm @@ -0,0 +1,761 @@ +* $Id: sccf.asm,v 1.1 1998/02/02 08:18:04 taubert Exp $ + + case on + +* Install an interrupt handler into the SIM tool. This uses the SIM +* library so it's really easy + +InstallInt START + + ph4 #IntVect + pea PortNum + jsl INSTALLINTVECT + rts + +oldVect ENTRY + dc i4'0' + END + +* Remove our SCC interrupt handler from the Main Interrupt Vector + +RemoveInt START + ph4 #IntVect + pea PortNum + jsl REMOVEINTVECT + rts + END + +IntVect START + using SerialData + + longa off + longi off + + php + long x +; JAWAID! *whap* +; check_stuff needs RR0 contents, not RR3! +; tay we need this for check_stuff + bit #Channel_Rx + beq t_Tx_Int + + phb + phk + plb + phd + long m + lda SerialDP + tcd + short m +; *whap* +; sty PortControl + lda >PortControl + pha + + lda >PortData + sta PortControl ; error reset + lda #$30 + sta >PortControl + +weepers lda #0 ; Reset high IUS + sta >PortControl + lda #$38 + sta >PortControl + + lda >PortControl + bit #1 + bne lp1 ; more data! + pld + plb +gohome anop + plp + clc + rtl + +notOurIntr anop + plp + sec + rtl + +t_Tx_Int anop + bit #Channel_Tx + beq statusInt + lda SerialDP + tcd + short m + phb + phk + plb +doTxChar ldy PortData + iny + cpy PortControl + lda #$38 + sta >PortControl + + plb + pld +; ply + bra gohome +turnOffTxInt lda #%00101000 + sta >PortControl + lda #0 + sta SerialDP + tcd + short m + phb + phk + plb + lda >PortControl + bit #%00100000 ; check status of CTS line + bne turniton + + lda #1 + sta PortControl + lda #$38 + sta >PortControl + + plb + pld +; ply + jmp gohome +turniton lda PortControl +; *whap* +; lda dtty+t_select_proc + cmp #$FFFF + beq done + +* someone is selecting on us, so call selwakeup with the process ID +* and our collision flag + pha + + lda >dtty+privFlags + and #TS_RCOLL + pha + jsl >dtty+t_selwakeup + lda >dtty+privFlags + and #TS_RCOLL.EOR.$FFFF + sta >dtty+privFlags + lda #$FFFF + sta >dtty+t_select_proc + +done anop + short m +goaway anop + rts +* we lost carrier detect, so send a sighup signal +sighupit anop + long m + lda #$FFFF + sta >$E00408 + pea 1 ; push signal number + lda >dtty+t_devNum + pha ; push our device number + jsl dtty+t_sendSignal +* short m ; see done, above + bra done + END + + longa on + longi on + +* ReadBuffer and WriteBuffer expect the D register to be set properly +* (i.e., to SerialDP) + +ReadBuffer START + using SerialData + + php + short m + sei + ldy PortControl +; lda >PortControl +; bit #Tx_empty see if something is in the Tx latch +; beq addToBuffer and if so stick char in the buffer + lda PortData + lda #1 + sta PortControl ; check the CTS line to make sure + bit #%00100000 ; the printer can accept data... + beq flowCheck ; if not, then wait for it + +txfull lda >PortControl ; make sure the transmit buffer + bit #%00000100 ; is empty + beq txfull + + pla + sta >PortData ; write our data! + long m + + return + END + +InitSCC START + + php + sei + short m + + lda >PortControl + lda #$09 + sta >PortControl + + lda #%00000010+PortReset channel reset, turn intrs off + sta >PortControl + nop + nop + nop + nop + nop + nop + nop + nop + + ldx #0 +a_ian_loop lda async_data,x + cmp #$FF + beq a_ian_leap + sta >PortControl + +* What's the timer for? + + inx + bra a_ian_loop + +a_ian_leap anop + long m + plp + rtl + +async_data dc i1'$04,$44' X16 clock mode, 1 stop bit + dc i1'$02,$00' no interrupt vector + dc i1'$03,%11100000' rx 8 bits/char, rx off, auto enables + dc i1'$05,$62' DTR = 0, tx 8 bits/char, tx off, RTS = 1 + dc i1'$09,%0010' no reset, all ints off + dc i1'$0A,$00' NRZ data encoding + dc i1'$0B,Reg11' xtal on, rx clock = brg out, tx clock = brg_out +initBaudLo ENTRY + dc i1'$0C,$04' low byte of brg time constant +initBaudHi ENTRY + dc i1'$0D,$00' high byte of brg time constant + dc i1'$0E,$80' source = brg, brg clock = xtal, brg off + dc i1'$0E,$01' brg on, brg clock = xtal + dc i1'$03,%11100001' rx 8 bits/char, rx on + dc i1'$05,DTR' DTR = 0, tx 8 bits/char, tx on, RTS = 1 + dc i1'$0F,%00101000' interrupt on CTS status change +* dc i1'$01,%00010001' rx char ints enable +* dc i1'$09,%00001010' master interrupt enable + dc i1'$FF' + END + +InitSCC2 START + using SerialData + + php + sei + short m + + lda >PortControl + lda #1 + sta >PortControl + lda #%00010010 ; intr on all rx and tx + sta >PortControl + lda #9 + sta >PortControl + lda #%1010 + sta >PortControl + +; hum, just for kicks... + lda #0 + sta >PortControl ; error reset + lda #$30 + sta >PortControl + lda #0 ; Reset high IUS + sta >PortControl + lda #$38 + sta >PortControl + + plp + rts + END + + longa on + longi on +DeInitSCC START + using SerialData + +* Turn off the SCC's interrupt generation completely + php + sei + short m + lda >PortControl + lda #9 + sta >PortControl + lda #%0010 + sta >PortControl + + lda #1 + sta >PortControl + lda #0 + sta >PortControl + + lda >PortData + lda #%11010000 + sta >PortControl + nop + nop + nop + nop + nop + lda #%00101000 + sta >PortControl + nop + nop + nop + nop + nop + lda #9 + sta >PortControl + lda #%1010 + sta >PortControl + +; lda >SerFlag +; and #%11111000 +; sta >SerFlag +; lda >ourSerFlag +; and #%11111000 +; sta >ourSerFlag + + long m + plp + rts + END + +StartSerial START + using SerialData +result equ 0 + subroutine (4:dp,4:inb,4:outb),2 + + stz result + lda inb + ldy #in_buf + sta [dp],y + lda inb+2 + ldy #in_buf+2 + sta [dp],y + lda outb + ldy #out_buf + sta [dp],y + lda outb+2 + ldy #out_buf+2 + sta [dp],y + + phd + + lda dp + sta >SerialDP + tcd ; 'return' will restore this + + lda #0 + sta SerialDP + tcd +lp lda PortControl + lda #DTR+$80 + sta >PortControl + sta PortControl + lda #DTR + sta >PortControl + sta SerialDP + tcd + php + short m + sei + lda #5 + sta >PortControl + lda #DTR + sta >PortControl + sta SerialDP + tcd + php + sei + short m + lda #5 + sta >PortControl + lda #DTR+$80 + sta >PortControl + sta baudTbl,x + sta CurBaud + +* reset the baud rate in the SCC + + tax + short m + lda >PortControl + lda #$0C + sta >PortControl + txa + sta >PortControl + lda #$0D + sta >PortControl + txa + xba + sta >PortControl + long m + +realFIN plp + rts + end diff --git a/kern/drivers/sccf.mac b/kern/drivers/sccf.mac new file mode 100644 index 0000000..9ec1598 --- /dev/null +++ b/kern/drivers/sccf.mac @@ -0,0 +1,249 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _ReadBParam +&lab ldx #$0C03 + jsl $E10000 + MEND + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend diff --git a/kern/gno/Makefile b/kern/gno/Makefile new file mode 100644 index 0000000..b8b3e62 --- /dev/null +++ b/kern/gno/Makefile @@ -0,0 +1,51 @@ +# $Id: Makefile,v 1.1 1998/02/02 08:18:19 taubert Exp $ + +.INCLUDE: /src/gno/paths.mk + +PROG= kern +OBJS= main.o patch.o kern.o sys.o signal.o ctool.o sem.o \ + queue.o data.o diag.o resource.o tty.o select.o gsos.o \ + p16.o pipe.o shellcall.o fastfile.o texttool.o driver.o \ + util.o var.o ep.o err.root regexp.root stat.o ports.o \ + sleep.o pty.o net.o \ + inout.o console.o box.root conpatch.o +CFLAGS+=-DKERNEL +.SOURCE: ../drivers + +$(PROG): $(OBJS) + gsh -c ${mktmp prefix 13 /lang/orca/libraries; $(LD) $(LDFLAGS) -o $@ $<} + compile +w $(PROG).rez keep=$@ + chtyp -t s16 $@ +$(PROG): $(PROG).rez + +# dependencies + +data.o: conf.h kernel.h proc.h q.h sem.h +diag.o: proc.h sys.h +ep.o: proc.h sys.h +fastfile.o: proc.h sys.h +main.o: proc.h gno.h sys.h sem.h tty.h +net.o: gno.h proc.h sys.h kernel.h net.h +patch.o: proc.h gno.h sys.h sem.h conf.h +ports.o: conf.h kernel.h proc.h gno.h +queue.o: q.h conf.h proc.h kernel.h sys.h +sem.o: sys.h sem.h proc.h q.h conf.h kernel.h gno.h +signal.o: conf.h kernel.h proc.h sys.h gno.h +sleep.o: proc.h sys.h kernel.h +stat.o: proc.h sys.h kernel.h +sys.o: conf.h proc.h kernel.h kvm.h gno.h sys.h +driver.o: m/driver.mac global.equates inc/tty.inc +err.o: m/err.mac +gsos.o: m/gsos.mac global.equates inc/gsos.inc inc/tty.inc +p16.o: m/p16.mac global.equates inc/gsos.inc inc/tty.inc +pipe.o: m/pipe.mac inc/kern.inc inc/gsos.inc +pty.o: inc/tty.inc +regexp.o: m/regexp.mac +resource.o: inc/gsos.inc +select.o: m/select.mac inc/tty.inc inc/gsos.inc inc/kern.inc global.equates +shellcall.o: m/shellcall.mac global.equates +texttool.o: m/texttool.mac global.equates +tty.o: m/tty.mac inc/tty.inc +util.o: m/util.mac +var.o: m/var.mac + diff --git a/kern/gno/TODO b/kern/gno/TODO new file mode 100644 index 0000000..f30cba0 --- /dev/null +++ b/kern/gno/TODO @@ -0,0 +1,88 @@ +todo +==== +- select() on pipes +- make console driver a loaded driver +- check drive full error code +- GetLang/SetLang +- access devices via /dev +- find out why tcp/ip takes so damn long to quit sometimes +- check p8 launching +- write up driver interface specs + revamp loaded driver interfaces so we can have stuff like /dev/audio +- how can we pass back correct error codes from SOCKrdwr to read() and write() + lib routines? +- create types, document diff between pid, kern pid, and kern table offset + +baz.todo +======== +- Rewrite the texttools to properly support texttools features + regardless of redirection. At the same time, implement a simple + buffering scheme for the texttools to greatly improve texttools + redirection. (must be tied into PGClose so we properly flush the + buffers all the time). + +libs +==== +- tc[gs]etattr, TIOCGETA, TIOCSETA +- getlogin +- sigemptyset, sigaddset, sigprocmask + +reported bugs +============= +1/1/95 - init messages appearing on single line + +done +==== +10/27/97 wait() fixed to return -1, ECHILD if no children +11/5/96 select() should re-start after signal + should return EINTR after signal + with wait & *wait = 0 should basically not block + semaphore and KERNkill code re-worked to not spaz out GNO for + EINTR cases +4/30/96 commonSwait wasn't working right for EINTR when != procBLOCKED +3/31/96 libc: fixed %m and LOG_PID in vsprintf() (data bank problems) + libc: added gettimeofday() + libc: added setre[gu]id() +3/11/96 fixed stack deallocation problems in KERNkill and KERNexecve +3/7/96 fdCount++ was misplaced in dup2() +2/13/96 select() timeout now works (YEA!) +1/6/96 gs/os files working with select() + select() returns the proper value +? filed& filed& -> bogus process due to context switch during KERNkill() + socket close swait() problem fixed by removing some swait() + dependencies from socket close code +1/25/95 echo code in tty.asm wasn't calling signalIO like it should + have, select() on ptys seems to work now +1/15/95 2.0.6b4 released +1/12/95 ctool.asm: stuff added on 1/7/95 had incorrect entries (-1 doh!) + ps entry for init is now FUCK, FUCK, FUCKED! why? ACK! don't + link gno with lenviron installed! +1/11/95 2.0.6b3 released +1/10/95 receiveCommon - $0080.EOR.$FFFF was evaluating to $0000, thanx + a lot, mikey. This was causing the flags to get all fucked up + and bank 0 space was disappearing because UserShutDown() was + being used on forked memids instead of DisposeAll() +1/9/95 serial drivers were checking RR3 for SIGHUPing rather than + RR0 + serial drivers do no SIGHUPing by default now - the special + condition interrupt enable and interrupt handler need to be + re-writen properly to handle different values for DHUP +1/7/95 more net stuff: shutdown(), getpeeraddr(), getsockaddr(), and + [gs]etsockopt() were added to the kern and libc +1/2/95 2.0.6b1 released + added version resource to kern + fixed InOutStart/End calling (I fuqed it up while playing with + making the console driver loadable) + libc: fixed strerror w/ network stuff + 2.0.6b2 released +1/1/95 modem, printer drivers working with select() + correct orcalib from baz + welcome version 2.0.6b1 + libc: added hosname stuff + libc: updated perror w/ network stuff + kernVersion returns $0206 now +12/?/94 null driver is now a loaded driver, and select() should work + right on it... +12/15/94 select() on sockets (ha! ha! bitch!) +12/12/94 Pass ioctl() on sockets directly to the usrreq routine + (do not pass go, do not collect $200) diff --git a/kern/gno/conf.h b/kern/gno/conf.h new file mode 100644 index 0000000..b953846 --- /dev/null +++ b/kern/gno/conf.h @@ -0,0 +1,19 @@ +/* $Id: conf.h,v 1.1 1998/02/02 08:18:21 taubert Exp $ */ + +/* conf.h - configuration and size constants */ + +/* the following defines can be changed but not deleted */ +#define NPROC 32 /* max user processes */ + +/* the following defines can be changed or deleted */ +#define GNOVERSION "for GS/OS 3.0 on Apple IIgs (65816) (5/28/91) - Jawaid Bazyar" +#define MESSAGE /* message passing available */ +#define NSEM 200 /* total number of semaphores */ +#define RTCLOCK /* system has a real-time clock */ +#define QUANTUM 100 /* milliseconds a process is allowed + to run without being rescheduled */ + +#define DEBUG_RESCHED /* if defined, displays information \ + about the processes being scheduled */ + +/* note: most of these are meaningless on the IIgs */ diff --git a/kern/gno/ctool.asm b/kern/gno/ctool.asm new file mode 100644 index 0000000..9bcceb8 --- /dev/null +++ b/kern/gno/ctool.asm @@ -0,0 +1,1175 @@ +* $Id: ctool.asm,v 1.1 1998/02/02 08:19:14 taubert Exp $ + + mcopy m/ctool.mac + + case on + +;TDISPOSEHAND START +; pha +; lda 9,s ; we have something on the stack dummy +; cmp #$8b98 +; bne goold +; lda 11,s +; cmp #$00E0 +; bne goold +; ldx #$2C03 +; jsl $E10000 +;always bra always +;goold pla +; dc i1'$5C' +;OLDDISPHAND ENTRY +; dc i4'0' +; END + +* all processes that end with RTL come here +endproc2 START + using KernelStruct + phk + plb + ldx curProcInd + sta exitCode,x + jmp >endproc + END + +kernTable START KERN2 + dc i4'(TheEnd-kernTable)/4' + + dc i4'tBootInit-1' ; 1 + dc i4'tStartUp-1' ; 2 + dc i4'tShutDown-1' ; 3 + dc i4'tVersion-1' ; 4 + dc i4'tReset-1' ; 5 + dc i4'tStatus-1' ; 6 + dc i4'NotImpMM-1' ; 7 + dc i4'NotImpMM-1' ; 8 + + dc i4'TIgetpid-1' ; 9 + dc i4'TIkill-1' ; a + dc i4'TIfork-1' ; b + dc i4'NotImpMM-1' ; c Was exec... + dc i4'TIswait-1' ; d + dc i4'TIssignal-1' ; e + dc i4'TIscreate-1' ; f + dc i4'TIsdelete-1' ; 10 + dc i4'TIkvm_open-1' ; 11 + dc i4'TIkvm_close-1' ; 12 + dc i4'TIkvm_getproc-1' ; 13 + dc i4'TIkvm_nextproc-1' ; 14 + dc i4'TIkvm_setproc-1' ; 15 + dc i4'TIsignal-1' ; 16 + dc i4'TIwait-1' ; 17 + dc i4'TItcnewpgrp-1' ; 18 + dc i4'TIsettpgrp-1' ; 19 + dc i4'TItctpgrp-1' ; 1a + dc i4'TIsigsetmask-1' ; 1b + dc i4'TIsigblock-1' ; 1c + dc i4'TIexecve-1' ; 1d + dc i4'TIalarm-1' ; 1e + dc i4'TIsetdebug-1' ; 1f + dc i4'TIsetsystemvector-1' ; 20 + dc i4'TIsigpause-1' ; 21 + dc i4'TIdup-1' ; 22 + dc i4'TIdup2-1' ; 23 + dc i4'TIpipe-1' ; 24 + dc i4'TIgetpgrp-1' ; 25 + dc i4'TIioctl-1' ; 26 + dc i4'TIstat-1' ; 27 + dc i4'TIfstat-1' ; 28 + dc i4'TIlstat-1' ; 29 + dc i4'TIgetuid-1' ; 2A + dc i4'TIgetgid-1' ; 2B + dc i4'TIgeteuid-1' ; 2C + dc i4'TIgetegid-1' ; 2D + dc i4'TIsetuid-1' ; 2E + dc i4'TIsetgid-1' ; 2F + dc i4'TIprocsend-1' ; 30 + dc i4'TIprocreceive-1' ; 31 + dc i4'TIrecvclr-1' ; 32 + dc i4'TIrecvtim-1' ; 33 + dc i4'TIsetpgrp-1' ; 34 + dc i4'TItimes-1' ; 35 + dc i4'TIpcreate-1' ; 36 + dc i4'TIpsend-1' ; 37 + dc i4'TIpreceive-1' ; 38 + dc i4'TIpdelete-1' ; 39 + dc i4'TIpreset-1' ; 3A + dc i4'TIpbind-1' ; 3B + dc i4'TIpgetport-1' ; 3C + dc i4'TIpgetcount-1' ; 3D + dc i4'TIscount-1' ; 3E + dc i4'TIfork2-1' ; 3F + dc i4'TIgetppid-1' ; 40 + dc i4'TISetGNOQuitRec-1' ; 41 + dc i4'TIalarm10-1' ; 42 + dc i4'TIselect-1' ; 43 + dc i4'TIInstallNetDriver-1' ; 44 + dc i4'TIsocket-1' ; 45 + dc i4'TIbind-1' ; 46 + dc i4'TIconnect-1' ; 47 + dc i4'TIlisten-1' ; 48 + dc i4'TIaccept-1' ; 49 + dc i4'TIrecvfrom-1' ; 4A + dc i4'TIsendto-1' ; 4B + dc i4'TIrecv-1' ; 4C + dc i4'TIsend-1' ; 4D + dc i4'TIgetpeername-1' ; 4E + dc i4'TIgetsockname-1' ; 4F + dc i4'TIgetsockopt-1' ; 50 + dc i4'TIsetsockopt-1' ; 51 + dc i4'TIshutdown-1' ; 52 + dc i4'TIsetreuid-1' ; 53 + dc i4'TIsetregid-1' ; 54 + +TheEnd anop + END + +QDSTARTUPPATCH START KERN2 + using KernelStruct + + php + long ai + + phb + phk + plb + pha + phx + phy + + pha + _QDStatus ; quickdraw is already started! + pla + bne killProc + + lda >curProcInd + tax + lda >ttyID,x + cmp #3 ; no QDStartup from a terminal! + bne killProc + + lda >flags,x + ora #64 ; COMPLIANT, NORESTART, QDSTARTUP + sta >flags,x + + ply + plx + pla + plb + plp + jmp >DoOldQD + +killProc anop + short m + lda #0 + sta >$E100FF + long m + + ph4 #badBoy + _WriteCString + + jmp >endproc + +badBoy dc c'QuickDraw is already started.' + + END + +DoOldQD START + dc i1'$5C' +OLDQDSTARTUP ENTRY + dc i4'0' + END + +* The new Sane Startup only stores the program's chosen SANE DP space +* into the kernel process entry. The context switcher must now +* copy the sanedp around. + +SANESUPATCH START + using KernelStruct +sanedp equ 7+1 + + phb + phk + plb + + lda sanedp,s + ldx curProcInd + sta SANEwap,x + plb + dc i1'$5C' +OLDSANESU ENTRY + dc i4'0' + END + +SANESDPATCH START + using KernelStruct + + phb + phk + plb + + lda #0 + ldx curProcInd + sta SANEwap,x + plb + phd + jmp bye0 + END + +SANESTPATCH START + using KernelStruct +sanest equ 7+1 + + phb + phk + plb + ldx curProcInd + lda SANEwap,x + beq goway + lda #$FFFF +goway sta sanest,s + plb + phd + jmp bye0 + END + +OURSYSFAILMGR START +errorCode equ 7+3+4 +strPtr equ 7+3 + + phb + phk + plb + phd + tsc + tcd + lda strPtr + ora strPtr+2 + bne yString + ph4 #defaultStr + bra dostr +yString anop + pei (strPtr+2) + pei (strPtr) +dostr _ErrWriteString + lda errorCode + ErrWriteChar #' ' + ErrWriteChar #'$' + lda errorCode + jsr writeacc + lda errorCode ; we must halt the system + cmp #$0305 + beq dopanic ; on certain error codes, or + cmp #$0308 + beq dopanic ; the system will act really goofy + cmp #$0681 + beq dopanic + cmp #$0682 + beq dopanic + cmp #$08FF + beq dopanic + ldx #$0903 + jsl $E10008 + pea $0009 ; kill us! + ldx #$0A03 + jsl $E10008 ; goodbye cruel world! + bra dopanic + +defaultStr str 'System Error ->' + +dopanic short m + lda >$E0C029 ; turn off SHR graphics + and #$7F + sta >$E0C029 + lda #$1F ; red on white, set text and bg + sta >$E0C022 ; color so error can always be seen + lda >$E100FF ; if busy flag is set, allow us to + bne dopanic1 ; enter GSBug to see what happened + sei +dopanic1 bra dopanic1 + END + longa on + longi on + +NotImpMM START KERN2 + sec + rtl + END + +NULLTOOLFUNC START KERN2 + clc + rtl + END + +tVersion START KERN2 + lda #$0206 + sta 7,s + lda #0 + clc + rtl + END + +tBootInit START KERN2 + clc + RTL + END + +tStartUp START KERN2 + clc + RTL + END + +tShutDown START KERN2 + clc + RTL + END + +tReset START KERN2 + clc + RTL + END + +tStatus START KERN2 + lda #$8100 + sta 7,s + lda #0 + clc + rtl + END + +TIalarm START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNalarm + END + +TIalarm10 START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNalarm10 + END + +TIdup START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNdup + END + +TIdup2 START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNdup2 + END + +TIgetpid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgetpid + END + +TIgetppid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgetppid + END + +TIgetpgrp START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgetpgrp + END + +TIsetpgrp START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetpgrp + END + +TIgetuid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgetuid + END + +TIgetgid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgetgid + END + +TIgeteuid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgeteuid + END + +TIgetegid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNgetegid + END + +TIsetuid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetuid + END + +TIsetreuid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetreuid + END + +TIsetgid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetgid + END + +TIsetregid START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetregid + END + +TIkill START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNkill + END + +TIfork START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNfork + END + +TIfork2 START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNFORK2 + END + +*TIexec START KERN2 +* tsc +* clc +* adc #3 +* tcs +* jmp >KERNexec +* END + +TIexecve START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNexecve + END + +TIswait START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNswait + END + +TIssignal START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNssignal + END + +TIscreate START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNscreate + END + +TIsdelete START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsdelete + END + +TIkvm_open START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNkvm_open + END + +TIkvm_close START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNkvm_close + END + +TIkvm_getproc START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNkvmgetproc + END + +TIkvm_nextproc START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNkvmnextproc + END + +TIkvm_setproc START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNkvmsetproc + END + +TIpipe START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNpipe + END + +TIsignal START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsignal + END + +TIsigpause START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsigpause + END + +TIsetdebug START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetdebug + END + +TIsetsystemvector START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsetsystemvector + END + +TIstat START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNstat + END + +TIfstat START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNfstat + END + +TIlstat START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNlstat + END + +TIwait START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNwait + END + +********************************************************** + +TItcnewpgrp START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNtcnewpgrp + END +TIsettpgrp START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsettpgrp + END + +TItctpgrp START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNtctpgrp + END + +********************************************************** + +TIsigsetmask START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsigsetmask + END +TIsigblock START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsigblock + END + +********************************************************** + +TIprocsend START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNsend + END +TIprocreceive START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNreceive + END +TIrecvclr START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNrecvclr + END +TIrecvtim START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNrecvtim + END + +TItimes START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNtimes + END + +TIpcreate START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPCREATE + END + +TIpsend START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPSEND + END + +TIpreceive START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPRECEIVE + END + +TIpdelete START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPDELETE + END + +TIpreset START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPRESET + END + +TIpbind START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPBIND + END + +TIpgetport START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPGETPORT + END + +TIpgetcount START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNPGETCOUNT + END + +TIscount START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNscount + END + +TISetGNOQuitRec START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNSETGNOQUITREC + END + +TIInstallNetDriver START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNINSTALLNETDRIVER + END +TIsocket START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNSOCKET + END +TIbind START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNBIND + END +TIconnect START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNCONNECT + END +TIlisten START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNLISTEN + END +TIaccept START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNACCEPT + END +TIrecvfrom START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNRECVFROM + END +TIsendto START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNSENDTO + END +TIrecv START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNRECV + END +TIsend START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNSEND + END +TIgetpeername START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNGETPEERNAME + END +TIgetsockname START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNGETSOCKNAME + END +TIgetsockopt START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNGETSOCKOPT + END +TIsetsockopt START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNSETSOCKOPT + END +TIshutdown START KERN2 + tsc + clc + adc #3 + tcs + jmp >KERNSHUTDOWN + END + +********************************************************** + +addsig START + using KernelStruct +space equ 0 + + subroutine (2:s,2:p),space + lda p + asl2 a + asl2 a + asl2 a + asl a + tax + lda >flpid,x + ldx s + jsr queueSignal + return + END + +execveHook START + using KernelStruct + using ctxtstuff + phk ; that this ever worked is amazing + plb ; 'sys' must usually be in another bank + lda ctx_S1 + tcs + short a + lda ctx_PC+2 + pha + long a + lda ctx_PC + dec a + pha ; rtl to the fledgling process + lda ctx_D + tcd + lda ctx_B + pha + ldx ctx_X + ldy ctx_Y + lda ctx_A + jsl decBusy ; heh heh, ha! + plb + plb + rtl + END + +ctxtRestore START + using KernelStruct + using ctxtstuff + phk + plb + + jsl cSignalHook ; unblock this signal + jsl incBusy + lda >curProcInd + tax + pla + sta >waitdone,x ; restore 'wait/block' status + pla + sta ctx_A + pla + sta ctx_X + pla + sta ctx_Y + pla + sta ctx_state ;S is implicit; use for process state + pla + sta ctx_D + pla + sta ctx_B + pla + sta ctx_P + pla + pla + sta ctx_PC + pla + sta ctx_K + +; now restore the registers and jml to the old PC, dude +; short m +; lda >ctx_K +; pha +; long m +; lda >ctx_PC ; we'll rtl back to the routine +; dec a +; pha + + sei + lda >curProcInd + tax + lda >ctx_state ; restore the old process state + sta >ProcessState,x + lda >ctx_Y + tay + lda >ctx_X + tax + lda >ctx_D + tcd + short a + lda >ctx_B + pha + plb + lda >ctx_P + pha + long a + lda >ctx_A + jsl decBusy +; plp +; xce + plp +; note that this rti isn't the one we created, it's the one shoved on +; the stack by an actual VBL or COP instruction. So we're pulling some major +; dick with this code. + + cop $7f ; in case process state changes + rti ; rti back to the routine + END + +ctxtstuff DATA +ctx_A dc i2'0' +ctx_X dc i2'0' +ctx_Y dc i2'0' +ctx_state dc i2'0' +ctx_D dc i2'0' +ctx_B dc i1'0' +ctx_B1 dc i1'0' +ctx_P dc i2'0' +ctx_S1 dc i2'0' ; argh- obsolete +ctx_PC dc i2'0' +ctx_K dc i2'0' + END + +tool_exit START + phy + tsc + clc + adc 1,s + tay + tsc + phx + tax + phb + pea $0000 + plb + plb + lda |7,x + sta |7,y + lda |5,x + sta |5,y + lda |3,x + sta |3,y + plb + plx + tsc + clc + adc 1,s + adc #2 + tcs + txa + cmp #1 + rtl + END + +exits START +bye4 ENTRY + ldx #0 + pld + ldy #4 + jmp tool_exit +bye6 ENTRY + ldx #0 + pld + ldy #6 + jmp tool_exit +bye0 ENTRY + ldx #0 + pld + ldy #0 + jmp tool_exit +bye2 ENTRY + ldx #0 + pld + ldy #2 + jmp tool_exit +bye8 ENTRY + ldx #0 + pld + ldy #8 + jmp tool_exit +bye10 ENTRY + ldx #0 + pld + ldy #10 + jmp tool_exit +bye14 ENTRY + ldx #0 + pld + ldy #14 + jmp tool_exit + END + +enableBuf START + using InOutData + php + phy + phx + pha + lda >bufState + beq nodec + dec a + sta >bufState + cmp #0 + bne nodec + IntSource #0 ; make sure Kbd ints are enabled + short mx + sta >$E0C001 ; re-enable 80-STORE + long mx + ph4 #cbuf + pea $011A + jsl $E100B0 +nodec anop + pla + plx + ply + plp + rtl +cbuf dc i2'5' + END + +disableBuf START + using InOutData + + php + phy + phx + pha + + lda >bufState + inc a + sta >bufState + cmp #1 + bne goaway + lda #0 + sta >OutStopped + + IntSource #1 ; turn off our kbd "interrupt" + ph4 #cbuf + pea $011A + jsl $E100B0 +goaway anop + pla + plx + ply + plp + rtl +cbuf dc i2'6' + END + diff --git a/kern/gno/data.c b/kern/gno/data.c new file mode 100644 index 0000000..e6eeb3b --- /dev/null +++ b/kern/gno/data.c @@ -0,0 +1,50 @@ +/* $Id: data.c,v 1.1 1998/02/02 08:18:22 taubert Exp $ */ + +/* data.c - nulluser, sysinit + global data structures + */ +#pragma optimize 79 + +#define INITSTK 2000 /* stack size of initial process */ +#define INITPRIO 20 /* priority of initial process */ +#define INITNAME "user_main" /* name of initial process */ + +#include "conf.h" +#include "kernel.h" +#include "proc.h" +#include "q.h" + +#if defined(NSEM) +#include "sem.h" +#endif /* defined(NSEM) */ + +/* declarations of major kernel variables */ +/* Not needed- we store our processTable elsewhere */ +/* struct pentry _proctab[NPROC];*/ /* process table */ + +#if defined(NSEM) +struct sentry *_semaph; +/*struct sentry _semaph[NSEM]; /* semaphore table */ +int _nextsem; /* next semaphore slot to use in screate */ +#endif /* defined(NSEM) */ + +/*struct qstruct nq[NQS];*/ +struct qstruct *nq; +struct qstruct *q_free; + +#ifdef NOTDEFINED +/* active system status */ +int _numproc; /* number of live user processes */ +int _currpid; /* id of currently running process */ + +/* real-time clock variables and sleeping process queue pointers */ +int _slnempty; /* FALSE if the sleep queue is empty */ +int *_sltop; /* address of key part of top entry in */ + +/* the sleep queue of sleeping processes */ +int _clockq; /* head of queue of sleeping processes */ + +int _rdyhead; /* head of ready list (q indices) ... */ +int _rdytail; /* ... and the tail */ +#endif + diff --git a/kern/gno/diag.c b/kern/gno/diag.c new file mode 100644 index 0000000..bd7378e --- /dev/null +++ b/kern/gno/diag.c @@ -0,0 +1,81 @@ +/* $Id: diag.c,v 1.1 1998/02/02 08:18:23 taubert Exp $ */ + +/* kernel diagnostics and error routines */ +#pragma optimize 79 + +#include "proc.h" +#include "sys.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" + +struct intState { + word irq_A; + word irq_X; + word irq_Y; + word irq_S; /* +06 */ + word irq_D; + byte irq_P; + byte irq_B; + byte irq_e; + byte irq_K; /* +13 */ + word irq_PC; /* +14 */ + word dummy[2]; /* +16 */ + word lastTool; /* +20 */ +}; +extern kernelStructPtr kp; + +#pragma databank 1 + +void traceback(word stack) +{ + word j; + + for (j = stack; (jprocTable[Kgetpid()]); + asm { + tsc + sta >0x600 + } + printf("BRK: pid: %d St: %04X\n",pr->flpid,stack); +/* traceback(stack); */ + printf("A:%04X X:%04X Y:%04X S:%04X D:%04X B:%02X P:%02X PC:%02X%04X\n" + "e:%02X Last Tool: %04X\n", + p->irq_A, p->irq_X, p->irq_Y, p->irq_S, p->irq_D, p->irq_B, p->irq_P, + p->irq_K, p->irq_PC,p->irq_e,p->lastTool); + printf("proc: PC:%02X%04X P:%04X\n",pr->irq_K, pr->irq_PC, pr->irq_P); +} + +void PANIC(char *str) +{ + word stack; + + disableps(); /* shut down context switching */ + *((byte *) 0xE0C022l) = 0x1F; + asm { + tsc + sta >stack + lda >0xE0C029 + and #0xFF7F + sta >0xE0C029 + } + traceback(stack+2); + kern_printf("SYSTEM PANIC: %s\n\r",str); + +noway: + goto noway; +} + +#pragma databank 0 + diff --git a/kern/gno/driver.asm b/kern/gno/driver.asm new file mode 100644 index 0000000..95f71b9 --- /dev/null +++ b/kern/gno/driver.asm @@ -0,0 +1,231 @@ +* $Id: driver.asm,v 1.1 1998/02/02 08:19:18 taubert Exp $ +* GNO- the only IIgs Operating System left! +************************************************************ +* +* Input/Output Drivers for TextTools +* +* .null +* GNO console +* redirection supervisory driver +* pipe interface driver for TextTools +* +************************************************************ +* +* Our texttool driver scheme supports two types- +* standard and supervisory. Standard drivers must +* support the same calls as a RAM-based texttools +* driver. Supervisory drivers must support In/Out/Err +* calls. They may call lower-level RAM-based protocol +* drivers if they wish (and likely will). +* +************************************************************ +* +* modified select stuff - Derek Taubert - 12/14/94 +* + + mcopy m/driver.mac + case on + copy global.equates + copy inc/tty.inc + copy inc/gsos.inc + +getTTindex START KERN2 +getTTindex name + using KernelStruct + + lda >truepid + asl a + asl a + asl a + asl a + asl a + asl a + tax + rts + END + +* given a GSstring as input, searches our device table for a match. +* if a match is found, the internal device number is returned. +* Note that these device numbers are the index+1, as 0 is not a valid +* pipe/refNum/device/.. number. However, the TextTools use index+0, +* so keep this in mind. + +findDevice START KERN2 +findDevice name + using KernelStruct +ind equ 0 +retval equ ind+2 +space equ retval+2 + subroutine (4:gsosp),space + + ldy #2 + lda [gsosp],y + and #$FF + cmp #'.' ; is this a driver name? + bne notadriver + + ph4 #dottty + ph4 gsosp + jsl GScaseEqual + cmp #0 + beq findloop1 + lda >curProcInd + tax + lda >ttyID,x + sta retval ; get the 'controlling' tty # + bra goaway + +findloop1 stz ind +findloop lda ind + asl a + asl a + tax + lda >DeviceNames+2,x + ora >DeviceNames,x + beq nodevice + lda >DeviceNames+2,x + pha + lda >DeviceNames,x + pha + ph4 gsosp + jsl GScaseEqual + cmp #0 + beq nodevice +* we have a device match. + lda ind + sta retval + bra goaway +nodevice lda ind + inc a + cmp #38 + bcs notadriver + sta ind + bra findloop + +notadriver lda #$FFFF + sta retval +goaway return 2:retval +dottty dc i2'4' + dc c'.tty' + END + +getProcPtr START +getProcPtr name + using KernelStruct + + lda >curProcInd + tay + clc + adc #KernelStruct + ldx #^KernelStruct + rtl + END + +* Installs a driver into the system by adding the pointer +* to the driver's header block into the system driver table. + +InstallDriver START KERN2 +InstallDriver name + subroutine (4:header,2:deviceNum,2:userID),0 + + lda deviceNum + asl a + asl a + tax + lda header + sta >DeviceBlock,x + lda header+2 + sta >DeviceBlock+2,x + + ldy #t_devNum + lda deviceNum + sta [header],y + + ldy #t_GetProcInd + lda tempGetPP + sta [header],y + ldy #t_GetProcInd+2 + lda tempGetPP+2 + sta [header],y + + ldy #t_userid + lda userID + sta [header],y + + ldy #t_sendSignal + lda tempQsig + sta [header],y + ldy #t_sendSignal+2 + lda tempQsig+2 + sta [header],y + + ldy #t_BGCheck + lda tempBG + sta [header],y + ldy #t_BGCheck+2 + lda tempBG+2 + sta [header],y + + ldy #t_selwakeup + lda tempSWU + sta [header],y + ldy #t_selwakeup+2 + lda tempSWU+2 + sta [header],y + +; initialize to the standard line discipline + + lda #0 ; line discipline code + ldy #t_linedisc + sta [header],y + ldy #privFlags + sta [header],y + ldy #st_flags + sta [header],y + lda deviceNum + beq nullDev + + ldy #t_read+2 + lda [header],y + ldy #t_read + ora [header],y + bne skipR + lda #ttread ; standard LD read routine + sta [header],y + lda #^ttread + ldy #t_read+2 + sta [header],y +skipR anop + ldy #t_write+2 + lda [header],y + ldy #t_write + ora [header],y + bne skipW + lda #ttwrite ; standard LD write routine + sta [header],y + lda #^ttwrite + ldy #t_write+2 + sta [header],y +skipW anop +; the driver's open routine must initialize the other line discipline +; vectors if they are not set up as static assignments (e.g. dc i4'CON_mutex') + +; allocate the edit buffer. + ph4 #4096 + jsl malloc + ldy #editBuf + sta [header],y + txa + ldy #editBuf+2 + sta [header],y + +nullDev return +tempAlloc jmp >asmSemNew +tempDealloc jmp >asmSemDispose +tempWait jmp >asmWait +tempSignal jmp >asmSignal +tempBG jmp >BGCheck +tempQsig jmp >ttyQSignal +tempGetPP jmp >getProcPtr +tempSWU jmp >selwakeup + END diff --git a/kern/gno/ep.c b/kern/gno/ep.c new file mode 100644 index 0000000..227d145 --- /dev/null +++ b/kern/gno/ep.c @@ -0,0 +1,398 @@ +/* $Id: ep.c,v 1.1 1998/02/02 08:18:25 taubert Exp $ */ + +/* Things to do before this code can be installed: + kernel must mutex all prefixes + this code should be changed from using GetPrefix to grabbing + the prefixes directly from the process entry +*/ +#pragma optimize 79 +segment "KERN2 "; + +#include "proc.h" +#include "sys.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include "/lang/orca/libraries/orcacdefs/ctype.h" +#include + +unsigned short err; +extern kernelStructPtr kp; +typedef GSString255Ptr Gstr; + +ExpandPathRecGS ep; +PrefixRecGS gp; + +/* this is for P16_EXPANDPATH */ +struct P16String { + byte length; + char text[255]; +} ; +typedef struct P16String P16String, *P16StringPtr; + +#define PRIME 31 +#define NUM_NP 20 + +struct h { + Gstr pfx; + Gstr exp_pfx; + struct h *next; +}; + +struct h h_pool[NUM_NP]; +unsigned int pool_ind = 0; +struct h *h_table[PRIME]; + +typedef struct stack { + Gstr name; + unsigned short ind; + char sep; +} *stackPtr; + +struct stack the_stack[3]; +unsigned short stack_ind = 0; + +void printGS(Gstr path) +{ +unsigned short i; + for (i = 0; i < path->length; i++) fputc(path->text[i],stderr); +} + +static unsigned long +hashpjw(Gstr s,unsigned short leng) +{ +char *p; +unsigned long h = 0, g; +unsigned short i; + + for (i = 1; i < leng; i++) { + h = (h << 4) + (toupper(s->text[i])); + if (g = h & 0xF0000000) { + h ^= (g >> 24); + h ^= g; + } + } + return h % PRIME; +} + +void init_htable(void) +{ +FILE *np; +Gstr p,map; +unsigned short hent; +unsigned short i; +short x; +char *line,*pt,*pt1; + + for (i = 0; i < NUM_NP; i++) { + h_pool[i].pfx = NULL; + h_pool[i].exp_pfx = NULL; + } + line = malloc(128l); + np = fopen("9/etc/namespace","r"); + if (np != NULL) { + while (!feof(np)) { + if (pool_ind == NUM_NP) { + printf("warning: more than 20 entries in the /etc/namespace file\n"); + break; + } + p = malloc(19); + map = malloc(67); + fgets(line,127,np); + if ((line[0] == 0) || (line[0] == '\n')) continue; + pt = line; + /* find end of first string */ + while ((*pt != 0) && (!isspace(*pt))) pt++; + if (*pt == 0) PANIC("invalid namespace specifier"); + /* find start of second string */ + *pt++ = 0; + while ((*pt != 0) && (isspace(*pt))) pt++; + if (*pt == 0) PANIC("invalid namespace specifier"); + pt1 = pt; + /* find end of second string */ + while ((*pt != 0) && (!isspace(*pt))) pt++; + *pt = 0; + + strcpy(p->text,line); + strcpy(map->text,pt1); + p->length = strlen(p->text); + map->length = strlen(map->text); + + hent = (unsigned short) hashpjw(p,p->length); + h_pool[pool_ind].next = h_table[hent]; + h_table[hent] = &h_pool[pool_ind]; + h_pool[pool_ind].pfx = p; + h_pool[pool_ind].exp_pfx = map; + /* printf("prefix: "); + printGS(p); + printf(" location: %d pool: %d\n",hent,pool_ind); */ + pool_ind++; + } + fclose(np); + } else printf("warning: could not locate :etc:namespace\n"); + free(line); +} + +#undef TOLOWER +#define TOLOWER(c) isupper(c) ? _tolower(c) : c + +int +strincmp (const char *s1, const char *s2, size_t n) +{ + unsigned int c1, c2; + size_t i; + + for (i=0; i c2) ? 1 : -1; + } + } + return 0; +} + +/* needs a fully expanded GS string */ +Gstr match(Gstr fname, unsigned short leng, char sep) +{ +unsigned short i,hent; +struct h *l; + + i = 1; + while ((i < leng) && (fname->text[i] != sep)) i++; + hent = (unsigned short) hashpjw(fname,i); + l = h_table[hent]; + while (l != NULL) { + /* make sure vol. name is same length as hashed entry */ + if ((l->pfx->length == i) + && (!strincmp(fname->text+1,l->pfx->text+1,i-1))) break; + l = l->next; + } + if (l == NULL) return NULL; + else return l->exp_pfx; +} + +unsigned short isSeparator(char c) +{ + if ((c == ':') || (c == '/')) return 1; + else return 0; +} + +void push(Gstr x, unsigned short y, char sep) +{ + the_stack[stack_ind].name = x; + the_stack[stack_ind].ind = y; + the_stack[stack_ind].sep = sep; + stack_ind++; +} + +stackPtr top(void) +{ + if (!stack_ind) return NULL; + else return &the_stack[stack_ind-1]; +} + +stackPtr pop(void) +{ + if (!stack_ind) return NULL; + else return &the_stack[--stack_ind]; +} + +void clearstack(void) +{ + stack_ind = 0; +} + +ResultBuf32 rbuf; +Gstr go = NULL; +static word nullGSOS = 0; + +#pragma databank 1 +Gstr gno_ExpandPath(Gstr i_path, int num, word npFlag) +{ +unsigned short i,j,pfxNum,oldlen,outind,outind2; +Gstr g_out,g1; +char SEP,nSEP; +Gstr g; +stackPtr sp; +extern int OldGSOSSt(word callnum, void *pBlock); + + if (go == NULL) go = malloc(1024l); + + if (i_path->length > 1024) return (Gstr) 0xFFFF0040l; + g_out = go; + rbuf.bufSize = 32; + ep.pCount = 3; + ep.flags = 0; + +/* Separator conversion and determination */ + i = 0; + while ((i < i_path->length) && !isSeparator(i_path->text[i])) i++; + if (i == i_path->length) SEP = ':'; + else SEP = i_path->text[i]; /* grab the separator character */ + + push(i_path,0,SEP); /* use this separator here */ + + if (!isSeparator(i_path->text[0])) { + + /* Scan for first component */ + i = 0; + while ((i < i_path->length) && (i_path->text[i] != SEP)) i++; + + /* Check for * prefix */ + if ( ((i == 1) && (i_path->text[0] == '*')) || + /* Check for device prefix */ + ((i > 1) && (i_path->text[0] == '.') && (i_path->text[1] != '.')) ) + { + /* Expand the prefix with old expandpath (source is input string + * with length temporarily set to trick ExpandPath). + * Add to copy stack, fix length. + */ + + oldlen = i_path->length; + i_path->length = i; + ep.inputPath = (Gstr) i_path; + ep.outputPath = (ResultBuf255Ptr) &rbuf; + err = OldGSOSSt(0x200e,&ep); + /* ExpandPathGS(&ep); */ + i_path->length = oldlen; + if (rbuf.bufString.text[0] == '.') { + clearstack(); + g_out = (Gstr) &rbuf.bufString; + goto goaway; + } + push((Gstr) &rbuf.bufString,i,':'); + goto phase2; + } + /* Check for @ prefix, add to copy stack if present */ + else if ((i == 1) && (i_path->text[0] == '@')) { + push((Gstr) PROC->prefix[0],i,':'); + goto phase2; + } + /* Check for numeric prefix */ + else if (isdigit(i_path->text[0])) { + /* Do a GetPrefix call on the parsed prefix number + * add to copy stack + */ + + j = 0; pfxNum = 0; + while ((j < i) && (isdigit(i_path->text[j]))) { + pfxNum = (pfxNum * 10) + (i_path->text[j] - '0'); + j++; + } + if (j == i) { + if (pfxNum > 31) { + clearstack(); + return (Gstr) 0xFFFF0040l; /* syntax error */ + } + g = (Gstr) PROC->prefix[pfxNum+1]; + if (g == NULL) push((Gstr) &nullGSOS,i,':'); + else push(g,i,':'); + goto phase2; + } /* if j != i, there was a non-numeral in the prefix number, + so fall through to concat prefix 0 onto it */ + } + /* else expand by prefix 0 (adding the pfx 0 ptr directly to the stack) */ + g = (Gstr) PROC->prefix[num+1]; + if (g == NULL) push((Gstr) &nullGSOS,0,':'); + else push(g,0,':'); + } + +phase2: + /* Check for named prefix */ + + if (!npFlag) { + g = top()->name; + /* SEP = top()->sep; */ + i = 1; + while ((i < g->length) && (g->text[i] != top()->sep)) i++; + /* If there's a match, add the result string to the top of the stack */ + if (i > 1) + if (g1 = match(g,i,SEP)) + push(g1,i,':'); + } + +/* Start at the top of the stack + scan each path component, checking for '.' or '..' removing bits + as appropriate + copy each component into the output buffer + at the end of the string, pop the stack + if the stack is empty, we're done, so return */ + + nSEP = ':'; + outind = i = 0; + while (sp = pop()) { + g = sp->name; + /* nSEP = sp->sep;*/ + if (top() == NULL) nSEP = SEP; + oldlen = g->length; + if (g->text[oldlen-1] == nSEP) oldlen--; + + while (i < oldlen) { + g_out->text[outind++] = ':'; + if (g->text[i] == nSEP) i++; + j = i; /* beginning of segment */ + + /* locate end of segment */ + while ((i < oldlen) && (g->text[i] != nSEP)) i++; + if ((i-j == 1) && (g->text[j] == '.')) outind--; + else if ((i-j == 2) && (g->text[j] == '.') && (g->text[j+1] == '.')) { + outind2 = outind-2; + while ((outind2 > 0) && (g_out->text[outind2] != ':')) outind2--; + if (outind2 != 0) outind = outind2; /* move outind back */ + else outind--; /* just zap the colon */ + } + else + while (j < i) g_out->text[outind++] = g->text[j++]; + } + i = sp->ind; + } + g_out->length = outind; +goaway: + if (kp->gsosDebug & 2) { + fprintf(stderr,"EP["); + printGS(g_out); fprintf(stderr,"]\n"); + } + if ((g_out->length == 1) && (g_out->text[0] == ':')) g_out->length = 0; + return g_out; +} + +GSString255 p_buf; +Gstr p16_ExpandPath(P16StringPtr path, int num, word npFlag) +{ + p_buf.length = path->length; + memcpy(p_buf.text, path->text, (longword) p_buf.length); + return gno_ExpandPath((Gstr) &p_buf,num,npFlag); +} + +#pragma databank 0 + +#ifndef KERNEL +char in[80]; + +int main(int argc, char *argv[]) +{ +unsigned l; +Gstr g,g1; + + init_htable(); + + while (1) { + gets(in); + l = strlen(in); + g = malloc(l+2); + memcpy(g->text,in,l); + g->length = l; + g1 = GNO_EXPANDPATH(g,0); + printGS(g1); + printf("\n"); + free(g); + } +} +#endif + diff --git a/kern/gno/err.asm b/kern/gno/err.asm new file mode 100644 index 0000000..b8cb5bb --- /dev/null +++ b/kern/gno/err.asm @@ -0,0 +1,298 @@ +* $Id: err.asm,v 1.1 1998/02/02 08:19:20 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* ERR.ASM +* By Tim Meekins +* +* Displays error messages for +* GS/OS +* Loader +* Memory Manager +* Resource manager +* GNO ($FFxx) +* +************************************************************************** + + mcopy m/err.mac + case on + +printError START KERN2 + + proc + + sta err + cmp #0 + bne gooderr + procendL + +gooderr anop + Int2Hex (err,#str1+1,#4) + ErrWriteCString #str1 + + ldx #0 +findtoolloop lda tooltbl+2,x + bmi foundtool + lda err + and #$FF00 + cmp tooltbl,x + beq foundtool + add2 @x,#8,@x + bra findtoolloop + +foundtool lda tooltbl+6,x + tay + lda tooltbl+4,x + ErrWriteString @ya + + ldx #0 +finderrloop lda errtbl,x + cmp #$FFFF + beq founderr + cmp err + beq founderr + add2 @x,#6,@x + bra finderrloop + +founderr lda errtbl+4,x + tay + lda errtbl+2,x + ErrWriteLine @ya + + procendL + +err ds 2 +str1 dc c'$0000 ',h'00' + +tooltbl dc i4'$0000',a4'tstr1' + dc i4'$0200',a4'tstr3' + dc i4'$1100',a4'tstr2' + dc i4'$1E00',a4'tstr4' + dc i4'$FF00',a4'tstr5' + dc i4'-1',a4'tstr0' + +errtbl dc i'$0001',a4'err0001' + dc i'$0004',a4'err0004' + dc i'$0005',a4'err0005' + dc i'$0006',a4'err0006' + dc i'$0007',a4'err0007' + dc i'$0010',a4'err0010' + dc i'$0011',a4'err0011' + dc i'$001F',a4'err001F' + dc i'$0020',a4'err0020' + dc i'$0021',a4'err0021' + dc i'$0022',a4'err0022' + dc i'$0023',a4'err0023' + dc i'$0024',a4'err0024' + dc i'$0025',a4'err0025' + dc i'$0026',a4'err0026' + dc i'$0027',a4'err0027' + dc i'$0028',a4'err0028' + dc i'$0029',a4'err0029' + dc i'$002B',a4'err002B' + dc i'$002C',a4'err002C' + dc i'$002D',a4'err002D' + dc i'$002E',a4'err002E' + dc i'$002F',a4'err002F' + dc i'$0040',a4'err0040' + dc i'$0042',a4'err0042' + dc i'$0043',a4'err0043' + dc i'$0044',a4'err0044' + dc i'$0045',a4'err0045' + dc i'$0046',a4'err0046' + dc i'$0047',a4'err0047' + dc i'$0048',a4'err0048' + dc i'$0049',a4'err0049' + dc i'$004A',a4'err004A' + dc i'$004B',a4'err004B' + dc i'$004C',a4'err004C' + dc i'$004D',a4'err004D' + dc i'$004E',a4'err004E' + dc i'$004F',a4'err004F' + dc i'$0050',a4'err0050' + dc i'$0051',a4'err0051' + dc i'$0052',a4'err0052' + dc i'$0053',a4'err0053' + dc i'$0054',a4'err0054' + dc i'$0055',a4'err0055' + dc i'$0056',a4'err0056' + dc i'$0057',a4'err0057' + dc i'$0058',a4'err0058' + dc i'$0059',a4'err0059' + dc i'$005A',a4'err005A' + dc i'$005B',a4'err005B' + dc i'$005C',a4'err005C' + dc i'$005D',a4'err005D' + dc i'$005E',a4'err005E' + dc i'$005F',a4'err005F' + dc i'$0060',a4'err0060' + dc i'$0061',a4'err0061' + dc i'$0062',a4'err0062' + dc i'$0063',a4'err0063' + dc i'$0064',a4'err0064' + dc i'$0065',a4'err0065' + dc i'$0067',a4'err0067' + dc i'$0069',a4'err0069' + dc i'$0070',a4'err0070' + dc i'$0071',a4'err0071' + dc i'$0201',a4'err0201' + dc i'$0202',a4'err0202' + dc i'$0203',a4'err0203' + dc i'$0204',a4'err0204' + dc i'$0205',a4'err0205' + dc i'$0206',a4'err0206' + dc i'$0207',a4'err0207' + dc i'$0208',a4'err0208' + dc i'$1101',a4'err1101' + dc i'$1102',a4'err1102' + dc i'$1103',a4'err1103' + dc i'$1104',a4'err1104' + dc i'$1105',a4'err1105' + dc i'$1107',a4'err1107' + dc i'$1108',a4'err1108' + dc i'$1109',a4'err1109' + dc i'$110A',a4'err110A' + dc i'$110B',a4'err110B' + dc i'$1E01',a4'err1E01' + dc i'$1E02',a4'err1E02' + dc i'$1E03',a4'err1E03' + dc i'$1E04',a4'err1E04' + dc i'$1E05',a4'err1E05' + dc i'$1E06',a4'err1E06' + dc i'$1E07',a4'err1E07' + dc i'$1E08',a4'err1E08' + dc i'$1E09',a4'err1E09' + dc i'$1E0A',a4'err1E0A' + dc i'$1E0B',a4'err1E0B' + dc i'$1E0C',a4'err1E0C' + dc i'$1E0D',a4'err1E0D' + dc i'$1E0E',a4'err1E0E' + dc i'$FF00',a4'errFF00' + dc i'$FF02',a4'errFF02' + dc i'$FF03',a4'errFF03' + dc i'$FF04',a4'errFF04' + dc i'$FF05',a4'errFF05' + dc i'$FF06',a4'errFF06' + dc i'$FFFF',a4'errFFFF' + +tstr0 str 'Unknown ' +tstr1 str 'GS/OS: ' +tstr2 str 'Loader: ' +tstr3 str 'Memory Manager: ' +tstr4 str 'Resource: ' +tstr5 str 'GNO: ' + +err0001 str 'Bad GS/OS call number' +err0004 str 'Parameter count out of range' +err0005 str 'Parameter pointer out of range' +err0006 str 'Communication error in IWM' +err0007 str 'GS/OS is busy' +err0010 str 'Device wasn''t found' +err0011 str 'Invalid device number requested' +err001F str 'Interrupt devices are not supported' +err0020 str 'Invalid request' +err0021 str 'Invalid control or status code' +err0022 str 'Bad call parameter' +err0023 str 'Character device not open' +err0024 str 'Character device already open' +err0025 str 'Interrupt table full' +err0026 str 'Resources not available' +err0027 str 'Disk I/O error' +err0028 str 'No device connected' +err0029 str 'Driver is busy' +err002B str 'Device is write-protected' +err002C str 'Invalid byte count' +err002D str 'Invalid block address' +err002E str 'Disk has been switched' +err002F str 'Device off line or no media present' +err0040 str 'Invalid pathname syntax' +err0042 str 'Too many files open' +err0043 str 'Invalid reference number' +err0044 str 'Subdirectory does not exist' +err0045 str 'Volume not found' +err0046 str 'File not found' +err0047 str 'Create or rename with existing name' +err0048 str 'Volume full' +err0049 str 'Volume directory full' +err004A str 'Version error (Incompatible file format)' +err004B str 'Unsupported storage type' +err004C str 'End of file encountered' +err004D str 'Position out of range' +err004E str 'Access not allowed' +err004F str 'Buffer too small' +err0050 str 'File is already open' +err0051 str 'Directory error' +err0052 str 'Unknown volume type' +err0053 str 'Parameter out of range' +err0054 str 'Out of memory' +err0055 str 'Block table full' +err0056 str 'Invalid buffer' +err0057 str 'Duplicate volume name' +err0058 str 'Not a block device' +err0059 str 'Level specified outside of legal range' +err005A str 'Block number too large' +err005B str 'Invalid path names for ChangePath' +err005C str 'Not an executable' +err005D str 'Operating system not supported' +err005E str '/RAM cannot be removed' +err005F str 'Too many applications on stack' +err0060 str 'Data unavailable' +err0061 str 'End of directory has been reached' +err0062 str 'Invalid FST call class' +err0063 str 'File does not contain required resource' +err0064 str 'FST ID is invalid' +err0065 str 'Invalid FST operation' +err0067 str 'Device exists with same name as replacement name' +err0069 str 'I/O terminated due to NewLine' +err0070 str 'Cannot expand device, resource fork already exists' +err0071 str 'Cannot add resource fork to this type of file' +err0201 str 'Unable to allocate block' +err0202 str 'Illegal operation on an empty handle' +err0203 str 'Empty handle expected for this operation' +err0204 str 'Illegal operation on a locked or immovable block' +err0205 str 'Attempt to purge an unpurgable block' +err0206 str 'Invalid handle' +err0207 str 'Invalid user ID' +err0208 str 'Illegal operation with specified attributes' +err1101 str 'Entry not found' +err1102 str 'OMF version error' +err1103 str 'Pathname error' +err1104 str 'File not in load file' +err1105 str 'Loader is busy' +err1107 str 'File version error' +err1108 str 'User ID error' +err1109 str 'Segment number out of sequence' +err110A str 'Illegal load record found' +err110B str 'Load segment is foreign' +err1E01 str 'Resource fork not empty' +err1E02 str 'Resource fork not correctly formatted' +err1E03 str 'No converter routine for resource type' +err1E04 str 'No current resource file' +err1E05 str 'Specified resource ID is already in use' +err1E06 str 'Specified resource not found' +err1E07 str 'Specified ID does not match an open file' +err1E08 str 'User ID not found' +err1E09 str 'No more resource IDs available' +err1E0A str 'Index is out of range' +err1E0B str 'System file is already open' +err1E0C str 'Resource has been changed' +err1E0D str 'Another converted already logged in' +err1E0E str 'Volume full' +errFF00 str 'Too many arguments' +errFF02 str 'Extra < encountered' +errFF03 str 'Illegal < syntax' +errFF04 str 'Extra > encountered' +errFF05 str 'Illegal > syntax' +errFF06 str '> and | conflict' + +errFFFF str 'error' + + END diff --git a/kern/gno/fastfile.c b/kern/gno/fastfile.c new file mode 100644 index 0000000..c24428a --- /dev/null +++ b/kern/gno/fastfile.c @@ -0,0 +1,715 @@ +/* $Id: fastfile.c,v 1.1 1998/02/02 08:18:27 taubert Exp $ */ + +/* + + fastfile.c + + C routines to duplicate the Orca Shell fastfile system + + I wouldn't do this except the Orca compilers require FastFile. + +*/ +#pragma optimize 72 + +#include "proc.h" +#include "sys.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include "/lang/orca/libraries/orcacdefs/stddef.h" +#include +#include +#include +#include +#include +#include + +typedef struct { + int action; + int index; + int flags; + handle fileHandle; + GSString255Ptr pathName; + int access; + int fileType; + long auxType; + int storageType; + TimeRec createDate; + TimeRec modDate; + void *option; + long fileLength; + long blocksUsed; +} my_FastFileGSPB; + +#pragma lint -1 + +void printGS(GSString255Ptr path); + +/*#define DEBUG*/ +#ifdef DEBUG +#define PRINT(arg) fprintf(stderr,arg) +#else +#define PRINT(arg) +#endif + +segment "KERN3 "; +extern void gnoSetHandleID(word, handle); + +struct ffentry { + int action; + int index; + int flags; + handle fileHandle; + GSString255Ptr pathnameGS; + char *pathnameP; + FileInfoRecGS info; + int hidden; + struct ffentry *next; +}; +typedef struct ffentry ffentry, *ffentryPtr; + +/*extern int OLDGSOSST(word callnum, void *pBlock); */ + +ffentryPtr ffList = NULL; +unsigned InFastFile = 0; + +int pstrlen(char *p) +{ return p[0]; } + +extern void copygs2res(void *,void*); + +void p2gs(char *src, GSString255Ptr gs) +{ + gs->length = pstrlen(src); + memcpy(gs->text,src+1,gs->length); +} + +ffentryPtr NewFF(GSString255Ptr pathnameGS) +{ +GSString255Ptr pathGS; +char *path; +ffentryPtr newEntry; +int tmp; + + path = malloc((size_t) (pathnameGS->length+1)); + path[0] = pathnameGS->length; + memcpy(path+1,pathnameGS->text,(size_t) path[0]); + /* perhaps we should change the seps AFTER we copy the contents of + the string */ + for (tmp = 1; tmp <= path[0]; tmp++) + if (path[tmp] == ':') path[tmp] = '/'; + pathGS = malloc((size_t) (pathnameGS->length+2)); + pathGS->length = pathnameGS->length; + memcpy(pathGS->text,pathnameGS->text,pathGS->length); + newEntry = malloc(sizeof(ffentry)); + +/* link into the list */ + newEntry->next = ffList; + ffList = newEntry; + + newEntry->pathnameP = path; + newEntry->pathnameGS = pathGS; + newEntry->fileHandle = NULL; + newEntry->hidden = 0; + return newEntry; +} + +#pragma databank 1 +void DeleteFF(ffentryPtr p) +{ +ffentryPtr prev; + + prev = ffList; + if (prev != p) + while (prev != NULL) { + if (prev->next == p) break; + prev = prev->next; + } + if (prev == NULL) { fprintf(stderr,"entry not found in DeleteFF\n"); + return; } + if (p->pathnameGS != NULL) nfree(p->pathnameGS); + if (p->pathnameP != NULL) nfree(p->pathnameP); + if (p->fileHandle != NULL) { + HUnlock(p->fileHandle); + DisposeHandle(p->fileHandle); + } + if (prev == p) { ffList = prev->next; } + else { prev->next = p->next; } + nfree(p); +} + +ffentryPtr FindIndFF(int index) +{ +ffentryPtr p; +int step = 0; + + p = ffList; + while (p != NULL) { + if (step == index) break; + step++; + p = p->next; + } + return p; +} + +ffentryPtr FindFF(GSString255Ptr path) +{ +ffentryPtr p; +extern int GScaseEqual(void*,void*); + + p = ffList; + while (p != NULL) { + if (GScaseEqual(path,p->pathnameGS) && (!p->hidden) ) break; + p = p->next; + } + return p; +} +#pragma databank 0 + +FileInfoRecGS fi; +CreateRecGS cr; +NameRecGS ds; +OpenRecGS op; +IORecGS re; +ExpandPathRecGS pcep; +int cl[2]; + +int upToDate(ffentryPtr p) +{ +FileInfoRecGS f; +word dateBuf[8]; + + if (p->flags & 0x8000) { + f.pCount = 7; + f.pathname = p->pathnameGS; + GetFileInfoGS(&f); + if (toolerror()) printf("GetFileInfo err %04X\n",toolerror()); + if (memcmp(&f.modDateTime,&p->info.modDateTime,sizeof(TimeRec))) + return 0; +/* memcpy(dateBuf,&f.modDateTime,sizeof(TimeRec)); + ConvSeconds(9,0l,(Pointer)dateBuf); + if ((dateBuf[0] != p->info.mod_date) || + (dateBuf[1] != p->info.mod_time)) return 0; */ +/* memcpy(dateBuf,&f.createDateTime,sizeof(TimeRec)); + ConvSeconds(9,0l,(Pointer)dateBuf); + if ((dateBuf[0] != p->info.create_date) || + (dateBuf[1] != p->info.create_time)) return 0; */ + } + return 1; +} + +void ffErr(int err) +{ +/* fprintf(stderr,"FastFile error: %04X\n",err); */ +} + +handle loadFile(GSString255Ptr pathGS, ffentryPtr p) +{ +handle fileHandle; +word dateBuf[8]; +char asciiBuf[30]; +longword secs; +int err; + + p->hidden = 1; + op.pCount = 13; + op.pathname = pathGS; + op.requestAccess = readEnable; + op.resourceNumber = 0; + op.optionList = NULL; + /* err = OLDGSOSST(0x2010,&op); */ + /* if (err) { ffErr(err); return NULL; } */ + OpenGS(&op); /* to prevent conflict with Open-remove code */ + if (_toolErr) { ffErr(_toolErr); p->hidden = 0; return NULL; } + fileHandle = NewHandle(op.eof,userid() | 0x0100, 0x8000, NULL); + if (fileHandle == NULL) { p->hidden = 0; ffErr(toolerror()); return NULL; } + re.pCount = 4; + re.refNum = op.refNum; + re.dataBuffer = *fileHandle; + re.requestCount = op.eof; + /*err = OLDGSOSST(0x2012,&re);*/ + ReadGS(&re); + if (err) { ffErr(err); } + cl[0] = 1; + cl[1] = op.refNum; + CloseGS(cl); + /*err = OLDGSOSST(0x2014,cl);*/ + p->fileHandle = fileHandle; + p->info.eof = op.eof; + p->info.blocksUsed = op.blocksUsed; + p->info.resourceEOF = op.resourceEOF; + p->info.resourceBlocks = op.resourceBlocks; + p->info.access = op.access; + p->info.fileType = op.fileType; + p->info.auxType = op.auxType; + p->info.storageType = op.storageType; + memcpy(&p->info.createDateTime,&op.createDateTime,sizeof(TimeRec)); + memcpy(&p->info.modDateTime,&op.modDateTime,sizeof(TimeRec)); + +/* memcpy(dateBuf,&op.createDateTime,sizeof(TimeRec)); + ConvSeconds(9,0l,(Pointer)dateBuf); + p->info.create_date = dateBuf[0]; + p->info.create_time = dateBuf[1]; + memcpy(dateBuf,&op.modDateTime,sizeof(TimeRec)); + ConvSeconds(9,0l,(Pointer)dateBuf); + p->info.mod_date = dateBuf[0]; + p->info.mod_time = dateBuf[1]; + + p->info.blocks_used = op.blocksUsed; */ + p->hidden = 0; + return fileHandle; +} + +/* + the entry point for all fastFile routines. The assembly code just + calls fastEntry with the address of the paramBlock (real one, not the + copy) + + osFlag = 0 for P16, 1 for GS/OS strings + ff must point to the first parameter, not the pCount in the new scheme + osFlag will always be 0 for now. I won't guess at what the Orca 2.0 + call format's going to be. +*/ + +#pragma databank 1 +int fastEntry(FastFilePB *ff, int osFlag, int pCount) +{ +my_FastFileGSPB *fg = (my_FastFileGSPB *) ff; +ffentryPtr p; +handle fileHandle,tmpHandle; +GSString255Ptr pathCopy; +ResultBuf255Ptr epRes; +int tmp,err; +char *tmps; +int dateBuf[4]; +extern void printGS(GSString255Ptr path); + + err = 0; +/* all calls but Indexed Load take path as input, so condition it */ + InFastFile = 1; + if (ff->action != 1) { + if (!osFlag) { + pathCopy = malloc(pstrlen(ff->pathname)+2); + p2gs(ff->pathname,pathCopy); + pcep.inputPath = pathCopy; + } else pcep.inputPath = fg->pathName; + + epRes = malloc(sizeof(ResultBuf255)); + epRes->bufSize = 255; + pcep.outputPath = epRes; + pcep.pCount = 3; + pcep.flags = (!osFlag) ? 0x8000 : 0; + ExpandPathGS(&pcep); + if (!osFlag) nfree(pathCopy); + pathCopy = &epRes->bufString; + /* for (tmp = 0; tmp < pathCopy->length; tmp++) + if (pathCopy->text[tmp] == ':') pathCopy->text[tmp] = '/'; */ + } + switch (ff->action) { + case 0: /* Load */ + case 2: /* Load from Memory */ +#ifdef DEBUG + if (ff->action == 0) printf("Load "); else printf("Load Memory "); + printGS(pathCopy); printf("\n"); +#endif + p = FindFF(pathCopy); /* find matching entry */ + if (p == NULL) { + if (ff->action == 2) { err = 0x46; break; } /* file not found */ + else p = NewFF(pathCopy); /* make a new entry */ + } + + if ((p->fileHandle != NULL) && /* handle allocated? */ + (*p->fileHandle != NULL) && /* handle purged? */ + (upToDate(p))) /* memory copy up to date? */ + { +#ifdef DEBUG +printGS(p->pathnameGS); +printf(" up to date\n"); +#endif + HLock(p->fileHandle); + /*if (!osFlag) ff->pathname = p->pathnameP;*/ + goto setpath; /* set the pathname */ + break; + } + /* handle was purged or image was not up to date. We dispose + here and loadFile will allocate a new one */ + if (p->fileHandle != NULL) DisposeHandle(p->fileHandle); + + fileHandle = loadFile(pathCopy,p); + if (fileHandle == NULL) { + err = toolerror(); + DeleteFF(p); + } + else p->flags = ff->flags; +setpath: if (!osFlag) + ff->pathname = p->pathnameP; + + /* printf("Load(Mem): flags:%04X\n",p->flags);*/ + break; + +/* Mike is totally off his rocker. FastFile $01 returns a pointer to a + resultBuffer. Hopefully the new version uses a GS/OS resultBuf. */ + + case 1: /* Indexed Load */ + PRINT(" ",ff->index); +#endif +retryil: + p = FindIndFF(ff->index); /* find matching entry */ + if (p == NULL) { err = 0x46; break; } + if ((*p->fileHandle != NULL)) { /*&& /* handle purged? */ + /* (upToDate(p))) { */ /* memory copy up to date? */ + if (!osFlag) + ff->pathname = p->pathnameP; + else { copygs2res(fg->pathName,p->pathnameGS); } + HLock(p->fileHandle); + ff->flags = p->flags; + break; + /* Mike copies it to a result buffer, but that's not safe in + a concurrent environment. This will do, as everyone assumes + you can't write to the pathname field */ + } + /* handle was purged or image was not up to date. We dispose + here and loadFile will allocate a new one */ + DisposeHandle(p->fileHandle); + /* if the file was not on disk, do not attempt to load it! + remove it from the FF system and retry the Indexed_Load call */ + /* if (!(p->flags & 0x8000)) { */ + DeleteFF(p); + goto retryil; + /* } */ + fileHandle = loadFile(p->pathnameGS,p); + if (fileHandle == NULL) { InFastFile = 0; return toolerror(); } + ff->flags = p->flags; + if (!osFlag) + ff->pathname = p->pathnameP; + else { copygs2res(fg->pathName,p->pathnameGS); } + break; + + case 3: /* Save */ + PRINT("Save:"); +#ifdef DEBUG + printGS(pathCopy); printf("\n"); +#endif + p = FindFF(pathCopy); + if (p != NULL) { + PRINT("save:file existed\n"); + if (ff->file_handle == p->fileHandle) + p->fileHandle = NULL; /* don't kill the block */ + DeleteFF(p); + } + p = NewFF(pathCopy); /* create a new entry */ + p->flags = ff->flags; + p->fileHandle = ff->file_handle; + p->info.eof = (osFlag ? fg->fileLength : ff->file_length); + cr.access = p->info.access = (osFlag ? fg->access : ff->access); + cr.fileType = p->info.fileType = + (osFlag ? fg->fileType : ff->file_type); + cr.auxType = p->info.auxType = + (osFlag ? fg->auxType : ff->aux_type); + + if (!osFlag) { + dateBuf[0] = ff->create_date; + dateBuf[1] = ff->create_time; + ConvSeconds(8,0l,(Pointer)dateBuf); + memcpy(&p->info.createDateTime,dateBuf,sizeof(TimeRec)); + dateBuf[0] = ff->mod_date; + dateBuf[1] = ff->mod_time; + ConvSeconds(8,0l,(Pointer)dateBuf); + memcpy(&p->info.modDateTime,dateBuf,sizeof(TimeRec)); + } else { + memcpy(&p->info.modDateTime,&fg->modDate,sizeof(TimeRec)); + memcpy(&p->info.createDateTime,&fg->createDate,sizeof(TimeRec)); + } + cr.pCount = 4; + cr.pathname = p->pathnameGS; +doCreate: + CreateGS(&cr); + if (toolerror()) { err = toolerror(); + if (err != 0x47) { DeleteFF(p); break; } + err = 0; + ds.pCount = 1; + ds.pathname = pathCopy; + p->hidden = 1; + DestroyGS(&ds); + p->hidden = 0; + if (!_toolErr) goto doCreate; + /*err = OLDGSOSST(0x2002,&ds);*/ + /*if (!err) goto doCreate;*/ + err = _toolErr; DeleteFF(p); break; + } + op.pCount = 2; + op.pathname = p->pathnameGS; + p->hidden = 1; + OpenGS(&op); + if (_toolErr) { err = _toolErr; DeleteFF(p); p->hidden = 0; break; } + /*err = OLDGSOSST(0x2010,&op); + if (err) { DeleteFF(p); p->hidden = 0; break; } */ + re.pCount = 4; + re.refNum = op.refNum; + re.dataBuffer = *p->fileHandle; + re.requestCount = p->info.eof; + /*err = OLDGSOSST(0x2013,&re);*/ + WriteGS(&re); + cl[0] = 1; cl[1] = op.refNum; + CloseGS(cl); + /*OLDGSOSST(0x2014,cl);*/ + p->hidden = 0; + fi.pCount = 10; + fi.optionList = NULL; + fi.pathname = p->pathnameGS; + GetFileInfoGS(&fi); + p->info.blocksUsed = fi.blocksUsed; + /* tmpHandle = NewHandle(GetHandleSize(p->fileHandle), + userid() | 0x0100, 0x8000, NULL); + HandToHand(p->fileHandle,tmpHandle, + GetHandleSize(p->fileHandle)); */ + /*p->fileHandle = tmpHandle;*/ + gnoSetHandleID(userid(),p->fileHandle); + err = 0; break; + + case 4: /* Add */ + PRINT("Add "); +#ifdef DEBUG + printGS(pathCopy); printf("\n"); +#endif + p = FindFF(pathCopy); /* is there already one? */ + if (p != NULL) + DisposeHandle(p->fileHandle); + else p = NewFF(pathCopy); + if (!osFlag) { + p->info.access = ff->access; + p->info.fileType = ff->file_type; + p->info.auxType = ff->aux_type; + p->info.storageType = ff->storage; + dateBuf[0] = ff->create_date; + dateBuf[1] = ff->create_time; + ConvSeconds(8,0l,(Pointer)dateBuf); + memcpy(&p->info.createDateTime,dateBuf,sizeof(TimeRec)); + dateBuf[0] = ff->mod_date; + dateBuf[1] = ff->mod_time; + ConvSeconds(8,0l,(Pointer)dateBuf); + memcpy(&p->info.modDateTime,dateBuf,sizeof(TimeRec)); + p->info.blocksUsed = ff->blocks_used; + p->info.eof = ff->file_length; + } else { + memcpy(&p->info.access,&fg->access,36l); + } + p->flags = ff->flags; + p->fileHandle = NewHandle(GetHandleSize(fg->fileHandle), + userid() | 0x0100, 0x8000, NULL); + HandToHand(fg->fileHandle,p->fileHandle, + GetHandleSize(fg->fileHandle)); + + /* printf("Add: flags: %04X,handle:$%06lX\n",p->flags, + p->fileHandle); */ + if (p->flags & 0x4000) + SetPurge(2,p->fileHandle); + else SetPurge(0,p->fileHandle); + break; + + case 5: + case 6: +#ifdef DEBUG + if (ff->action == 5) printf("Delete ");else printf("Remove "); + printGS(pathCopy); printf("\n"); +#endif + p = FindFF(pathCopy); /* find the file */ + if (p == NULL) { err = 0x46; break; } + if (ff->action == 6) p->fileHandle = NULL; + DeleteFF(p); + break; + + case 7: /* Purge */ + PRINT(" "); +#endif + p = FindFF(pathCopy); /* find matching entry */ + if (p == NULL) { err = 0x46; break; } /* file not found */ + if (p->flags & 0x4000) { + SetPurge(2,p->fileHandle); + HUnlock(p->fileHandle); + } + break; + } + if (ff->action != 1) nfree(epRes); + if (!err) + switch (ff->action) { + case 0: /* argh! why'd Mike stick Pathname in the middle of the */ + case 1: /* return values instead of the beginning? */ + case 2: + if (!osFlag) { + ff->file_handle = p->fileHandle; + ff->file_length = p->info.eof; + ff->access = p->info.access; + ff->file_type = p->info.fileType; + ff->aux_type = p->info.auxType; + ff->storage = p->info.storageType; + + memcpy(dateBuf,&p->info.createDateTime,sizeof(TimeRec)); + ConvSeconds(9,0l,(Pointer)dateBuf); + ff->create_date = dateBuf[0]; + ff->create_time = dateBuf[1]; + memcpy(dateBuf,&p->info.modDateTime,sizeof(TimeRec)); + ConvSeconds(9,0l,(Pointer)dateBuf); + ff->mod_date = dateBuf[0]; + ff->mod_time = dateBuf[1]; + +/* ff->create_date = p->info.createDate; + ff->create_time = p->info.createTime; + ff->mod_date = p->info.modDate; + ff->mod_time = p->info.modTime; */ + ff->blocks_used = p->info.blocksUsed; + if (ff->action == 1) ff->flags = p->flags; + } + else switch (pCount) { + case 14: fg->blocksUsed = p->info.blocksUsed; + case 13: fg->fileLength = p->info.eof; + case 12: fg->option = p->info.optionList; + case 11: memcpy(&fg->modDate,&p->info.modDateTime,sizeof(TimeRec)); + case 10: memcpy(&fg->createDate,&p->info.createDateTime, + sizeof(TimeRec)); + case 9: fg->storageType = p->info.storageType; + case 8: fg->auxType = p->info.auxType; + case 7: fg->fileType = p->info.fileType; + case 6: fg->access = p->info.access; + default: fg->fileHandle = p->fileHandle; + if (ff->action == 1) fg->flags = p->flags; + } + } +/* if (err) printf("[err:%04X] ",err); */ + InFastFile = 0; + return err; +} + +extern kernelStructPtr kp; + +typedef struct { + char *sFile; + char *dFile; + char *parms; + char *iString; + byte merr; + byte merrf; + byte lops; + byte kflag; + unsigned long mFlags; + unsigned long pFlags; + unsigned long org; +} oLInfoPB; + +typedef struct { + GSString255Ptr sFile; + GSString255Ptr dFile; + GSString255Ptr parms; + GSString255Ptr iString; + byte merr; + byte merrf; + byte lops; + byte kflag; + unsigned long mFlags; + unsigned long pFlags; + unsigned long org; +} oLInfoRec; + +void convcol2sl(char *p) +{ +int i; + + for (i = 1; i <= p[0]; i++) + if (p[i] == ':') p[i] = '/'; +} + +int cSetLInfo(oLInfoPB *pBlock, int cmdNum) +{ +oLInfoRec *tmp; +extern void copyp2gs(void *, void *); +extern void copygsstr(void *, void *); + + /* $$$ tmp = kp->procTable[Kgetpid()].LInfo; */ + tmp = PROC->LInfo; + if (tmp == NULL) { tmp = malloc(sizeof(oLInfoRec)); + /* $$$ kp->procTable[Kgetpid()].LInfo = tmp; */ + PROC->LInfo = tmp; + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + tmp->sFile = tmp->dFile = tmp->parms = tmp->iString = NULL; +#else + tmp->sFile = NULL; + tmp->dFile = NULL; + tmp->parms = NULL; + tmp->iString = NULL; +#endif + } + if (tmp->sFile != NULL) { + nfree(tmp->sFile); + nfree(tmp->dFile); + nfree(tmp->iString); + nfree(tmp->parms); + } + if (cmdNum == 0x0102) { + tmp->sFile = malloc(pBlock->sFile[0] + 2); + copyp2gs(tmp->sFile,pBlock->sFile); + tmp->dFile = malloc(pBlock->dFile[0] + 2); + copyp2gs(tmp->dFile,pBlock->dFile); + tmp->parms = malloc(pBlock->parms[0] + 2); + copyp2gs(tmp->parms,pBlock->parms); + tmp->iString = malloc(pBlock->iString[0] + 2); + copyp2gs(tmp->iString,pBlock->iString); + } else { + tmp->sFile = malloc( ((oLInfoRec *) pBlock)->sFile->length + 2); + copygsstr(tmp->sFile,pBlock->sFile); + tmp->dFile = malloc( ((oLInfoRec *) pBlock)->dFile->length + 2); + copygsstr(tmp->dFile,pBlock->dFile); + tmp->parms = malloc( ((oLInfoRec *) pBlock)->parms->length + 2); + copygsstr(tmp->parms,pBlock->parms); + tmp->iString = malloc( ((oLInfoRec *) pBlock)->iString->length + 2); + copygsstr(tmp->iString,pBlock->iString); + } + tmp->merr = pBlock->merr; + tmp->merrf = pBlock->merrf; + tmp->lops = pBlock->lops; + tmp->kflag = pBlock->kflag; + tmp->mFlags = pBlock->mFlags; + tmp->pFlags = pBlock->pFlags; + tmp->org = pBlock->org; + return 0; +} + +int cGetLInfo(oLInfoPB *pBlock, int cmdNum) +{ +oLInfoRec *tmp; +extern void copygs2p(void *, void *); +extern void copygs2res(void *, void *); + + /* $$$ tmp = kp->procTable[Kgetpid()].LInfo; */ + tmp = PROC->LInfo; + if (tmp == NULL) return 0; + if (cmdNum == 0x0101) { + copygs2p(pBlock->sFile,tmp->sFile); + convcol2sl((char *)pBlock->sFile); + copygs2p(pBlock->dFile,tmp->dFile); + convcol2sl((char *)pBlock->dFile); + copygs2p(pBlock->iString,tmp->iString); + copygs2p(pBlock->parms,tmp->parms); + } + else { + copygs2res(pBlock->sFile,tmp->sFile); + copygs2res(pBlock->dFile,tmp->dFile); + copygs2res(pBlock->iString,tmp->iString); + copygs2res(pBlock->parms,tmp->parms); + } + pBlock->merr = tmp->merr; + pBlock->merrf = tmp->merrf; + pBlock->lops = tmp->lops; + pBlock->kflag = tmp->kflag; + pBlock->mFlags = tmp->mFlags; + pBlock->pFlags = tmp->pFlags; + pBlock->org = tmp->org; + return 0; +} + +#pragma databank 0 + diff --git a/kern/gno/global.equates b/kern/gno/global.equates new file mode 100644 index 0000000..9831889 --- /dev/null +++ b/kern/gno/global.equates @@ -0,0 +1,28 @@ +********************************************************************* +* +* GSOS/P16/Shell Call DP locations +* +********************************************************************* + +pBlock gequ 0 +cmdNum gequ 4 +procEnt gequ 6 +temp0 gequ 6 +pCount gequ 10 + +********************************************************************* +* +* Kernel process state IDs +* +********************************************************************* + +NPROC gequ 32 +pUnused gequ $00 +pRunning gequ $01 +pReady gequ $02 +pBlocked gequ $03 +pNew gequ $04 ; ready, but no int info +pSuspended gequ $05 +pWait gequ $06 +pWaitSigCH gequ $07 +pPaused gequ $08 diff --git a/kern/gno/gno.h b/kern/gno/gno.h new file mode 100644 index 0000000..0102a40 --- /dev/null +++ b/kern/gno/gno.h @@ -0,0 +1,92 @@ +/* $Id: gno.h,v 1.1 1998/02/02 08:18:29 taubert Exp $ */ + +/* + gno.h + + libgno interface file for GNO Kernel + v1.0b2 + Copyright 1991-1998, Procyon Inc. +*/ + +#include + +#ifndef udispatch +#define udispatch 0xE10008 +#endif +extern pascal int kernVersion() inline(0x0403, udispatch); +extern pascal int kernStatus() inline(0x0603, udispatch); + +#ifndef KERNEL +int getppid(void); +int fork(void *subr); +int exec(char *filename,char *cmdline); +int tcnewpgrp(int fdtty); +int settpgrp(int fdtty); +int tctpgrp(int fdtty, int pid); +int setdebug(int code); +void *setsystemvector(void *vect); +int pipe(int filedes[2]); +int getpgrp(int pid); +int setpgrp(int pid,int pgrp); +int ioctl(int d, unsigned long request, void *argp); +/* 'dup()' appears in fcntl.h, dup2() should too, but I'm not rewriting + any more O**A C header files */ +int dup2(int filedes, int filedes2); + +void SetGNOQuitRec(word,void *,word); +unsigned int sleep(unsigned int); + +#ifdef __stdio__ +FILE *fdopen(int,char*); +#endif + +int execve(char *filename,char *cmdline); +int fork2(void *subr, int stack, int prio, char *name, int nargs, ...); +int screate(int count); +int ssignal(int sem); +int swait(int sem); +int scount(int sem); +int sdelete(int sem); +int getpid(void); + +int kill(int pid, int sig); +int wait(union wait *status); +void *signal(int sig, void (*func)()); +longword sigblock(longword mask); +longword sigsetmask(longword mask); +longword alarm(longword seconds); +longword alarm10(longword tenths); +int sigpause(longword mask); +longword procrecvclr(void); +longword procreceive(void); +longword procrecvtim(int timeout); +int procsend(int pid, unsigned long msg); + +#else +int kern_printf(const char *, ...); + +int KERNexecve(int *ERRNO, char *cmdline, char *filename); +int Kscreate(int *ERRNO, int count); +int KERNssignal(int *ERRNO, int sem); +int Kscount(int *ERRNO, int sem); +int KERNsdelete(int *ERRNO, int sem); +int KERNkill(int *ERRNO, int signum, int pid); +void *Ksignal(int *ERRNO, void (*func)(), int sig ); +longword Ksigblock(int *ERRNO, longword mask); +longword Ksigsetmask(int *ERRNO, longword mask); +int KERNkvmsetproc(int *ERRNO, struct kvmt *kd); + +#define Kexecve(__e, __p1, __p2) \ + { asm { pha } KERNexecve(__e, __p1, __p2); asm { pla } } +#define Kssignal(__e, __p1) \ + { asm { pha } KERNssignal(__e, __p1); asm { pla } } +#define Ksdelete(__e, __p1) \ + { asm { pha } KERNsdelete(__e, __p1); asm { pla } } +#define Kkill(__e, __p1, __p2) \ + { asm { pha } KERNkill(__e, __p1, __p2); asm { pla } } +#define Kkvmsetproc(__e, __p1) \ + { asm { pha } KERNkvmsetproc(__e, __p1); asm { pla } } + +extern int errno; + +#endif diff --git a/kern/gno/gsos.asm b/kern/gno/gsos.asm new file mode 100644 index 0000000..9ca1d99 --- /dev/null +++ b/kern/gno/gsos.asm @@ -0,0 +1,2281 @@ +* $Id: gsos.asm,v 1.1 1998/02/02 08:19:23 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* GSOS.ASM +* By Tim Meekins +* and Jawaid Bazyar +* and Derek Taubert (modified socket stuff) +* +* This file contains routines for patching GS/OS to intercept Shell +* calls and do special things with certain GS/OS calls. +* +* taken over by JB on 6/18/91 +* 10/29/91 - extensive modifications to better support the data structures +* of the fd (file descriptor) table +* +************************************************************************** + + copy global.equates + mcopy m/gsos.mac + case on + copy inc/gsos.inc + copy inc/tty.inc + +GSOStable START + dc a2'GNOStandard' ; $2001 Create + dc a2'GNOStandard' ; $2002 Destroy + dc a2'NotImpGS' ; $2003 OSShutDown + dc a2'GNOChangePath' ; $2004 ChangePath + dc a2'GNOStandard' ; $2005 SetFileInfo + dc a2'GNOStandard' ; $2006 GetFileInfo + dc a2'NotImpGS' ; $2007 JudgeName + dc a2'NotImpGS' ; $2008 Volume + + dc a2'GNOSetPrefix' ; $2009 SetPrefix + dc a2'PGGetPrefix' ; $200A GetPrefix + dc a2'GNOStandard' ; $200B ClearBackupBit + dc a2'NotImpGS' ; $200C SetSysPrefs + dc a2'NotImpGS' ; $200D Null + dc a2'GNOExpandPath' ; $200E ExpandPath + dc a2'NotImpGS' ; $200F GetSysPrefs + dc a2'GNOOpen' ; $2010 Open + dc a2'GNONewLine' ; $2011 NewLine + dc a2'GNORdWr' ; $2012 Read + dc a2'GNORdWr' ; $2013 Write + dc a2'PGClose' ; $2014 Close + dc a2'GNORefCommon' ; $2015 Flush + dc a2'GNORefCommon' ; $2016 SetMark + dc a2'GNORefCommon' ; $2017 GetMark + dc a2'GNORefCommon' ; $2018 SetEOF + dc a2'GNORefCommon' ; $2019 GetEOF + dc a2'GNOSetLevel' ; $201A SetLevel + dc a2'GNOGetLevel' ; $201B GetLevel + dc a2'GNORefCommon' ; $201C GetDirEntry + dc a2'NotImpGS' ; $201D BeginSession + dc a2'NotImpGS' ; $201E EndSession + dc a2'NotImpGS' ; $201F SessionStatus + dc a2'GNOStandard' ; $2020 GetDevNumber + dc a2'NotImpGS' ; $2021 + dc a2'NotImpGS' ; $2022 + dc a2'NotImpGS' ; $2023 + dc a2'NotImpGS' ; $2024 Format + dc a2'NotImpGS' ; $2025 EraseDisk + dc a2'NotImpGS' ; $2026 ResetCache + dc a2'GNOGetName' ; $2027 GetName + dc a2'NotImpGS' ; $2028 GetBootVol + dc a2'GNOQuit' ; $2029 Quit + dc a2'NotImpGS' ; $202A GetVersion + dc a2'NotImpGS' ; $202B GetFSTInfo + dc a2'NotImpGS' ; $202C DInfo + dc a2'NotImpGS' ; $202D DStatus + dc a2'NotImpGS' ; $202E DControl + dc a2'NotImpGS' ; $202F DRead + dc a2'NotImpGS' ; $2030 DWrite + dc a2'NotImpGS' ; $2031 BindInt + dc a2'NotImpGS' ; $2032 UnbindInt + dc a2'NotImpGS' ; $2033 FSTSpecific + dc a2'NotImpGS' ; $2034 AddNotifyProc + dc a2'NotImpGS' ; $2035 DelNotifyProc + dc a2'NotImpGS' ; $2036 DRename + dc a2'GNOGetStdRefNum' ; $2037 GetStdRefNum + dc a2'NotImpGS' ; $2038 GetRefNum + dc a2'GNOGetRefInfo' ; $2039 GetRefInfo + dc a2'NotImpGS' ; $203A SetStdRefNum + END + +; +; Patch GS/OS +; This has been modified greatly to install itself through our special +; Permanent Init (PIF) file. This will allow us to do GSBug OS call traps +; properly +; + +GSOSinfo DATA +storeHandle dc i4'0' +patchType dc i2'0' ; 0 = no gnobug, 1 = gnobug +gnobugPath str '*:system:system.setup:gnobug' + END + +patchGSOS START + using GSOSinfo +handle equ 0 +nextHandle equ 4 +lookuid equ 8 +; +location equ 0 +attributes equ 4 +userID equ 6 +length equ 8 +last equ 12 +next equ 16 + + subroutine (0:foo),10 + pha + ph4 #gnobugPath + _GetUserID + cmp #0 + beq okay1 + jmp reggalar +okay1 pla + sta lookuid + + FindHandle #patchGSOS,handle + +lb1 ldy #last + lda [handle],y + tax + iny2 + ora [handle],y + beq lb1a + lda [handle],y + sta handle+2 + stx handle + bra lb1 + +lb1a anop +lb2 lda handle + ora handle+2 + jeq reggalar + ldy #next + lda [handle],y + sta nextHandle + iny2 + lda [handle],y + sta nextHandle+2 + ldy #userID + lda [handle],y + cmp lookuid + beq around1 + jmp lb3 +around1 anop + ldy #attributes + lda [handle],y + cmp #$C018 ; always, for PIF + beq around2 + jmp lb3 + +lb3 mv4 nextHandle,handle + jmp lb2 + +around2 anop ; we've got the handle + lda [handle] + sta nextHandle + ldy #2 + lda [handle],y + sta nextHandle+2 + + lda [nextHandle] + sta OldGSOS + lda [nextHandle],y + sta OldGSOS+2 + iny2 + lda [nextHandle],y + sta OldGSOSSt + iny2 + lda [nextHandle],y + sta OldGSOSSt+2 + + lda #OurGSOS + iny + sta [nextHandle],y + + lda #StackGSOS + iny + sta [nextHandle],y + mv4 nextHandle,storeHandle + lda #1 + sta patchType + return + +reggalar anop + pla + stz patchType + mv4 >$E100A8,OldGSOS + ld2 $E100A8+1 + ld2 >OurGSOS,>$E100A8+2 + + mv4 >$E100B0,OldGSOSSt + ld2 $E100B0+1 + ld2 >StackGSOS,>$E100B0+2 + return + + END + +; +; UnPatch GS/OS +; +unpatchGSOS START + using GSOSinfo +patchPtr equ 0 + subroutine (0:foo),4 + + lda patchType + beq oldType + mv4 storeHandle,patchPtr + + ldy #2 + lda OldGSOS + sta [patchPtr] + lda OldGSOS+2 + sta [patchPtr],y + iny2 + lda OldGSOSSt + sta [patchPtr],y + iny2 + lda OldGSOSSt+2 + sta [patchPtr],y + return +oldType anop + mv4 OldGSOS,>$E100A8 + mv4 OldGSOSSt,>$E100B0 + return + END + +OurGSOS START + php ; these six bytes are where + phb ; the call info (cmdNum/pBlockPtr) + long ai + phy ; get stored + pha ; + pha ; p/b reg contents + pha ; y reg contents + pha ; a reg contents + lda 11,s ; copy p,b, and y further down + sta 5,s ; so we can pull them off + lda 9,s ; before the call + sta 3,s + short a + lda 15,s ; set data bank to pBlock's + pha ; bank (to use short-based) + plb ; stack indirect adressing + long a + ldy #1 + lda (13,s),y ; cmdNum + sta 7,s + + ldy #5 ; copy high word of pBlock + lda (13,s),y ; pointer + sta 11,s + + ldy #3 ; low word of pBlock pointer + lda (13,s),y + sta 9,s + lda 13,s + clc + adc #6 ; set rtl address to point after + sta 13,s ; the call information + + pla + ply + plb + plp + jsl StackGSOS + rtl + END + +StackGSOS START + using KernelStruct + + phb ;Save the data bank + php ;Save the proc status + long ai + phx + phy + phd + phk + plb + cld + ldx curProcInd + sta exitCode,x + lda gsosDebug + and #1 + beq noDebug + ErrWriteChar #'(' + ErrWriteChar #'$' + lda 12,s + jsr writeacc + lda gsosDebug + and #32 + beq noDebug + ErrWriteChar #',' + ErrWriteChar #'$' + lda 16,s + and #$00FF + jsr writeacc + lda 14,s + jsr writeacc +noDebug anop +* check here to see if it's one of the call groups we handle + lda 12,s + and #$FF00 + cmp #0 ; P16? + beq ok + cmp #$2000 ; GS/OS? + beq ok + cmp #$0100 ; ORCA? + beq ok + pld ; nope, go to the real GS/OS entry + ply ; point + plx + plp + plb +* real stack entry point +OldGSOSSt ENTRY + dc i4'0' + brk 0 +* real inline entry point +OldGSOS ENTRY + dc i4'0' + brk 0 + +ok anop + tsc + sec + sbc #$1F + tcd + dec a + tcs + lda 45 + sta pBlock + lda 47 + sta pBlock+2 + lda 43 + sta cmdNum + lda 41 + sta 47 + lda 40 + sta 46 + lda 38 + sta 44 + lda 36 + sta 42 + lda 34 + sta 40 + lda 32 + sta 38 + + jsl incBusy + lda cmdNum + and #$FF00 ;Is it a shell command? + cmp #$0100 + beq shellit + cmp #$0000 ; P16? + beq P16it + jmp GSOSit ; must be GS/OS then! + +P16it anop + +; create pointer to process entry for the current process + + lda curProcInd + clc + adc #|CKernData + sta procEnt + lda #^CKernData + sta procEnt+2 + lda cmdNum + and #$00FF ; mask off (nothing!) + cmp #$32+1 + bcc rangeOK + jmp NotImpP16 +rangeOK anop + asl a + tax + jmp (P16table-2,x) + +GSOSit anop +; create pointer to process entry for the current process + + lda curProcInd + clc + adc #|CKernData + sta procEnt + lda #^CKernData + sta procEnt+2 + + lda cmdNum + and #$00FF ; mask off $2000 + cmp #$3A+1 + bcc range + jmp NotImpGS +range anop + asl a + tax + jmp (GSOStable-2,x) + +shellit anop + lda cmdNum + and #$40 + bne orca2 + + lda #0 + sta pCount + bra chkcmd +orca2 anop + lda [pBlock] + sta pCount + lda pBlock + clc + adc #2 + sta pBlock + lda pBlock+2 + adc #0 + sta pBlock+2 + +chkcmd anop + lda cmdNum + and #$3F ;Strip entry type 2 [don't ask] + cmp #$20 ; new calls + bcs BadCommand + + asl a + tax + jmp (ShellCallTbl-2,x) + + +; | p pstat from before call +; | acch +; | accl +; | p pstat containing cznv result of cmp #1 + +; +; Not a valid command +; + +BadCommand anop + lda #1 +; [6/29/91] removed all this duplicated code [jb] +; +; Return from a GSOS call +; +GSOSReturn ENTRY +ShellReturn ENTRY + + sta $1E+6 ; neat trick coming up + tsc + clc + adc #$1E+6 ; so we can pull the result + tcs +; pla + + jsl decBusy + +; pha + lda >gsosDebug + and #1 + beq noDebug1 + lda >gsosDebug + and #4 + beq noDebug2 + lda 1,s + beq noDebug2 ; if no error, no message + ErrWriteChar #15 + ErrWriteChar #'#' ; error codes get a # sign + ldy #1 + lda 1,s ; the error number (incognito) + jsr writeacc ; + ErrWriteChar #14 +noDebug2 anop + ErrWritechar #')' + ErrWriteChar #13 +noDebug1 anop + pla + + pld + ply + plx +; insert from here + pha + cmp #1 + lda 1,s + php + short m + lda 1,s + and #%11000011 + sta 1,s + lda 4,s + and #%00111100 + ora 1,s + sta 4,s + pla + long m + lda 3,s + xba + sta 3,s ; swap two bytes around + pla +; to here + plb ; modifies the fucking P! + plp + rtl + +* Amazing how I've finally managed to merge all this code! Augh! + +NotImpGS ENTRY +NotImpP16 ENTRY +NotImp ENTRY + + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + jmp GSOSReturn + END + +* New GetPrefix code +* instead of a handle, we'll use a small malloc'd record as follows: + +PGGetPrefix START + using KernelStruct +pfxRec equ 10 +pfxString equ 14 + + ldy #prefixh-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta pfxRec ; we dereference it later + iny2 + lda [procEnt],y + sta pfxRec+2 + + lda cmdNum + and #$FF00 + beq ok2 + + lda [pBlock] + cmp #2 + beq ok1 + lda #$04 + jmp GSOSReturn + +ok2 lda [pBlock] + bra lookuppfx + +ok1 ldy #2 + lda [pBlock],y + +lookuppfx anop + inc a + asl a + asl a + tay + iny2 + lda [pfxRec],y + sta pfxString+2 + pha + dey2 + lda [pfxRec],y + sta pfxString + pha + + ora 3,s + bne notnull + pla + pla + ph4 #nullGSOS + ld4 nullGSOS,pfxString + +notnull lda cmdNum + and #$FF00 + beq p16vers + + ldy #6 + lda [pBlock],y + pha + ldy #4 + lda [pBlock],y + pha + jsl copygs2res + jmp GSOSReturn + +* for P16 calls, we need to condition the returned pathname somewhat + +p16vers anop + lda [pfxString] + beq patherror ; length is zero, avoid major memtrashing + tay + iny + short m + +* Scan the prefix for a slash; if one is present, return a null pathname +* because after processing ':'s to '/'s the pathname would be totally +* incorrect. + +slashloop lda [pfxString],y + cmp #'/' + beq patherror + dey + cpy #2 + bcs slashloop + long m + ldy #4 + lda [pBlock],y + sta pfxString+2 + pha + ldy #2 + lda [pBlock],y + sta pfxString + pha + jsl copygs2p + lda [pfxString] + and #$00FF + tay + short m +fixloop lda [pfxString],y + cmp #':' + bne nofix + lda #'/' + sta [pfxString],y +nofix dey + bne fixloop + long m + + lda #0 + jmp GSOSReturn +patherror long m + pla ; remove input params + pla ; store a zero as length, + ldy #4 ; and don't return an error + lda [pBlock],y + sta pfxString+2 + ldy #2 + lda [pBlock],y + sta pfxString + lda #0 + short m + sta [pfxString] + long m + jmp GSOSReturn +nullGSOS dc i2'0' + END + +GNOSetPrefix START + using KernelStruct +pfxRec equ 10 +pfxInd equ 14 + +pfxpCount equ 16 +pfxpfxNum equ 18 +pfxpathname equ 20 +newPath equ 24 + + ldy #prefixh-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta pfxRec ; we dereference it later + iny2 + lda [procEnt],y + sta pfxRec+2 + + lda [pBlock] + cmp #2 + beq ok1 + lda #$04 + jmp GSOSReturn + +ok1 anop + pea 1 ; don't do the named pfx expansion + ldy #2 ; push the prefix number + lda [pBlock],y + pha + ldy #6 ; push the path to be expanded + lda [pBlock],y + pha + ldy #4 + lda [pBlock],y + pha + jsl gno_ExpandPath ; call our C routine + sta pfxpathname + stx pfxpathname+2 ; store result + cpx #$FFFF ; did an error occur? + bne noerr + jmp GSOSReturn + +noerr anop + ldy #2 + lda [pBlock],y + inc a + asl a + asl a + + sta pfxInd + tay + iny2 + lda [pfxRec],y + pha + dey2 + lda [pfxRec],y + pha + ora 3,s + bne dodispose + pla + pla + bra nodispose +dodispose jsl ~NDISPOSE + +nodispose lda [pfxpathname] + inc a + inc a + inc a + pea 0 + pha + jsl ~NEW + sta newPath + stx newPath+2 + + ldy pfxInd ; copy the addr of the new mem into the + sta [pfxRec],y ; prefix record + iny2 + txa + sta [pfxRec],y + + ph4 pfxpathname ; copy the string + ph4 newPath + jsl copygsstr + lda [newPath] + inc a + tay + lda [newPath],y ; check to see if there's a + and #$00FF + cmp #':' ; separator at the end of the + beq alright + short m ; prefix, and if not, then + lda #':' + iny ; add one. Note that we alloced + sta [newPath],y ; one extra byte for this possibility + long m + dey + tya + sta [newPath] +alright lda #0 + jmp GSOSReturn + END + +GNOChangePath START +temp1 equ 10 +temp2 equ 14 +oldpathres equ 18 +newmem equ 22 + + ldy #2 + lda [pBlock],y + sta temp1 + iny2 + lda [pBlock],y + sta temp1+2 + iny2 + lda [pBlock],y + sta temp2 + iny2 + lda [pBlock],y + sta temp2+2 + + pea 0 + pea 0 + pushlong temp1 + jsl gno_ExpandPath + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr phx + pha ; push source addr for copy + stx oldpathres+2 + sta oldpathres + + pea $0000 + lda [oldpathres] + clc + adc #2 + pha + jsl ~NEW + stx newmem+2 + sta newmem + + phx + pha ; push dest address + + ldy #2 + sta [pBlock],y + iny2 + txa + sta [pBlock],y + dey2 + ora [pBlock],y + beq memoryErr + + jsl copygsstr ; copy the expanded path to temp + + pea 0 + pushword #0 + pushlong temp2 + jsl gno_ExpandPath + cpx #$FFFF + bne noerr1 + ph4 newmem + jsl ~NDISPOSE + jmp GSOSReturn +noerr1 anop + ldy #6 + sta [pBlock],y + iny2 + txa + sta [pBlock],y + + movelong pBlock,pb + lda cmdNum + sta cn + + jsl OldGSOS +cn dc i2'0' ; set to same call # we are +pb dc i4'0' + pha ; return any error we get + pushlong newmem + jsl ~NDISPOSE + +interdict anop + ldy #2 + lda temp1 + sta [pBlock],y + iny2 + lda temp1+2 + sta [pBlock],y + iny2 + lda temp2 + sta [pBlock],y + iny2 + lda temp2+2 + sta [pBlock],y + pla + jmp GSOSReturn +memoryErr pla + pla + pea $0054 + bra interdict + END + +GNOStandard START +oldpath equ 10 +exppath equ 14 + + ldy #2 + lda [pBlock],y + sta oldpath + iny2 + lda [pBlock],y + sta oldpath+2 + + pea 0 + pushword #0 + pushlong oldpath + jsl gno_ExpandPath + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr anop + sta exppath + stx exppath+2 + ph4 exppath + jsl findDevice + cmp #$FFFF + beq notdevice + lda #$0058 ; not a block device! + bra goaway + +notdevice anop + ldy #2 + lda exppath + sta [pBlock],y + ldy #4 + lda exppath+2 + sta [pBlock],y + + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + + pha ; return any error we get + + lda cmdNum + cmp #$2002 + beq docff + cmp #$2005 + bne noff +docff anop + ldx oldpath+2 + lda oldpath + jsr checkFF + +noff anop + ldy #2 + lda oldpath + sta [pBlock],y + ldy #4 + lda oldpath+2 + sta [pBlock],y + pla +goaway jmp GSOSReturn + END + +checkFF START + using KernelStruct + + tay + + lda gsosDebug ; don't print the path twice + pha + stz gsosDebug + + pea 1 + pea 0 + phx ; pathname pointer + phy + jsl gno_ExpandPath ; expand it again, but this time + phx ; pointer to expanded pathname + pha + jsl FindFF + phx ; pointer to ff entry, if any + pha + ora 3,s ; null pointer means not in FF + beq noFF + jsl DeleteFF + +goaway pla + sta gsosDebug + + rts +noFF pla + pla + bra goaway + END + +PcheckFF START + using KernelStruct + + tay + + lda gsosDebug ; don't print the path twice + pha + stz gsosDebug + + pea 1 + pea 0 + phx ; pathname pointer + phy + jsl p16_ExpandPath ; expand it again, but this time + phx ; pointer to expanded pathname + pha + jsl FindFF + phx ; pointer to ff entry, if any + pha + ora 3,s ; null pointer means not in FF + beq noFF + jsl DeleteFF + +goaway pla + sta gsosDebug + + rts +noFF pla + pla + bra goaway + END + + +GNOOpen START + using KernelStruct +temp1 equ 10 +files equ 14 +fd equ 18 +fdPtr equ 20 +ttyn equ 24 + +* Save the old pathname so we can restore before we exit + + ldy #4 + lda [pBlock],y + sta temp1 + iny2 + lda [pBlock],y + sta temp1+2 + + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 + pea 0 + pushword #0 + pushlong temp1 + jsl gno_ExpandPath + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr anop + phx + pha + phx + pha + jsl findDevice + cmp #$FFFF + jne openTTY + + pla + plx + ldy #4 ; forgetting this is B A D (baaaad) + sta [pBlock],y + txa + iny2 + sta [pBlock],y + movelong pBlock,pb + lda cmdNum + sta cn + + ldy #FDTLevel ; open the file with the proper + lda [files],y ; GS/OS level + sta dolevel+2 + ldy #FDTLevelMode + lda [files],y + sta dolevel+4 + ph4 #dolevel + pea $201A ; SetLevelGS + jsl OldGSOSSt + + jsl OldGSOS +cn dc i2'0' ; set to same call # we are +pb dc i4'0' + pha + cmp #0 + jne error + +; alloc a process file entry ONLY if GS/OS opened the file okay + + lda [files] ; inc the number of open files, + inc a ; allocFD does not do this + sta [files] + + pea 0 ; push the (dp) address of + tdc ; our local 'fd' + clc + adc #fd + pha + jsl allocFD + sta fdPtr + stx fdPtr+2 + + ldy #openFiles-CKernData + lda [procEnt],y + sta files + iny2 + lda [procEnt],y + sta files+2 + + ldy #2 + lda [pBlock],y + pha + pea FDgsos + jsl AddRefnum ; add to our tracking table + + ldy #2 ; refNum returned by open + lda [pBlock],y + ldy #FDrefNum + sta [fdPtr],y ; and store the new refnum in the list + + lda fd ; retreive the fd number and + ldy #2 ; return it in the pBlock + sta [pBlock],y + ldy #FDTLevel + lda [files],y + ldy #FDTLevelMode ; handle internal levels + ora [files],y + ldy #FDrefLevel + sta [fdPtr],y ; store file level with refnum + + lda #0 + sta 1,s ; no error! trick the stack +error anop + + ldx temp1+2 + lda temp1 + jsr checkFF + + ldy #4 + lda temp1 + sta [pBlock],y + iny2 + lda temp1+2 + sta [pBlock],y + pla + jmp GSOSReturn +* this should be common between P16/GSOS +openTTY anop + inc a + sta ttyn + pla + pla ; remove junk + + pei (ttyn) + pea FDtty ; we're looking for this type + jsl FindRefnum + sta fdPtr + stx fdPtr+2 ; if fdptr==NULL, then there are + ora fdPtr+2 ; no references to this TTY + bne notfirst + +* create a reference to this TTY + pei (ttyn) + pea FDtty + jsl AddRefnum + +* since this is the first open on this TTY, reassign this process' controlling +* tty to this terminal. Also, make sure the terminal's process group is +* 0 (but not the process'- this allows the real controlling terminal to +* signal the process) + + ldx curProcInd + lda ttyn + dec a + sta ttyID,x + lda ttyn + dec a + asl a + tax + stz ttyStruct,x + +* here, call the Init routine in the Device Driver + lda ttyn + dec a ; 0-n device number + pha + ldy #t_open + jsl LineDiscDispatch + cmp #0 + bne iserr ; open failed! + bra part2 +notfirst anop +* should check here for exclusive access bit. If set, then the +* open call will fail (before we change any counts) + lda ttyn + jsl checkExclTTY + cpy #0 + beq not_excl + lda #$50 + bra iserr99 ; do NOT DecRefNum - we never inc'd it +iserr pha + pei (ttyn) + pea FDtty + jsl DecRefnum clean up after ourselves + pla +iserr99 jmp GSOSReturn ; the file is already open! + +not_excl pei (ttyn) + pea FDtty + jsl IncRefnum ; tell 'em we're here to party! + +part2 anop ; no errors- + pea 0 + tdc + clc + adc #fd + pha ; push address of 'fd' (dp) + jsl allocFD + sta fdPtr + stx fdPtr+2 + ora fdPtr+2 + bne noerror9 + + lda #$42 + bra iserr ; exit with error & cleanup + +noerror9 anop +; re-dereference files since allocFD can modify it + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 + + ldy #FDrefNum + lda ttyn + sta [fdPtr],y ; store device number + ldy #FDrefType + lda #FDtty + sta [fdPtr],y ; and file descriptor type + ldy #FDTLevel + lda [files],y ; and the file level + ldy #FDrefLevel + sta [fdPtr],y + lda #0 + ldy #FDrefFlags ; no flags for TTYs yet! + sta [fdPtr],y + ldy #FDNLenableMask ; make sure newline mode is off + sta [fdPtr],y + + ldy #FDTCount + lda [files],y + inc a + sta [files],y + + lda fd ; retreive the fd number and + ldy #2 ; return it in the pBlock + sta [pBlock],y + lda [pBlock] + cmp #5 + bcc ttybyebye + ldy #8 + lda [pBlock],y + bne storeAccess + lda #3 +storeAccess ldy #12 + sta [pBlock],y + +ttybyebye lda #0 + jmp GSOSReturn + +dolevel dc i2'2' + dc i2'0' + dc i2'0' + END + +GNOSetLevel START + using KernelStruct +files equ 10 + + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 + lda [pBlock] + cmp #1 + beq okay + cmp #2 + beq okay1 + lda #$04 + bra error +okay anop + pea $8000 ; default to 'user' mode + bra okay2 +okay1 anop + ldy #4 ; use the mode they passed us + lda [pBlock],y + and #$8000 + pha + +okay2 lda 1,s + bit #$8000 + beq okay3 + ldy #2 + lda [pBlock],y + bit #$8000 + beq okay3 + pla + lda #$59 + jmp GSOSReturn + +okay3 ldy #2 + lda [pBlock],y + ldy #FDTLevel + sta [files],y + pla + ldy #2 ; calculate the real file level + eor [pBlock],y + and #$8000 + ldy #FDTLevelMode + sta [files],y + + lda #0 +error jmp GSOSReturn + END + +GNOGetLevel START + using KernelStruct +files equ 10 + + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 + lda [pBlock] + cmp #1 + beq okay + cmp #2 + beq okay1 + lda #$04 + bra error +okay anop + pea $8000 + bra okay2 +okay1 anop + ldy #4 + lda [pBlock],y ; levelmode is an input + and #$8000 + pha +okay2 ldy #FDTLevel + lda [files],y + ldy #FDTLevelMode + ora [files],y + eor 1,s + ldy #2 + sta [pBlock],y + pla + lda #0 +error jmp GSOSReturn + END + +GNOExpandPath START ; not to be confused with gno_EP +gep_flags equ 10 +outPath equ 12 +pathName equ 16 +in_ind equ 20 +out_ind equ 22 + + lda #0 + sta gep_flags + lda [pBlock] + cmp #2 + bcs okay + lda #4 + jmp GSOSReturn +okay anop + beq okay1 + ldy #$0A + lda [pBlock],y + sta gep_flags +okay1 anop + ldy #6 + lda [pBlock],y + sta outPath + iny2 + lda [pBlock],y + sta outPath+2 + + pea 1 + pea $0000 ; prefix 0 + ldy #4 ; push the old pathname ptr + lda [pBlock],y + pha + dey + dey + lda [pBlock],y ; on the stack and call C expandpath + pha + jsl gno_ExpandPath ; ha! + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr anop + sta pathName + stx pathName+2 + ldy #6 + lda [pBlock],y + sta outPath + iny2 + lda [pBlock],y + sta outPath+2 + + lda [pathName] + clc + adc #4 + cmp [outPath] + beq okay2 + bcc okay2 + ldy #2 + sta [outPath],y + lda #$4F + jmp GSOSReturn +okay2 anop + + lda [pathName] + ldy #2 + sta [outPath],y + tax ; count down with X reg + beq noCopy + sty in_ind + lda #4 + sta out_ind + + short m +loop anop + ldy in_ind + lda [pathName],y + bit gep_flags+1 ; hi bit into 'N' preg bit + bpl noupper + cmp #'a' + bcc noupper + cmp #'z'+1 + bcs noupper + sec + sbc #'a'-'A' +noupper anop + ldy out_ind + sta [outPath],y + long m + inc in_ind + inc out_ind + short m + dex + bne loop + +noCopy anop + long m + lda #0 + jmp GSOSReturn + END + +GNOQuit START + using KernelStruct + ldx curProcInd + lda flags,x + ora #%00001000 ; FL_NORMTERM + sta flags,x + lda [pBlock] + cmp #2 + bcs doFlags + pea 0 + bra noFlags +doFlags ldy #6 + lda [pBlock],y + pha +noFlags lda [pBlock] + cmp #1 + bcs doPname + pea 0 + pea 0 + bra noPname +doPname ldy #4 + lda [pBlock],y + pha + ldy #2 + lda [pBlock],y + pha + ora 3,s + beq noPname + jsl gs2cstr + phx + pha ; push the coverted pathname +noPname anop + jsl CommonQuit + jmp GSOSReturn ; only returns on error + END + +* Flush 2015 +2 +* GetDirEntry 201C +2 +* GetEOF 2019 +2 tty,pipe +* GetMark 2017 +2 tty,pipe +* GetRefInfo 2039 +2 +* SetEOF 2018 +2 tty,pipe +* SetMark 2016 +2 tty,pipe + +getFDptr START + using KernelStruct +files equ 0 + + subroutine (2:rn),4 + lda rn + cmp #32 ; max # of open files + bcs invalidRN + + ldx curProcInd + lda openFiles,x + sta files + lda openFiles+2,x + sta files+2 + lda rn + asl a + asl a + asl a + asl a + sec + sbc #FDsize-FDTTable + clc + adc files + sta files + lda files+2 + adc #0 + sta files+2 +goaway return 4:files +invalidRN stz files + stz files+2 + bra goaway + END + +mapRN START + using KernelStruct +files equ 0 +retval equ 4 + subroutine (2:rn),6 + + lda rn + cmp #32 + bcs invalidRN + + ldx curProcInd + lda openFiles,x + sta files + lda openFiles+2,x + sta files+2 + lda rn + asl a + asl a + asl a + asl a + sec + sbc #FDsize-FDTTable + tay + lda [files],y + sta retval +goaway return 2:retval +invalidRN stz retval + bra goaway + END + +* search the specified file descriptor table for the physical +* refnum specified. Returns 0 if the file wasn't found, or +* returns the refnum (index into table) + +SearchFDTable START +rn equ 0 + + subroutine (4:fdptr,2:refnum),2 + lda #0 + sta rn + +loop asl a + asl a + asl a + asl a + clc + adc #FDTTable ; don't forget the 6 bytes on top + tay + lda [fdptr],y + cmp refnum + bne nxt + iny + iny + lda [fdptr],y + cmp #FDgsos + beq gotit + +nxt inc rn + lda rn + cmp #32 + bcc loop + + stz rn ; search failed, return 0 + bra byebye +gotit inc rn ; rn + 1 is actual refnum +byebye return 2:rn + END + +GNOGetRefInfo START + +oldRN equ 10 +fdPtr equ 12 + + ldy #2 + lda [pBlock],y + beq badRef ; refnum 0 is BAD + sta oldRN + pha + jsl getFDptr + sta fdPtr + stx fdPtr+2 + ora fdPtr+2 + beq badRef + lda [fdPtr] + cmp #0 + bne okay +badRef lda #$43 + jmp GSOSReturn +okay anop + ldy #FDrefType + lda [fdPtr],y + cmp #FDgsos + beq typeOkay + cmp #FDpipe + beq notGSOS + + ldy #FDrefNum + lda [fdPtr],y + dec a + asl a + asl a + tax + + lda #3 + ldy #4 + sta [pBlock],y + + lda [pBlock] + cmp #3 + bcc gohome + + lda >DeviceNames+2,x + pha + lda >DeviceNames,x + pha + ldy #8 + lda [pBlock],y + pha + ldy #6 + lda [pBlock],y + pha + jsl copygs2res +gohome lda #0 + jmp GSOSReturn ; basically ignore the call. no harm +typeOkay lda [fdPtr] + ldy #2 + sta [pBlock],y + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + lda oldRN + ldy #2 + sta [pBlock],y + pla + jmp GSOSReturn +notGSOS lda #$58 + jmp GSOSReturn + END + +GNORefCommon START +oldRN equ 10 +fdPtr equ 12 + + ldy #2 + lda [pBlock],y + sta oldRN + pha + bne notzero + lda cmdNum + cmp #$2015 + jeq FlushSpecial + pla + lda #$43 + jmp GSOSReturn + +notzero jsl getFDptr + sta fdPtr + stx fdPtr+2 + lda [fdPtr] + cmp #0 + bne okay + lda #$43 + jmp GSOSReturn +okay anop + ldy #FDrefType + lda [fdPtr],y + cmp #FDgsos + beq typeOkay + jmp notGSOS + cmp #FDpipe + bne notGSOS + lda #0 + jmp GSOSReturn ; basically ignore the call. no harm +typeOkay lda [fdPtr] + ldy #2 + sta [pBlock],y + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + lda oldRN + ldy #2 + sta [pBlock],y + pla + jmp GSOSReturn +notGSOS lda #$58 + jmp GSOSReturn + +* Special case this: Flush() is the only routine here which can accept +* zero as a legal refnum; it should flush all open files, and we pass +* the call _unmodified_ into GS/OS for this reason. + +FlushSpecial anop + pla + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + jmp GSOSReturn + END + +GNONewLine START +oldRN equ 10 +fdrec equ 12 +trueRN equ 16 + + ldy #2 + lda [pBlock],y + sta oldRN + pha + jsl getFDptr + sta fdrec + stx fdrec+2 + ora fdrec+2 + beq badRef ; bad refnum + ldy #FDrefNum + lda [fdrec],y + cmp #0 + bne okay +badRef lda #$43 + jmp GSOSReturn +okay anop + sta trueRN + ldy #FDrefType + lda [fdrec],y + cmp #FDgsos + bne nlPipe + + lda trueRN + ldy #2 + sta [pBlock],y + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + lda oldRN + ldy #2 + sta [pBlock],y + pla + jmp GSOSReturn +nlPipe ldy #4 + lda [pBlock],y + ldy #FDNLenableMask + sta [fdrec],y + beq noerror + ldy #6 + lda [pBlock],y + ldy #FDNLnumChars + sta [fdrec],y + cmp #1 + bcc doerror + cmp #256+1 + bcs doerror + + ldy #8 + lda [pBlock],y + tax + iny2 + lda [pBlock],y + ldy #FDNLtable+2 + sta [fdrec],y + dey2 + txa + sta [fdrec],y + ldy #FDrefFlags + lda [fdrec],y + and #%1111111111110111 ; ~rfP16NEWL + sta [fdrec],y + +noerror lda #0 + jmp GSOSReturn +doerror ldy #FDNLenableMask + lda #0 + sta [fdrec],y + lda #$53 + jmp GSOSReturn + END + +GNORdWr START + using KernelStruct +files equ 10 +fdrec equ 14 +rn equ 18 + + ldx curProcInd + lda openFiles,x + sta files + lda openFiles+2,x + sta files+2 + ldy #2 + lda [pBlock],y + pha + sta rn + jsl getFDptr + sta fdrec + stx fdrec+2 + ora fdrec+2 + bne refIsOk + lda #$43 + jmp GSOSReturn +refIsOk ldy #FDrefType + lda [fdrec],y + asl a + tax + jmp (rdwrtable,X) + +rdwrtable dc i2'doGSOS' + dc i2'doPipe' + dc i2'doTTY' + dc i2'doSocket' + +******************* +doGSOS anop + ldy #FDrefNum + lda [fdrec],y + ldy #2 + sta [pBlock],y + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + ldy #2 + lda rn + sta [pBlock],y + pla + jmp GSOSReturn + +******************* +doPipe anop + jsl decBusy +; ph4 (pBlock)+2 + lda pBlock + clc + adc #2 + tay + lda pBlock+2 + adc #0 + pha + phy + ldy #FDrefNum + lda [fdrec],y + pha + lda cmdNum + cmp #$2012 + beq pread + jsl pipeHiWrite + bra goback +pread ph4 fdrec ; we need this for newline + jsl pipeHiRead +goback anop + jsl incBusy + jmp GSOSReturn + +******************* +doTTY anop + jsl decBusy + ldy #8 + lda [pBlock],y + pha + ldy #6 + lda [pBlock],y + pha + ldy #4 + lda [pBlock],y + pha + lda cmdNum + cmp #$2012 + beq tread + ldy #FDrefNum ; tty devId number + lda [fdrec],y + dec a + pha + ldy #t_write + jsl LineDiscDispatch + bra goaway2 +tread ldy #FDrefNum ; the tty device ID number + lda [fdrec],y + dec a + pha + ldy #t_read + jsl LineDiscDispatch +goaway2 anop + phx + ldy #12 + sta [pBlock],y ; to provide a way for TTYs to + lda #0 ; return EOF properly + ldy #14 + sta [pBlock],y + jsl incBusy + pla + jmp GSOSReturn + +******************* +doSocket anop + ldy #FDrefNum + lda [fdrec],y + pha + ph2 cmdNum +; ph4 pBlock + pei (pBlock+2) + lda pBlock + inc a + inc a + pha + jsl SOCKrdwr + jmp GSOSReturn + + END + +PGClose START + using KernelStruct + +rn equ 10 +files equ 12 +fdptr equ 16 +errno equ 20 +cnt equ 22 +level equ 24 + + stz errno + ldy #openFiles-CKernData ; get the address of the fd table + lda [procEnt],y + sta files + iny2 + lda [procEnt],y + sta files+2 + + ldy #0 + lda cmdNum + cmp #$0014 ; P16 refNum is at offset 0 + beq whichOS + lda [pBlock] + cmp #1 + beq pCountOkay + lda #$04 + jmp GSOSReturn +pCountOkay ldy #2 ; GSOS refNum is at offset 2 +whichOS lda [pBlock],y + sta rn + beq doClose0 + pha + jsl getFDptr + stx fdptr+2 + sta fdptr + ora fdptr+2 + beq refIsBad + + ph4 fdptr + jsl subClose + cmp #$43 + beq dontdecr + pha + lda [files] ; decr the # of open files + dec a + sta [files] + pla +dontdecr jmp GSOSReturn +refIsBad lda #$43 + jmp GSOSReturn +doClose0 anop + lda files + clc + adc #FDTTable + sta fdptr + lda files+2 + adc #0 + sta fdptr+2 + + ldy #FDTLevel ; calculate the actual + lda [files],y ; system level from the + ldy #FDTLevelMode ; user level setting + ora [files],y ; and the levelMode + sta level + + lda [files] ; number of entries + sta cnt +loop anop + lda cnt + beq doneClose0 + lda [fdptr] ; zero refNum means empty entry + beq nextEntry + +; ldy #FDTLevel ; handle 'internal' file levels +; lda [files],y ; like System 6 +; ldy #FDTLevelMode +; ora [files],y +; ldy #FDrefLevel +; cmp [fdptr],y +; bcs noclose + + lda level ; our calculated level + ldy #FDTLevel + cmp [files],y ; 'global' file level + bcc noclose + + ph4 fdptr + jsl subClose + cmp #0 + beq noerror + sta errno +noerror anop + lda [files] ; decr the # of open files + dec a + sta [files] +noclose dec cnt +nextEntry lda fdptr + clc + adc #FDsize + sta fdptr + lda fdptr+2 + adc #0 + sta fdptr+2 + bra loop +doneClose0 lda errno + jmp GSOSReturn + END + +subClose START +CLpCount equ 0 +CLrefNum equ 2 +err equ 4 + + subroutine (4:fdptr),6 + stz err + ldy #FDrefNum + lda [fdptr],y + bne validRN + lda #$43 + sta err + jmp errorRet + +validRN anop + ldy #FDrefType + lda [fdptr],y + + asl a + tax + jmp (closetable,X) + +closetable dc i2'subGSOS' + dc i2'subPipe' + dc i2'subTTY' + dc i2'subSocket' + +******************* +subSocket anop + ldy #FDrefNum + lda [fdptr],y + pha + pea FDsocket + jsl DecRefnum + cmp #0 ; there are still more references + bne subSock1 ; to this file, don't close it! + ldy #FDrefNum + lda [fdptr],y + pha + jsl SOCKclose + sta err +subSock1 jmp goaway + +******************* +subGSOS anop + ldy #FDrefNum + lda [fdptr],y + sta CLrefNum + pha + + lda #1 + sta CLpCount + pea FDgsos ; we know refType == gsos + jsl DecRefnum + cmp #0 ; there are still more references + bne goaway ; to this file, don't close it! + + pea $0000 ; stack is always in bank 0! + phd + pea $2014 ; command number + jsl OldGSOSSt + sta err + jmp goaway + +******************* +subPipe anop + + ldy #FDrefNum + lda [fdptr],y + pha + ldy #FDrefFlags + lda [fdptr],y + pha + jsl decPipe + ldy #FDrefNum + lda [fdptr],y + pha + pea FDpipe + jsl DecRefnum + cmp #0 + bne goaway + ldy #FDrefNum + lda [fdptr],y + pha + jsl disposePipe + +goaway anop + lda #0 + ldy #FDrefNum + sta [fdptr],y + ldy #FDrefType + sta [fdptr],y + +errorRet anop + return 2:err + +******************* +subTTY anop + ldy #FDrefNum + lda [fdptr],y + pha + pea FDtty + jsl DecRefnum + cmp #0 + bne goaway + +* Now, adjust the process group the terminal was in + ldy #FDrefNum + lda [fdptr],y + dec a + asl a + tax + lda ttyStruct,x + beq nopgrp ; no pgrp was set + dec a ; adjust, since pgrps start at + dec a ; number 2 + asl a + tay + lda #0 ; zero the pgrp + sta ttyStruct,x + tyx + lda pgrpInfo,x ; decrement the pgrp count + dec a + sta pgrpInfo,x + +nopgrp ldy #FDrefNum + lda [fdptr],y + dec a + pha + ldy #t_close ; shutdown the device driver + jsl LineDiscDispatch + + bra goaway + + END + +GNOGetName START + using KernelStruct +pathptr equ 10 +resptr equ 14 +outind equ 18 +inind equ 20 +pathlen equ 22 + +* Note that forked processes will get the name of their parent + lda [pBlock] + beq pcerr + cmp #3 + bcs pcerr + bra goaround +pcerr lda #4 + jmp GSOSReturn + +goaround anop + ldy #4 + lda [pBlock],y + sta resptr+2 + ldy #2 + lda [pBlock],y + sta resptr + + ldx curProcInd ; get the full pathname of + lda procUserID,x ; the process. + pha + pha ; space for tool call. ARGH!!! + pha + pea $1 + _LGetPathname2 + pl4 pathptr + lda [pathptr] + inc a + sta pathlen + tay + short m +loop lda [pathptr],y + cmp #':' + beq gotfname + dey + bra loop +gotfname long m + iny + sty inind + lda [pathptr] ; get length + sec + sbc inind ; length of filename + clc + adc #2 ; minus the length word + cmp [resptr] ; length of buffer? + beq okay ; <= is okay + bcs buffer2small +okay anop + ldy #2 + sta [resptr],y ; store length of filename + + ldy #4 + sty outind + short m +cploop ldy inind + lda [pathptr],y + ldy outind + sta [resptr],y + ldy inind + cpy pathlen + bcs donecopy + long m + inc inind + inc outind + short m + bra cploop +donecopy long m + lda [pBlock] + cmp #1 + beq done + ldx curProcInd + lda procUserID,x + ldy #6 + sta [pBlock],y +done lda #0 + jmp GSOSReturn + +buffer2small ldy #2 + sta [resptr],y + lda #$4F + jmp GSOSReturn ; buffer too small error + END + +GNOGetStdRefNum START + lda [pBlock] + cmp #2 + beq PCokay + lda #4 + jmp GSOSReturn + +PCokay ldy #2 + lda [pBlock],y + cmp #10 + bcc pfxerr + cmp #13 + bcs pfxerr + + sec + sbc #9 + ldy #4 + sta [pBlock],y + lda #0 + jmp GSOSReturn +pfxerr lda #$53 + jmp GSOSReturn + END diff --git a/kern/gno/inc/gsos.inc b/kern/gno/inc/gsos.inc new file mode 100644 index 0000000..8804176 --- /dev/null +++ b/kern/gno/inc/gsos.inc @@ -0,0 +1,23 @@ +* $Id: gsos.inc,v 1.1 1998/02/02 08:20:54 taubert Exp $ +* if you change FDsize, look for the comment "a * FDsize". You must +* change code there. + +FDsize gequ 16 +FDrefNum gequ 0 ; type and level must be so +FDrefType gequ 2 +FDrefLevel gequ 4 +FDrefFlags gequ 6 +FDNLenableMask gequ 8 +FDNLnumChars gequ 10 +FDNLtable gequ 12 + +FDgsos gequ 0 ; refTypes +FDpipe gequ 1 +FDtty gequ 2 +FDsocket gequ 3 + +FDTCount gequ 0 +FDTLevel gequ 2 +FDTLevelMode gequ 4 +FDTfdTableSize gequ 6 +FDTTable gequ 8 diff --git a/kern/gno/inc/kern.inc b/kern/gno/inc/kern.inc new file mode 100644 index 0000000..6fe77b6 --- /dev/null +++ b/kern/gno/inc/kern.inc @@ -0,0 +1,9 @@ +* $Id: kern.inc,v 1.1 1998/02/02 08:20:57 taubert Exp $ +* These equates are used in code that calls setHoldSig. + +hsHoldSig gequ 1 +hsNoHoldSig gequ 0 + +FL_SELECTING gequ $100 + +PS_SLEEP gequ 9 diff --git a/kern/gno/inc/tty.inc b/kern/gno/inc/tty.inc new file mode 100644 index 0000000..1fe3e40 --- /dev/null +++ b/kern/gno/inc/tty.inc @@ -0,0 +1,132 @@ +* $Id: tty.inc,v 1.1 1998/02/02 08:20:59 taubert Exp $ + +* Select codes +SEL_READ gequ 0 +SEL_WRITE gequ 1 +SEL_EXCEPT gequ 2 + +* Error codes +EINVAL gequ 6 ; Invalid argument +EBADF gequ 7 ; bad file descriptor +EINTR gequ 14 ; Interrupted system call +ENOTTY gequ 20 ; Not a terminal + +* privFlags: +HUPCL gequ 1 ; hang up modem on last close +EXCL gequ 2 ; don't allow any more opens +TS_RCOLL gequ 4 ; select collision flag + +* tty mode flags +CBREAK gequ $0002 /* half-cooked mode */ +LCASE gequ $0004 /* simulate lower case */ +ECHO gequ $0008 /* echo input */ +CRMOD gequ $0010 /* map \r to \r\n on output */ +RAW gequ $0020 /* no i/o processing */ +ODDP gequ $0040 /* get/send odd parity */ +EVENP gequ $0080 /* get/send even parity */ + +LCRTBS gequ $0001 /* do backspacing for crt */ +LPRTERA gequ $0002 /* \ ... / erase */ +LCRTERA gequ $0004 /* " \b " to wipe out char */ +LTILDE gequ $0008 /* hazeltine tilde kludge */ +LMDMBUF gequ $0010 /* start/stop output on carrier intr */ +LLITOUT gequ $0020 /* literal output */ +LTOSTOP gequ $0040 /* SIGSTOP on background output */ +LFLUSHO gequ $0080 /* flush output to terminal */ +LNOHANG gequ $0100 /* no SIGHUP on carrier drop */ +LPASS8OUT gequ $0200 /* 8 bit no parity for cooked output */ +LCRTKIL gequ $0400 /* kill line with " \b " */ +LPASS8 gequ $0800 /* 8 bit no parity for cooked input */ +LCTLECH gequ $1000 /* echo control chars as ^X */ +LPENDIN gequ $2000 /* tp->t_rawq needs reread */ +LDECCTQ gequ $4000 /* only ^Q starts after ^S */ +LNOFLSH gequ $8000 /* no output flush on signal */ + +B0 gequ 0 +B50 gequ 1 +B75 gequ 2 +B110 gequ 3 +B134 gequ 4 +B150 gequ 5 +B200 gequ 6 +B300 gequ 7 +B600 gequ 8 +B1200 gequ 9 +B1800 gequ 10 +B2400 gequ 11 +B4800 gequ 12 +B9600 gequ 13 +B19200 gequ 14 +EXTA gequ 14 +B38400 gequ 15 +EXTB gequ 15 + +* Definition of the tty structure + +sg_ispeed gequ 0 input speed +sg_ospeed gequ 1 output speed +sg_erase gequ 2 erase character +sg_kill gequ 3 kill character +sg_flags gequ 4 mode flags +local gequ 6 local mode flags (new driver) + +t_intrc gequ 8 +t_quitc gequ 9 +t_startc gequ 10 +t_stopc gequ 11 +t_eofc gequ 12 +t_brkc gequ 13 + +t_suspc gequ 14 +t_dsuspc gequ 15 +t_rprntc gequ 16 +t_flushc gequ 17 +t_werasc gequ 18 +t_lnextc gequ 19 + +ws_row gequ 20 +ws_col gequ 22 +ws_xpixel gequ 24 +ws_ypixel gequ 26 + +t_open gequ 28 +t_close gequ 32 +t_ioctl gequ 36 +t_read gequ t_ioctl+4 +t_write gequ t_read+4 +mutex gequ t_write+4 +demutex gequ mutex+4 +out_enq gequ demutex+4 +in_enq gequ out_enq+4 +out_deq gequ in_enq+4 +in_deq gequ out_deq+4 +size_inq gequ in_deq+4 +size_outq gequ size_inq+4 +editInd gequ size_outq+4 +editBegin gequ editInd+2 +st_flags gequ editBegin+2 +editBuf gequ st_flags+2 ; 4K input editing buffer +t_linedisc gequ editBuf+4 +t_devNum gequ t_linedisc+2 +privFlags gequ t_devNum+2 ; +t_sendSignal gequ privFlags+2 ; a jml statement +t_BGCheck gequ t_sendSignal+4 +t_GetProcInd gequ t_BGCheck+4 +t_userid gequ t_GetProcInd+4 +t_signalIO gequ t_userid+2 +t_select_proc gequ t_signalIO+4 +t_select gequ t_select_proc+2 ; the select function pointer +t_selwakeup gequ t_select+4 ; set during install +ttyRecSize gequ t_selwakeup+4 + +* pty structure additions - these are actually maintained in bank 0 +p_bufAptr gequ 0 +p_bufBptr gequ p_bufAptr+4 +p_Aleft gequ p_bufBptr+4 +p_Bleft gequ p_Aleft+2 +p_sem gequ p_Bleft+2 +p_Ahead gequ p_sem+2 +p_Atail gequ p_Ahead+2 +p_Bhead gequ p_Atail+2 +p_Btail gequ p_Bhead+2 +ptyRecSize gequ p_Btail+2 diff --git a/kern/gno/kern.asm b/kern/gno/kern.asm new file mode 100644 index 0000000..a6ed49e --- /dev/null +++ b/kern/gno/kern.asm @@ -0,0 +1,2314 @@ +* $Id: kern.asm,v 1.1 1998/02/02 08:19:28 taubert Exp $ + +* GNO Multitasking environment +* Low-level Kernel code +* Context switching, tool patch vector, CDA patches, +* process ID allocation, etc. +* Copyright 1991-1998, Procyon Software +* added select() timeout support - DT - 2/13/96 + + mcopy m/kern.mac + copy global.equates + case on + +TIMESLICE gequ 3 +NUM_DEFER gequ 16 + +;IncBusy gequ $E10064 +;DecBusy gequ $E10068 +BusyFlag gequ $E100FF + +**************************************************************************** +* Equates - Various equates required by these routines. +* +versionNumber gequ $0100 ; The version number of this library. + +dispatch1 gequ $e10000 ; The first toolbox dispatch vector. +dispatch2 gequ $e10004 ; The second toolbox dispatch vector. +ToolPointerTable gequ $e103c0 ; Pointer to the active System TPT. +UserToolPointerTable gequ $e103c8 ; Pointer to the active User TPT. + +; Error return values from the routines InstallE10000 and RemoveE10000 + +noError gequ $0000 ; Value returned if no error occurs. +badHeaderError gequ $8001 ; Patch header wasn't valid. +headerNotFoundError gequ $8002 ; Header to remove wasn't in the +; linked list. + +**************************************************************************** +* CheckPatch - Checks the passed toolbox dispatch vector to see if it +* points to a valid patch. +* +* Input: Passed via the stack following C conventions. +* newPatchAddr (long) - Address of the patch routine. +* +* Output: +* If newPatchAddr is a valid patch - +* Carry clear +* If newPatchAddr is not a valid patch - +* Carry set +* +CheckPatch START + +zprtl equ $01 ; The address for the rtl on our direct +; page. +newPatchAddr equ zprtl+3 ; Address of patch (parameter to this +; routine). + + tsc ; Make the stack the direct page after +; saving + phd ; the current direct page. + tcd + + + lda newPatchAddr+2 ; Simple check to check for a valid +; pointer. + and #$ff00 + bne BadPatch ; Wasn't zero, can't be a valid pointer. + + lda [newPatchAddr] ; Check for the first JML instruction. + and #$00ff + cmp #$005c + bne BadPatch + + ldy #$04 ; Check for the second JML instruction. + lda [newPatchAddr],y + and #$00ff + cmp #$005c + bne BadPatch + + ldy #$08 ; Check for the third JML instruction. + lda [newPatchAddr],y + and #$00ff + cmp #$005c + bne BadPatch + + ldy #$0c ; Check for the fourth JML instruction. + lda [newPatchAddr],y + and #$00ff + cmp #$005c + bne BadPatch + + ldy #$10 ; Check for the rtl and phk instructions. + lda [newPatchAddr],y + cmp #$4b6b + bne BadPatch + + iny ; Check for the phk and pea instructions. + lda [newPatchAddr],y + cmp #$f44b + bne BadPatch + + clc ; Calculate the address of the rtl +; instruction. + lda newPatchAddr + adc #$000f + ldy #$13 ; Check for address of the rtl +; instruction. + cmp [newPatchAddr],y + bne BadPatch + +GoodPatch anop + pld ; Restore the direct page and report + clc ; that it was a good patch. + rtl + +BadPatch anop + pld ; Restore the direct page and report + sec ; that something was wrong. + rtl + + END + +**************************************************************************** +* InstallE10000 - Sets the jump vector at $e10000 and $e10004 to point to +* the passed new toolbox dispatch vector patch. This routine +* also updates the linked lists so that more than one routine +* can be patched into the dispatch vectors. +* +* Input: Passed via the stack following C conventions. +* newPatchAddr (long) - Address of the patch routine. +* + +* Output: +* If an error occurred - +* Carry set, Accumulator contains one of the following error codes: +* badHeaderError +* If no error occurred and patch was installed successfully - +* Carry clear, Accumulator contains zero. +* +InstallE10000 START + +oldPatchAddr equ $01 ; Address of existing patch. +zprtl equ oldPatchAddr+4 ; The address for the rtl. +zpsize equ zprtl-oldPatchAddr ; Size of direct page we'll have on +; the stack. +newPatchAddr equ zprtl+3 ; Address of patch (parameter to +; this routine). + + tsc ; Move the stack pointer to point beyond + sec ; the direct page variables that we'll + sbc #zpsize ; place on the stack. + tcs + phd ; Save the direct page register. + tcd ; Set the direct page. + php ; Disable interrupts + sei + + pei newPatchAddr+2 ; Check if patch header is valid. + pei newPatchAddr + jsl CheckPatch + plx ; Remove the parameters from the stack. + plx + bcc x1 ; Report the badHeaderError if detected. + ldy #badHeaderError + jmp Exit + +x1 lda >dispatch1 ; Set up the next1Vector in the new patch. + sta [newPatchAddr] ; The JML instruction and low byte. + lda >dispatch1+2 + ldy #$02 + sta [newPatchAddr],y ; The middle and upper bytes. + + lda >dispatch2 ; Set up the next2Vector in the new patch. + ldy #$04 + sta [newPatchAddr],y ; The JML instruction and low byte. + lda >dispatch2+2 + ldy #$06 + sta [newPatchAddr],y ; The middle and upper bytes. + + lda >dispatch1+3 ; See if there's already a patch in +; dispatch1. + and #$00ff + sta oldPatchAddr+2 + pha ; High byte of possible header address. + lda >dispatch1+1 + sec + sbc #$0011 + sta oldPatchAddr + pha ; Low byte of possible header address. + jsl CheckPatch + plx + plx + bcs First ; JIF this will be the first patch +; installed. + + ldy #$08 ; Set up the dispatch1Vector in the new +; patch. + lda [oldPatchAddr],y + sta [newPatchAddr],y ; The JML instruction and low byte. + ldy #$0a + lda [oldPatchAddr],y + sta [newPatchAddr],y ; The middle and upper bytes. + + ldy #$0c ; Set up the dispatch2Vector in the new +; patch. + lda [oldPatchAddr],y + sta [newPatchAddr],y ; The JML instruction and low byte. + ldy #$0e + lda [oldPatchAddr],y + sta [newPatchAddr],y ; The middle and upper bytes. + + bra PatchIt ; Now patch dispatch1 and dispatch2. + +First ldy #$08 ; Set up the dispatch1Vector in the new +; patch. + lda >dispatch1 + sta [newPatchAddr],y ; The JML instruction and low byte. + ldy #$0a + lda >dispatch1+2 + sta [newPatchAddr],y ; The middle and upper bytes. + + ldy #$0c ; Set up the dispatch2Vector in the new +; patch. + lda >dispatch2 + sta [newPatchAddr],y ; The JML instruction and low byte. + ldy #$0e + lda >dispatch2+2 + sta [newPatchAddr],y ; The middle and upper bytes. + +PatchIt anop + clc ; Calculate the address of the new +; dispatch2. + lda newPatchAddr + adc #$0015 + sta newPatchAddr + xba + and #$ff00 ; Mask in the JML instruction. + ora #$005c + sta >dispatch2 ; The JML instruction and low byte. + lda newPatchAddr+1 + sta >dispatch2+2 ; The middle and upper bytes. + + sec ; Calculate the address of the new +; dispatch1. + lda newPatchAddr + sbc #$0004 + sta newPatchAddr + xba + and #$ff00 ; Mask in the JML instruction. + ora #$005c + sta >dispatch1 ; The JML instruction and low byte. + lda newPatchAddr+1 + sta >dispatch1+2 ; The middle and upper bytes. + + ldy #noError ; Report that all went well. + +Exit plp ; Restore the interrupt state. + pld ; Restore the previous direct page +; register. + tsc ; Restore the stack pointer. + clc + adc #zpsize + tcs + tya ; Value to return. + beq noerr + sec ; Report that there was an error. + rtl +noerr clc ; Report that there was no error. + rtl + + END + + +**************************************************************************** +* RemoveE10000 - Removes the specified patch from the dispatch1 and dispatch2 +* vectors and updates the linked lists for the remaining +* toolbox patches. +* +* Input: Passed via the stack following C conventions. +* patchToRemove (long) - Address of the patch to remove. +* +* Output: +* If an error occurred - +* Carry set, Accumulator contains one of the following error codes: +* badHeaderError +* headerNotFoundError +* If no error occurred and patch was removed successfully - +* Carry clear, Accumulator contains zero. +* +RemoveE10000 START + +patchDispAddr equ $01 ; Address of existing patch (and 1 +; extra byte). +prevHeader equ patchDispAddr+5 ; Used to search through the +; linked list. +zprtl equ prevHeader+4 ; The address for the rtl. +zpsize equ zprtl-patchDispAddr ; Size of direct page we'll have +; on the stack. +patchToRemove equ zprtl+3 ; Address of patch (parameter to +; this routine). + + tsc ; Move the stack pointer to point beyond + sec ; the direct page variables that we'll + sbc #zpsize ; place on the stack. + tcs + phd ; Save the direct page register. + tcd ; Set the direct page. + php ; Disable interrupts + sei + + pei patchToRemove+2 ; Check if patch header we were asked to + pei patchToRemove ; remove is a valid header. + jsl CheckPatch + plx ; Remove the parameters from the stack. + plx + bcc x1 ; Report the badHeaderError if detected. + ldy #badHeaderError + jmp Exit + +x1 clc ; Create the JML instruction that would +; exist + lda patchToRemove ; if the patchToRemove was installed. + adc #$0011 + sta patchDispAddr+1 + lda patchToRemove+2 + sta patchDispAddr+3 + lda patchDispAddr ; Mask in the JML instruction. + and #$ff00 + ora #$005c + sta patchDispAddr + + cmp >dispatch1 ; Check if the patch to remove is the +; first + bne NotFirstOne ; patch installed. + lda >dispatch1+2 + cmp patchDispAddr+2 + bne NotFirstOne + + lda [patchToRemove] ; Restore the Dispatch1 vector. + sta >dispatch1 + ldy #$02 + lda [patchToRemove],y + sta >dispatch1+2 + + + ldy #$04 ; Restore the Dispatch2 vector. + lda [patchToRemove],y + sta >dispatch2 + ldy #$06 + lda [patchToRemove],y + sta >dispatch2+2 + + bra NoErr ; Everything went well. + +NotFirstOne anop + sec ; Assume that whatever is in dispatch1 is + lda >dispatch1+1 ; patch and get the address of its header. + sbc #$0011 + sta prevHeader ; Low and middle bytes. + lda >dispatch1+3 + and #$00ff + sta prevHeader+2 ; Upper byte of header address. + +loop pei prevHeader+2 ; Check if it really is a valid header. + pei prevHeader + jsl CheckPatch + plx ; Remove the parameters from the stack. + plx + bcc x2 ; Report that the patch that we asked to + ldy #headerNotFoundError ; remove wasn't found. + bra Exit + +x2 lda [prevHeader] ; See if this patch points to patch we + cmp patchDispAddr ; want to remove. + bne nope + ldy #$02 + lda [prevHeader],y + cmp patchDispAddr+2 + bne nope + + lda [patchToRemove] ; Restore the next1Vector. + sta [prevHeader] + ldy #$02 + lda [patchToRemove],y + sta [prevHeader],y + + ldy #$04 ; Restore the next2Vector. + lda [patchToRemove],y + sta [prevHeader],y + ldy #$06 + lda [patchToRemove],y + sta [prevHeader],y + + bra NoErr ; Everything went well. + +nope ldy #$02 ; Get the address of the next patch +; header. + lda [prevHeader],y + tax + lda [prevHeader] + sta prevHeader + stx prevHeader+2 + + sec + lda prevHeader+1 + sbc #$11 + sta prevHeader + lda prevHeader+3 + and #$00ff + sta prevHeader+2 + + + bra loop ; Now check this header. + +NoErr ldy #noError ; Report that all went well. + +Exit plp ; Restore the interrupt state. + pld ; Restore the previous direct page +; register. + tsc ; Restore the stack pointer. + clc + adc #zpsize + tcs + tya ; Value to return. + beq xnoerr + sec ; Report that there was an error. + rtl +xnoerr clc ; Report that there was no error. + rtl + END + +toolV2Dat DATA KERN2 +t2Stack ds 128*32 + END + +**************************************************************************** +* PatchHeader - Header required of all routines that will be patched +* into the toolbox dispatch vectors. +* +* Note: The code between next1Vector and NewDispatch2 must be included +* for all calls. The code below NewDispatch2 only needs to be +* included for patches that want to post patch the calls. +* +PatchHeader START + using toolV2Dat + using KernelStruct + +next1Vector ENTRY ; Where dispatch1 should go when +; finished. + jml next1Vector ; (Filled in by InstallE10000). +next2Vector ENTRY ; Where dispatch2 should go when +; finished. + jml next2Vector ; (Filled in by InstallE10000). +dispatch1Vector ENTRY ; Holds the JML instruction from +; $e10000. + jml dispatch1Vector ; (Filled in by InstallE10000). +dispatch2Vector ENTRY ; Holds the JML instruction from +; $e10004. + jml dispatch2Vector ; (Filled in by InstallE10000). + +anRtl rtl ; An RTL instruction. Its address +; will be +* ; pushed on the stack for dispatch1 +; calls. + +NewDispatch1 ENTRY ; Entry point for dispatch1 toolbox +; vector. + + phk ; Push program bank. + pea anRtl-1 ; Push the address of a RTL. + +NewDispatch2 ENTRY ; Entry point for dispatch2 toolbox +; vector. + +; The following code should be included in the PatchHeader if the patch wants +; to perform post patching. This code will determine if the call that was +; made actually exists and if it does, post patching can occur. If the call +; doesn't exist, any pre-call routines can be executed, but the post patching +; shouldn't be attempted because the dispatcher will remove the second return +; address from the stack, thus not returning to your post patching routines. +; Stack equates for this routine. + +aLong equ $0001 ; A temporary long value. +oldDP equ aLong+4 ; Where the direct page is saved to. +oldTM equ oldDP+2 ; Where the tool call number is saved. + + phx ; Save the call that's being made. + phd ; Save the current direct page. + lda >ToolPointerTable+2 ; Get the TPT to determine the number + pha ; of tool sets loaded. + lda >ToolPointerTable + pha + tsc ; Set the direct page to the stack. + tcd + txa ; See if this tool set exits. + and #$00ff + cmp [aLong] ; Is it larger than the number of tool +; sets? + bcs noCall ; JIF this tool set doesn't exist. + asl a + asl a + tay ; Now get the pointer to the FPT. + lda [aLong],y + tax + iny + iny + lda [aLong],y + sta aLong+2 + stx aLong + lda oldTM ; Get the function number. + and #$ff00 + xba + cmp [aLong] ; Compare it to the number of entries in +; table. +noCall anop + pla ; Remove aLong from the stack. + pla + pld ; Restore the original direct page. + plx ; Recover the tool number. + bcs noCall2 ; don't pre patch, because we +* ; cannot post-patch + +; At this point the carry flag is set if the tool call doesn't exist and clear +; if the tool call exits. No post patching must occur if the carry flag is +; set. + + php + sei + phb + phk + plb ; 5,s + pha ; 3,s + phx ; 1,s + + jsl incBusy + + ldx curProcInd + lda t2StackPtr,x + asl a + asl a + clc + adc curProcInd ; add current proc offset + tax + lda 7,s + sta >t2Stack,x + short m + lda 9,s + sta >t2Stack+2,x + long m + ldx curProcInd + inc t2StackPtr,x + +* Now, put our return address on the stack instead + + short m + lda #^t2Return-1 + sta 9,s + long m + lda #t2Return-1 + sta 7,s + plx + pla + plb + plp +noCall2 anop + jmp next2Vector ; Go to the original $e10004 jump +; instruction. +t2Return anop + phb + pha ; space for return address + + php ; 6,s + sei + phb ; 5,s + phk + plb + pha ; 3,s + phx ; 1,s + + ldx curProcInd + lda t2StackPtr,x + dec a + sta t2StackPtr,x + asl a + asl a + clc + adc curProcInd + tax + short m + lda >t2Stack+2,x + sta 9,s + long m + lda >t2Stack,x + sta 7,s + plx + pla + plb + plp + jmp >decBusy +; jsl decBusy +; rtl + + END + +SaveAllPatch START + using toolV2Dat + using KernelStruct + using IgnoreInfo + + php + sei + long ai + + phb + phk + plb + pha + phx + phy +; jsl incBusy + + lda curProcInd + sta tcurProcInd + lda truepid + sta ttruepid + lda #0 + sta curProcInd + sta truepid + lda gsosDebug + sta tgsosDebug + stz gsosDebug + + +* we need to move some tool stack info to make it look like the kernel +* process called "SaveAll". + ldx tcurProcInd + lda t2StackPtr,x + dec a + sta t2StackPtr,x + asl a + asl a + clc + adc tcurProcInd + tax + lda >t2Stack,x + sta tstack + lda >t2Stack+2,x + sta tstack+2 + + lda t2StackPtr + asl a + asl a + tax + lda tstack + sta >t2Stack,x + lda tstack+2 + sta >t2Stack+2,x + lda t2StackPtr + inc a + sta t2StackPtr + + pushword #$0000 ; system tool set + pushword #$0C ; texttools + pushlong >oldTextTT ; thar she blows + _SetTSPtr + ply + plx + pla + plb + plp + dc i1'$5C' +OLDSAVEALL ENTRY + dc i4'0' + +RestAllPatch ENTRY + php + sei + long ai + + phb + phk + plb + pha + phx + phy + phd + + lda tcurProcInd + sta curProcInd + lda ttruepid + sta truepid + lda tgsosDebug + sta gsosDebug + +* we need to move some tool stack info to make it look like the interrupted +* process called "RestoreAll". + lda t2StackPtr + dec a + sta t2StackPtr + asl a + asl a + tax + lda >t2Stack,x + sta tstack + lda >t2Stack+2,x + sta tstack+2 + + ldx tcurProcInd + lda t2StackPtr,x + asl a + asl a + clc + adc tcurProcInd + tax + lda tstack + sta >t2Stack,x + lda tstack+2 + sta >t2Stack+2,x + ldx tcurProcInd + lda t2StackPtr,x + inc a + sta t2StackPtr,x + +; set the flag to ignore the next occurrences of those +; particular tools that are grieving us right now. +; for ROM 01 this works, as they only try to restore IN OUT, not ERR. + + lda #1 + sta ignSetInDev + sta ignSetInGlo + sta ignSetOutDev + sta ignSetOutGlo + pushword #$0000 ; system tool set + pushword #$0C ; texttools + pushlong #TTtable ; thar she blows + _SetTSPtr + +; jsl decBusy + pld + ply + plx + pla + plb + plp + +; ldx #0 +; ldy #0 +; jmp tool_exit + +gooldRest dc i1'$5C' +OLDRESTALL ENTRY + dc i4'0' + +savedCDAInfo ENTRY +tblockCP dc i2'0' ; FIXME - remove this +tcount dc i2'0' ; FIXME - remove this +tbufState dc i2'0' ; FIXME - remove this +ttruepid dc i2'0' +tcurProcInd dc i2'0' +tgsosDebug dc i2'0' +tstack dc i4'0' + END + +cdaPatch START + using KernelStruct + + php + lda >reschedFlag + inc a + sta >reschedFlag + lda 4,s + sta >rtlSave+2 + lda 1,s + sta 4,s + long m + lda 2,s + sta >rtlSave + pla + short m + pla + plp + +; jsl oldCDAVect + + php + php + php + php + short m + lda >rtlSave+2 + sta 4,s + long m + lda >rtlSave + sta 2,s + lda >reschedFlag + dec a + sta >reschedFlag + plp + rtl +rtlSave dc i4'0' + END + +; BrkVect +; kills the offending process +; gets info on the BRK by doing a GetInterruptState + +BrkVect START + using KernelStruct + + sei + clc ; (might not be necessary, but fuck it) + xce + phk + plb + long ai + jsl incBusy + + lda >curProcInd + tax + lda >lastTool,x + sta >brkState+20 + + pushlong #brkState + pushword #$14 + _GetInterruptState + + lda 4,s ; copy PC into record + sta brkState+13 + lda 2,s + sta brkState+14 + tsc ; copy S into record + sta brkState+6 + + pushlong #brkState + tsc + pha + jsl PRINTBRK + bra brkproc +BrkVect1 ENTRY + Using KernelStruct + + sei + clc ; (might not be necessary, but fuck it) + xce + phk + plb + long ai + jsl incBusy + + lda >curProcInd + tax + lda >lastTool,x + sta >brkState+20 + + pushlong #brkState + pushword #$14 + _GetInterruptState + + lda 2,s + sta brkState+$0E + short a + lda 4,s + sta brkState+$0D + long a + + pushlong #brkState + tsc + pha + jsl PRINTBRK +; jsr FlexBeep + +; kill() now resets mutex to 0 if prog crashes in mutex +brkproc anop + tsc + sta >$604 + + pha + pha + jsl KERNgetpid ; this is #pragma toolparms 1 + pea 9 + ph4 #killerr + jsl KERNkill ; this is #pragma toolparms 1 + pla +oops bra oops + +killerr dc i2'0' +brkState ds 32 + END + +; since the kernel null process doesn't _resched, we won't get in +; an 'exploding time slice' situation. Make sure null process never calls +; _resched + +CopVect START + using IntState + using KernelStruct + + clc + xce + long mx + php + phb + + sta >int_A ; save accumulator + lda #0 ; 0 indicates COP + sta >intType + +* start saving off the registers + short m + pla + sta >int_B ; save data bank + pla + sta >int_P ; save status of 'e' bit + + lda >$E0C02D + sta >int_SLTROM + lda >$E0C068 + sta >int_STATEREG + long a + +* the value of s that's saved shouldn't differ from the value upon +* entry + tsc + sta >int_S ; save stack pointer + + tdc + sta >int_D ; save direct page + phk + plb + stx int_X + sty int_Y ; save X & Y + lda >$E0C035 + and #%1111111111110111 ; don't ever change SHR shadowing + sta int_state + jsl contextSwitch +; restore stuff +newViaCOP ENTRY + long mx ; just for kicks + lda >$E0C035 ; don't ever change SHR shadowing + and #%0000000000001000 ; get old SHR shadow bit + ora >int_state + sta >$E0C035 + lda >int_Y + tay + lda >int_X + tax + lda >int_D + tcd + + short m + lda >int_B + pha + plb + lda >int_SLTROM + sta >$E0C02D + lda >int_STATEREG + sta >$E0C068 + + lda >int_P + pha + + long m + lda >int_A + plp + xce + rti + END + + longa on + longi on +InitKernel START + using KernelStruct +; TO CONSOLE +; using InOutData + phb + phk + plb + + move3 $E10071,oldBrk+1 +; move3 #BrkVect,$E10071 + + pha + pha + pea $5 + _GetVector + pl4 oldCop + +; move3 $E10015,oldCop + pea $5 + ph4 #CopVect + _SetVector +; move3 #CopVect,$E10015 + +; pha +; _MMStartUp +; pla +; sta userID +; kp->userID set in main.c + +; TO CONSOLE +; jsl InOutStart ; good enough here.... + jsl patchGSOS + jsr PatchText + jsl initvar + jsl patchRM + + ldx #0 +loop lda #0 + sta ParentProc,x + sta ProcessState,x + txa + clc + adc #procEntSize + tax + cpx #(procEntSize*NPROC) + bcc loop + lda #pRunning + sta ProcessState +; let's do it, dude! + + pushlong #alarmHB + _SetHeartBeat + + php ; jb 6/23/91 + sei ; jb 6/23/91 + move3 $E10069,oldDecBusy+1 + move3 #newDecBusy,$E10069 + move3 $E10011,oldInt+1 + move3 #IntHndl,$E10011 +; mv4 >$E10048,oldCDAvect +; move3 #CDAPatch,>$E10049 + + ph4 #PatchHeader + jsl InstallE10000 + ply + ply + plp ; jb 6/23/91 + plb + rtl + +DeInitKern ENTRY + pushlong #alarmHB + _DelHeartBeat + + pea $4 ; Interrupt Manager + ph4 oldInt+1 + _SetVector + pea $5 ; COP Manager + ph4 oldCop + _SetVector + + ph4 #PatchHeader + jsl RemoveE10000 + ply + ply + move3 oldDecBusy+1,$E10069 + move3 oldBrk+1,$E10071 +; mv4 oldCDAvect,>$E10048 + + jsl unPatchRM + jsl unpatchGSOS + jsr UnPatchText +; TO CONSOLE +; jsl InOutEnd + rtl +oldInt ENTRY + jmp >$000000 + dc i2'0' ; buffer space! +oldBrk ENTRY + jmp >$000000 +oldCop dc i4'0' +oldTool1 dc i4'0' +;oldCDAvect ENTRY +; dc i4'0' +oldDecBusy ENTRY + jmp >$000000 + END + +mapPID START + using KernelStruct +retval equ 0 + subroutine (2:pid),2 + + ldx #0 +lp anop + lda ProcessState,x + beq trynext ; no process here, don't check + lda flpid,x + cmp pid + beq gotit +trynext anop + txa + clc + adc #procEntSize + cmp #(procEntSize*NPROC) + bcs notfound + tax + bra lp +gotit txa + lsr a + lsr a + lsr a + lsr a + lsr a + lsr a + lsr a + +goaway anop + sta retval + return 2:retval +notfound lda #-1 + bra goaway ; my stupidity amazes me. NOT gotit + END + +allocPID START + using KernelStruct +retval equ 0 + subroutine (0:foo),2 + + jsl incBusy +lp0 anop + ldx #0 +lp anop + lda ProcessState,x + beq nextent + lda floatingPID + cmp flpid,x + beq trynext +nextent anop ; inc x to next entry + txa + clc + adc #procEntSize + cmp #(procEntSize*NPROC) + bcs gotone + tax + bra lp +trynext lda floatingPID + inc a + bpl inrange + lda #1 +inrange sta floatingPID + bra lp0 +gotone lda floatingPID + sta retval + inc a + bpl inrange2 + lda #1 +inrange2 sta floatingPID + jsl decBusy + return 2:retval + END + +IntState DATA +int_A dc i2'0' +int_X dc i2'0' +int_Y dc i2'0' +int_S dc i2'0' +int_D dc i2'0' +int_B dc i2'0' + +int_P dc i2'0' ; needed to go back to emulation mode +intType dc i2'0' +int_state dc i2'0' +int_SLTROM dc i1'0' +int_STATEREG dc i1'0' + END + +IntHndl START + using IntState + using KernelStruct + +; bvc nobrk +; jsr FlexBeep +; jmp BrkVect1 +nobrk anop + clc + xce + bcs ohmygod + php + short a + pha + lda $E1C046 + and #$08 + bne gotVBL +tofw pla + plp +ohmygod xce + jmp oldInt + +gotVBL anop + +; lda >reschedFlag +; sta >$E00626 + lda >timeleft + beq noMoreTime + dec a + sta >timeleft + bne tofw + +noMoreTime anop + lda #1 ;1 indicates VBL + sta >intType + pla +; sei + + long ai + sta >int_A ; save accumulator + + short a + lda >$E0C02D + sta >int_SLTROM + lda >$E0C068 + sta >int_STATEREG + pla + sta >int_P + phb + pla + sta >int_B ; save data bank + long a + tsc + sta >int_S ; save stack pointer + tdc + sta >int_D ; save direct page + + phk ; set up kernel's databank + plb + + txa + sta >int_X + tya + sta >int_Y ; save X & Y + + ldx curProcInd ; update the process' + lda ticks,x + adc #TIMESLICE + sta ticks,x + bcc nocarry + inc ticks+2,x +nocarry anop + + lda >$E0C035 + and #%1111111111110111 + sta >int_state + jsl contextSwitch +; restore stuff +newViaVBL ENTRY + long mx + lda >$E0C035 + and #%0000000000001000 + ora >int_state +; lda >int_state + sta >$E0C035 + lda >int_Y + tay + lda >int_X + tax + lda >int_D + tcd + + short a + lda >int_B + pha + plb + lda >int_SLTROM + sta >$E0C02D + lda >int_STATEREG + sta >$E0C068 + lda >int_P + pha + + long a + lda >int_A + plp + xce + jmp oldInt + END + +* Databank MUST be set up before entry + +contextSwitch Start + Using KernelStruct + Using IntState + +; there used to be a LONG here, but it's unnecessary + + lda >BusyFlag + beq humph + brl goaway + +humph anop + + lda #TIMESLICE + sta timeleft ; run me again please + + ldx curProcInd + jsr GetInterruptState + + ldx curProcInd + tsc +; sta irq_S1,x + +; if the process state isn't Running, the kernel wants to change it's status, +; so oblige it by not changing it to 'Ready' + + lda ProcessState,x + cmp #pRunning ; change of state? + bne findit + +spcl anop + lda #pReady + sta ProcessState,x +findit jsr FindNextEntry + stx curProcInd + txa + clc + adc #KernelStruct + sta >procPtr + lda #^KernelStruct + adc #0 + sta >procPtr+2 + + txa + lsr a + lsr a + lsr a + lsr a + lsr a + lsr a ; divide by 128 to get true pid + lsr a + sta truepid + +* Repair SANE's DP space + phd + lda >$E103CA + pha + lda >$E103C8 + pha + tsc + tcd + ldy #$A*4 + ldx curProcInd + lda SANEwap,x + sta [1],y + pla + pla + pld + + lda ProcessState,x + cmp #pNew + bne okay + +; the following code is hopelessly obtuse, but it basically creates information +; on the stack to simulate an interrupt, so that the new process starts it's +; time slice like every other one does + + lda #pRunning + sta ProcessState,x + dec irq_S,x ; make room on new stack + dec irq_S,x ; + dec irq_S,x ; + dec irq_S,x ; + jsr SetInterruptState ; set up A,X,Y, etc + lda irq_D,x + tcd + lda irq_S,x ; new proc's stack + tcs ; + lda irq_P,x ; + and #%11111011 ; make sure interrupts are on when + sta 1,S ; we start the new process + lda irq_PC,x ; fake an interrupt + sta 2,S ; on the new process' stack + short a + lda irq_K,x + sta 4,s + pha + plb + long a + lda >intType + bne vbl + jmp newViaCOP ; this is required in order to +vbl jmp newViaVBL ; turn off VBL if one occurred + + longa on ; grr stupid stupid m/x 816 + longi on ; fricken bits + +okay anop +* ; we'll return to COP or int hndl + jsr SetInterruptState + ldx curProcInd + lda #pRunning + sta ProcessState,x +; lda irq_S1,x +; clc +; adc #3 + lda irq_S,x + tcs + lda >intType + bne vbl1 + jmp newViaCOP ; this is required in order to +vbl1 jmp newViaVBL ; turn off VBL if one occurred + +goaway anop ; well, so much for that! + rtl +temp dc i4'0' +timState dc i2'0' +stat dc i2'0' + END + + longa on + longi on + +GetInterruptState START + using KernelStruct + using IntState + + lda int_A + sta irq_A,x + lda int_X + sta irq_X,x + lda int_Y + sta irq_Y,x + lda int_B + sta irq_B,x + lda int_P + sta irq_P,x + lda int_D + sta irq_D,x + lda int_S + sta irq_S,x + lda int_state + sta irq_state,x + lda int_SLTROM + sta irq_SLTROM,x + rts + END + +SetInterruptState START + using KernelStruct + using IntState + + lda irq_A,x + sta int_A + lda irq_X,x + sta int_X + lda irq_Y,x + sta int_Y + lda irq_B,x + sta int_B + lda irq_P,x + sta int_P + lda irq_D,x + sta int_D + lda irq_S,x + sta int_S + lda irq_state,x + sta int_state + lda irq_SLTROM,x + sta int_SLTROM + rts + END + +; we need FindNextEntry to return x -> ProcessState,x +; When we're of a mind to, rewrite this to support priority scheduling +; (it will involve keeping a queue of 'Ready' processes). + +FindNextEntry Start + Using KernelStruct + ldx curProcInd + txa + clc + adc #procEntSize + tax + cpx #(procEntSize*NPROC) + bmi loop + ldx #0 +loop lda ProcessState,x + cmp #pReady + beq found + cmp #pNew + beq found + txa + clc + adc #procEntSize + tax + + cpx #(procEntSize*NPROC) + bcc loop + ldx #0 + bra loop +found rts + End + +* if X is -1 then the FindEmptyEntry call failed +* this needs to return offset in ProcessState otherwise + +FindEmptyEntry Start + Using KernelStruct + ldx #procEntSize +loop lda ProcessState,x + cmp #pUnused + beq found + txa + clc + adc #procEntSize + tax + cpx #(procEntSize*NPROC) + bcc loop +notfound ldx #$FFFF +found rts + End + + +; the NASTY assembly interface to the process tables +; currently, eight process entries are defined, and this must be set +; manually if NUMPROC in the system header files are changed. Kinda yucky, +; but then there's no other way. + +KernelStruct DATA +CKernData ENTRY +ParentProc dc i2'-1' ;0 +ProcessState dc i2'0' ;2 +procUserID dc i2'0' ;4 +ttyID dc i2'0' ;6 +irq_A dc i2'0' ;8 +irq_X dc i2'0' ;10 +irq_Y dc i2'0' ;12 +irq_S dc i2'0' ;14 +irq_D dc i2'0' ;16 +irq_B dc i2'0' ;18 +irq_P dc i2'0' ;20 +irq_state dc i2'0' ;22 +irq_PC dc i2'0' ;24 +irq_K dc i2'0' ;26 +psem dc i2'0' ;28 +prefixh dc i4'0' ;30 +argsp dc i4'0' ;34 +env dc i4'0' ;38 +siginfo dc i4'0' ;42 +irq_SLTROM dc i1'0' ;46 +irq_STATEREG dc i1'0' ;47 +resapp anop +lastTool dc i2'0' ;48 +ticks dc i4'0' ;50 +flags dc i2'0' ;54 +openFiles dc i4'0' ;56 +pgrp dc i2'0' ;60 +exitCode dc i2'0' ;62 +LInfo dc i4'0' ;64 +stoppedState dc i2'0' ;68 +alarmCount dc i4'0' ;70 +executeHook dc i4'0' ;74 +queueLink dc i2'0' ;78 +waitq dc i4'0' ;80 +waitdone dc i2'0' ;84 +flpid dc i2'1' ;86 +retStack dc i4'0' ;88 +t2StackPtr dc i2'0' ;92 +p_uid dc i2'0' ;94 +p_gid dc i2'0' ;96 +p_euid dc i2'0' ;98 +p_egid dc i2'0' ;100 +SANEwap dc i2'0' ;102 +msg dc i4'0' ;104 +childTicks dc i4'0' ;108 +p_waitvec dc i4'0' ;112 +p_slink dc i2'0' ;116 +p_link dc i4'0' ;118 +p_rlink dc i4'0' ;122 +p_prio dc i2'0' ;126 +procEntSize gequ *-CKernData + +ProcessQueue ds 128*31 ; more o' the above +curProcInd dc i2'0' ; basically current process ID +userID dc i2'0' ; kernel userID +mutexNOMO dc i2'0' ; system-wide mutex flag. +timeleft dc i2'TIMESLICE' ; number of ticks left in timeslice +numProcs dc i2'1' ; number of processes active (inc.Null) +truepid dc i2'0' ; curProcInd/128 +shutdown dc i2'0' ; should the null process exit? +gsosDebug dc i2'0' ; GS/OS Debug level +floatingPID dc i2'2' ; next pid to allocate +reschedFlag dc i2'0' + END + +_asmresched START + using KernelStruct + +* give process our remaining time plus theirs + lda >timeleft + inc a + sta >timeleft + cop $7f ; force a context switch + rts + END + +vogue DATA + dc c'TIDDLYWINKS000000',h'00' + END + +NullProcess START + using KernelStruct + using sigQueue + using deferdata + +itself anop + +; check for deferred actions (probably from an interrupt handler to wake +; up a process) and execute them until no more are left. +defer_loop lda defer_num + beq no_defer + jsl exec_defer + bra defer_loop +no_defer anop + +* if a CDA event is pending across two consecutive runs of the nullprocess, +* GetNextEvent to initiate the CDA. +* Only do the check every four invocations of NullProcess to avoid +* unnecessary overhead + + dec loopcnt + bne noCDA + lda #4 + sta loopcnt + + pha + pea $0400 + ph4 #evtRecord + _EventAvail + pla + cmp #0 + beq noCDA + lda cdaFlag + cmp #1 + bcc justInc + pha + pea $0400 + ph4 #evtRecord + _GetNextEvent + pla + stz cdaFlag + bra noCDA + +justInc inc a + sta cdaFlag + +noCDA lda sighead + cmp sigtail + beq nosigs + jsl incBusy + lda sighead + asl a + tax + + pha + lda procs,x + pha + lda sigs,x + pha + ph4 #sigerr + jsl KERNkill ; this is #pragma toolparms 1 + pla + + lda sighead + inc a + sta sighead + cmp #32 + bcc inrange + stz sighead +inrange jsl decBusy + +nosigs anop + lda shutdown + bne endGNO ; kill() will shut down processes before this + jsl readyEntry + cpx #0 ; if it only found us, loop to avoid + beq jumpfuck ; interrupt overhead + cop $7f ; otherwise, let that process run +jumpfuck jmp itself +endGNO anop + rtl +sigerr dc i2'0' +loopcnt dc i2'4' +cdaFlag dc i2'0' +evtRecord ds 16 + END + +sigQueue DATA +sighead dc i2'0' +sigtail dc i2'0' +sigs ds 64 +procs ds 64 + END + +queueSignal START + using sigQueue + pha + phx + lda sigtail + asl a + tax + lda 1,s + sta sigs,x + lda 3,s + sta procs,x + + lda sigtail + inc a + sta sigtail + cmp #32 + bcc inrange + stz sigtail + +inrange plx + pla + rts + END + + longa off +alarmHB DATA + dc i4'0' +ALtimer dc i2'6' + dc h'5AA5' + END +alarmRoutine START + using alarmHB + using KernelStruct + using SelTimStruct + + php + long ai + + phb + phk + plb +; re-activate our heart beat entry + lda #6 + sta ALtimer + +; check for SIGALRM timeouts + ldx #0 +loop anop + lda ProcessState,x + cmp #pUnused + beq nextProc + lda alarmCount,x + ora alarmCount+2,x + beq nextProc + lda alarmCount,x + sec + sbc #1 + sta alarmCount,x + lda alarmCount+2,x + sbc #0 + sta alarmCount+2,x + ora alarmCount,x + bne nextProc + phx + lda flpid,x + ldx #14 + jsr queueSignal + plx +nextProc anop + txa + clc + adc #procEntSize + tax + cpx #(procEntSize*NPROC) + bcc loop + +; check for select() timeouts + ldx #0 +selloop anop + lda SelTimTimeout,x + ora SelTimTimeout+2,x + beq nextSel + lda SelTimTimeout,x + sec + sbc #1 + sta SelTimTimeout,x + lda SelTimTimeout+2,x + sbc #0 + sta SelTimTimeout+2,x + ora SelTimTimeout,x + bne nextSel + lda #1 + sta SelTimExpired,x + phx + lda SelTimPID,x ; wake up this PID + pha + pea 0 ; no collision + jsl selwakeup + plx +nextSel anop + txa + clc + adc #8 + tax + cpx #(8*NPROC) + bcc selloop + + plb + plp + rtl + END + +* AHHA! +* The remarkably simple new Kernel mutex method +* is totally based off of BusyFlag. Now things seem to work much +* smoother, and I can accomplish all sorts of stuff now. +* Yea, right, you dumbshit (jb 7/5/93) + +incBusy START +disableps ENTRY + jmp >$E10064 +decBusy ENTRY +enableps ENTRY + jmp >$E10068 + END + +newDecBusy START + using KernelStruct + + php + pha + jsl oldDecBusy + lda >timeleft + bne stillmore + lda >BusyFlag + bne stillmore + lda >reschedFlag + bne stillmore ; don't reschedule + +* We now allow a context switch when interrupts are off - this +* allows flawless execution of semaphore sleep code, etc. + + lda 3,s ; check the P reg- is the + bit #4 ; i bit set? if so, do not task + bne stillmore ; switch + + lda >$E100CB + and #$FF + bne stillmore ; we're in an interrupt handler! + + tsc + and #$FF00 + cmp #$0100 + beq stillmore + + pla + plp + jsl fakeACop +; cop $7f ; we're out o' time + rtl +stillmore pla + plp + rtl + + END + +ttyStruct START +pgrp dc 38i2'0' + END + +* BGCheck MUST MUST MUST be called only if the busy flag is zero +* otherwise, the process will not be suspended before it does the +* I/O procedure. +* Note that the use of this routine in TextTools to generate an error code +* is okay, because the only way for a program to have blocked or ignored +* the signal is to be aware of GNO, and if they do that they should check for +* errors from these texttools calls (which they should check for anyway). +* Input: A = signal number +* X = TTY device number +* needs to be in the kernel segment + +BGCheck START + using KernelStruct + +retval equ 1 +signum equ 1 +signum2 equ 5 +sigptr equ 1 + + phb + phk + plb + phd + pha ; push input parameter + tsc + tcd + + txa + asl a + tax + lda ttyStruct,x + beq nopgrp + ldx curProcInd + cmp pgrp,x + beq nopgrp ; it's the foreground process + lda siginfo+2,x + pha + lda siginfo,x + pha + tsc + tcd + lda #$0010 + ldy signum2 + cpy #21 + beq noasl + asl a +noasl ldy #2 + and [sigptr],y + bne sigblocked + lda signum2 + dec a + asl a + asl a + clc + adc #8 + tay + lda [sigptr],y + cmp #1 + bne notign + iny2 + lda [sigptr],y + cmp #0 + bne notign +* the signal is ignored or blocked, so do not send the signal, and +* tell the caller that we did not. +sigblocked pla + pla + pla + lda #-1 + pld + plb + rtl +* the signal was not ignored or blocked, so send the signal, +* tell the caller that we did, and return + +notign lda pgrp,x + pha + pei (signum2) + jsl asmkillpg + cop $7F + pla + pla + pla + lda #1 + pld + plb + rtl +* the caller was indeed in the TTY's process group, and so should be left +* quite alone. +nopgrp pla + lda #0 + pld + plb + rtl + END + +asmkillpg START + using KernelStruct + subroutine (2:pg,2:signum),0 + + ldx #128 ; don't EVER signal the kernel +sigloop lda ProcessState,x + cmp #pUnused + beq nextproc + lda pgrp,x + cmp pg + bne nextproc + + phx + lda flpid,x + ldx signum + jsr queueSignal + plx + +nextproc anop + txa + clc + adc #128 + tax + cpx #4096 ; oops! + bcc sigloop + return + END + +extQSignal START + using KernelStruct +space equ 0 + subroutine (2:s,2:p),space + lda p + ldx s + jsr queueSignal + return + END + +ttyQSignal START + using KernelStruct +space equ 0 + subroutine (2:s,2:tty),space + + lda tty + asl a + tax + lda ttyStruct,x + beq noSignal ; no process group + pha + ldx #128 ; don't EVER signal the kernel +sigloop lda ProcessState,x + cmp #pUnused + beq nextproc + lda pgrp,x + cmp 1,s + bne nextproc + + phx + lda >flpid,x + ldx s + jsr queueSignal + plx +nextproc anop + txa + clc + adc #128 + tax + cpx #4096 ; oops! + bcc sigloop + pla +noSignal return + END + +snooperInfo DATA KERN2 +blockLen dc i2'len-blockLen' +nameString str '~PROCYON~GNO~SNOOPER' +s_procTable dc i4'CKernData' +s_pipeTable dc i4'pipeRecord' +refTrack dc i4'pipeData' ; lots of dereffing, but hey! +queueSig dc i4'extQSignal' +info1 dc i4'savedCDAInfo' +reftty dc i4'ttyStruct' +refpgrp dc i4'pgrpInfo' +refRefTab dc i4'pipeData' +len equ * + END + +* At this point, the process RTL address is on the stack. Push the P +* register to complete simulating the interrupt environment. + +fakeACop START + php + sei + long m + pha + lda 4,s + inc a ; 'fix' rti address + sta 4,s + pla + jmp >CopVect + END + +readyEntry Start KERN2 + Using KernelStruct + + ldx #(1*procEntSize) +loop lda >ProcessState,x + cmp #pReady + beq found + cmp #pNew + beq found + txa + clc + adc #procEntSize + tax + + cpx #(procEntSize*NPROC) + bcc loop + ldx #0 + rtl +found rtl + End + +sleepbusy START KERN2 + php + sei + short m + lda >$E100FF + pha + lda #0 + sta >$E100FF + cop $7F + pla + sta >$E100FF + plp + rtl + END + + longa on + longi on + +exec_defer START + using deferdata +proc equ 0 +val1 equ 4 +val2 equ 6 + + subroutine (0:foo),8 + + phb + phk + plb + + php + sei + ldy defer_tail + tya + iny + cpy #NUM_DEFER + bne nowrap + ldy #0 +nowrap sty defer_tail + dec defer_num + asl a + asl a + tax + lda defertab,x + sta proc + lda defertab+2,x + sta proc+2 + lda defertab+4,x + sta val1 + lda defertab+6,x + sta val2 + plp + +; pass params in 'C' format + pei (val2) + pei (val1) +; push return address + phk + pea |comeback-1 +; push routine address + short m + lda proc+2 + pha + long m + lda proc + dec a + pha + rtl + +comeback anop + plb + return + + END + +defer START + using deferdata + subroutine (4:procPtr,2:val1,2:val2), + + phb + phk + plb + + php + sei + lda defer_num + cmp #NUM_DEFER + beq fail + + ldy defer_head + tya + iny + cpy #NUM_DEFER + bne nowrap + ldy #0 +nowrap sty defer_head + inc defer_num + asl a + asl a + tax + lda procPtr + sta defertab,x + lda procPtr+2 + sta defertab+2,x + lda val1 + sta defertab+4,x + lda val2 + sta defertab+6,x +fail1 plp + + plb + return +fail anop + short m + lda >$E0C034 + and #$F0 + pha + lda >$E0C034 + inc a + and #$F + ora 1,s + sta >$E0C034 + pla + long m + bra fail1 + END + +deferdata DATA +defer_head dc i2'0' +defer_tail dc i2'0' +defer_num dc i2'0' +defertab ds 8*NUM_DEFER + END + +k_sleep START + using KernelStruct + +hv equ 0 +last equ 2 +pid128 equ 4 + + subroutine (2:pid,2:pri,4:vec),6 + + jsl disableps + + lda vec hv = hash_vector(vec); + and #$3F + sta hv + lda pid + and #$00FF + xba + lsr a + sta pid128 + tax + lda vec + sta >p_waitvec,x + lda vec+2 + sta >p_waitvec+2,x + + lda hv + asl a + tax + lda >hv_tab,x + sta last + cmp #0 + bne addtoend + lda pid + sta >hv_tab,x + bra skip1 + +addtoend anop + and #$FF + xba + lsr a + tax + lda >p_slink,x + bne addtoend + +; last proc index is in X + + lda pid + sta >p_slink,x +skip1 lda #0 + ldx pid128 + sta >p_slink,x + pei (pid) + jsl dosleep + jsl sleepbusy + jsl enableps + return + END + + longa on + longi on +* used to be in signal.c, orig. C source still is +Kreceive START KERN2 + using KernelStruct + +tmp equ 0 + subroutine (4:errnoptr),4 + + lda >curProcInd + tax + + php + sei + lda #2 + sta >waitdone,x + lda >flags,x + bit #$0080 ; FL_MSGRECVD + bne gotmsg + lda #3 + sta >ProcessState,x + jsl sleepbusy +gotmsg lda >waitdone,x + cmp #2 + bne huhwhat + lda >msg,x + sta tmp + lda >msg+2,x + sta tmp+2 + lda >flags,x +; and #$0080.EOR.$FFFF + and #$FF7F + sta >flags,x + bra what2 +huhwhat lda #$FFFF + sta tmp + sta tmp+2 +what2 plp + return 4:tmp + END diff --git a/kern/gno/kern.rez b/kern/gno/kern.rez new file mode 100644 index 0000000..13d5f86 --- /dev/null +++ b/kern/gno/kern.rez @@ -0,0 +1,13 @@ +/* + * $Id: kern.rez,v 1.1 1998/02/02 08:20:08 taubert Exp $ + */ + +#include "Types.rez" // include the type definitions + +resource rVersion (1) { + {2,0,6,release,0}, + verUS, + "GNO Kernel (network)", + "Copyright 1991-1998, Procyon, Inc." + }; + diff --git a/kern/gno/kernel.h b/kern/gno/kernel.h new file mode 100644 index 0000000..4ac57d4 --- /dev/null +++ b/kern/gno/kernel.h @@ -0,0 +1,40 @@ +/* $Id: kernel.h,v 1.1 1998/02/02 08:18:30 taubert Exp $ */ + +/* kernel.h - disable, enable, halt, restore */ + +/* Symbolic constants used throughout Xinu */ + +#ifndef NULL +#define NULL (void*)0l +#endif + +typedef char Bool; /* Boolean type */ +#define FALSE 0 /* Boolean constants */ +#define TRUE 1 +#define SYSCALL int /* system call */ +#define LOCAL static /* local procedure */ +#define INTPROC int /* interrupt procedure */ +#define PROCESS int /* process declaration */ +#define RESCHYES 1 /* tell ready to reschedule */ +#define RESCHNO 0 /* tell not ready to reschedule */ +#define MININT 0100000 /* minimum short integer (-32768) */ +#define MAXINT 0077777 /* maximum short integer */ +#define MINSTK 40 /* minimum process stack size */ +#define OK 0 /* returned when system call ok */ +#define SYSERR -1 /* returned when system call fails */ + +/* actually these just fiddle with the interrupt from the timer */ + +#define disableps() asm { jsl 0xE10064 } +#define enableps() asm { jsl 0xE10068 } +#define _resched() asm { cop 0x7f } + +#define disable(oldmask) disableps() +#define enable() (void) KERNsigsetmask(&errno, 0) +#define restore(oldmask) enableps() + +extern int _rdyhead, _rdytail; +extern int mapPID(int); +extern int allocPID(void); +#define mpid2KToff(__m) ((__m) << 7) + diff --git a/kern/gno/kvm.h b/kern/gno/kvm.h new file mode 100644 index 0000000..b54f8b5 --- /dev/null +++ b/kern/gno/kvm.h @@ -0,0 +1,32 @@ +/* $Id: kvm.h,v 1.1 1998/02/02 08:18:32 taubert Exp $ */ + +/* + Kernel VM access routines + written June 4, 1991 by Jawaid Bazyar + mod. October 17, 1991 for new call paradigm + Copyright 1991-1998 Procyon, Inc. + + Note that there is absolutely no VM involved here, I simply kept the + same names as BSD/SunOS for compatibility. +*/ + +#ifndef __KVM_H__ +#define __KVM_H__ + +#include "proc.h" + +struct kvmt { + int procIndex; /* don't futz with this */ + int pid; /* you can use this to determine pid */ + struct pentry kvm_pent; +}; +typedef struct kvmt kvmt; + +kvmt *kvm_open(void); +int kvm_close(kvmt *k); +struct pentry *kvmgetproc(kvmt *kd, int pid); +struct pentry *kvmnextproc(kvmt *kd); +int kvmsetproc(kvmt *kd); + +#endif /* __KVM_H__ */ + diff --git a/kern/gno/m/ctool.mac b/kern/gno/m/ctool.mac new file mode 100644 index 0000000..eb078e4 --- /dev/null +++ b/kern/gno/m/ctool.mac @@ -0,0 +1,293 @@ + MACRO +&lab ErrWriteChar &a1 +&lab ph2 &a1 + Tool $190c + mend + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab _ErrWriteString +&lab ldx #$1D0C + jsl $E10000 + MEND + MACRO +&lab str &string +&lab dc i1'l:&string',c'&string' + MEND + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab asl2 &a +&lab asl &a + asl &a + mend + MACRO +&lab IntSource &a1 +&lab ph2 &a1 + tool $2303 + mend + MACRO +&lab _WriteCString +&lab ldx #$200C + jsl $E10000 + MEND + MACRO +&lab _QDStatus +&lab ldx #$0604 + jsl $E10000 + MEND + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/driver.mac b/kern/gno/m/driver.mac new file mode 100644 index 0000000..9468807 --- /dev/null +++ b/kern/gno/m/driver.mac @@ -0,0 +1,247 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + macro +&l dosin &adr +&l dc i"l:~&sysname&syscnt" +~&sysname&syscnt dc c"&adr" + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab LD4 &val,&adr +&lab lcla &count + lda #<&val +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda #+(&val)|-16 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/err.mac b/kern/gno/m/err.mac new file mode 100644 index 0000000..5310134 --- /dev/null +++ b/kern/gno/m/err.mac @@ -0,0 +1,221 @@ + MACRO +&lab Int2Hex &a1 +&lab ph2 &a1(1) + ph4 &a1(2) + ph2 &a1(3) + Tool $220b + mend + MACRO +&lab ErrWriteLine &a1 +&lab ph4 &a1 + Tool $1b0c + mend + MACRO +&lab ErrWriteString &a1 +&lab ph4 &a1 + Tool $1d0c + mend + MACRO +&lab ErrWriteCString &a1 +&lab ph4 &a1 + Tool $210c + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk1 + rep #%00100000 +.chk1 + aif "&char"<>"{",.chk2 +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + ldy #2 + lda (&parm),y + pha + lda (&parm) + pha + ago .shorten +.chk2 + aif "&char"<>"[",.absolute + ldy #2 + lda &parm,y + pha + lda &parm + pha + ago .shorten +.absolute + lda &parm+2 + pha + lda &parm + pha + ago .shorten +.at +&char1 amid &parm,2,1 +&char2 setc &char1 + ph&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + ph&char2 + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea +(&parm)|-16 + pea &parm + ago .done +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab Str &string +&lab dc i1'L:&string' + dc c"&string" + mend + MACRO +&lab proc &rg +&lab anop + aif c:&rg,.cc + lclc &rg +.cc + aif c:®,.dd + gblc ® +.dd +® setc "" + phb + aif l:&rg=0,.bb +® setc &rg + lcla &plen + lclc &ch + lcla &i +&plen seta l:® +&i seta 0 +.aa + aif &i=&plen,.bb +&i seta &i+1 +&ch amid ®,&i,1 + ph&ch + ago ^aa +.bb + phk + plb + mend + MACRO +&lab procendL +&lab anop + lclc &ch + lcla &plen +&plen seta l:® +.aa + aif &plen=0,.bb +&ch amid ®,&plen,1 + pl&ch +&plen seta &plen-1 + ago ^aa +.bb + plb + rtl + mend + MACRO +&lab add2 &arg1,&arg2,&dest + lclc &char +&lab clc +&char amid &arg1,1,1 + aif "&char"="@",.at1 + lda &arg1 + ago .add +.at1 +&char amid &arg1,2,1 + aif "&char"="x",.x1 + aif "&char"="X",.x1 + aif "&char"="y",.y1 + aif "&char"="Y",.y1 + ago .add +.x1 + txa + ago .add +.y1 + tya +.add + adc &arg2 +&char amid &dest,1,1 + aif "&char"="@",.at2 + sta &dest + ago .b +.at2 +&char amid &dest,2,1 + aif "&char"="x",.x2 + aif "&char"="X",.x2 + aif "&char"="y",.y2 + aif "&char"="Y",.y2 + ago .b +.x2 + tax + ago .b +.y2 + tay +.b + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/gsos.mac b/kern/gno/m/gsos.mac new file mode 100644 index 0000000..53bdce0 --- /dev/null +++ b/kern/gno/m/gsos.mac @@ -0,0 +1,527 @@ + MACRO +&lab pushlong &addr,&offset +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 + AIF "&C"="#",.immediate + AIF "&C"="[",.zeropage + AIF C:&offset=0,.nooffset + AIF "&offset"="s",.stack + pushword &addr+2,&offset + pushword &addr,&offset + MEXIT +.nooffset + pushword &addr+2 + pushword &addr + MEXIT +.immediate +&REST AMID &addr,2,L:&addr-1 + dc I1'$F4',I2'(&REST)|-16' + dc I1'$F4',I2'&REST' + MEXIT +.stack + pushword &addr+2,s + pushword &addr+2,s + MEXIT +.zeropage + ldy #&offset+2 + pushword &addr,y + ldy #&offset + pushword &addr,y + MEND + MACRO +&lab pushword &SYSOPR +&lab ANOP + AIF c:&SYSOPR=0,.b + LCLC &C +&C AMID "&SYSOPR",1,1 + AIF ("&C"="#").AND.(S:LONGA),.immediate + lda &SYSOPR + pha + MEXIT +.b + pha + MEXIT +.immediate + LCLC &REST + LCLA &BL +&BL ASEARCH "&SYSOPR"," ",1 + AIF &BL>0,.a +&BL SETA L:&SYSOPR+1 +.a +&REST AMID "&SYSOPR",2,&BL-2 + dc I1'$F4',I2'&REST' + MEND + MACRO +&lab ErrWriteChar &a1 +&lab ph2 &a1 + Tool $190c + mend + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab str &string +&lab dc i1'l:&string',c'&string' + MEND + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab movelong &from,&to1,&to2 +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &from,1,1 +&REST AMID &from,2,L:&from-1 + AIF "&C"="[",.zeropage + AIF C:&to2=0,.a + AIF ("&to1"="s").or.("&to1"="x").or.("&to1"="y"),.indexed + moveword &from,&to1,&to2 + AGO .b +.a + moveword &from,&to1 +.b + AIF "&C"="#",.immediate + AIF C:&to2=0,.c + moveword &from+2,&to1+2,&to2+2 + MEXIT +.c + moveword &from+2,&to1+2 + MEXIT +.immediate + AIF C:&to2=0,.d + moveword #^&REST,&to1+2,&to2+2 + MEXIT +.d + moveword #^&REST,&to1+2 + MEXIT +.zeropage + moveword &from,&to1,&to2 + ldy #&to1+2 + lda &from,y + sta &to2+2 + MEXIT +.indexed + lda &from,&to1 + sta &to2 + lda &from+2,&to1 + sta &to2+2 + MEND + MACRO +&lab moveword &from,&to1,&to2 +&lab ANOP + LCLC &C +&C AMID &from,1,1 + AIF "&C"="[",.zeropage + lda &from + sta &to1 + AIF C:&to2=0,.a + sta &to2 +.a + MEXIT +.zeropage + AIF "&to1"="0",.b + ldy #&to1 + lda &from,y + sta &to2 + MEXIT +.b + lda &from + sta &to2 + MEND + MACRO +&lab dey2 +&lab dey + dey + mend + MACRO +&lab LD2 &val,&adr +&lab lcla &count + lda #&val +&count seta 1 +.loop + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop +.done + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab FindHandle &a1,&a2 +&lab pha + pha + ph4 &a1 + tool $1a02 + pl4 &a2 + mend + MACRO +&lab _GetUserID +&lab ldx #$1011 + jsl $E10000 + MEND + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _LGetPathname2 +&lab ldx #$2211 + jsl $E10000 + MEND + MACRO +&lab LD4 &val,&adr +&lab lcla &count + lda #<&val +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda #+(&val)|-16 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/kern.mac b/kern/gno/m/kern.mac new file mode 100644 index 0000000..aaf1a3d --- /dev/null +++ b/kern/gno/m/kern.mac @@ -0,0 +1,454 @@ + MACRO +&lab pushlong &addr,&offset +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 + AIF "&C"="#",.immediate + AIF "&C"="[",.zeropage + AIF C:&offset=0,.nooffset + AIF "&offset"="s",.stack + pushword &addr+2,&offset + pushword &addr,&offset + MEXIT +.nooffset + pushword &addr+2 + pushword &addr + MEXIT +.immediate +&REST AMID &addr,2,L:&addr-1 + dc I1'$F4',I2'(&REST)|-16' + dc I1'$F4',I2'&REST' + MEXIT +.stack + pushword &addr+2,s + pushword &addr+2,s + MEXIT +.zeropage + ldy #&offset+2 + pushword &addr,y + ldy #&offset + pushword &addr,y + MEND + MACRO +&lab pushword &SYSOPR +&lab ANOP + AIF c:&SYSOPR=0,.b + LCLC &C +&C AMID "&SYSOPR",1,1 + AIF ("&C"="#").AND.(S:LONGA),.immediate + lda &SYSOPR + pha + MEXIT +.b + pha + MEXIT +.immediate + LCLC &REST + LCLA &BL +&BL ASEARCH "&SYSOPR"," ",1 + AIF &BL>0,.a +&BL SETA L:&SYSOPR+1 +.a +&REST AMID "&SYSOPR",2,&BL-2 + dc I1'$F4',I2'&REST' + MEND + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab str &string +&lab dc i1'l:&string',c'&string' + MEND + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _DelHeartBeat +&lab ldx #$1303 + jsl $E10000 + MEND + MACRO +&lab _ReadBParam +&lab ldx #$0C03 + jsl $E10000 + MEND + MACRO +&lab _SetHeartBeat +&lab ldx #$1203 + jsl $E10000 + MEND + MACRO +&lab _GetVector +&lab ldx #$1103 + jsl $E10000 + MEND + MACRO +&lab _SetVector +&lab ldx #$1003 + jsl $E10000 + MEND + MACRO +&lab _GetInterruptState +&lab ldx #$3103 + jsl $E10000 + MEND + MACRO +&lab move3 &from,&to1,&to2 +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &from,1,1 +&REST AMID &from,2,L:&from-1 + AIF C:&to2=0,.a + moveword &from,&to1,&to2 + AGO .b +.a +&lab moveword &from,&to1 +.b + AIF "&C"="#",.immediate + AIF C:&to2=0,.c + move1 &from+2,&to1+2,&to2+2 + MEXIT +.c + move1 &from+2,&to1+2 + MEXIT +.immediate + AIF C:&to2=0,.d + move1 #^&REST,&to1+2,&to2+2 + MEXIT +.d + move1 #^&REST,&to1+2 + MEND + MACRO +&lab moveword &from,&to1,&to2 +&lab ANOP + LCLC &C +&C AMID &from,1,1 + AIF "&C"="[",.zeropage + lda &from + sta &to1 + AIF C:&to2=0,.a + sta &to2 +.a + MEXIT +.zeropage + AIF "&to1"="0",.b + ldy #&to1 + lda &from,y + sta &to2 + MEXIT +.b + lda &from + sta &to2 + MEND + MACRO +&lab move1 &from,&to1,&to2 +&lab ANOP + shortm + lda &from + sta &to1 + AIF C:&to2=0,.a + sta &to2 +.a + longm + MEND + MACRO +&lab longm +&lab ANOP + rep #%00100000 + longa on + MEND + MACRO +&lab shortm +&lab ANOP + sep #%00100000 + longa off + MEND + MACRO +&lab _MMStartUp +&lab ldx #$0202 + jsl $E10000 + MEND + MACRO +&lab _SetTSPtr +&lab ldx #$0A01 + jsl $E10000 + MEND + MACRO +&lab _EventAvail +&lab ldx #$0B06 + jsl $E10000 + MEND + MACRO +&lab _GetNextEvent +&lab ldx #$0A06 + jsl $E10000 + MEND + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/p16.mac b/kern/gno/m/p16.mac new file mode 100644 index 0000000..e86863c --- /dev/null +++ b/kern/gno/m/p16.mac @@ -0,0 +1,352 @@ + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab pushlong &addr,&offset +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 + AIF "&C"="#",.immediate + AIF "&C"="[",.zeropage + AIF C:&offset=0,.nooffset + AIF "&offset"="s",.stack + pushword &addr+2,&offset + pushword &addr,&offset + MEXIT +.nooffset + pushword &addr+2 + pushword &addr + MEXIT +.immediate +&REST AMID &addr,2,L:&addr-1 + dc I1'$F4',I2'(&REST)|-16' + dc I1'$F4',I2'&REST' + MEXIT +.stack + pushword &addr+2,s + pushword &addr+2,s + MEXIT +.zeropage + ldy #&offset+2 + pushword &addr,y + ldy #&offset + pushword &addr,y + MEND + MACRO +&lab pushword &SYSOPR +&lab ANOP + AIF c:&SYSOPR=0,.b + LCLC &C +&C AMID "&SYSOPR",1,1 + AIF ("&C"="#").AND.(S:LONGA),.immediate + lda &SYSOPR + pha + MEXIT +.b + pha + MEXIT +.immediate + LCLC &REST + LCLA &BL +&BL ASEARCH "&SYSOPR"," ",1 + AIF &BL>0,.a +&BL SETA L:&SYSOPR+1 +.a +&REST AMID "&SYSOPR",2,&BL-2 + dc I1'$F4',I2'&REST' + MEND + MACRO +&lab movelong &from,&to1,&to2 +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &from,1,1 +&REST AMID &from,2,L:&from-1 + AIF "&C"="[",.zeropage + AIF C:&to2=0,.a + AIF ("&to1"="s").or.("&to1"="x").or.("&to1"="y"),.indexed + moveword &from,&to1,&to2 + AGO .b +.a + moveword &from,&to1 +.b + AIF "&C"="#",.immediate + AIF C:&to2=0,.c + moveword &from+2,&to1+2,&to2+2 + MEXIT +.c + moveword &from+2,&to1+2 + MEXIT +.immediate + AIF C:&to2=0,.d + moveword #^&REST,&to1+2,&to2+2 + MEXIT +.d + moveword #^&REST,&to1+2 + MEXIT +.zeropage + moveword &from,&to1,&to2 + ldy #&to1+2 + lda &from,y + sta &to2+2 + MEXIT +.indexed + lda &from,&to1 + sta &to2 + lda &from+2,&to1 + sta &to2+2 + MEND + MACRO +&lab moveword &from,&to1,&to2 +&lab ANOP + LCLC &C +&C AMID &from,1,1 + AIF "&C"="[",.zeropage + lda &from + sta &to1 + AIF C:&to2=0,.a + sta &to2 +.a + MEXIT +.zeropage + AIF "&to1"="0",.b + ldy #&to1 + lda &from,y + sta &to2 + MEXIT +.b + lda &from + sta &to2 + MEND + MACRO +&lab dey2 +&lab dey + dey + mend + MACRO +&lab ph4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk1 + rep #%00100000 +.chk1 + aif "&char"<>"{",.chk2 +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + ldy #2 + lda (&parm),y + pha + lda (&parm) + pha + ago .shorten +.chk2 + aif "&char"<>"[",.absolute + ldy #2 + lda &parm,y + pha + lda &parm + pha + ago .shorten +.absolute + lda &parm+2 + pha + lda &parm + pha + ago .shorten +.at +&char1 amid &parm,2,1 +&char2 setc &char1 + ph&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + ph&char2 + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea +(&parm)|-16 + pea &parm + ago .done +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _LGetPathname +&lab ldx #$1111 + jsl $E10000 + MEND + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/pipe.mac b/kern/gno/m/pipe.mac new file mode 100644 index 0000000..dff9f40 --- /dev/null +++ b/kern/gno/m/pipe.mac @@ -0,0 +1,329 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab str &string +&lab dc i1'l:&string',c'&string' + MEND + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab _SetHandleSize +&lab ldx #$1902 + jsl $E10000 + MEND + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab _DisposeHandle +&lab ldx #$1002 + jsl $E10000 + MEND + MACRO +&lab _NewHandle +&lab ldx #$0902 + jsl $E10000 + MEND + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab dey2 +&lab dey + dey + mend + MACRO +&lab getpid +&lab case on + jsl getpid + case off + MEND + MACRO +&lab _HLock +&lab ldx #$2002 + jsl $E10000 + MEND + MACRO +&lab _HUnlock +&lab ldx #$2202 + jsl $E10000 + MEND + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/pty.mac b/kern/gno/m/pty.mac new file mode 100644 index 0000000..7279839 --- /dev/null +++ b/kern/gno/m/pty.mac @@ -0,0 +1,278 @@ + MACRO +&lab _NewHandle +&lab ldx #$0902 + jsl $E10000 + MEND + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/regexp.mac b/kern/gno/m/regexp.mac new file mode 100644 index 0000000..f10b8c2 --- /dev/null +++ b/kern/gno/m/regexp.mac @@ -0,0 +1,210 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab LD2 &val,&adr +&lab lcla &count + lda #&val +&count seta 1 +.loop + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop +.done + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab add2 &arg1,&arg2,&dest + lclc &char +&lab clc +&char amid &arg1,1,1 + aif "&char"="@",.at1 + lda &arg1 + ago .add +.at1 +&char amid &arg1,2,1 + aif "&char"="x",.x1 + aif "&char"="X",.x1 + aif "&char"="y",.y1 + aif "&char"="Y",.y1 + ago .add +.x1 + txa + ago .add +.y1 + tya +.add + adc &arg2 +&char amid &dest,1,1 + aif "&char"="@",.at2 + sta &dest + ago .b +.at2 +&char amid &dest,2,1 + aif "&char"="x",.x2 + aif "&char"="X",.x2 + aif "&char"="y",.y2 + aif "&char"="Y",.y2 + ago .b +.x2 + tax + ago .b +.y2 + tay +.b + mend + MACRO +&lab if2 &var,&rel,&val,&label +&lab ago .skip + ble + bgt +.skip + lclc &char1 + lclc &char2 +&char1 amid &var,1,1 +&char2 amid &var,2,1 + aif "&char1"="@",.index + lda &var +.cmp + cmp &val + ago .branch +.index + aif "&char2"="x",.x1 + aif "&char2"="X",.x1 + aif "&char2"="y",.y1 + aif "&char2"="Y",.y1 + ago ^cmp +.x1 + cpx &val + ago .branch +.y1 + cpy &val +.branch +&char1 amid &rel,1,1 + aif "&char1"="@",.done + b&rel &label +.done + mend + MACRO +&lab bgt &loc +&lab beq *+4 + bcs &loc + mend + MACRO +&lab ble &loc +&lab bcc &loc + beq &loc + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/resource.mac b/kern/gno/m/resource.mac new file mode 100644 index 0000000..cdde72d --- /dev/null +++ b/kern/gno/m/resource.mac @@ -0,0 +1,355 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _SetTSPtr +&lab ldx #$0A01 + jsl $E10000 + MEND + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab _GetTSPtr +&lab ldx #$0901 + jsl $E10000 + MEND + MACRO +&lab _GetMapHandle +&lab ldx #$261E + jsl $E10000 + MEND + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/select.mac b/kern/gno/m/select.mac new file mode 100644 index 0000000..7ceed83 --- /dev/null +++ b/kern/gno/m/select.mac @@ -0,0 +1,442 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND + MACRO +&lab _PostEvent +&lab ldx #$1406 + jsl $E10000 + MEND + MACRO +&lab _ClampMouse +&lab ldx #$1C03 + jsl $E10000 + MEND + MACRO +&lab _SetAbsClamp +&lab ldx #$2A03 + jsl $E10000 + MEND + MACRO +&lab _SetMouse +&lab ldx #$1903 + jsl $E10000 + MEND + MACRO +&lab _HomeMouse +&lab ldx #$1A03 + jsl $E10000 + MEND + MACRO +&lab _ReadMouse +&lab ldx #$1703 + jsl $E10000 + MEND + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&LAB ~SETM +&LAB ANOP + AIF C:&~LA,.B + GBLB &~LA + GBLB &~LI +.B +&~LA SETB S:LONGA +&~LI SETB S:LONGI + AIF S:LONGA.AND.S:LONGI,.A + REP #32*(.NOT.&~LA)+16*(.NOT.&~LI) + LONGA ON + LONGI ON +.A + MEND + MACRO +&LAB ~RESTM +&LAB ANOP + AIF (&~LA+&~LI)=2,.I + SEP #32*(.NOT.&~LA)+16*(.NOT.&~LI) + AIF &~LA,.H + LONGA OFF +.H + AIF &~LI,.I + LONGI OFF +.I + MEND + MACRO +&LAB PL4 &N1 + LCLC &C +&LAB ANOP + AIF S:LONGA=1,.A + REP #%00100000 +.A +&C AMID &N1,1,1 + AIF "&C"<>"{",.B +&C AMID &N1,L:&N1,1 + AIF "&C"<>"}",.F +&N1 AMID &N1,2,L:&N1-2 + PLA + STA (&N1) + LDY #2 + PLA + STA (&N1),Y + AGO .D +.B + AIF "&C"<>"[",.C + PLA + STA &N1 + LDY #2 + PLA + STA &N1,Y + AGO .D +.C + PLA + STA &N1 + PLA + STA &N1+2 +.D + AIF S:LONGA=1,.E + SEP #%00100000 +.E + MEXIT +.F + MNOTE "Missing closing '}'",16 + MEND + MACRO +&LAB PH4 &N1 + LCLC &C +&LAB ANOP +&C AMID &N1,1,1 + AIF "&C"="#",.D + AIF S:LONGA=1,.A + REP #%00100000 +.A + AIF "&C"<>"{",.B +&C AMID &N1,L:&N1,1 + AIF "&C"<>"}",.G +&N1 AMID &N1,2,L:&N1-2 + LDY #2 + LDA (&N1),Y + PHA + LDA (&N1) + PHA + AGO .E +.B + AIF "&C"<>"[",.C + LDY #2 + LDA &N1,Y + PHA + LDA &N1 + PHA + AGO .E +.C + LDA &N1+2 + PHA + LDA &N1 + PHA + AGO .E +.D +&N1 AMID &N1,2,L:&N1-1 + PEA +(&N1)|-16 + PEA &N1 + AGO .F +.E + AIF S:LONGA=1,.F + SEP #%00100000 +.F + MEXIT +.G + MNOTE "Missing closing '}'",16 + MEND + MACRO +&LAB PH8 &N1 + MACRO +&LAB MUL4 &N1,&N2,&N3 +&LAB ~SETM + PH4 &N1 + PH4 &N2 + JSL ~MUL4 + AIF C:&N3,.A + PL4 &N1 + AGO .B +.A + PL4 &N3 +.B + ~RESTM + MEND diff --git a/kern/gno/m/shellcall.mac b/kern/gno/m/shellcall.mac new file mode 100644 index 0000000..0da184e --- /dev/null +++ b/kern/gno/m/shellcall.mac @@ -0,0 +1,432 @@ + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab dey2 +&lab dey + dey + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab MV2 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop +.done + mend + MACRO +&lab LD2 &val,&adr +&lab lcla &count + lda #&val +&count seta 1 +.loop + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop +.done + mend + MACRO +&lab ph4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk1 + rep #%00100000 +.chk1 + aif "&char"<>"{",.chk2 +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + ldy #2 + lda (&parm),y + pha + lda (&parm) + pha + ago .shorten +.chk2 + aif "&char"<>"[",.absolute + ldy #2 + lda &parm,y + pha + lda &parm + pha + ago .shorten +.absolute + lda &parm+2 + pha + lda &parm + pha + ago .shorten +.at +&char1 amid &parm,2,1 +&char2 setc &char1 + ph&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + ph&char2 + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea +(&parm)|-16 + pea &parm + ago .done +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab GSStr &string +&lab dc i2'L:&string' + dc c"&string" + mend + MACRO +&lab Destroy &a1 +&lab gsos $2002,&a1 + mend + MACRO +&lab Create &a1 +&lab gsos $2001,&a1 + mend + MACRO +&lab SetMark &a1 +&lab gsos $2016,&a1 + mend + MACRO +&lab GetEOF &a1 +&lab gsos $2019,&a1 + mend + MACRO +&lab Open &a1 +&lab gsos $2010,&a1 + mend + MACRO +&lab GetPrefixGS &a1 +&lab gsos $200A,&a1 + mend + MACRO +&lab Close &a1 +&lab gsos $2014,&a1 + mend + MACRO +&lab gsos &a1,&a2 +&lab jsl $E100A8 + dc i2'&a1' + dc i4'&a2' + mend + MACRO +&lab jcs &loc +&lab bcc *+5 + jmp &loc + mend + MACRO +&lab asl2 &a +&lab asl &a + asl &a + mend + MACRO +&lab LD4 &val,&adr +&lab lcla &count + lda #<&val +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda #+(&val)|-16 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab GetDirEntry &a1 +&lab gsos $201C,&a1 + mend + MACRO +&lab movelong &from,&to1,&to2 +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &from,1,1 +&REST AMID &from,2,L:&from-1 + AIF "&C"="[",.zeropage + AIF C:&to2=0,.a + AIF ("&to1"="s").or.("&to1"="x").or.("&to1"="y"),.indexed + moveword &from,&to1,&to2 + AGO .b +.a + moveword &from,&to1 +.b + AIF "&C"="#",.immediate + AIF C:&to2=0,.c + moveword &from+2,&to1+2,&to2+2 + MEXIT +.c + moveword &from+2,&to1+2 + MEXIT +.immediate + AIF C:&to2=0,.d + moveword #^&REST,&to1+2,&to2+2 + MEXIT +.d + moveword #^&REST,&to1+2 + MEXIT +.zeropage + moveword &from,&to1,&to2 + ldy #&to1+2 + lda &from,y + sta &to2+2 + MEXIT +.indexed + lda &from,&to1 + sta &to2 + lda &from+2,&to1 + sta &to2+2 + MEND + MACRO +&lab moveword &from,&to1,&to2 +&lab ANOP + LCLC &C +&C AMID &from,1,1 + AIF "&C"="[",.zeropage + lda &from + sta &to1 + AIF C:&to2=0,.a + sta &to2 +.a + MEXIT +.zeropage + AIF "&to1"="0",.b + ldy #&to1 + lda &from,y + sta &to2 + MEXIT +.b + lda &from + sta &to2 + MEND + macro +&lab popvariables &dcb +&lab ~setm + jsl $E100A8 + dc i2'$0117' + dc i4'&dcb' + ~restm + mend + macro +&lab pushvariables &dcb +&lab ~setm + jsl $E100A8 + dc i2'$0118' + dc i4'&dcb' + ~restm + mend + macro +&lab ~restm +&lab anop + aif (&~la+&~li)=2,.i + sep #32*(.not.&~la)+16*(.not.&~li) + aif &~la,.h + longa off +.h + aif &~li,.i + longi off +.i + mend + macro +&lab ~setm +&lab anop + aif c:&~la,.b + gblb &~la + gblb &~li +.b +&~la setb s:longa +&~li setb s:longi + aif s:longa.and.s:longi,.a + rep #32*(.not.&~la)+16*(.not.&~li) + longa on + longi on +.a + mend + MACRO +&lab push3 &addr,® +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 +&REST AMID &addr,2,L:&addr + AIF C:®>0,.indexed + AIF "&C"="#",.immediate + lda &addr+1 + pha + AGO .a +.immediate + lda #(&REST)|-8 + pha +.a + phb + lda &addr + sta 1,s + MEXIT +.indexed + lda &addr+1,® + pha + phb + lda &addr,® + sta 1,s + MEND + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + macro +&lab ExpandPath &a1 +&lab gsos $200E,&a1 + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/texttool.mac b/kern/gno/m/texttool.mac new file mode 100644 index 0000000..32e8ce0 --- /dev/null +++ b/kern/gno/m/texttool.mac @@ -0,0 +1,490 @@ + MACRO +&lab pulllong &addr1,&addr2 +&lab ANOP + AIF C:&addr1=0,.a + AIF C:&addr2=0,.b + LCLC &C +&C AMID &addr1,1,1 + AIF "&C"="[",.zeropage + pullword &addr1 + sta &addr2 + pullword &addr1+2 + sta &addr2+2 + MEXIT +.a + pullword + pullword + MEXIT +.b + pullword &addr1 + pullword &addr1+2 + MEXIT +.zeropage + ldy #&addr2 + pullword &addr1,y + ldy #&addr2+2 + pullword &addr1,y + MEND + MACRO +&lab pullword &SYSOPR +&lab ANOP + pla + AIF c:&SYSOPR=0,.end + sta &SYSOPR +.end + MEND + MACRO +&lab pushlong &addr,&offset +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 + AIF "&C"="#",.immediate + AIF "&C"="[",.zeropage + AIF C:&offset=0,.nooffset + AIF "&offset"="s",.stack + pushword &addr+2,&offset + pushword &addr,&offset + MEXIT +.nooffset + pushword &addr+2 + pushword &addr + MEXIT +.immediate +&REST AMID &addr,2,L:&addr-1 + dc I1'$F4',I2'(&REST)|-16' + dc I1'$F4',I2'&REST' + MEXIT +.stack + pushword &addr+2,s + pushword &addr+2,s + MEXIT +.zeropage + ldy #&offset+2 + pushword &addr,y + ldy #&offset + pushword &addr,y + MEND + MACRO +&lab pushword &SYSOPR +&lab ANOP + AIF c:&SYSOPR=0,.b + LCLC &C +&C AMID "&SYSOPR",1,1 + AIF ("&C"="#").AND.(S:LONGA),.immediate + lda &SYSOPR + pha + MEXIT +.b + pha + MEXIT +.immediate + LCLC &REST + LCLA &BL +&BL ASEARCH "&SYSOPR"," ",1 + AIF &BL>0,.a +&BL SETA L:&SYSOPR+1 +.a +&REST AMID "&SYSOPR",2,&BL-2 + dc I1'$F4',I2'&REST' + MEND + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab movelong &from,&to1,&to2 +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &from,1,1 +&REST AMID &from,2,L:&from-1 + AIF "&C"="[",.zeropage + AIF C:&to2=0,.a + AIF ("&to1"="s").or.("&to1"="x").or.("&to1"="y"),.indexed + moveword &from,&to1,&to2 + AGO .b +.a + moveword &from,&to1 +.b + AIF "&C"="#",.immediate + AIF C:&to2=0,.c + moveword &from+2,&to1+2,&to2+2 + MEXIT +.c + moveword &from+2,&to1+2 + MEXIT +.immediate + AIF C:&to2=0,.d + moveword #^&REST,&to1+2,&to2+2 + MEXIT +.d + moveword #^&REST,&to1+2 + MEXIT +.zeropage + moveword &from,&to1,&to2 + ldy #&to1+2 + lda &from,y + sta &to2+2 + MEXIT +.indexed + lda &from,&to1 + sta &to2 + lda &from+2,&to1 + sta &to2+2 + MEND + MACRO +&lab moveword &from,&to1,&to2 +&lab ANOP + LCLC &C +&C AMID &from,1,1 + AIF "&C"="[",.zeropage + lda &from + sta &to1 + AIF C:&to2=0,.a + sta &to2 +.a + MEXIT +.zeropage + AIF "&to1"="0",.b + ldy #&to1 + lda &from,y + sta &to2 + MEXIT +.b + lda &from + sta &to2 + MEND + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab _SetTSPtr +&lab ldx #$0A01 + jsl $E10000 + MEND + MACRO +&lab _GetTSPtr +&lab ldx #$0901 + jsl $E10000 + MEND + MACRO +&lab if2 &var,&rel,&val,&label +&lab ago .skip + ble + bgt +.skip + lclc &char1 + lclc &char2 +&char1 amid &var,1,1 +&char2 amid &var,2,1 + aif "&char1"="@",.index + lda &var +.cmp + cmp &val + ago .branch +.index + aif "&char2"="x",.x1 + aif "&char2"="X",.x1 + aif "&char2"="y",.y1 + aif "&char2"="Y",.y1 + ago ^cmp +.x1 + cpx &val + ago .branch +.y1 + cpy &val +.branch +&char1 amid &rel,1,1 + aif "&char1"="@",.done + b&rel &label +.done + mend + MACRO +&lab bgt &loc +&lab beq *+4 + bcs &loc + mend + MACRO +&lab ble &loc +&lab bcc &loc + beq &loc + mend + MACRO +&lab inx2 +&lab inx + inx + mend + MACRO +&lab push3 &addr,® +&lab ANOP + LCLC &C + LCLC &REST +&C AMID &addr,1,1 +&REST AMID &addr,2,L:&addr + AIF C:®>0,.indexed + AIF "&C"="#",.immediate + lda &addr+1 + pha + AGO .a +.immediate + lda #(&REST)|-8 + pha +.a + phb + lda &addr + sta 1,s + MEXIT +.indexed + lda &addr+1,® + pha + phb + lda &addr,® + sta 1,s + MEND + MACRO +&lab WriteChar &a1 +&lab ph2 &a1 + Tool $180c + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab _ReadChar +&lab ldx #$220C + jsl $E10000 + MEND + MACRO +&lab eor2 &arg1,&arg2,&dest +&lab anop + lclc &char +&char amid &arg1,1,1 + aif "&char"="@",.at1 + lda &arg1 + ago .add +.at1 +&char amid &arg1,2,1 + aif "&char"="x",.x1 + aif "&char"="X",.x1 + aif "&char"="y",.y1 + aif "&char"="Y",.y1 + ago .add +.x1 + txa + ago .add +.y1 + tya +.add + eor &arg2 +&char amid &dest,1,1 + aif "&char"="@",.at2 + sta &dest + ago .b +.at2 +&char amid &dest,2,1 + aif "&char"="x",.x2 + aif "&char"="X",.x2 + aif "&char"="y",.y2 + aif "&char"="Y",.y2 + ago .b +.x2 + tax + ago .b +.y2 + tay +.b + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab _SetInGlobals +&lab ldx #$090C + jsl $E10000 + MEND + MACRO +&lab _SetOutGlobals +&lab ldx #$0A0C + jsl $E10000 + MEND + MACRO +&lab _SetErrGlobals +&lab ldx #$0B0C + jsl $E10000 + MEND + MACRO +&lab _SetInputDevice +&lab ldx #$0F0C + jsl $E10000 + MEND + MACRO +&lab _SetOutputDevice +&lab ldx #$100C + jsl $E10000 + MEND + MACRO +&lab _SetErrorDevice +&lab ldx #$110C + jsl $E10000 + MEND + MACRO +&lab _FWEntry +&lab ldx #$2403 + jsl $E10000 + MEND + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/tty.mac b/kern/gno/m/tty.mac new file mode 100644 index 0000000..c2d2d23 --- /dev/null +++ b/kern/gno/m/tty.mac @@ -0,0 +1,407 @@ + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + macro +&lab ph4 &n1 + aif "&n1"="*",.f + lclc &c +&lab anop +&c amid &n1,1,1 + aif "&c"="#",.d + aif s:longa=1,.a + rep #%00100000 +.a + aif "&c"<>"{",.b +&c amid &n1,l:&n1,1 + aif "&c"<>"}",.g +&n1 amid &n1,2,l:&n1-2 + ldy #2 + lda (&n1),y + pha + lda (&n1) + pha + ago .e +.b + aif "&c"<>"[",.c + ldy #2 + lda &n1,y + pha + lda &n1 + pha + ago .e +.c + aif "&c"<>"<",.c1 +&n1 amid &n1,2,l:&n1-1 + pei &n1+2 + pei &n1 + ago .e +.c1 + lda &n1+2 + pha + lda &n1 + pha + ago .e +.d +&n1 amid &n1,2,l:&n1-1 + pea +(&n1)|-16 + pea &n1 + ago .f +.e + aif s:longa=1,.f + sep #%00100000 +.f + mexit +.g + mnote "Missing closing '}'",16 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND + MACRO +&lab _PostEvent +&lab ldx #$1406 + jsl $E10000 + MEND + MACRO +&lab _ClampMouse +&lab ldx #$1C03 + jsl $E10000 + MEND + MACRO +&lab _SetAbsClamp +&lab ldx #$2A03 + jsl $E10000 + MEND + MACRO +&lab _SetMouse +&lab ldx #$1903 + jsl $E10000 + MEND + MACRO +&lab _HomeMouse +&lab ldx #$1A03 + jsl $E10000 + MEND + MACRO +&lab _ReadMouse +&lab ldx #$1703 + jsl $E10000 + MEND + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + macro +&l sub &parms,&work +&l anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+4+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + aif &work=0,.f + sec + sbc #&work + tcs +.f + phd + tcd + mend + macro +&l ret &r +&l anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+2 + sta &worklen+&totallen+2 + lda &worklen+1 + sta &worklen+&totallen+1 +.i + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend diff --git a/kern/gno/m/util.mac b/kern/gno/m/util.mac new file mode 100644 index 0000000..a47a14b --- /dev/null +++ b/kern/gno/m/util.mac @@ -0,0 +1,373 @@ + MACRO +&lab if2 &var,&rel,&val,&label +&lab ago .skip + ble + bgt +.skip + lclc &char1 + lclc &char2 +&char1 amid &var,1,1 +&char2 amid &var,2,1 + aif "&char1"="@",.index + lda &var +.cmp + cmp &val + ago .branch +.index + aif "&char2"="x",.x1 + aif "&char2"="X",.x1 + aif "&char2"="y",.y1 + aif "&char2"="Y",.y1 + ago ^cmp +.x1 + cpx &val + ago .branch +.y1 + cpy &val +.branch +&char1 amid &rel,1,1 + aif "&char1"="@",.done + b&rel &label +.done + mend + MACRO +&lab bgt &loc +&lab beq *+4 + bcs &loc + mend + MACRO +&lab ble &loc +&lab bcc &loc + beq &loc + mend + MACRO +&lab add2 &arg1,&arg2,&dest + lclc &char +&lab clc +&char amid &arg1,1,1 + aif "&char"="@",.at1 + lda &arg1 + ago .add +.at1 +&char amid &arg1,2,1 + aif "&char"="x",.x1 + aif "&char"="X",.x1 + aif "&char"="y",.y1 + aif "&char"="Y",.y1 + ago .add +.x1 + txa + ago .add +.y1 + tya +.add + adc &arg2 +&char amid &dest,1,1 + aif "&char"="@",.at2 + sta &dest + ago .b +.at2 +&char amid &dest,2,1 + aif "&char"="x",.x2 + aif "&char"="X",.x2 + aif "&char"="y",.y2 + aif "&char"="Y",.y2 + ago .b +.x2 + tax + ago .b +.y2 + tay +.b + mend + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab ph4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk1 + rep #%00100000 +.chk1 + aif "&char"<>"{",.chk2 +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + ldy #2 + lda (&parm),y + pha + lda (&parm) + pha + ago .shorten +.chk2 + aif "&char"<>"[",.absolute + ldy #2 + lda &parm,y + pha + lda &parm + pha + ago .shorten +.absolute + lda &parm+2 + pha + lda &parm + pha + ago .shorten +.at +&char1 amid &parm,2,1 +&char2 setc &char1 + ph&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + ph&char2 + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea +(&parm)|-16 + pea &parm + ago .done +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab long &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi on +&t seta &t+16 + ago ^c +.m + longa on +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + rep #&t +.d + mend + MACRO +&lab short &stat +&lab anop + lcla &t + lcla &len + lclc &ch +&t seta 0 +&len seta l:&stat +.a + aif &len=0,.b +&ch amid &stat,&len,1 + aif ("&ch"="x").or.("&ch"="y").or.("&ch"="i"),.i + aif ("&ch"="a").or.("&ch"="m"),.m +.c +&len seta &len-1 + ago ^a +.i + longi off +&t seta &t+16 + ago ^c +.m + longa off +&t seta &t+32 + ago ^c +.b + aif &t=0,.d + sep #&t +.d + mend + MACRO +&lab LD2 &val,&adr +&lab lcla &count + lda #&val +&count seta 1 +.loop + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop +.done + mend + MACRO +&lab ErrWriteChar &a1 +&lab ph2 &a1 + Tool $190c + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab dey2 +&lab dey + dey + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/m/var.mac b/kern/gno/m/var.mac new file mode 100644 index 0000000..1d20562 --- /dev/null +++ b/kern/gno/m/var.mac @@ -0,0 +1,378 @@ + MACRO +&lab ph4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk1 + rep #%00100000 +.chk1 + aif "&char"<>"{",.chk2 +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + ldy #2 + lda (&parm),y + pha + lda (&parm) + pha + ago .shorten +.chk2 + aif "&char"<>"[",.absolute + ldy #2 + lda &parm,y + pha + lda &parm + pha + ago .shorten +.absolute + lda &parm+2 + pha + lda &parm + pha + ago .shorten +.at +&char1 amid &parm,2,1 +&char2 setc &char1 + ph&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + ph&char2 + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea +(&parm)|-16 + pea &parm + ago .done +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab pl4 &parm + lclc &char + lclc &char1 + lclc &char2 +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"<>"{",.chk +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ldy #2 + pla + sta (&parm),y + ago .shorten +.chk + aif "&char"<>"[",.chk2 + pla + sta &parm + ldy #2 + pla + sta &parm,y + ago .shorten +.chk2 + aif "&char"<>"@",.absolute +&char1 amid &parm,2,1 +&char2 setc &char1 + pl&char1 + aif l:&parm<3,.chk2a +&char2 amid &parm,3,1 +.chk2a + pl&char2 + ago .shorten +.absolute + pla + sta &parm + pla + sta &parm+2 +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab LD2 &val,&adr +&lab lcla &count + lda #&val +&count seta 1 +.loop + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop +.done + mend + MACRO +&lab MV4 &src,&adr +&lab lcla &count + lda &src +&count seta 1 +.loop1 + sta &adr(&count) +&count seta &count+1 + aif &count>c:&adr,.part2 + ago ^loop1 +.part2 + lda &src+2 +&count seta 1 +.loop2 + sta &adr(&count)+2 +&count seta &count+1 + aif &count>c:&adr,.done + ago ^loop2 +.done + mend + MACRO +&lab iny2 +&lab iny + iny + mend + MACRO +&lab dey2 +&lab dey + dey + mend + MACRO +&lab jeq &loc +&lab bne *+5 + jmp &loc + mend + MACRO +&lab jne &loc +&lab beq *+5 + jmp &loc + mend + MACRO +&lab jmi &loc +&lab bpl *+5 + jmp &loc + mend + MACRO +&lab subroutine &parms,&work +&lab anop + aif c:&work,.a + lclc &work +&work setc 0 +.a + gbla &totallen + gbla &worklen +&worklen seta &work +&totallen seta 0 + aif c:&parms=0,.e + lclc &len + lclc &p + lcla &i +&i seta c:&parms +.b +&p setc &parms(&i) +&len amid &p,2,1 + aif "&len"=":",.c +&len amid &p,1,2 +&p amid &p,4,l:&p-3 + ago .d +.c +&len amid &p,1,1 +&p amid &p,3,l:&p-2 +.d +&p equ &totallen+3+&work +&totallen seta &totallen+&len +&i seta &i-1 + aif &i,^b +.e + tsc + sec + sbc #&work + tcs + inc a + phd + tcd + phb + phk + plb + mend + MACRO +&lab return &r +&lab anop + lclc &len + aif c:&r,.a + lclc &r +&r setc 0 +&len setc 0 + ago .h +.a +&len amid &r,2,1 + aif "&len"=":",.b +&len amid &r,1,2 +&r amid &r,4,l:&r-3 + ago .c +.b +&len amid &r,1,1 +&r amid &r,3,l:&r-2 +.c + aif &len<>2,.d + ldy &r + ago .h +.d + aif &len<>4,.e + ldx &r+2 + ldy &r + ago .h +.e + aif &len<>10,.g + ldy #&r + ldx #^&r + ago .h +.g + mnote 'Not a valid return length',16 + mexit +.h + aif &totallen=0,.i + lda &worklen+1 + sta &worklen+&totallen+1 + lda &worklen + sta &worklen+&totallen +.i + plb + pld + tsc + clc + adc #&worklen+&totallen + tcs + aif &len=0,.j + tya +.j + rtl + mend + MACRO +&lab UDivide &a1,&a2 +&lab pha + pha + ph2 &a1(1) + ph2 &a1(2) + Tool $0b0b + pl2 &a2(1) + pl2 &a2(2) + mend + MACRO +&lab tool &a1 +&lab ldx #&a1 + jsl $e10000 + mend + MACRO +&lab ph2 &parm + lclc &char +&lab anop + aif c:&parm=0,.done +&char amid &parm,1,1 + aif "&char"="#",.immediate + aif "&char"="@",.at + aif s:longa=1,.chk + rep #%00100000 +.chk + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + lda (&parm) + pha + ago .shorten +.absolute + lda &parm + pha + ago .shorten +.immediate +&parm amid &parm,2,l:&parm-1 + pea &parm + ago .done +.at +&char amid &parm,2,1 + ph&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing closing '}'",16 + mend + MACRO +&lab pl2 &parm + lclc &char +&lab anop + aif s:longa=1,.start + rep #%00100000 +.start +&char amid &parm,1,1 + aif "&char"="@",.at + aif "&char"<>"{",.absolute +&char amid &parm,l:&parm,1 + aif "&char"<>"}",.error +&parm amid &parm,2,l:&parm-2 + pla + sta (&parm) + ago .shorten +.absolute + pla + sta &parm + ago .shorten +.at +&char amid &parm,2,1 + pl&char +.shorten + aif s:longa=1,.done + sep #%00100000 +.done + mexit +.error + mnote "Missing Closing '}'",16 + mend + MACRO +&lab asl2 &a +&lab asl &a + asl &a + mend + MACRO +&lab add4 &arg1,&arg2,&dest +&lab anop + lclc &ch +&ch amid &arg2,1,1 + clc + lda &arg1 + adc &arg2 + sta &dest + lda &arg1+2 + aif "&ch"="#",.a + adc &arg2+2 + ago .b +.a + adc &arg2|-16 +.b + sta &dest+2 + mend + MACRO +&lab name +&lab anop + aif DebugSymbols=0,.pastName + brl pastName&SYSCNT + dc i'$7771' + dc i1'L:&lab',c'&lab' +pastName&SYSCNT anop +.pastName + MEND diff --git a/kern/gno/main.c b/kern/gno/main.c new file mode 100644 index 0000000..82bb435 --- /dev/null +++ b/kern/gno/main.c @@ -0,0 +1,455 @@ +/* $Id: main.c,v 1.1 1998/02/02 08:18:33 taubert Exp $ */ + +segment "KERN2 "; + +#pragma stacksize 1024 +#pragma optimize 79 + +#include "proc.h" +#include "gno.h" +#include "sys.h" +#include "sem.h" +#include "tty.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef udispatch +#define udispatch 0xE10008 +#endif +extern pascal int kernStatus() inline(0x0603, udispatch); + +struct pentry *procPtr; + +#ifdef UNUSED_CODE +static void prResultString(ResultBuf255Ptr r) +{ +int i; + + putchar('('); + for (i = 0; i < r->bufString.length; i++) putchar(r->bufString.text[i]); + putchar(')'); + printf("[%d]",r->bufString.length); + putchar('\n'); +} +#endif + +kernelStructPtr kp; +int sysR; +char initX[80] = "9/gsh", initCmd[80] = "gsh"; + +static void doShell(void) +{ +int cl[2]; +GSString32 ttyPath = { 6, ".ttyco" }; +OpenRecGS o; +FILE *initf; + +#ifdef DEBUG_FIRST_FORK + WriteCString("\n\rInside doShell\n\r"); + ReadChar(0); +#endif + /* we don't want processes to inherit the sys.resources fd */ + cl[0] = 1; cl[1] = 0; CloseGS(cl); + + o.pCount = 3; + o.pathname = (GSString255Ptr) &ttyPath; /* our console driver mabob */ + o.requestAccess = readEnable; + OpenGS(&o); /* open stdin */ + o.requestAccess = writeEnable; + OpenGS(&o); /* open stdout */ + o.requestAccess = writeEnable; + OpenGS(&o); /* open stderr */ + + initf = fopen("9/initrc","r"); + if (initf) { + fgets(initX,80,initf); + initX[strlen(initX)-1] = 0; /* take off trailing \r */ + fgets(initCmd,80,initf); + initCmd[strlen(initCmd)-1] = 0; /* take off trailing \r */ + fclose(initf); + } + + cl[0] = 0; + PUSH_VARIABLES(cl); +#ifdef DEBUG_FIRST_FORK + WriteCString("Calling Kexecve()\n\r"); + ReadChar(0); +#endif + Kexecve(&errno,initCmd,initX); + WriteCString("\n\rCould not locate: "); + WriteCString(initX); + WriteCString("\n\r"); + if (initf) + WriteCString("error in INITRC configuration file\n\r"); + else + WriteCString("could not find INITRC configuration file\n\r"); + WriteCString("Press a key to exit GNO\n\r"); + ReadChar(0); +} + +GSString255Ptr __C2GSMALLOC(char *s) +{ +GSString255Ptr g; +size_t l; + + l = strlen(s); + g = malloc(l+2); + g->length = l; + memcpy(g->text,s,l); + return g; +} + +static int numDrivers; +static int driverUserID[16]; +GSString255Ptr DeviceNames[40]; + +extern void InstallDriver(int,int,void *); + +static void setuppty(void) +{ +char pty[] = ".ptyq0"; +char tty[] = ".ttyq0"; +const char conv[] = "0123456789abcdef"; +unsigned int ptyno, slotno; +extern PTYMastHeader; +extern PTYSlaveHeader; + + slotno = 6; + for (ptyno = 0; ptyno < 16; ptyno++) { + tty[5] = pty[5] = conv[ptyno]; + DeviceNames[slotno] = __C2GSMALLOC(pty); + DeviceNames[slotno+1] = __C2GSMALLOC(tty); + InstallDriver(kp->userID, slotno, &PTYMastHeader); + InstallDriver(kp->userID, slotno+1, &PTYSlaveHeader); + slotno+=2; + } +} + +static void setuptty(void) +{ +static char line[80]; +char *line1; +FILE *ttys; +word ILuserID; +InitialLoadOutputRec il_rec; +int e; +static GSString255 filename; +int devNum; +static char devname[20]; +extern ConsoleHeader; + + numDrivers = 0; + + strcpy(line,"9:dev:"); /* all loaded devices are referenced from 9:dev */ + line1 = line+6; + setuppty(); /* install 16 pty devices */ + + /* .ttyco is not loadable quite yet... */ + DeviceNames[3] = __C2GSMALLOC(".ttyco"); + InstallDriver(kp->userID,3,&ConsoleHeader); + + ttys = fopen("9/etc/tty.config","r"); + while (!feof(ttys)) { + fgets(line1,80,ttys); + if (strlen(line1) < 2) continue; /* skip blank lines */ + if (line1[0] == '#') continue; /* skip comment lines */ + sscanf(line,"%s %d %s", filename.text, &devNum, devname); + filename.length = strlen(filename.text); +#ifdef DEBUG_DRIVER_LOAD + printf("filename:%s, devNum:%d, devname:%s\n",filename.text,devNum,devname); +#endif + DeviceNames[devNum] = __C2GSMALLOC(devname); + + /* InitialLoad device file */ + ILuserID = (kp->userID & 0xF0FF) | (((devNum+2) & 0xf) << 8); + il_rec = InitialLoad2(ILuserID, (Pointer)&filename, 1, 1); + if ((e = toolerror())) { + printf("Could not load driver: %s, error: %04X\n",filename.text,e); + } else { + InstallDriver(ILuserID & 0xF0FF, devNum, il_rec.startAddr); + driverUserID[numDrivers++] = ILuserID; + } + } + fclose(ttys); +} + +static char *pg = "\pProcyon~GNOME~"; +QuitRecGS quitParms; +static PrefixRecGS pr; +static GetRefNumRecGS grn; + +int main(int argc, char *argv) +{ +extern void NullProcess(void); +extern void test(void); +extern void ROUTINE5(void); +extern CKernData; +extern TEXTTOOLSINFO; +extern void TESTPROC(void); +extern void InitRefnum(void); +extern void AddRefnum(int,int); +extern void init_htable(void); +extern void initPTY(void); +extern int pinit(int); +extern void GetDaMouseMod(void); +extern void InOutStart(void); +extern void InOutEnd(void); +int newPID,stat; +handle fstack; +extern kernTable[]; +ResultBuf255Ptr p0; +GSString255Ptr sysRpath; +struct pentry *p; +word state; +byte slot, statereg; +int i; +char *kptr; +GSString255Ptr *pfxRec; +handle emdp; +extern snooperInfo; +word nargs = 0; + + TextStartUp(); + SetInGlobals(0xFF,0x00); + SetOutGlobals(0xFF,0x00); + SetErrGlobals(0xFF,0x00); + SetInputDevice(pascalType,3l); + SetOutputDevice(pascalType,3l); + SetErrorDevice(pascalType,3l); + InitTextDev(input); + InitTextDev(output); + InitTextDev(errorOutput); + + kernStatus(); + if (!toolerror()) { + printf("GNO Kernel already active\n"); + exit(1); + } + MessageByName(1,(Pointer)&snooperInfo); + quitParms.pCount = 0; + TLStartUp(); + + printf("%c\nGNO Kernel v2.0.6 (network)\n",12); + printf("Copyright 1991-1998, Procyon, Inc.\n%c",6); + /* initialize kernel queues, etc */ + SetTSPtr(0x8000, 3, (Pointer)kernTable); + kp = (kernelStructPtr) &CKernData; +#ifdef DEBUG_STARTUP + printf("\nmain thinks kp is :%08lX\n",kp); +#endif + kp->userID = userid(); +#ifdef DEBUG_GSOS + kp->gsosDebug = ~0; +#endif + + emdp = NewHandle(0x0100l,kp->userID,0xC005,0l); + i = _toolErr; + EMStartUp((word)*emdp,0,0,0,0,0,kp->userID); +#ifdef DEBUG_STARTUP + printf("After EMStartUp\n"); +#endif + GetDaMouseMod(); + /* mouseMode = ReadMouse(); */ +#ifdef DEBUG_STARTUP + printf("After GetDaMouseMod\n"); +#endif + +/* start up kernel subsections */ + _seminit(); +#ifdef DEBUG_STARTUP + printf("After _seminit\n"); +#endif + + p0 = malloc(sizeof(ResultBuf255)); + p0->bufSize = 255; + + procPtr = p = &(kp->procTable[0]); + p->userID = kp->userID & 0xF0FF; + p->ttyID = 3; + p->prefix = malloc(33*sizeof(GSString255Ptr)); + + for (i = -1; i < 32; i++) { + pr.pCount = 2; + pr.prefixNum = i; + pr.buffer.getPrefix = p0; + GetPrefixGS(&pr); + p->prefix[i+1] = malloc(p0->bufString.length+2); + copygsstr(p->prefix[i+1],&p0->bufString); + } + nfree(p0); + + p->siginfo = malloc(sizeof(struct sigrec)); + memset(p->siginfo, 0, sizeof(struct sigrec)); + /* allocate the file table with the initial number of files */ + i = sizeof(fdentry)*(FD_SIZE-1); + p->openFiles = malloc(sizeof(fdtable)+i); + memset(p->openFiles, 0, sizeof(fdtable)+i); + p->openFiles->fdTableSize = FD_SIZE; + p->alarmCount = 0l; + + sysRpath = malloc(sizeof(GSString255)); + strcpy(sysRpath->text,"*:system:system.setup:sys.resources"); + sysRpath->length = strlen(sysRpath->text); + grn.pCount = 4; + grn.pathname = sysRpath; + grn.resNum = 1; + GetRefNumGS(&grn); + nfree(sysRpath); + sysR = grn.refNum; + if (sysR == 0) { + printf("FATAL SYSTEM ERROR: Sys.Resources file isn't open!\n" + "hit a key to exit\n"); + ReadChar(0); + exit(1); + } + p->openFiles->fdCount = 1; + p->openFiles->fdLevelMode = 0x8000; + p->openFiles->fdLevel = 1; + p->openFiles->fds[sysR-1].refNum = sysR; + p->openFiles->fds[sysR-1].refLevel = 30; + + InitRefnum(); +#ifdef DEBUG_STARTUP + printf("After InitRefnum\n"); +#endif + AddRefnum(0 /*FDgsos*/, sysR); + + asm { + lda 0xE0C035 + sta state + sep #0x30 + lda 0xE0C02D + sta slot + lda 0xE0C068 + sta statereg + rep #0x30 + } + p->irq_state = state; + p->irq_SLTROM = slot; + p->irq_STATEREG = statereg; + p->ticks = 0l; + p->flags = FL_FORKED | FL_COMPLIANT; + p->parentpid = -1; + p->LInfo = NULL; + p->executeHook = NULL; + p->flpid = 1; + p->waitq = NULL; + p->args = "BYTEWRKSNullProcess\0"; + p->alarmCount = 0l; + p->SANEwap = (word) GetWAP(0,0xA); + + pinit(MAXMSGS); + init_htable(); + setuptty(); /* initialize the tty subsystem and load drivers */ + initPTY(); +#ifdef DEBUG_STARTUP + printf("After initPTY\n"); +#endif + + /* do when console driver is loaded */ + InOutStart(); +#ifdef DEBUG_STARTUP + printf("After InOutStart\n"); +#endif + + patchTools(); +#ifdef DEBUG_STARTUP + printf("After patchTools\n"); +#endif + /* Last chance to use a printf() in the kernel's context */ + InitKernel(); + + /* + * Orca/C 2.0.1 fd based printf()s won't work from this point on in + * the kernel's context (NullProcess) because gno doesn't use + * fd -1 -2 -3 like Orca does, and fd 1 2 3 aren't open. + * printf()s in the tool routines will however work in the context of + * the caller's process. Note that a printf() in the kernel in a tool + * routine will end up on fd 2 3 of the calling process, NOT the + * kernel. Use kern_printf() inside a tool routine to display + * information in the kernel's context (via TextTools). Make sure + * you fflush() any printf()s to stdout before returning to the caller, + * or your output could end up buffered and sent to a completely + * different process the next time printf() is called. + */ + stdin->_file = 1; /* Attempt to send printf information inside */ + stdout->_file = 2; /* tool routines to the standard locations */ + stderr->_file = 3; /* in the caller's context. */ + + SendRequest(0x8000,sendToName,(long)pg,0l,NULL); + /* + * Re-setup text tool information for kernel debug output now that + * we've patched the hell out of everything. + */ + SetInGlobals(0xFF,0x00); + SetOutGlobals(0xFF,0x00); + SetErrGlobals(0xFF,0x00); + SetInputDevice(pascalType,3l); + SetOutputDevice(pascalType,3l); + SetErrorDevice(pascalType,3l); + WriteCString("\n\r\n\r\n\r"); + + commonFork(doShell, 1024, 0, NULL, &nargs, &errno); + +/* + * this is the kernel null process. it must NEVER call the assembly + * _resched routine, or the time slice variable will grow uncontrollably + * if no other processes are Ready + */ + + NullProcess(); +endGNO: + SendRequest(0x8001,sendToName,(long)pg,0l,NULL); + unpatchTools(); + + /* Shut down the Event Manager */ + EMShutDown(); + DisposeHandle(emdp); + + DeInitKern(); + + /* do when console driver is shutdown */ + InOutEnd(); + + for (stat = 0; stat < numDrivers; stat++) + UserShutDown(driverUserID[stat],0); + TLShutDown(); + HUnlockAll(kp->userID); + SetPurgeAll(2,kp->userID); + QuitGS(&quitParms); +} + +#include +/* turn off debug 25 and on debug 8 for vararg function */ +#pragma debug 0 +#pragma optimize 79 +#define KP_BUFSIZ 256 +int kern_printf(const char *format, ...) +{ +static char buffer[KP_BUFSIZ]; /* pray this is large enough (need vsnprintf) */ +va_list list; +int ret; + + va_start(list, format); + ret = vsprintf(buffer, format, list); + if (ret >= KP_BUFSIZ) { + asm {brk 0xbf} + } + WriteCString(buffer); + va_end(list); + return ret; +} + diff --git a/kern/gno/net.c b/kern/gno/net.c new file mode 100644 index 0000000..056237a --- /dev/null +++ b/kern/gno/net.c @@ -0,0 +1,430 @@ +/* $Id: net.c,v 1.1 1998/02/02 08:18:36 taubert Exp $ */ + +/* + * GNO/ME Network Support + * + * Copyright 1994-1998, Procyon Enterprises Inc. + * + * Written by Derek Taubert and Jawaid Bazyar + * + * KERNInstallNetDriver(inf *netcore,int *ERRNO) + * KERNsocket(int domain, int type, int protocol, int *ERRNO) + * KERNbind(int fd, struct sockaddr *my_addr, int addrlen, int *ERRNO) + * KERNconnect(int fd, struct sockaddr *serv_addr, int addrlen, int *ERRNO) + * KERNlisten(int fd, int backlog, int *ERRNO) + * KERNaccept(int fd, struct sockaddr *rem_addr, int *addrlen, int *ERRNO) + * KERNrecvfrom(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int *addrlen, int *ERRNO) + * KERNsendto(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int addrlen, int *ERRNO) + * KERNrecv(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO) + * KERNsend(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO) + * + * KERNgetpeername(int s, struct sockaddr *peer_addr, int *addrlen, int *ERRNO) + * KERNgetsockname(int s, struct sockaddr *sock_addr, int *addrlen, int *ERRNO) + * KERNgetsockopt(int s, int level, int optname, void *optval, int *optlen, int *ERRNO) + * KERNsetsockopt(int s, int level, int optname, void *optval, int optlen, int *ERRNO) + */ + +#include "gno.h" +#include "proc.h" +#include "sys.h" +#include "kernel.h" +#include "net.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include +#include +#include +#include +#include +#include + +/*#define DEBUG +#include */ + +#pragma optimize 79 +segment "KERN3 "; + +extern void selwakeup(int col_flag, int pid); + +int (*pr_usrreq)(int socknum, int req, void *m, size_t *m_len, + struct sockaddr *addr, int *addrlen, void *rights) = NULL; + +#pragma databank 1 +int SOCKioctl(void *dataptr, longword tioc, int sock) +{ + if (!pr_usrreq) return EPFNOSUPPORT; + return (*pr_usrreq)(sock,PRU_CONTROL,(void *)&tioc,NULL,(struct sockaddr *)dataptr,NULL,NULL); +} + +/* socket number to select on, and flags */ +int SOCKselect(int pid, int fl, int sock) +{ + if (!pr_usrreq) return EPFNOSUPPORT; + sock++; /* downfall of optimization in calling routine */ + (*pr_usrreq)(sock,PRU_SELECT,NULL,(size_t *)&pid,(struct sockaddr *)&fl,NULL,NULL); + return (fl != 0) ? 1 : 0; +} + +int SOCKclose(int sock) +/* Called from inside GS/OS, has to return special error codes */ +{ +int err = 0; + + if (!pr_usrreq) return EPFNOSUPPORT|0x4300; + (*pr_usrreq)( + sock, + PRU_DISCONNECT, + NULL, + NULL, + NULL, + NULL, + NULL); + err = (*pr_usrreq)( + sock, + PRU_DETACH, + NULL, + NULL, + NULL, + NULL, + NULL); + return (!err) ? 0 : 0x4300 | err; +} + +/* returns the refNum field of a file descriptor if that fd is a socket, + and is valid. Otherwise, returns -ERRNO */ + +int getsocknum(int fd) +{ +fdentryPtr fdp; +extern fdentryPtr getFDptr(int); + + if (!pr_usrreq) return -EPFNOSUPPORT; + fdp = getFDptr(fd); + if (fdp == NULL) return -EBADF; + if (fdp->refType != rtSOCKET) return -ENOTSOCK; /* Not a socket */ + return fdp->refNum; +} + +struct rwPBlock { + word ref; + void *buffer; + size_t reqCount; + size_t xferCount; + word cachePriority; +}; + +int SOCKrdwr(struct rwPBlock *pb, word cmd, int sock) +/* Called from inside GS/OS, has to return special error codes */ +{ +size_t len; +int err; + + if (!pr_usrreq) return 0x4300|EPFNOSUPPORT; + len = pb->reqCount; + err = (*pr_usrreq) ( + sock, + (((cmd & 0xFF) == 0x12) ? PRU_RCVD : PRU_SEND), + pb->buffer, + &len, + NULL, + NULL, + NULL); + pb->xferCount = len; + return (err == 0) ? 0 : err | 0x4300; +} + +#pragma toolparms 1 +pascal int KERNInstallNetDriver(void *netcore,int domain,int *ERRNO) +{ + pr_usrreq = netcore; + /* don't need domain yet, we only support one type of network */ + return 0; +} + +pascal int KERNsocket(int domain, int type, int protocol, int *ERRNO) +{ +int fd,sock; +fdentryPtr fdp; +fdtablePtr fdt; + + if ((domain != PF_INET) || (!pr_usrreq)) { + *ERRNO = EPFNOSUPPORT; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + type, + PRU_ATTACH, + &sock, + (size_t *)selwakeup, + (struct sockaddr *) &protocol, + NULL, + NULL)) return -1; + disableps(); + fdt = PROC->openFiles; + fdt->fdCount++; + + fdp = allocFD(&fd); + fdp->refNum = sock; + fdp->refType = rtSOCKET; + fdp->refFlags = 0; + fdp->refLevel = fdt->fdLevel | fdt->fdLevelMode; + fdp->NLenableMask = 0; + fdp->NLnumChars = 0; + fdp->NLtable = NULL; + AddRefnum(rtSOCKET,sock); + enableps(); + return fd; +} + +pascal int KERNbind(int fd, struct sockaddr *my_addr, int addrlen, int *ERRNO) +{ +int err,sock; + + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_BIND, + NULL, + NULL, + my_addr, + &addrlen, + NULL)) return -1; + return 0; +} + +pascal int KERNconnect(int fd, struct sockaddr *serv_addr, int addrlen, int *ERRNO) +{ +int sock; + + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_CONNECT, + NULL, + NULL, + serv_addr, + &addrlen, + NULL)) return -1; + return 0; +} + +pascal int KERNlisten(int fd, int backlog, int *ERRNO) +{ +int sock; + + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_LISTEN, + &backlog, + NULL, + NULL, + NULL, + NULL)) return -1; + return 0; +} + +pascal int KERNaccept(int fd, struct sockaddr *rem_addr, int *addrlen, int *ERRNO) +{ +int newfd,sock; +fdentryPtr fdp; +fdtablePtr fdt; + + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_ACCEPT, + &newfd, + (size_t *)selwakeup, + rem_addr, + addrlen, + NULL)) return -1; + disableps(); + fdt = PROC->openFiles; + fdt->fdCount++; + fdp = allocFD(&fd); + fdp->refNum = newfd; + fdp->refType = rtSOCKET; + fdp->refFlags = 0; + fdp->refLevel = fdt->fdLevel | fdt->fdLevelMode; + fdp->NLenableMask = 0; + fdp->NLnumChars = 0; + fdp->NLtable = NULL; + AddRefnum(rtSOCKET,newfd); + enableps(); + return fd; +} + +pascal int KERNrecvfrom(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int *addrlen, int *ERRNO) +{ +int sock; + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + (flags & MSG_OOB) ? PRU_RCVOOB : PRU_RCVD, + buf, + &len, + rem_addr, + addrlen, + NULL)) return -1; + return len; +} + +pascal int KERNsendto(int fd, void *buf, size_t len, unsigned int flags, struct sockaddr *rem_addr, int addrlen, int *ERRNO) +{ +int sock; + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, + buf, + &len, + rem_addr, + &addrlen, + NULL)) return -1; + return len; +} + +pascal int KERNrecv(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO) +{ +int sock; + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + (flags & MSG_OOB) ? PRU_RCVOOB : PRU_RCVD, + buf, + &len, + NULL, + NULL, + NULL)) return -1; + return len; +} + +pascal int KERNsend(int fd, void *buf, size_t len, unsigned int flags, int *ERRNO) +{ +int sock; + if ((sock = getsocknum(fd)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, + buf, + &len, + NULL, + NULL, + NULL)) return -1; + return len; +} + +pascal int KERNgetpeername(int s, struct sockaddr *peer_addr, int *addrlen, int *ERRNO) { +int sock; + if ((sock = getsocknum(s)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_PEERADDR, + NULL, + NULL, + peer_addr, + addrlen, + NULL)) return -1; + return 0; +} + +pascal int KERNgetsockname(int s, struct sockaddr *sock_addr, int *addrlen, int *ERRNO) { +int sock; + if ((sock = getsocknum(s)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_SOCKADDR, + NULL, + NULL, + sock_addr, + addrlen, + NULL)) return -1; + return 0; +} + +pascal int KERNgetsockopt(int s, int level, int optname, void *optval, int *optlen, int *ERRNO) { +int sock; + if ((sock = getsocknum(s)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_CO_GETOPT, + &level, + (size_t *)&optname, + (struct sockaddr *)optval, + optlen, + NULL)) return -1; + return 0; +} + +pascal int KERNsetsockopt(int s, int level, int optname, void *optval, int optlen, int *ERRNO) { +int sock; + if ((sock = getsocknum(s)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_CO_SETOPT, + &level, + (size_t *)&optname, + (struct sockaddr *)optval, + &optlen, + NULL)) return -1; + return 0; +} + +pascal int KERNshutdown(int s, int how, int *ERRNO) +{ +int sock; + + if ((sock = getsocknum(s)) < 0) { + *ERRNO = -sock; + return -1; + } + if (*ERRNO = (*pr_usrreq)( + sock, + PRU_SHUTDOWN, + &how, + NULL, + NULL, + NULL, + NULL)) return -1; + return 0; +} +#pragma toolparms 0 +#pragma databank 0 + diff --git a/kern/gno/net.h b/kern/gno/net.h new file mode 100644 index 0000000..5beed16 --- /dev/null +++ b/kern/gno/net.h @@ -0,0 +1,35 @@ +/* $Id: net.h,v 1.1 1998/02/02 08:18:39 taubert Exp $ */ + +/* + * GNO/ME Network Support + * + * Copyright 1994-1998, Procyon Enterprises Inc. + * + * Written by Derek Taubert and Jawaid Bazyar + * + */ + +/* Request types for pr_usrreq() */ + +#define PRU_ABORT 0 +#define PRU_ACCEPT 1 +#define PRU_ATTACH 2 +#define PRU_BIND 3 +#define PRU_CONNECT 4 +#define PRU_CONNECT2 5 +#define PRU_CONTROL 6 +#define PRU_DETACH 7 +#define PRU_DISCONNECT 8 +#define PRU_LISTEN 9 +#define PRU_PEERADDR 10 +#define PRU_RCVD 11 +#define PRU_RCVOOB 12 +#define PRU_SEND 13 +#define PRU_SENDOOB 14 +#define PRU_SENSE 15 +#define PRU_SHUTDOWN 16 +#define PRU_SOCKADDR 17 +#define PRU_CO_GETOPT 18 +#define PRU_CO_SETOPT 19 +#define PRU_SELECT 20 + diff --git a/kern/gno/p16.asm b/kern/gno/p16.asm new file mode 100644 index 0000000..dd9b088 --- /dev/null +++ b/kern/gno/p16.asm @@ -0,0 +1,821 @@ +* $Id: p16.asm,v 1.1 1998/02/02 08:19:33 taubert Exp $ +************************************************************************** +* +* P16.ASM +* By Jawaid Bazyar +* +* This file contains routines for patching Prodos 16 calls to maintain +* the information the kernel needs to keep track of things. +* +************************************************************************** + + copy global.equates + mcopy m/p16.mac + + copy inc/gsos.inc + copy inc/tty.inc + case on + +* if you change FDsize, look for the commend "a * FDsize". You must +* change code there. + +rfPIPEREAD gequ 1 ;* read end of the pipe * +rfPIPEWRITE gequ 2 ;* write end of the pipe * +rfCLOSEEXEC gequ 4 ;* close this file on an exec() * +rfP16NEWL gequ 8 ;* special prodos-16 newline mode * + +P16table START + dc a2'P16Standard' ; $2001 CREATE + dc a2'P16Standard' ; $2002 DESTROY + dc a2'NotImpP16' ; $2003 + dc a2'P16ChangePath' ; $2004 CHANGE_PATH + dc a2'P16Standard' ; $2005 SET_FILE_INFO + dc a2'P16Standard' ; $2006 GET_FILE_INFO + dc a2'NotImpP16' ; $2007 + dc a2'NotImpP16' ; $2008 VOLUME + + dc a2'P16SetPrefix' ; $2009 SET_PREFIX + dc a2'PGGetPrefix' ; $200A GET_PREFIX + + dc a2'P16Standard' ; $200B CLEAR_BACKUP_BIT + dc a2'NotImpP16' ; $200C + dc a2'NotImpP16' ; $200D + dc a2'NotImpP16' ; $200E + dc a2'NotImpP16' ; $200F + dc a2'P16Open' ; $2010 OPEN + dc a2'P16NewLine' ; $2011 NEWLINE + dc a2'P16RdWr' ; $2012 READ + dc a2'P16RdWr' ; $2013 WRITE + dc a2'PGClose' ; $2014 CLOSE + dc a2'P16RefCommon' ; $2015 FLUSH + dc a2'P16RefCommon' ; $2016 SET_MARK + dc a2'P16RefCommon' ; $2017 GET_MARK + dc a2'P16RefCommon' ; $2018 SET_EOF + dc a2'P16RefCommon' ; $2019 GET_EOF + dc a2'P16SetLevel' ; $201A SET_LEVEL + dc a2'P16GetLevel' ; $201B GET_LEVEL + dc a2'P16RefCommon' ; $201C GET_DIR_ENTRY + dc a2'NotImpP16' ; $201D + dc a2'NotImpP16' ; $201E + dc a2'NotImpP16' ; $201F + dc a2'NotImpP16' ; $2020 GET_DEV_NUM + dc a2'NotImpP16' ; $2021 GET_LAST_DEV + dc a2'NotImpP16' ; $2022 READ_BLOCK + dc a2'NotImpP16' ; $2023 WRITE_BLOCK + dc a2'NotImpP16' ; $2024 FORMAT + dc a2'NotImpP16' ; $2025 ERASE_DISK + dc a2'NotImpP16' ; $2026 + dc a2'P16GetName' ; $2027 GET_NAME + dc a2'NotImpP16' ; $2028 GET_BOOT_VOL + dc a2'P16Quit' ; $2029 QUIT + dc a2'NotImpP16' ; $202A GET_VERSION + dc a2'NotImpP16' ; $202B + dc a2'NotImpP16' ; $202C D_INFO + dc a2'NotImpP16' ; $202D + dc a2'NotImpP16' ; $202E + dc a2'NotImpP16' ; $202F + dc a2'NotImpP16' ; $2030 + dc a2'NotImpP16' ; $2031 ALLOC_INTERRUPT + dc a2'NotImpP16' ; $2032 DEALLOC_INTERRUPT + END + +P16SetPrefix START + using KernelStruct + +pfxRec equ 10 +pfxInd equ 14 + +pfxpCount equ 16 +pfxpfxNum equ 18 +pfxpathname equ 20 +newPath equ 24 + + ldy #prefixh-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta pfxRec ; we dereference it later + iny2 + lda [procEnt],y + sta pfxRec+2 + + pea 1 + lda [pBlock] + pha ; pfx# for expandpath + ldy #4 + lda [pBlock],y + pha + ldy #2 + lda [pBlock],y + pha + jsl p16_ExpandPath ; call our C routine + sta pfxpathname + stx pfxpathname+2 ; store result + cpx #$FFFF ; did an error occur? + bne noerr + jmp GSOSReturn + +noerr anop + lda [pBlock] + inc a + asl a + asl a + sta pfxInd + tay + iny2 + lda [pfxRec],y + pha + dey2 + lda [pfxRec],y + pha + ora 3,s + bne dodispose + pla + pla + bra nodispose + +dodispose jsl ~NDISPOSE + +nodispose lda [pfxpathname] + inc a + inc a + inc a + pea 0 + pha + jsl ~NEW + sta newPath + stx newPath+2 + + ldy pfxInd ; copy the addr of the new mem into the + sta [pfxRec],y ; prefix record + iny2 + txa + sta [pfxRec],y + + ph4 pfxpathname ; copy the string + ph4 newPath + jsl copygsstr + lda [newPath] + inc a + tay + lda [newPath],y ; check to see if there's a + and #$00FF + cmp #':' ; separator at the end of the + beq alright + short m ; prefix, and if not, then + lda #':' + iny ; add one. Note that we alloced + sta [newPath],y ; one extra byte for this possibility + long m + dey + tya + sta [newPath] +alright lda #0 + jmp GSOSReturn + END + +P16Standard START +oldPath equ 10 +pathName equ 14 +tmpLength equ 18 +exppath equ 20 + + lda [pBlock] + sta oldPath + ldy #2 + lda [pBlock],y + sta oldPath+2 + + pea 0 + pushword #0 + pushlong oldPath + jsl p16_ExpandPath + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr anop + sta exppath + stx exppath+2 +* ph4 exppath + phx + pha + jsl findDevice + cmp #$FFFF + beq notdevice + lda #$0058 ; not a block device! + bra goaway + +notdevice anop + ldx exppath+2 + lda exppath + ldy #0 + sta pathName + inc a ; part of 'fix string' + sta [pBlock],y + bne incr + inx +incr txa + iny2 + sta pathName+2 ; $$$ if the inx is taken, this is + sta [pBlock],y ; incorrect (pathname+2 is) + lda [pathName] + sta tmpLength + xba + sta [pathName] +* short m +* ldy #1 +* sta [pathName],y +* long m + + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + +* movelong pBlock,pb ; $$$ switch to stack-based +* lda cmdNum +* sta cn + +* jsl OldGSOS +*cn dc i2'0' ; set to same call # we are +*pb dc i4'0' + + pha ; return any error we get + lda tmpLength + sta [pathName] + + lda cmdNum + cmp #$0002 + beq docff + cmp #$0005 + bne noff +docff anop + ldx oldPath+2 + lda oldPath + jsr PcheckFF +noff anop + + lda oldPath + sta [pBlock] + ldy #2 + lda oldPath+2 + sta [pBlock],y + pla +goaway jmp GSOSReturn + END + +P16Open START + using KernelStruct +temp1 equ 10 +pathName equ 14 +tmpLength equ 18 +files equ 20 +fd equ 24 +fdptr equ 26 + + ldy #2 + lda [pBlock],y + sta temp1 + ldy #4 + lda [pBlock],y + sta temp1+2 + + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 + + pea 0 + ph2 #0 + ph4 temp1 + jsl p16_ExpandPath + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr anop + ldy #2 + sta pathName + inc a + sta [pBlock],y + bne incr + inx +incr txa + iny2 + sta pathName+2 + sta [pBlock],y + + lda [pathName] + sta tmpLength + xba + sta [pathName] + + movelong pBlock,pb + lda cmdNum + sta cn + + jsl OldGSOS +cn dc i2'0' ; set to same call # we are +pb dc i4'0' + pha ; return any error we get + cmp #0 + bne error + + lda [pBlock] + pha + ph2 #0 + jsl AddRefnum + + lda [files] ; inc the number of open files, + inc a + sta [files] + + pea 0 ; allocate a file descriptor + tdc + clc + adc #fd + pha + jsl allocFD + sta fdptr + stx fdptr+2 + +; rederef the openFiles pointer + ldy #openFiles-CKernData + lda [procEnt],y + sta files + iny2 + lda [procEnt],y + sta files+2 + + lda [pBlock] + ldy #FDrefNum + sta [fdptr],y ; and store the new refnum in the list + lda fd + sta [pBlock] ; and store it + ldy #FDTLevel + lda [files],y + ldy #FDTLevelMode + ora [files],y + ldy #FDrefLevel + sta [fdptr],y ; store file level with refnum + +error anop + lda tmpLength + sta [pathName] + + ldx temp1+2 + lda temp1 + jsr PcheckFF + + ldy #2 + lda temp1 + sta [pBlock],y + ldy #4 + lda temp1+2 + sta [pBlock],y + pla + jmp GSOSReturn + END + +P16Quit START + using KernelStruct + ldx curProcInd + lda flags,x + ora #%00001000 ; FL_NORMTERM + sta flags,x + + ldy #4 ; push the flags word + lda [pBlock],y + pha + + ldy #2 ; push the pathname + lda [pBlock],y + pha + ldy #0 + lda [pBlock],y + pha + ora 3,s + beq noPname + jsl p2cstr + phx + pha ; push the coverted pathname +noPname anop + jsl CommonQuit + jmp GSOSReturn ; only returns on error + END + +P16SetLevel START + using KernelStruct +files equ 10 + + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 +okay anop + ldy #FDTLevel + lda [pBlock] + sta [files],y + lda #$8000 + ldy #FDTLevelMode + sta [files],y + lda #0 +error jmp GSOSReturn + END + +P16GetLevel START + using KernelStruct +files equ 10 + + ldy #openFiles-CKernData ; copy the handle of the prefix rec + lda [procEnt],y ; out of the process table + sta files ; we dereference it later + iny2 + lda [procEnt],y + sta files+2 +okay anop + ldy #2 + lda [files],y + sta [pBlock] + lda #0 +error jmp GSOSReturn + END + +P16ChangePath START +temp1 equ 10 +temp2 equ 14 +oldpathres equ 18 +newmem equ 22 + + pea 0 + pushword #0 + ldy #2 + lda [pBlock],y + pha + lda [pBlock] + pha ; push source onto stack + jsl p16_ExpandPath + cpx #$FFFF + bne noerr + jmp GSOSReturn +noerr phx + pha ; push source addr for copy + stx oldpathres+2 + sta oldpathres + + pea $0000 + lda [oldpathres] + clc + adc #2 + pha + jsl ~NEW + stx newmem+2 + sta newmem + stx pathname+2 + sta pathname + + phx + pha ; push dest address + + ora pathname+2 + beq memoryErr + + jsl copygsstr ; copy the expanded path to temp + + pea 0 + pushword #0 + ldy #6 + lda [pBlock],y + pha + dey2 + lda [pBlock],y + pha ; push source onto stack + jsl p16_ExpandPath + cpx #$FFFF + bne noerr1 + ph4 newmem + jsl ~NDISPOSE + jmp GSOSReturn +noerr1 anop + stx newpathname+2 + sta newpathname + + pushlong #chPathPB + pea $2004 + + jsl OldGSOSSt + pha ; return any error we get + pushlong newmem + jsl ~NDISPOSE + +interdict anop + pla + jmp GSOSReturn +memoryErr pla + pla + pea $0054 + bra interdict + +chPathPB anop + dc i2'2' +pathname dc i4'0' +newpathname dc i4'0' + END + +* Flush 2015 +2 +* GetDirEntry 201C +2 +* GetEOF 2019 +2 tty,pipe +* GetMark 2017 +2 tty,pipe +* GetRefInfo 2039 +2 +* SetEOF 2018 +2 tty,pipe +* SetMark 2016 +2 tty,pipe + +P16RefCommon START +oldRN equ 10 +fdPtr equ 12 + + lda [pBlock] + sta oldRN + pha + cmp #0 + bne notzero + lda cmdNum + cmp #$0015 + jeq FlushSpecial + pla + lda #$43 + jmp GSOSReturn + +notzero jsl getFDptr + sta fdPtr + stx fdPtr+2 + ora fdPtr+2 + beq refIsBad + lda [fdPtr] + cmp #0 + bne okay +refIsBad lda #$43 + jmp GSOSReturn +okay anop + ldy #FDrefType + lda [fdPtr],y + cmp #FDgsos + beq typeOkay + jmp notGSOS +typeOkay lda [fdPtr] + sta [pBlock] + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + lda oldRN + sta [pBlock] + pla + jmp GSOSReturn +notGSOS lda #$58 + jmp GSOSReturn + +FlushSpecial anop + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + jmp GSOSReturn + END + +P16NewLine START +oldRN equ 10 +fdrec equ 12 +trueRN equ 16 + + lda [pBlock] + sta oldRN + pha + jsl getFDptr + sta fdrec + stx fdrec+2 + ora fdrec+2 + beq refIsBad + ldy #FDrefNum + lda [fdrec],y + cmp #0 + bne okay +refIsBad lda #$43 + jmp GSOSReturn +okay anop + sta trueRN + ldy #FDrefType + lda [fdrec],y + cmp #FDpipe + beq nlPipe + ldy #FDrefNum + + lda trueRN + sta [pBlock] + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + lda oldRN + sta [pBlock] + pla + jmp GSOSReturn +nlPipe anop + ldy #2 + lda [pBlock],y + ldy #FDNLenableMask + sta [fdrec],y + beq noerror + + ldy #FDrefFlags + lda [fdrec],y + and #rfP16NEWL + sta [fdrec],y ; tell 'em it's a P16 NewLine + + ldy #4 + lda [pBlock],y + ldy #FDNLnumChars + sta [fdrec],y + +noerror lda #0 + jmp GSOSReturn + END + +P16RdWr START + using KernelStruct +files equ 10 +fdrec equ 14 +rn equ 18 + + ldx curProcInd + lda openFiles,x + sta files + lda openFiles+2,x + sta files+2 + lda [pBlock] + sta rn + pha + jsl getFDptr + sta fdrec + stx fdrec+2 + ora fdrec+2 + bne refIsOk + lda #$43 + jmp GSOSReturn +refIsOk ldy #FDrefType + lda [fdrec],y + asl a + tax + jmp (rdwrtable,X) +rdwrtable dc i2'doGSOS' + dc i2'doPipe' + dc i2'doTTY' + dc i2'doSocket' + +******************* +doGSOS anop + ldy #FDrefNum + lda [fdrec],y + sta [pBlock] + ph4 pBlock + ph2 cmdNum + jsl OldGSOSSt + pha + lda rn + sta [pBlock] + pla + jmp GSOSReturn + +******************* +doPipe anop + jsl decBusy + ph4 pBlock + ldy #FDrefNum + lda [fdrec],y + pha + lda cmdNum + cmp #$0012 + beq pread + jsl pipeHiWrite + bra goback +pread ph4 fdrec + jsl pipeHiRead +goback anop + jsl incBusy + jmp GSOSReturn + +******************* +doTTY anop + jsl decBusy + ldy #6 + lda [pBlock],y + pha + ldy #4 + lda [pBlock],y + pha + ldy #2 + lda [pBlock],y + pha + lda cmdNum + cmp #$0012 + beq tread + ldy #FDrefNum + lda [fdrec],y + dec a + pha + ldy #t_write + jsl LineDiscDispatch + bra goaway2 +tread ldy #FDrefNum + lda [fdrec],y + dec a + pha + ldy #t_read + jsl LineDiscDispatch +goaway2 anop + phx + ldy #10 + sta [pBlock],y ; to provide a way for TTYs to + lda #0 + ldy #12 + sta [pBlock],y ; bug! must clear hi word o'transCnt + jsl incBusy + pla + jmp GSOSReturn + +******************* +doSocket anop + ldy #FDrefNum + lda [fdrec],y + pha + ph2 cmdNum + ph4 pBlock + jsl SOCKrdwr + jmp GSOSReturn + + END + +P16GetName START + using KernelStruct +pathptr equ 10 +resptr equ 14 +outind equ 18 +inind equ 20 +pathlen equ 22 + +* Note that forked processes will get the name of their parent + + ldy #2 + lda [pBlock],y + sta resptr+2 + lda [pBlock] + sta resptr + + ldx curProcInd ; get the full pathname of + lda procUserID,x ; the process. + pha + pha ; space for tool call. ARGH!!! + pha + pea $1 + _LGetPathname + pl4 pathptr + lda [pathptr] + and #$00FF + sta pathlen + inc a + tay + short m +loop lda [pathptr],y + cmp #'/' + beq gotfname + dey + bra loop +gotfname long m + iny + sty inind + lda [pathptr] ; get length + sec + sbc inind ; length of filename + clc + adc #1 ; minus the length word + sta [resptr] ; store length of filename + + ldy #1 + sty outind + short m +cploop ldy inind + lda [pathptr],y + ldy outind + sta [resptr],y + ldy inind + cpy pathlen + bcs donecopy + long m + inc inind + inc outind + short m + bra cploop +donecopy long m + lda #0 + jmp GSOSReturn + + END diff --git a/kern/gno/patch.c b/kern/gno/patch.c new file mode 100644 index 0000000..ce25679 --- /dev/null +++ b/kern/gno/patch.c @@ -0,0 +1,109 @@ +/* $Id: patch.c,v 1.1 1998/02/02 08:18:40 taubert Exp $ */ + +segment "KERN2 "; + +#pragma optimize 79 + +#include "proc.h" +#include "gno.h" +#include "sys.h" +#include "sem.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include +#include +#include +#include + +struct patchEntry { + word toolNum; + longword oldFunc,newFunc; + longword *chainPoint; +}; + +/* tool patch entry points */ +extern byte NULLTOOLFUNC; +extern byte OURSYSFAILMGR; +extern byte SaveAllPatch; +extern byte RestAllPatch; +extern byte QDSTARTUPPATCH; +extern byte SANESUPATCH; +extern byte SANESDPATCH; +extern byte SANESTPATCH; +extern byte TDISPOSEHAND; +extern byte NewGetNextEvent, NewEMStartUp, NewGetOSEvent, NewOSEventAvail, + NewEMShutDown,NewEventAvail; + +/* tool patch 'old' vectors, for patches that want to call the old routine */ +extern longword OLDSAVEALL, OLDRESTALL, OLDQDSTARTUP, OLDSANESU, OLDDISPHAND; +extern longword OldGetNextEvent, OldOSEventAvail, OldGetOSEvent, OldEventAvail; + +static struct patchEntry patchArray[] = { + { 0x0B05, 0l, (longword) (&SaveAllPatch), &OLDSAVEALL }, + { 0x0C05, 0l, (longword) (&RestAllPatch), &OLDRESTALL }, + { 0x0204, 0l, (longword) (&QDSTARTUPPATCH), &OLDQDSTARTUP }, + { 0x020A, 0l, (longword) (&SANESUPATCH), &OLDSANESU }, + { 0x0201, 0l, (longword) (&NULLTOOLFUNC), NULL }, + { 0x0301, 0l, (longword) (&NULLTOOLFUNC), NULL }, + { 0x1503, 0l, (longword) (&OURSYSFAILMGR), NULL }, + { 0x030A, 0l, (longword) (&SANESDPATCH), NULL }, + { 0x060A, 0l, (longword) (&SANESTPATCH), NULL }, +/* { 0x1002, 0l, (longword) (&TDISPOSEHAND), &OLDDISPHAND }, */ + { 0x0206, 0l, (longword) (&NewEMStartUp), NULL }, + { 0x0A06, 0l, (longword) (&NewGetNextEvent), &OldGetNextEvent }, + { 0x0B06, 0l, (longword) (&NewEventAvail), &OldEventAvail }, + { 0x1606, 0l, (longword) (&NewGetOSEvent), &OldGetOSEvent }, + { 0x1706, 0l, (longword) (&NewOSEventAvail), &OldOSEventAvail }, + { 0x0306, 0l, (longword) (&NewEMShutDown), NULL }, + { ~0, 0l, 0l, NULL}}; + +void patchTools(void) +{ +longword *TLfunc; +int i; +word Tool, Func; + + i = 0; + while ((Tool = patchArray[i].toolNum) != ~0) { + Func = (Tool & 0xFF00) >> 8; + Tool &= 0xff; + TLfunc = (longword *) GetTSPtr(0x0000, Tool); + patchArray[i].oldFunc = TLfunc[Func]; + if (patchArray[i].chainPoint) { + if (*(patchArray[i].chainPoint)) { + /* takes care of jmp >$000000 patches */ + *(patchArray[i].chainPoint) |= ((TLfunc[Func]+1) << 8); + } else { + /* takes care of dc i4'0' patches */ + *(patchArray[i].chainPoint) = TLfunc[Func]+1; + } + } +#ifdef DEBUG_TOOL_PATCH + printf("%lx %lx %lx %lx %lx\n", &TLfunc[Func], patchArray[i].oldFunc, + patchArray[i].chainPoint, *(patchArray[i].chainPoint), + patchArray[i].newFunc); +#endif + TLfunc[Func] = patchArray[i].newFunc-1; +#ifdef DEBUG_TOOL_PATCH + printf(" %lx\n", TLfunc[Func]); +#endif + i++; + } +} + +void unpatchTools(void) +{ +longword *TLfunc; +int i; +word Tool, Func; + + i = 0; + while ((Tool = patchArray[i].toolNum) != -1) { + Func = (Tool & 0xFF00) >> 8; + Tool &= 0xff; + TLfunc = (longword *) GetTSPtr(0x0000, Tool); + TLfunc[Func] = patchArray[i].oldFunc; + i++; + } +} + diff --git a/kern/gno/pipe.asm b/kern/gno/pipe.asm new file mode 100644 index 0000000..28faf65 --- /dev/null +++ b/kern/gno/pipe.asm @@ -0,0 +1,1329 @@ +* $Id: pipe.asm,v 1.1 1998/02/02 08:19:37 taubert Exp $ +************************************************************************** +* +* PIPE.ASM +* +* by Jawaid Bazyar +* +* takes proper care of refNums, so redirection is handled just like +* Unix. Also, implements the hooks necessary for pipes. +* +************************************************************************** + mcopy m/pipe.mac + case on + copy global.equates + copy inc/kern.inc + +* the maximum number of pipes is NPROC-1, and we need 4 sems per pipe, +* so NASMSEM is a good approximation + +NASMSEM gequ NPROC*4+20 +PIPESIZE gequ 4096 + +rfPIPEREAD gequ 1 ;* read end of the pipe * +rfPIPEWRITE gequ 2 ;* write end of the pipe * +rfCLOSEEXEC gequ 4 ;* close this file on an exec() * +rfP16NEWL gequ 8 ;* special prodos-16 newline mode * + +RRsize gequ 6 +RRrefnum gequ 0 +RRtype gequ 2 +RRcount gequ 4 + + copy inc/gsos.inc + +pipeData DATA +refHandle dc i4'0' +refHandleSize dc i2'0' + END + +writeEvent gequ 1 + +PRsize gequ 32 +PRnum gequ NPROC + +* the new pipe record +pipeRecord DATA +bufferH dc i4'0' ; the pipe data handle +in dc i2'0' ; write pointer +out dc i2'0' ; read pointer +qflags dc i2'0' +RrnCount dc i2'0' ; Why? Because special stuff has to +WrnCount dc i2'0' ; happen in strange conditions + +accessSem dc i2'0' ; semaphores +needReadSem dc i2'0' +needWriteSem dc i2'0' +needRead dc i2'0' +needWrite dc i2'0' +writeLeft dc i2'0' +readLeft dc i2'0' +writeStatus dc i2'0' +dummy dc i2'0' + ds 32*31 ; 32 pipes max- think about it + END + +************************************************************************** +* +* FindRefnum(int rn, int type) +* searches the table for a specified refnum. It returns a pointer +* to the entry, or NIL if no matching refnum is found. +* +************************************************************************** + +FindRefnum START + using pipeData +tmpHandle equ 0 +tmpPtr equ 4 +retval equ 8 + + subroutine (2:refnum,2:type),12 + + mv4 refHandle,tmpHandle + + lda [tmpHandle] + sta tmpPtr + ldy #2 + lda [tmpHandle],y + sta tmpPtr+2 + ldy #0 +findloop lda refnum + cmp [tmpPtr],y + bne nextone + lda type + iny2 + cmp [tmpPtr],y + beq gotit + dey2 +nextone anop + tya + clc + adc #RRsize + tay + cpy refHandleSize + bcc findloop + stz tmpPtr + stz tmpPtr+2 + bra goaway +gotit dey2 + tya + clc + adc tmpPtr + sta tmpPtr + lda tmpPtr+2 + adc #0 + sta tmpPtr+2 +goaway anop + return 4:tmpPtr + END + +InitRefnum START + using KernelStruct + using pipeData + +tmpHandle equ 0 +tmpPtr equ 4 + + subroutine (0:foo),8 + lda #240 + sta refHandleSize + +; NewHandle (#240,UserID,#0,#0),tmpHandle + ph4 #0 ; result space dammit! + ph4 #240 + ph2 userID + ph2 #8 + ph4 #0 + _NewHandle + cmp #0 + bne handfailure + pla + sta tmpHandle + sta refHandle + pla + sta tmpHandle+2 + sta refHandle+2 + + ph4 tmpHandle ; we must lock the handle or badness + _HLock ; will occur- it could get purged! + + lda [tmpHandle] + sta tmpPtr + ldy #2 + lda [tmpHandle],y + sta tmpPtr+2 + + ldy #0 + tya +clrloop anop + sta [tmpPtr],y + iny2 + cpy refHandleSize + bcc clrloop + return +handfailure anop + jsr writeacc + ph4 #0 + jsl PANIC + END + +GrowRefnum START + using pipeData + +tmpHandle equ 0 +tmpPtr equ 4 +newsize equ 8 + + subroutine (0:foo),10 + + ph4 refHandle + _HUnlock + + lda refHandleSize + clc + adc #240 + sta newsize + + pea $0000 + pha + ph4 refHandle + _SetHandleSize + cmp #0 + beq okay + ph4 errtxt + jsl PANIC +okay anop + ph4 refHandle + _HLock + + mv4 refHandle,tmpHandle + lda [tmpHandle] + sta tmpPtr + ldy #2 + lda [tmpHandle],y + sta tmpPtr+2 + + ldy refHandleSize + lda #0 +clrloop anop + sta [tmpPtr],y + iny2 + cpy newsize + bcc clrloop + return +errtxt dc c'Error growing kernel refnum table',i1'0' + END + + +************************************************************************** +* +* AddRefnum(int type, int refnum) +* Adds a refnum/type to the refcount table. If the refnum/type +* already exists, a system panic will occur +* +************************************************************************** + +AddRefnum START + using pipeData +ptr equ 0 + + subroutine (2:refnum,2:type),4 +findEmpty anop + phy + phx + + pei (refnum) + pei (type) + jsl FindRefnum + phx + ora 1,s + bne addpanic + pla + + ph2 #0 + ph2 #0 + jsl FindRefnum + sta ptr + stx ptr+2 + ora ptr+2 + bne okay + jsl GrowRefnum + bra findEmpty +okay anop + ldy #RRrefnum + lda refnum + sta [ptr],y + ldy #RRtype + lda type + sta [ptr],y + ldy #RRcount + lda #1 + sta [ptr],y + plx + ply + return +addstr str 'AddRefnum:' +addpanic ph4 #addp + jsl PANIC +addp dc c'AddRefnum: refnum/type already exists!',i'0' + END + +IncRefnum START +ptr equ 0 + + subroutine (2:refnum,2:type),4 + + phy + phx + + ph2 refnum + ph2 type + jsl FindRefnum + sta ptr + stx ptr+2 + ora ptr+2 +; beq goaway + beq errorpanic + ldy #RRcount + lda [ptr],y + inc a + sta [ptr],y + +goaway anop + plx + ply + return +incstr str 'IncRefnum:' +errorpanic anop + brk $00 + ph4 #decerror + jsl PANIC +decerror dc c'IncRefnum- ref/type combo not found',i'0' + END + +************************************************************************** +* +* DecRefnum(int refnum) +* +************************************************************************** + +DecRefnum START +ptr equ 0 +retval equ 4 + + subroutine (2:refnum,2:type),6 + phx + + stz retval + ph2 refnum + ph2 type + jsl FindRefnum + sta ptr + stx ptr+2 + ora ptr+2 + beq errorpanic + ldy #RRcount + lda [ptr],y + dec a + sta [ptr],y + sta retval + cmp #0 + bne goaway + lda #0 + ldy #RRrefnum + sta [ptr],y ; the count is down to zero + ldy #RRtype + sta [ptr],y +goaway anop + plx + return 2:retval +addstr str 'DecRefnum:' +errorpanic anop + brk $00 + ph4 #decerror + jsl PANIC +decerror dc c'DecRefnum- ref/type combo not found',i'0' + END + +* an assembly semaphore + +asmSemTable DATA +alloced dc i2'0' +semCount dc i2'0' +queuePtr dc i2'0' ; we'll use indexen, not pointers + dc i2'0' + ds 1184 ; (NASMSEM-1)*8 , NASMSEM = 128 + END + +asmSemNew START +retval equ 0 + using asmSemTable + subroutine (2:cnt),2 + + php + sei + ldy #0 +loop lda alloced,y + beq gotit + tya + clc + adc #8 + tay + cpy #(NASMSEM*8) + bra loop +gotit lda #1 + sta alloced,y + lda #0 + sta queuePtr,y + lda cnt + sta semCount,y + tya + lsr a + lsr a + lsr a + inc a + ora #$8000 + sta retval + plp + return 2:retval + END + +asmSemDispose START + using asmSemTable + using KernelStruct +retval equ 0 + subroutine (2:sem),2 + + php + sei + lda sem + and #$7FFF + dec a + asl a + asl a + asl a + tax + lda alloced,x + beq error + stz alloced,x ; deallocate the semaphore! + + lda queuePtr,x + tax +readyLoop cpx #0 + beq done + lda ProcessState,x + cmp #pUnused ; it's gone, by god + beq skipProc + + lda #pReady + sta ProcessState,x +skipProc lda queueLink,x + tax + bra readyLoop +done stz retval +bye plp + return 2:retval +error lda #-1 + sta retval + bra bye + END + +asmWait START + using asmSemTable + using KernelStruct + subroutine (2:sem),0 + +; jsl incBusy ; ahh, critical section + php + sei +notowner anop + lda sem + and #$7FFF + dec a + asl a + asl a + asl a + tay + + lda semCount,y ; line for line from 'sem.c' + dec a + sta semCount,y + bpl goaway + +* Add the current process to the queue. Use the handy 'queueLink' field +* provided in the process structure to accomplish the link + + lda queuePtr,y + tax + bne loop + lda >curProcInd + sta queuePtr,y + tax + lda #0 + sta queueLink,x + bra nomo +loop lda queueLink,x + beq gotit + tax + bra loop +gotit lda >curProcInd + sta queueLink,x + tax + lda #0 + sta queueLink,x + +* Now that the process is enqueued, make it wait + +nomo ldx curProcInd ; 'suspend' the process + lda #pWait ; put the process in a 'wait' state + sta ProcessState,x +; This will cause havoc with KERNkill and normal sem's EINTR +; lda sem +; sta psem,x + short m + lda >$E100FF + pha + lda #0 + sta >$E100FF + cop $7F + pla + sta >$E100FF + long m + plp ; restore interrupts + bra goaway2 + +goaway anop + plp +; jsl decBusy ; leave critical section +goaway2 anop + return + END + +asmSignal START + using asmSemTable + using KernelStruct + subroutine (2:sem),0 + +; jsl incBusy + php + sei +notowner anop ; line for line from sem.c/ssignal + lda sem + and #$7FFF + dec a + asl a + asl a + asl a + tay + + lda semCount,y + bpl goaway ; if >=0, no processes waiting + +* Remove the next process from the queue and ready it for running + + lda queuePtr,y + pha ; store it for later + tax + lda queueLink,x + sta queuePtr,y ; that's pretty simple + plx ; it's ready! + lda ProcessState,x + cmp #pUnused ; it's gone! + beq goaway + lda #pReady + sta ProcessState,x +goaway anop + lda semCount,y + inc a + sta semCount,y +; jsl decBusy + plp + return + END + +*checkOA START +* short m +*loop anop +* lda >$E0C061 +* bpl loop +*loop2 anop +* lda >$E0C061 +* bmi loop2 +* long m +* rts +* END + +* only for testing, we're hacking this. + +newPipe START + using pipeRecord + using KernelStruct +pipeind equ 0 +retval equ 2 +pipediv equ 4 +hand equ 6 +buf equ 10 + + subroutine (0:foo),14 + ldy #0 + stz pipediv +findlp lda bufferH+2,y + ora bufferH,y + beq gotone ; found an empty one + tya + clc + adc #PRsize + tay + inc pipediv + cpy #PRsize*PRnum + bcc findlp + lda #$FFFF + sta retval + jmp goaway + +* We found an empty slot, now allocate the semaphores & memory +gotone anop + sty pipeind + + ph2 #1 + jsl asmSemNew + ldy pipeind + sta accessSem,y + + ph2 #0 + jsl asmSemNew + ldy pipeind + sta needReadSem,y + + ph2 #0 + jsl asmSemNew + ldy pipeind + sta needWriteSem,y + + lda #0 + sta needWrite,y + sta needRead,y + sta readLeft,y + lda #PIPESIZE-1 + sta writeLeft,y + +* ph2 #0 +* jsl asmSemNew +* ldy pipeind +* sta writeStatus,y + lda #1 + sta WrnCount,y + sta RrnCount,y + lda #0 + sta in,y + sta out,y + sta qflags,y + ph4 #0 + ph4 #PIPESIZE + ph2 userID + ph2 #0008 ; may not use special memory + ph4 #0 + _NewHandle + ldy pipeind + pla + sta bufferH,y + sta hand + pla + sta bufferH+2,y + sta hand+2 + +* zero out the pipe buffer so we can see what's going on better + lda [hand] + sta buf + ldy #2 + lda [hand],y + sta buf+2 + ldy #PIPESIZE-1 + lda #0 + short m +lp sta [buf],y + dey + bpl lp + long m + + lda pipediv + inc a + sta retval +goaway return 2:retval + END + +disposePipe START + using pipeRecord + using KernelStruct +retval equ 0 +pipeind equ 2 + + subroutine (2:pipe),4 + + lda pipe + jsl calcPipeInd + sta pipeind + + tay + +* push all the stack info we need in one big glob- no errors can occur + + lda bufferH+2,y + pha + lda bufferH,y + pha + lda needWriteSem,y + pha + lda needReadSem,y + pha + lda accessSem,y + pha +* lda writeStatus,y +* pha + + jsl asmSemDispose + jsl asmSemDispose + jsl asmSemDispose +* jsl asmSemDispose + _DisposeHandle + lda #0 + ldy pipeind + sta bufferH,y + sta bufferH+2,y +goaway return + END + +IOreqCount gequ 6 +IOrefNum gequ 0 +IOdataBuf gequ 2 +IOtransCount gequ 10 + + +pipeHiRead START + using pipeRecord + +pipeInd equ 0 +locReadleft equ 2 +transLeft equ 4 +doCount equ 8 +curDataPtr equ 10 +pipeBuf equ 14 +pipeH equ 18 +didTransfer equ 22 +retVal equ 26 +usrOutInd equ 28 +NLenableMask equ 30 +numnewlines equ 32 +newlinebuf equ 34 +P16newlinech equ 38 ; note that these are only checked +tempChar equ 40 ; in 8-bit mode + + subroutine (4:pBlock,2:pipe,4:fdrec),42 +* Initialize a bunch of crap + + lda pipe + jsl calcPipeInd + sta pipeInd + +* set up our local variables to do newline checking + ldy #FDNLenableMask + lda [fdrec],y + sta NLenableMask + beq nlOff ; if NL's are off, save a few cycles + ldy #FDrefFlags + lda [fdrec],y + and #rfP16NEWL + beq doNormalNewL + + ldy #FDNLnumChars + lda [fdrec],y + sta P16newlinech + lda #1 + sta numnewlines + stz newlinebuf+2 + tdc + clc + adc #P16newlinech + sta newlinebuf + bra nlOff + +doNormalNewL ldy #FDNLnumChars ; otherwise copy the info we need + lda [fdrec],y + sta numnewlines + ldy #FDNLtable + lda [fdrec],y + sta newlinebuf + iny2 + lda [fdrec],y + sta newlinebuf+2 + +nlOff stz retVal ; no error right now + +* copy the # of bytes wanted to our "current count" counter + ldy #IOreqCount+2 + lda [pBlock],y + sta transLeft+2 + ldy #IOreqCount + lda [pBlock],y + sta transLeft +* move the data pointer to our "current pointer" pointer + ldy #IOdataBuf+2 + lda [pBlock],y + sta curDataPtr+2 + ldy #IOdataBuf + lda [pBlock],y + sta curDataPtr + stz didTransfer + stz didTransfer+2 + +l1 anop + +; lda #hsHoldSig +; jsl setHoldSig ; hold signals until we tell you + +* get access to the pipe record + ldy pipeInd + lda accessSem,y + pha + jsl asmWait + +* calculate number of bytes actually in the pipe that can be read + ldy pipeInd + lda bufferH,y + sta pipeH + lda bufferH+2,y + sta pipeH+2 + lda readLeft,y + sta locReadleft ; temporary location + + lda [pipeH] + sta pipeBuf + ldy #2 + lda [pipeH],y + sta pipeBuf+2 + +* determine how many bytes to transfer in this chunk + lda transLeft+2 + bne gt1 + lda transLeft + cmp locReadleft + bcs gt1 + lda transLeft + sta doCount + bra lt1 +gt1 lda locReadleft + sta doCount +lt1 anop + cmp #0 ; no data to read? what? morons! + bne havedata + +* there's no data, so see if there are any writers left + ldy pipeInd + lda WrnCount,y +* there are writers, so go wait for data + jne wait4data + lda #$4C + sta retVal + jmp goaway + +havedata ldy pipeInd + lda out,y + tax + stz usrOutInd + short m +* main data copy loop +lp1 anop + txy +* $$$ Squeeze the NewLine mode check in here somewhere +* (ptys will use NewLine's to implement the cooked tty mode) + lda [pipeBuf],y + sta tempChar + ldy usrOutInd + sta [curDataPtr],y + inx + cpx #PIPESIZE + bcc nomod + ldx #0 +nomod anop + iny + sty usrOutInd + ldy doCount + dey + sty doCount + +* this is the newline character check (note the massive overhead) + lda NLenableMask ; if the mask is 0, we don't do NL + bne doNLcheck + + tya ; get the Z flag again + bne lp1 + bra donexfer +doNLcheck anop + and tempChar + ldy #0 +lp cpy numnewlines + beq ckLastByte ; all out o' + cmp [newlinebuf],y + beq gotnewline + iny + bra lp +ckLastByte ldy doCount + bne lp1 + beq donexfer + +gotnewline anop +; bne lp1 y != 0 + long m + lda #1 + sta retVal + +* update our buffer pointers +donexfer long m + ldy usrOutInd + sty doCount ; reset this + tya + clc + adc curDataPtr + sta curDataPtr + lda curDataPtr+2 + adc #0 + sta curDataPtr+2 + + tya + clc + adc didTransfer + sta didTransfer + lda didTransfer+2 + adc #0 + sta didTransfer+2 + + ldy pipeInd + txa + sta out,y + + lda transLeft + sec + sbc doCount + sta transLeft + lda transLeft+2 + sbc #0 + sta transLeft+2 + + lda readLeft,y + sec + sbc doCount + sta readLeft,y + lda writeLeft,y + clc + adc doCount + sta writeLeft,y + + lda needWrite,y + beq noneedwrite + dea + sta needWrite,y + lda needWriteSem,y ; release a process that needs to + pha ; write into the pipe + jsl asmSignal + +noneedwrite anop +* anything left to transfer? + lda retVal + cmp #1 + bne notNL + stz retVal + bra goaway +notNL lda transLeft + ora transLeft+2 + beq goaway + ldy pipeInd +* tell a writer that we need more data, and block ourselves +wait4data anop + lda needRead,y + ina + sta needRead,y +* release the pipe structure + lda accessSem,y + pha + jsl asmSignal +* wait for someone to write more data +* Note that if a writer terminates while we're waiting here, +* we'll go above, & read data, then come back here because the reader +* wants still more data. Then we hang. We need to check for a lack of +* writers again here +* We can only get here because there's not enough data in the pipe +* to satisfy the request. + +; lda #hsNoHoldSig +; jsl setHoldSig ; don't hold signals +; jsl checkHeldSig ; did we get one? +; lda #hsHoldSig +; jsl setHoldSig ; hold signals until we tell you + + ldy pipeInd + lda WrnCount,y + beq nomowrite + lda needReadSem,y + pha + jsl asmWait +; jsl checkHeldSig + + jmp l1 +nomowrite lda #$4C + sta retVal +goaway anop +* release the pipe (we're leaving, yea! Back to Kansas...) + ldy pipeInd + lda accessSem,y + pha + jsl asmSignal + lda didTransfer + ldy #IOtransCount + sta [pBlock],y + lda didTransfer+2 + ldy #IOtransCount+2 + sta [pBlock],y + +; lda #hsNoHoldSig +; jsl setHoldSig ; we're done, you can clobber us +; jsl checkHeldSig + + return 2:retVal + END + +pipeHiWrite START + using pipeRecord +pipeInd equ 0 +locWriteleft equ 2 +transLeft equ 4 +doCount equ 8 +curDataPtr equ 10 +pipeBuf equ 14 +pipeH equ 18 +didTransfer equ 22 +retVal equ 26 +usrInInd equ 28 + + subroutine (4:pBlock,2:pipe),30 +* Initialize a bunch of crap + + lda pipe + jsl calcPipeInd + sta pipeInd + stz retVal ; no error right now + +* copy the # of bytes wanted to our "current count" counter + ldy #IOreqCount+2 + lda [pBlock],y + sta transLeft+2 + ldy #IOreqCount + lda [pBlock],y + sta transLeft +* move the data pointer to our "current pointer" pointer + ldy #IOdataBuf+2 + lda [pBlock],y + sta curDataPtr+2 + ldy #IOdataBuf + lda [pBlock],y + sta curDataPtr + stz didTransfer + stz didTransfer+2 + +l1 anop + +; lda #hsHoldSig +; jsl setHoldSig + +* get access to the pipe record + ldy pipeInd + lda accessSem,y + pha + jsl asmWait + +* calculate number of bytes actually in the pipe that can be read + ldy pipeInd + lda bufferH,y + sta pipeH + lda bufferH+2,y + sta pipeH+2 + lda writeLeft,y + sta locWriteleft ; temporary location + + lda [pipeH] + sta pipeBuf + ldy #2 + lda [pipeH],y + sta pipeBuf+2 + +* determine how many bytes to transfer in this chunk + lda transLeft+2 + bne gt1 + lda transLeft + cmp locWriteleft + bcs gt1 + lda transLeft + sta doCount + bra lt1 +gt1 lda locWriteleft + sta doCount +lt1 anop + +* see if there are any readers left + ldy pipeInd + lda RrnCount,y +* there are readers, so go check for data + jne check4data +* ack! there are no readers left! + lda needWriteSem,y + pha + jsl asmSignal ; for the next orphaned writer + ldy pipeInd + lda accessSem,y + pha + jsl asmSignal ; we need to relinquish pipe access + +; lda #hsNoHoldSig ; so the signal below will get +; jsl setHoldSig ; delivered +; jsl checkHeldSig + +* do not call checkHeldSig since we want this sent first + + pha + pha + jsl KERNgetpid ; this is #pragma toolparms 1 + pea 13 ; SIGPIPE + ph4 #errno + jsl KERNkill ; this is #pragma toolparms 1 + pla + lda #$27 + sta retVal + jmp goaway + +check4data lda doCount + cmp #0 ; no room to write data? + jeq wait4data ; no data, go wait for some + +havedata ldy pipeInd + lda in,y + tax + stz usrInInd + short m +* main data copy loop +lp1 anop + ldy usrInInd + lda [curDataPtr],y + txy + sta [pipeBuf],y + inx + cpx #PIPESIZE + bcc nomod + ldx #0 +nomod ldy usrInInd + iny + sty usrInInd + ldy doCount + dey + sty doCount + bne lp1 +* update our buffer pointers + long m + ldy usrInInd + sty doCount ; reset this + tya + clc + adc curDataPtr + sta curDataPtr + lda curDataPtr+2 + adc #0 + sta curDataPtr+2 + + tya + clc + adc didTransfer + sta didTransfer + lda didTransfer+2 + adc #0 + sta didTransfer+2 + + ldy pipeInd + txa + sta in,y + + lda transLeft + sec + sbc doCount + sta transLeft + lda transLeft+2 + sbc #0 + sta transLeft+2 + + lda readLeft,y + clc + adc doCount + sta readLeft,y + lda writeLeft,y + sec + sbc doCount + sta writeLeft,y + + lda needRead,y + beq noneedwrite + dea + sta needRead,y + lda needReadSem,y ; release a process that needs to + pha ; read from the pipe + jsl asmSignal + +noneedwrite anop +* anything left to transfer? + lda transLeft + ora transLeft+2 + beq goaway + ldy pipeInd +* tell a reader that we need more room, and block ourselves +wait4data lda needWrite,y + ina + sta needWrite,y + +* release the pipe structure + lda accessSem,y + pha + jsl asmSignal + +; lda #hsNoHoldSig +; jsl setHoldSig +; jsl checkHeldSig +; lda #hsHoldSig +; jsl setHoldSig + +* wait for someone to read more data + ldy pipeInd + lda needWriteSem,y + pha + jsl asmWait +; jsl checkHeldSig + jmp l1 + +goaway anop +* release the pipe (we're leaving, yea! Back to Kansas...) + ldy pipeInd + lda accessSem,y + pha + jsl asmSignal + lda didTransfer + ldy #IOtransCount + sta [pBlock],y + lda didTransfer+2 + ldy #IOtransCount+2 + sta [pBlock],y + +; lda #hsNoHoldSig +; jsl setHoldSig +; jsl checkHeldSig + + return 2:retVal + END + +* Input: +* A = pipe number +* Output: +* A = pipe index +* pipeInd = (pipe - 1) * 32 + +calcPipeInd START + dec a + asl a + asl a + asl a + asl a + asl a + rtl + END + +incPipe START + using pipeRecord +pipeInd equ 0 + subroutine (2:pipe,2:fl),2 + lda pipe + jsl calcPipeInd + sta pipeInd + tay + lda accessSem,y + pha + jsl asmWait + ldy pipeInd + lda fl + bit #2 + bne wc + bit #1 + bne rc ; invalid happening + brk $00 +rc lda RrnCount,y + inc a + sta RrnCount,y + bra goaway +wc lda WrnCount,y + inc a + sta WrnCount,y +goaway anop + lda accessSem,y + pha + jsl asmSignal + return + END + +decPipe START + using pipeRecord +pipeInd equ 0 + + subroutine (2:pipe,2:fl),2 + lda pipe + jsl calcPipeInd + sta pipeInd + tay + lda accessSem,y + pha + jsl asmWait + ldy pipeInd + lda fl + bit #2 + bne wc + bit #1 + bne rc ; don't know- this is a BAD thing + brk $00 + +rc lda RrnCount,y + dec a + sta RrnCount,y + bne goaway + + lda needWrite,y + beq goaway + dec a + sta needWrite,y + + lda needWriteSem,y + pha + jsl asmSignal ; tell writers to go thru so they + bra goaway ; notice there's no more reader +wc lda WrnCount,y + dec a + sta WrnCount,y +* sta >$e00400 + bne goaway + lda needRead,y +* sta >$e00402 + beq goaway + dec a + sta needRead,y +g1 lda needReadSem,y + pha + jsl asmSignal + +goaway anop + ldy pipeInd + lda accessSem,y + pha + jsl asmSignal + return + END diff --git a/kern/gno/ports.c b/kern/gno/ports.c new file mode 100644 index 0000000..427917a --- /dev/null +++ b/kern/gno/ports.c @@ -0,0 +1,341 @@ +/* $Id: ports.c,v 1.1 1998/02/02 08:18:41 taubert Exp $ */ + +#include "conf.h" +#include "kernel.h" +#include "proc.h" +#include "gno.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include +#include + +#pragma optimize 79 + +struct ptnode *ptfree; /* list of free queue nodes */ +struct pt ports[NPORTS]; +int ptnextp; + +extern void PANIC(char *s); + +#ifdef KERNEL +segment "KERN2 "; +#else +#include "tests/testports.c" +#endif + +/* + * pinit - initialize all ports + */ + +SYSCALL pinit(int maxmsgs) +{ +int i; +struct ptnode *next,*prev; + + if ( (ptfree=malloc(maxmsgs*sizeof(struct ptnode)))==NULL ) + PANIC("pinit - insufficient memory"); + for (i = 0; i < NPORTS; i++) { + ports[i].ptstate = PTFREE; + ports[i].ptseq = 0; + } + ptnextp = NPORTS - 1; + + /* link up free list of message pointer nodes */ + for (prev = next = ptfree; --maxmsgs > 0; prev = next) + prev->ptnext = ++next; + prev->ptnext = NULL; + return(OK); +} + +#pragma databank 1 +#pragma toolparms 1 +/* + * pcreate - create a port that allows "count" outstanding messages + */ +pascal SYSCALL KERNpcreate(int count, int *ERRNO) +{ +int ps; +int i,p; +struct pt *ptptr; + + if (count < 0) return SYSERR; + disableps(); + for (i = 0; i < NPORTS; i++) { + if ((p = ptnextp--) < 0) + ptnextp = NPORTS - 1; + if ((ptptr = &ports[p])->ptstate == PTFREE) { + ptptr->ptstate = PTALLOC; + ptptr->ptname = PTUNNAMED; + ptptr->ptssem = Kscreate(ERRNO, count); + if (ptptr->ptssem == SYSERR) { + bad: ptptr->ptstate = PTFREE; + *ERRNO = ENOMEM; + enableps(); + return SYSERR; + } + ptptr->ptrsem = Kscreate(ERRNO, 0); + if (ptptr->ptrsem == SYSERR) { + Ksdelete(ERRNO, ptptr->ptssem); + goto bad; + } + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + ptptr->pthead = ptptr->pttail = NULL; +#else + ptptr->pthead = NULL; + ptptr->pttail = NULL; +#endif + ptptr->ptseq++; + ptptr->ptmaxcnt = count; + enableps(); + return p; + } + } + enableps(); + *ERRNO = ENOMEM; + return SYSERR; +} + +/* + * psend - send a message to a port by enqueueing it + */ + +pascal SYSCALL KERNpsend(int portid, long int msg, int *ERRNO) +{ +int ps; +struct pt *ptptr; +int seq; +struct ptnode *freenode; + + disableps(); + if (isbadport(portid) || + (ptptr = &ports[portid])->ptstate != PTALLOC) { + enableps(); + return SYSERR; + } + /* wait for space and verify port is still allocated */ + seq = ptptr->ptseq; + if (commonSwait(ERRNO,ptptr->ptssem,procBLOCKED,BLOCKED_PRECEIVE) == SYSERR) { + enableps(); + /* *ERRNO set in commonSwait() */ + return SYSERR; + } + if (ptptr->ptstate != PTALLOC || ptptr->ptseq != seq) { + enableps(); + return SYSERR; + } + if (ptfree == NULL) + PANIC("Ports - out of nodes"); + freenode = ptfree; + ptfree = freenode->ptnext; + freenode->ptnext = NULL; + freenode->ptmsg = msg; + if (ptptr->pttail == NULL) { + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + ptptr->pthead = ptptr->pttail = freenode; +#else + ptptr->pthead = freenode; + ptptr->pttail = freenode; +#endif + } else { + (ptptr->pttail)->ptnext = freenode; + ptptr->pttail = freenode; + } + Kssignal(ERRNO, ptptr->ptrsem); + enableps(); + return OK; +} + +/* + * preceive - receive a message from a port, blocking if port empty + */ + +pascal long SYSCALL KERNpreceive(int portid, int *ERRNO) +{ +int ps; +struct pt *ptptr; +int seq; +long int msg; +struct ptnode *nxtnode; + + disableps(); + if (isbadport(portid) || + (ptptr = &ports[portid])->ptstate != PTALLOC) { + enableps(); + return SYSERR; + } + /* wait for message and verify that the port is still allocated */ + seq = ptptr->ptseq; + /* sleep, and return EINTR/SYSERR if we were interrupted */ + if (commonSwait(ERRNO,ptptr->ptrsem,procBLOCKED,BLOCKED_PRECEIVE) == SYSERR) { + enableps(); + /* *ERRNO set in commonSwait() */ + return SYSERR; + } + if (ptptr->ptstate != PTALLOC || ptptr->ptseq != seq) { + enableps(); + return SYSERR; + } + /* dequeue first message that is waiting in the port */ + + nxtnode = ptptr->pthead; + msg = nxtnode->ptmsg; + if (ptptr->pthead == ptptr->pttail) { /* delete last item */ + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + ptptr->pthead = ptptr->pttail = NULL; +#else + ptptr->pthead = NULL; + ptptr->pttail = NULL; +#endif + } else ptptr->pthead = nxtnode->ptnext; + nxtnode->ptnext = ptfree; /* return to free list */ + ptfree = nxtnode; + Kssignal(ERRNO, ptptr->ptssem); + enableps(); + return msg; +} + +#pragma toolparms 0 + +/* + * _ptclear - used by pdelete and preset to clear a port + */ + +_ptclear(struct pt *ptptr, int newstate, int (*dispose)(long int)) +{ +struct ptnode *p; + + /* put port in limbo until done freeing processes */ + ptptr->ptstate = PTLIMBO; + ptptr->ptseq++; + if ((p=ptptr->pthead) != NULL) { + for (; p != NULL; p=p->ptnext) + /* only do this if they specified a disposition */ + if (dispose != NULL) (*dispose)(p->ptmsg); + (ptptr->pttail)->ptnext = ptfree; + ptfree = ptptr->pthead; + } + if (newstate == PTALLOC) { + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + ptptr->pthead = ptptr->pttail = NULL; +#else + ptptr->pthead = NULL; + ptptr->pttail = NULL; +#endif + /* sreset(ptptr->ptssem, ptptr->ptmaxcnt); + sreset(ptptr->ptrsem, 0); */ + } else { + enableps(); + Ksdelete(&errno, ptptr->ptssem); + Ksdelete(&errno, ptptr->ptrsem); + disableps(); + } + ptptr->ptstate = newstate; +} + +#pragma toolparms 1 +/* + * pdelete - delete a port, freeing waiting processes and messages + */ + +pascal SYSCALL KERNpdelete(int portid, int (*dispose)(long int), int *ERRNO) +{ +int ps; +struct pt *ptptr; + + disableps(); + if (isbadport(portid) || + (ptptr = &ports[portid])->ptstate != PTALLOC) { + enableps(); + return SYSERR; + } + _ptclear(ptptr,PTFREE,dispose); + /* dispose of the port's name */ + if (ptptr->ptname != NULL) { + free(ptptr->ptname); + ptptr->ptname = NULL; + } + enableps(); + return OK; +} + +/* + * preset - reset a port, freeing waiting processes and messages + */ + +pascal SYSCALL KERNpreset(int portid, int (*dispose)(long int), int *ERRNO) +{ +int ps; +struct pt *ptptr; + + disableps(); + if (isbadport(portid) || + (ptptr = &ports[portid])->ptstate != PTALLOC) { + enableps(); + return SYSERR; + } + _ptclear(ptptr, PTALLOC, dispose); + enableps(); + return OK; +} + +/* + * pbind - binds a port to a name + */ + +pascal SYSCALL KERNpbind(int portid, char *name, int *ERRNO) +{ +struct pt *ptptr; + + disableps(); + if (isbadport(portid) || + (ptptr = &ports[portid])->ptstate != PTALLOC) { + enableps(); + return SYSERR; + } + if (ptptr->ptname != PTUNNAMED) { + enableps(); + return SYSERR; + } + ptptr->ptname = malloc(33); + strncpy(ptptr->ptname,name,32); + enableps(); + return OK; +} + +pascal SYSCALL KERNpgetport(char *name, int *ERRNO) +{ +struct pt *ptptr; +unsigned i; + + disableps(); + for (i = 0; i < NPORTS; i++) + if ((ports[i].ptstate == PTALLOC) && (ports[i].ptname != NULL) + && (!strncmp(ports[i].ptname,name,32))) { + enableps(); + return i; + } + enableps(); + return SYSERR; +} + +pascal SYSCALL KERNpgetcount(int portid, int *ERRNO) +{ +struct pt *ptptr; +int c,d; + + disableps(); + if (isbadport(portid) || + (ptptr = &ports[portid])->ptstate != PTALLOC) { + enableps(); + return SYSERR; + } + c = Kscount(ERRNO, ptptr->ptssem); + d = (c == SYSERR) ? ptptr->ptmaxcnt : ptptr->ptmaxcnt - c; + enableps(); + return d; +} + diff --git a/kern/gno/proc.h b/kern/gno/proc.h new file mode 100644 index 0000000..f81f5ec --- /dev/null +++ b/kern/gno/proc.h @@ -0,0 +1,154 @@ +/* $Id: proc.h,v 1.1 1998/02/02 08:18:43 taubert Exp $ */ + +/* + Kernel Process table structure + Copyright 1991-1998 Procyon, Inc. +*/ + +#ifndef PROC_KERN +#define PROC_KERN + +#include +#include +#include + +/* the various process states are defined here */ + +#define procUNUSED 0 +#define procRUNNING 1 +#define procREADY 2 +#define procBLOCKED 3 +#define procNEW 4 +#define procSUSPENDED 5 +#define procWAIT 6 +#define procWAITSIGCH 7 +#define procPAUSED 8 +#define procSLEEP 9 + +#define BLOCKED_RECEIVE 2 +#define BLOCKED_PRECEIVE 3 +#define BLOCKED_SWAIT 4 + +#define SYSERR -1 +#define SYSOK 0 + +#define rtGSOS 0 +#define rtPIPE 1 +#define rtTTY 2 +#define rtSOCKET 3 + +#define rfPIPEREAD 1 /* read end of the pipe */ +#define rfPIPEWRITE 2 /* write end of the pipe */ +#define rfCLOSEEXEC 4 /* close this file on an exec() */ +#define rfP16NEWL 8 /* special prodos-16 newline mode */ + +typedef struct fdentry { + word refNum; /* refNum, pipeNum, ttyID, or sockNum */ + word refType; /* 0 = GS/OS refnum, 1 = pipe, 2 = tty, 3 = socket */ + word refLevel; /* "file level" of the refnum */ + word refFlags; /* see flags above */ + word NLenableMask; /* these three fields are for newline handling */ + word NLnumChars; + void *NLtable; +} fdentry, *fdentryPtr; + +typedef struct fdtable { + word fdCount; + word fdLevel; + word fdLevelMode; + word fdTableSize; + fdentry fds[1]; +} fdtable, *fdtablePtr; + +#define FD_SIZE 32 + +typedef struct quitStack { + struct quitStack *next; + char data[1]; +} quitStack; + +/* these flags are set by execve() and fork() during process creation. */ + +#define FL_RESOURCE 1 /* does the process have and use a resource fork? */ +#define FL_FORKED 2 /* was the process started with fork() ? */ +#define FL_COMPLIANT 4 /* is the process fully GNO compliant? */ +#define FL_NORMTERM 8 /* did the program terminate via exit()? 1=yes */ +#define FL_RESTART 16 /* is the program restartable? (set by QuitGS) */ +#define FL_NORESTART 32 /* don't allow this code to restart */ +#define FL_QDSTARTUP 64 /* flag set if QDStartUp was called */ +#define FL_MSGRECVD 128 /* flag set if there's a send() msg waiting */ +#define FL_SELECTING 256 /* this process is 'selecting' */ + +struct pentry { + int parentpid; /* pid of this process' parent */ + int processState; + int userID; /* a GS/OS UserID, used to keep track of memory */ + int ttyID; /* driver (not GS/OS) number of i/o port */ + word irq_A; /* context information for the process */ + word irq_X; + word irq_Y; + word irq_S; + word irq_D; + byte irq_B; + byte irq_B1; + word irq_P; + word irq_state; + word irq_PC; + word irq_K; + int psem; /* semaphoreID process is blocked on */ + char **prefix; /* cwd's (GS/OS prefixes 0,1, and 9 */ + char *args; /* the command line that invoked the process program */ + char **env; /* environment variables for the program */ + struct sigrec *siginfo; /* global mask of which signals are blocked */ + byte irq_SLTROM; + byte irq_STATEREG; + word lastTool; + longword ticks; + word flags; + fdtablePtr openFiles; + word pgrp; + word exitCode; + void *LInfo; + word stoppedState; /* process state before stoppage */ + longword alarmCount; + void *executeHook; /* for a good time call... */ + word queueLink; +#ifdef KERNEL + chldInfoPtr waitq; /* where waits wait to be processed */ +#else + void *waitq; +#endif + int waitdone; + int flpid; + quitStack *returnStack; + word t2StackPtr; + word p_uid, p_gid; + word p_euid, p_egid; + word SANEwap; + longword msg; + longword childTicks; + unsigned long p_waitvec; + unsigned p_slink; + struct pentry *p_link,*p_rlink; + int p_prio; + /* no unused entries */ +}; +typedef struct pentry procState, *procStatePtr; + +#ifdef KERNEL +struct kernelStruct { + procState procTable[32]; + int curProcInd; + int userID; + int mutex; + int timeleft; + int numProcs; + word truepid; + word shutdown; + word gsosDebug; + int floatingPID; +}; +typedef struct kernelStruct kernelStruct, *kernelStructPtr; + +#endif /* KERNEL */ +#endif /* PROC_KERN */ diff --git a/kern/gno/pty.asm b/kern/gno/pty.asm new file mode 100644 index 0000000..f188f71 --- /dev/null +++ b/kern/gno/pty.asm @@ -0,0 +1,1337 @@ +* $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 diff --git a/kern/gno/q.h b/kern/gno/q.h new file mode 100644 index 0000000..c751f0d --- /dev/null +++ b/kern/gno/q.h @@ -0,0 +1,42 @@ +/* $Id: q.h,v 1.1 1998/02/02 08:18:46 taubert Exp $ */ + +/* q.h - firstid, firstkey, isempty, lastkey, nonempty */ +#if 0 +#ifndef NQNET +#define NQENT NPROC + NSEM + NSEM + 4 /* for ready & sleep */ +#endif + +struct qent { /* one for each process plust two for each list */ + int qkey; /* key on which the queue is ordered */ + int qnext; /* pointer to next process or tail */ + int qdata; /* extra data to be stored with the key */ + int qprev; /* pointer to previous process or head */ +}; + +extern struct qent _q[]; + +/* list manipulation macros */ +#define isempty(list) (_q[(list)].qnext >= NPROC) +#define nonempty(list) (_q[(list)].qnext < NPROC) +#define firstkey(list) (_q[_q[(list)].qnext].qkey) +#define lastkey(tail) (_q[_q[(tail)].qprev].qkey) +#define firstid(list) (_q[(list)].qnext) + +#define EMPTY -1 /* equivalent of null pointer */ + +#else + +struct qstruct { /* one for each process plust two for each list */ + struct pentry *head; /* head of the q */ + struct pentry *tail; /* tail of the q */ +}; + +#define NQS NSEM+2 /* ready, sleep, and # of semaphores */ +#define isbadqnum(__qn) (((__qn) < 0) || ((__qn) >= NQS)) + +extern struct qstruct *nq; +extern struct qstruct *q_free; + +#define nonempty(q) (nq[(q)].head != NULL) + +#endif diff --git a/kern/gno/queue.c b/kern/gno/queue.c new file mode 100644 index 0000000..264ddc8 --- /dev/null +++ b/kern/gno/queue.c @@ -0,0 +1,157 @@ +/* $Id: queue.c,v 1.1 1998/02/02 08:18:48 taubert Exp $ */ + +#pragma optimize 79 + +#ifdef KERNEL +#include "proc.h" +#include "sys.h" +#include "conf.h" +#include "kernel.h" +#include "q.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" + +extern kernelStructPtr kp; +#else +#include "tests/testqueue.c" +#endif + +void initQ(void) +{ +int i; + + for (i=0; iprocTable[i].p_link = NULL; + kp->procTable[i].p_rlink = NULL; + } + + if (!(nq = calloc(NQS,sizeof(struct qstruct)))) + PANIC("Could not allocate Q entries"); + for (i=0; ihead; + newQ->head = NULL; + newQ->tail = NULL; + return (newQ - nq); +} + +void Qdispose(int qnum) +{ +struct qstruct *qn; + + if (isbadqnum(qnum)) + PANIC("Bogus qnum passed to Qdispose"); + qn = &nq[qnum]; + qn->head = (struct pentry *) q_free; + q_free = qn; +} + +int _enqueue(int item, int qnum) +/* insert item at the tail of a list */ +{ +struct pentry *tptr; /* points to tail entry */ +struct pentry *mptr; /* points to item entry */ + + if (isbadqnum(qnum)) + PANIC("Bogus qnum passed to Qdispose"); + mptr = &kp->procTable[item]; + if (mptr->p_link || mptr->p_rlink) { + asm {brk 0xee}; + PANIC("Attempt to _enqueue pentry on multiple queues"); + } + + tptr = nq[qnum].tail; + mptr->p_rlink = tptr; + mptr->p_link = NULL; + if (tptr) + tptr->p_link = mptr; + else + nq[qnum].head = mptr; /* if there was nothing in list... */ + nq[qnum].tail = mptr; + return item; +} + +int _getfirst(int qnum) +/* remove item from the front of a queue and return it */ +{ +struct pentry *mptr; + + if (isbadqnum(qnum)) + PANIC("Bogus qnum passed to _getfirst"); + mptr = nq[qnum].head; + if (!mptr) return SYSERR; + nq[qnum].head = mptr->p_link; + if (!mptr->p_link) nq[qnum].tail = NULL; + else mptr->p_link->p_rlink = NULL; + + mptr->p_link = NULL; + mptr->p_rlink = NULL; + + return (mptr - kp); +} + +/* we don't use _getlast anywhere */ + +int _dequeueitem(int item, int qnum) +/* remove an item from a list and return it */ +{ +struct pentry *mptr; /* pointer to q entry for item */ +struct pentry *test; + + if (isbadqnum(qnum)) + PANIC("Bogus qnum passed to _dequeueitem"); + mptr = &kp->procTable[item]; + + test = nq[qnum].head; + while (test != mptr) { + if (!test) return SYSERR; /* item not found */ + test = test->p_link; + } + + if (!mptr->p_link) nq[qnum].tail = mptr->p_rlink; + else mptr->p_link->p_rlink = mptr->p_rlink; + if (!mptr->p_rlink) nq[qnum].head = mptr->p_link; + else mptr->p_rlink->p_link = mptr->p_link; + + mptr->p_link = NULL; + mptr->p_rlink = NULL; + + return(item); +} + +int _insert(int proc, int qnum, int key) +/* insert a process into a q list in key order */ +/* int proc; process to insert */ +/* int qnum; q index of head of list */ +/* int key; key to use for this process */ +{ +struct pentry *mptr, *next, *prev; + + if (isbadqnum(qnum)) + PANIC("Bogus qnum passed to _insert"); + mptr = &kp->procTable[proc]; + if (mptr->p_link || mptr->p_rlink) { + asm {brk 0xee}; + PANIC("Attempt to _insert pentry on multiple queues"); + } + + prev = NULL; + for (next=nq[qnum].head;next&&(next->p_priop_link) + prev = next; + if (mptr->p_rlink = prev) prev->p_link = mptr; + else nq[qnum].head = mptr; + if (mptr->p_link = next) next->p_rlink = mptr; + else nq[qnum].tail = mptr; + return OK; +} + diff --git a/kern/gno/regexp.asm b/kern/gno/regexp.asm new file mode 100644 index 0000000..52cd951 --- /dev/null +++ b/kern/gno/regexp.asm @@ -0,0 +1,303 @@ +* $Id: regexp.asm,v 1.1 1998/02/02 08:19:42 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* RegExp() +* +* Tim's Regular Expression Parser +* Written by Tim Meekins, 6/13/91 +* +* Copyright 1991 by Tim Meekins +* This function is hereby donated to the public domain as long as I am +* given credit as the author. +* +* Version 1.0 +* - First release, not very fancy or efficient, but I wrote the entire +* program in 2 hours and is has to be the world's shortest regular +* expression parser! +* +* "Look Ma, no non-deterministic finite state transition table!" +* +************************************************************************** +* +* INPUT: +* PH4 addr ;This is the address to a pattern for matching +* PH4 addr ;This is the text match against +* PH4 word ;This a flag. Bit 16 = 1 if case sensitive. +* jsl RegExp +* +* OUTPUT: +* On Exit A=0 if no match, else a match was found. +* +* EXAMPLE: +* while ((*p != 0) && (RegExp(pattern,*p))) p++; +* +* This example will search sequentially through a list until a match is found. +* Or at least I hope this works, never actually tried this example. +* +* PATTERNS are built the following way: +* +* pure text is matched directly to the text +* '*' matchs 0 or more characters +* '+' matches 1 or more characters +* '?' matches 0 or 1 characters +* '[..]' matches one of the characters contained in the brackets. If two +* characters are separated by '-' then matches if the character is +* within the range. If the first character in the list is a '^' +* then a match will occur if NONE of the characters in brackets macth. +* '\' exactly matches the following character. This lets you match the above +* characters and '\' itself. Otherwise known as character quoting. +* +************************************************************************** +* +* meekins@cis.ohio-state.edu +* timm@pro-tc.cts.com +* +************************************************************************** + + mcopy m/regexp.mac + case on + +RegExp START + +result equ 0 +ch equ result+2 +negflag equ ch+2 +space equ negflag+2 + + subroutine (4:pattern,4:text,2:flag),space + + ld2 0,result + +;========================================================================= +; +; PHASE 1. Match characters one by one +; +;========================================================================= + +phase1 lda [pattern] + jsr ToLower + cmp #0 + beq patt0 + cmp #'\' + beq quote + cmp #'+' + beq plus + cmp #'*' + beq star + cmp #'?' + jeq quest + cmp #'[' + jeq lbrak + +phase1a sta ch + lda [text] + jsr ToLower + cmp ch + bne done + inc pattern + bne inc01 + inc pattern+2 +inc01 inc text + bne inc02 + inc text+2 +inc02 bra phase1 + +patt0 lda [text] + and #$FF + bne done + bra match + +quote anop ;do character quoting + inc pattern + bne inc03 + inc pattern+2 +inc03 lda [pattern] + jsr ToLower + cmp #0 + beq done + bra phase1a + + +;========================================================================= +; +; PHASE 2. non-deterministic matching +; +;========================================================================= + +; +; Match one or more characters +; +plus anop + inc text + bne inc04 + inc text+2 +inc04 lda [text] + and #$FF + beq done +; +; Match 0 or more characters +; +star anop + inc pattern + bne inc05 + inc pattern+2 +inc05 lda [pattern] + and #$FF + beq match +starloop lda [text] + and #$FF + beq done + pei (pattern+2) + pei (pattern) + pei (text+2) + pei (text) + pei (flag) + jsl RegExp + cmp #0 + bne match + inc text + bne starloop + inc text+2 + bra starloop +; +; If a positive match is made, jump to match +; If no match is made, jump to done. +; + +match ld2 1,result +done return 2:result + +; +; Match 0 or 1 characters +; +quest anop + inc pattern + bne inc06 + inc pattern+2 +inc06 pei (pattern+2) + pei (pattern) + pei (text+2) + pei (text) + pei (flag) + jsl RegExp + cmp #0 + bne match + inc text + bne inc07 + inc text+2 +inc07 pei (pattern+2) + pei (pattern) + pei (text+2) + pei (text) + pei (flag) + jsl RegExp + cmp #0 + bne match + bra done +; +; Match one character contained in brackets +; +lbrak anop + stz negflag + lda [text] + jsr ToLower + cmp #0 + beq done + sta ch + ldy #1 + lda [pattern],y + and #$FF + cmp #'^' + bne lbrak3 + inc negflag + +lbrak2 iny + lda [pattern],y + and #$FF +lbrak3 cmp #']' + beq braknomatch + iny + lda [pattern],y + dey + and #$FF + cmp #'-' + beq range + + lda [pattern],y ;match a single character + jsr ToLower + cmp #0 + jeq done + cmp ch + bne lbrak2 + +brakmatch lda negflag + beq brakdone + jmp done + +braknomatch lda negflag + bne brakdone2 + jmp done + +brakdone iny +brakdone2 lda [pattern],y + and #$FF + jeq done + cmp #']' + bne brakdone + iny + clc + tya + adc pattern + sta pattern + bne inc08 + inc pattern+2 +inc08 inc text + bne inc09 + inc text+2 +inc09 jmp phase1 + +range lda [pattern],y + iny2 + and #$FF + jeq done + dec a + cmp ch + bcc range2 + lda [pattern],y + and #$FF + jeq done + bra range3 +range2 lda [pattern],y + and #$FF + jeq done + cmp ch + bcs brakmatch +range3 jmp lbrak2 + +;========================================================================= +; +; Takes a sixteen bit value, strips to 8 bit and converts to lower case. +; +;========================================================================= + +ToLower anop + + and #$FF + ldx flag + bmi lowered + if2 @a,cc,#'A',lowered + if2 @a,cs,#'Z'+1,lowered + add2 @a,#'a'-'A',@a + +lowered rts + + END diff --git a/kern/gno/resource.asm b/kern/gno/resource.asm new file mode 100644 index 0000000..35d3773 --- /dev/null +++ b/kern/gno/resource.asm @@ -0,0 +1,1071 @@ +* $Id: resource.asm,v 1.1 1998/02/02 08:19:44 taubert Exp $ +************************************************************************** +* +* RESOURCE.ASM +* +* v1.0 (11/17/91) +* by Jawaid Bazyar +* +* This file patches the Resource Manager to take proper care of +* refNum's/FDs in our new environment, and also keeps track of the +* CurResourceApp value- it makes sure that the Resource Manager +* always has correct info about the App making a call +* +************************************************************************** + + case on + mcopy m/resource.mac + +OldRMtable DATA +oldOpenFiles dc i4'0' +rmStackPtr dc i2'0' +rmStack dc 16i4'0' +rmFuncs dc 60i4'0' + END + + copy inc/gsos.inc + +* We set the BootInit function to a null function to avoid calling the +* real ResourceManager BootInit function- which could be rather catastrophic + +* We'll patch the StartUp and ShutDown functions when we track CurResourceApp. +* The new 6.0.1 OpenResourceFileByID() calls OpenResourceFile to do its +* dirty work, so leaving it as-is won't cause any problems. + +NewRMtable DATA +rmsize dc i4'0' ; copy this from old table + dc i4'NULLTOOLFUNC-1' ; BootInit + dc i4'NewRMSU-1' ; StartUp + dc i4'NewRMSD-1' ; ShutDown + dc i4'0' ; Version + dc i4'0' ; Reset + dc i4'0' ; Status + dc i4'0' + dc i4'0' + + dc i4'NewRMFunc-1' ; 9 + dc i4'NewORF-1' ; A + dc i4'NewRMFunc-1' ; B + dc i4'NewRMFunc-1' ; C + dc i4'NewRMFunc-1' ; D + dc i4'NewRMFunc-1' ; E + dc i4'NewRMFunc-1' ; F + dc i4'NewRMFunc-1' ; 10 + dc i4'NewRMFunc-1' ; 11 + dc i4'NewRMFunc-1' ; 12 + dc i4'NewSCRA-1' ; 13 + dc i4'NewRMFunc-1' ; 14 + dc i4'NewRMFunc-1' ; 15 + dc i4'NewRMFunc-1' ; 16 + dc i4'NewRMFunc-1' ; 17 + dc i4'NewRMFunc-1' ; 18 + dc i4'NewRMFunc-1' ; 19 + dc i4'NewRMFunc-1' ; 1A + dc i4'NewRMFunc-1' ; 1B + dc i4'NewRMFunc-1' ; 1C + dc i4'NewRMFunc-1' ; 1D + dc i4'NewRMFunc-1' ; 1E + dc i4'NewGOFRN-1' ; 1F + dc i4'NewRMFunc-1' ; 20 + dc i4'NewRMFunc-1' ; 21 + dc i4'NewRMFunc-1' ; 22 + dc i4'NewRMFunc-1' ; 23 + dc i4'NewRMFunc-1' ; 24 + dc i4'NewRMFunc-1' ; 25 + dc i4'NewRMFunc-1' ; 26 + dc i4'NewRMFunc-1' ; 27 + dc i4'NewRMFunc-1' ; 28 + dc i4'NewRMFunc-1' ; 29 + dc i4'NewRMFunc-1' ; 2A + dc i4'NewRMFunc-1' ; 2B + dc i4'NewRMFunc-1' ; 2C + dc i4'NewRMFunc-1' ; 2D + dc i4'NewRMFunc-1' ; 2E + dc i4'NewRMFunc-1' ; 2F + + END + +patchRM START + using OldRMtable + using NewRMtable +tsPtr equ 0 + subroutine (0:foo),4 + pha + pha + ph2 #0 + ph2 #$1E + _GetTSPtr + pl4 tsPtr + + lda [tsPtr] + sta rmFuncs + sta rmsize + tax + ldy #2 + lda [tsPtr],y + sta rmFuncs,y + sta rmsize+2 + iny2 +copyloop cpx #0 + beq donecopy + lda [tsPtr],y + sta rmFuncs,y + iny2 + lda [tsPtr],y + sta rmFuncs,y + iny2 + dex + bra copyloop +donecopy anop + ph2 #0 + ph2 #$1E + ph4 #NewRMtable + _SetTSPtr + return + END + +unPatchRM START + using OldRMtable +tsPtr equ 0 + subroutine (0:foo),4 + pha + pha + ph2 #0 + ph2 #$1E + _GetTSPtr + pl4 tsPtr + + lda [tsPtr] + tax + ldy #4 +copyloop cpx #0 + beq donecopy + lda rmFuncs,y + sta [tsPtr],y + iny2 + lda rmFuncs,y + sta [tsPtr],y + iny2 + dex + bra copyloop +donecopy anop + return + END + + +* Makes sure that the CurResourceApp setting is correct. + +SetCurRes START + using KernelStruct + + lda >curProcInd + tax + lda >resapp,X + beq okay ; no resource thingy set + cmp >CurResApp + beq okay ; cur is the one we want + + pha + ldx #$131E + jsl $E10000 +; _SetCurResourceApp + +okay rts + END + + +* We keep a stack of return addresses, since to pre-and-post patch these +* tool calls, we have to displace one of the two return addresses already +* there. +* We also copy the current process' openFiles pointer to a safe temp, +* and install the Kernel Null process' open files list. All Resource +* manager calls are made with the Kernel's file list, so it will always +* have all files accessible + +NewRMFunc START + using OldRMtable + using KernelStruct + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s ; prolly not necessary, but fuck it + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* get the last return address on the stack (at 9,s) and save it in +* our return stack + + lda rmStackPtr + bne noSwitch + ldx curProcInd + lda openFiles,x + sta oldOpenFiles + lda openFiles+2,x + sta oldOpenFiles+2 + lda openFiles ; Kernel open file list + sta openFiles,x + lda openFiles+2 + sta openFiles+2,x ; + lda rmStackPtr +noSwitch anop + asl a + asl a + tax + lda 12,s + sta rmStack,x + lda 13,s + sta rmStack+1,x + inc rmStackPtr + +* Now, put our return address on the stack instead + + lda #(rmReturn-1)|-8 + sta 13,s + lda #rmReturn-1 + sta 12,s + + jsr SetCurRes + +* Finally, shove the address of the old function to call onto the +* stack and RTL to it. + + lda 5,s ; X + and #$FF00 ; mask off tool # + xba ; swap + asl a + asl a + tax + lda rmFuncs+1,x + sta 10,s + lda rmFuncs,x + sta 9,s + pla + ply + plx + plb + plp + rtl +rmReturn anop +* we push three space bytes - here we'll store the original second rtl +* address, and rtl out of our patch + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + + lda rmStackPtr + dec a + sta rmStackPtr + bne noSwitch2 + ldx curProcInd + lda oldOpenFiles + sta openFiles,x + lda oldOpenFiles+2 + sta openFiles+2,x + lda rmStackPtr +noSwitch2 anop + asl a + asl a + tax + lda rmStack+1,x + sta 10,s + lda rmStack,x + sta 9,s + pla + ply + plx + plb + plp + rtl + END + +* Resource Manager GetOpenFileRefNum patch +* +* call old GetOpenFileRefNum (result in 'ref') +* search current process' file table for existence of 'ref'. +* If the refNum is found, then return the file descriptor +* else, find the ref in the kernel's file table, and copy +* the entry to a new entry in the process' file descriptor +* table, and return the new FD. + +NewGOFRN START + using OldRMtable + using KernelStruct +kernFDPtr equ 1 +procFDPtr equ 5 +ref equ 9 + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s ; prolly not necessary, but fuck it + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* get the last return address on the stack (at 9,s) and save it in +* our return stack + + lda rmStackPtr + bne noSwitch + ldx curProcInd + lda openFiles,x + sta oldOpenFiles + lda openFiles+2,x + sta oldOpenFiles+2 + lda openFiles ; Kernel open file list + sta openFiles,x + lda openFiles+2 + sta openFiles+2,x ; is attacted to process + lda rmStackPtr +noSwitch anop + asl a + asl a + tax + lda 12,s + sta rmStack,x + lda 13,s + sta rmStack+1,x + inc rmStackPtr + +* Now, put our return address on the stack instead + + lda #(rmReturn-1)|-8 + sta 13,s + lda #rmReturn-1 + sta 12,s + +* Finally, shove the address of the old function to call onto the +* stack and RTL to it. + + jsr SetCurRes + + ldx #$1F*4 + lda rmFuncs+1,x + sta 10,s + lda rmFuncs,x + sta 9,s + pla + ply + plx + plb + plp + rtl +rmReturn anop +* we push three space bytes - here we'll store the original second rtl +* address, and rtl out of our patch + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + + lda rmStackPtr + dec a + sta rmStackPtr + bne noSwitch2 + ldx curProcInd + lda oldOpenFiles + sta openFiles,x + lda oldOpenFiles+2 + sta openFiles+2,x + lda rmStackPtr +noSwitch2 anop + asl a + asl a + tax + lda rmStack+1,x + sta 10,s + lda rmStack,x + sta 9,s +********** + lda 1,s + beq noerror + jmp doerror +noerror lda 15,s ; get the ref value returned by + tay ; the real GetOpenFileRefNum + phd + tsc + sec + sbc #10 + tcs + tcd + + sty ref + + ldx curProcInd ; push the process' fd table ptr + lda openFiles+2,x + sta procFDPtr+2 + pha + lda openFiles,x + sta procFDPtr + pha + ph2 ref + jsl SearchFDTable + + cmp #0 + bne gotrefnum + + lda [procFDPtr] ; increment the file count, we're + inc a ; opening a new one up! + sta [procFDPtr] + +* lda openFiles+2 ; kernel file table pointer +* pha +* lda openFiles +* pha +* ph2 ref +* jsl SearchFDTable + + mv4 openFiles,kernFDPtr + lda ref + dec a + asl a + asl a + asl a + asl a + clc + adc #FDTTable + tay + lda [kernFDPtr],y + cmp #0 + beq rmpanic + + phy ; save the index across this call + + pha ; push the mapped refNum + pea FDgsos + jsl IncRefnum ; inc the system-wide count + + pla ; from above phy + clc + adc kernFDPtr + sta kernFDPtr + lda #0 + adc kernFDPtr+2 + sta kernFDPtr+2 ; create pointer to kern spot + + pea 0 + tdc + clc + adc #ref + pha ; push address of 'ref' + jsl allocFD ; process' entry must be restored + sta procFDPtr + stx procFDPtr+2 + + ph4 #FDsize + ph4 kernFDPtr + ph4 procFDPtr + jsl memcpy + lda ref +gotrefnum tay + tsc + clc + adc #10 + tcs + pld + tya + sta 15,s +********** +doerror pla + ply + plx + plb + plp + rtl + +rmpanic ph4 #rmpanicstr + jsl PANIC +rmpanicstr dc c'RM: can''t find refNum in nullProc',i'0' + END + + +* OpenResourceFile patch. +* watches for use of memory-based resource maps, and if encountered, +* maps the refNum passed in the resourceMap structure + +NewORF START + using OldRMtable + using KernelStruct +resMapPtr equ 11 ; amt. of local space & parm offset +kernFDPtr equ 1 +procFDPtr equ 5 +ref equ 9 +resFileNum equ $10 + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s ; prolly not necessary, but fuck it + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* get the last return address on the stack (at 9,s) and save it in +* our return stack + + lda rmStackPtr + bne noSwitch + ldx curProcInd + lda openFiles,x + sta oldOpenFiles + lda openFiles+2,x + sta oldOpenFiles+2 + lda openFiles ; Kernel open file list + sta openFiles,x + lda openFiles+2 + sta openFiles+2,x ; + lda rmStackPtr +noSwitch anop + asl a + asl a + tax + lda 12,s + sta rmStack,x + lda 13,s + sta rmStack+1,x + inc rmStackPtr + +* Now, put our return address on the stack instead + + lda #(rmReturn-1)|-8 + sta 13,s + lda #rmReturn-1 + sta 12,s + +* Finally, shove the address of the old function to call onto the +* stack and RTL to it. + + jsr SetCurRes + + ldx #$0A*4 ; we know the tool number + lda rmFuncs+1,x + sta 10,s + lda rmFuncs,x + sta 9,s + + lda 15+4+3,s + ora 15+6+3,s + sta mbrmFlag + + pla + ply + plx + plb + plp + rtl +rmReturn anop +* we push three space bytes - here we'll store the original second rtl +* address, and rtl out of our patch + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +***** +* begin patch +***** +*9-11: second RTL +*12-14: first rtl + + cmp #0 + jne notopen ; didn't open the file! + lda mbrmFlag + jeq nomembase + phd + tsc + sec + sbc #14 + tcs + tcd + + pha ; push space for retval, dammit! + pha + lda 15+16+4,s ; return value (file ID) + pha + _GetMapHandle + pla + sta kernFDPtr + pla + sta kernFDPtr+2 + lda [kernFDPtr] + sta resMapPtr + ldy #2 + lda [kernFDPtr],y + sta resMapPtr+2 + + mv4 oldOpenFiles,procFDPtr + ldy #resFileNum + lda [resMapPtr],y + dec a + asl a + asl a + asl a + asl a + clc + adc #FDTTable + tay + tax + lda [procFDPtr],y + beq nofutzing ; it will fall thru to an error later + sta ref + + tay + txa ; make a pointer to the fd entry + clc + adc procFDPtr + sta procFDPtr + lda #0 + adc procFDPtr+2 + sta procFDPtr+2 + + lda openFiles+2 + pha + lda openFiles + pha + phy ; saved above + jsl SearchFDTable ; is it in the kernel table? + cmp #0 ; find it? + bne gotit ; already have the guy + + pei (ref) ; push the mapped refNum + pea 0 + jsl IncRefnum ; inc the system-wide count + + pea 0 ; allocate a new fd + tdc + clc + adc #ref + pha ; push address of 'ref' + jsl allocFD ; process' entry must be restored + sta kernFDPtr + stx kernFDPtr+2 + ph4 #FDsize + ph4 procFDPtr + ph4 kernFDPtr + jsl memcpy + lda ref +gotit ldy #resFileNum + sta [resMapPtr],y +nofutzing anop + tsc + clc + adc #14 + tcs + pld +nomembase anop +notopen anop + +***** +* end patch +***** + + lda rmStackPtr + dec a + sta rmStackPtr + bne noSwitch2 + ldx curProcInd + lda oldOpenFiles + sta openFiles,x + lda oldOpenFiles+2 + sta openFiles+2,x + lda rmStackPtr +noSwitch2 anop + asl a + asl a + tax + lda rmStack+1,x + sta 10,s + lda rmStack,x + sta 9,s + pla + ply + plx + plb + plp + rtl +mbrmFlag dc i2'0' + END + +NewSCRA START + using OldRMtable + using KernelStruct + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s ; prolly not necessary, but fuck it + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* get the last return address on the stack (at 9,s) and save it in +* our return stack + + lda rmStackPtr + bne noSwitch + ldx curProcInd + lda openFiles,x + sta oldOpenFiles + lda openFiles+2,x + sta oldOpenFiles+2 + lda openFiles ; Kernel open file list + sta openFiles,x + lda openFiles+2 + sta openFiles+2,x ; + lda rmStackPtr +noSwitch anop + asl a + asl a + tax + lda 12,s + sta rmStack,x + lda 13,s + sta rmStack+1,x + inc rmStackPtr + +* Get the resapp id, for use after the call + lda 18,s + sta >tempresapp + +* Now, put our return address on the stack instead + + lda #(rmReturn-1)|-8 + sta 13,s + lda #rmReturn-1 + sta 12,s + +* Finally, shove the address of the old function to call onto the +* stack and RTL to it. + +; jsr SetCurRes ; duh + + ldx #$13*4 ; we know the call number + lda rmFuncs+1,x + sta 10,s + lda rmFuncs,x + sta 9,s + pla + ply + plx + plb + plp + rtl +rmReturn anop +* we push three space bytes - here we'll store the original second rtl +* address, and rtl out of our patch + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* last bit of the patch + cmp #0 + bne waserr + lda >curProcInd + tax + lda >tempresapp + sta >CurResApp + sta >resapp,X + +waserr lda rmStackPtr + dec a + sta rmStackPtr + bne noSwitch2 + ldx curProcInd + lda oldOpenFiles + sta openFiles,x + lda oldOpenFiles+2 + sta openFiles+2,x + lda rmStackPtr +noSwitch2 anop + asl a + asl a + tax + lda rmStack+1,x + sta 10,s + lda rmStack,x + sta 9,s + pla + ply + plx + plb + plp + rtl +tempresapp dc i2'0' +CurResApp ENTRY + dc i2'$401E' + END + +NewRMSU START + using OldRMtable + using KernelStruct + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s ; prolly not necessary, but fuck it + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* get the last return address on the stack (at 9,s) and save it in +* our return stack + + lda rmStackPtr + bne noSwitch + ldx curProcInd + lda openFiles,x + sta oldOpenFiles + lda openFiles+2,x + sta oldOpenFiles+2 + lda openFiles ; Kernel open file list + sta openFiles,x + lda openFiles+2 + sta openFiles+2,x ; + lda rmStackPtr +noSwitch anop + asl a + asl a + tax + lda 12,s + sta rmStack,x + lda 13,s + sta rmStack+1,x + inc rmStackPtr + +* Get the resapp id, for use after the call + lda 18,s + sta >tempresapp + +* Now, put our return address on the stack instead + + lda #(rmReturn-1)|-8 + sta 13,s + lda #rmReturn-1 + sta 12,s + +* Finally, shove the address of the old function to call onto the +* stack and RTL to it. + + jsr SetCurRes + + ldx #$02*4 ; we know the call number + lda rmFuncs+1,x + sta 10,s + lda rmFuncs,x + sta 9,s + pla + ply + plx + plb + plp + rtl +rmReturn anop +* we push three space bytes - here we'll store the original second rtl +* address, and rtl out of our patch + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* last bit of the patch + cmp #0 + bne waserr + lda >curProcInd + tax + lda >tempresapp + sta >CurResApp + sta >resapp,X + + +waserr lda rmStackPtr + dec a + sta rmStackPtr + bne noSwitch2 + ldx curProcInd + lda oldOpenFiles + sta openFiles,x + lda oldOpenFiles+2 + sta openFiles+2,x + lda rmStackPtr +noSwitch2 anop + asl a + asl a + tax + lda rmStack+1,x + sta 10,s + lda rmStack,x + sta 9,s + pla + ply + plx + plb + plp + rtl +tempresapp dc i2'0' + END + +NewRMSD START + using OldRMtable + using KernelStruct + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s ; prolly not necessary, but fuck it + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* get the last return address on the stack (at 9,s) and save it in +* our return stack + + lda rmStackPtr + bne noSwitch + ldx curProcInd + lda openFiles,x + sta oldOpenFiles + lda openFiles+2,x + sta oldOpenFiles+2 + lda openFiles ; Kernel open file list + sta openFiles,x + lda openFiles+2 + sta openFiles+2,x ; + lda rmStackPtr +noSwitch anop + asl a + asl a + tax + lda 12,s + sta rmStack,x + lda 13,s + sta rmStack+1,x + inc rmStackPtr + +* Get the resapp id, for use after the call +* Now, put our return address on the stack instead + + lda #(rmReturn-1)|-8 + sta 13,s + lda #rmReturn-1 + sta 12,s + +* Finally, shove the address of the old function to call onto the +* stack and RTL to it. + + jsr SetCurRes + + ldx #$03*4 ; we know the call number + lda rmFuncs+1,x + sta 10,s + lda rmFuncs,x + sta 9,s + pla + ply + plx + plb + plp + rtl +rmReturn anop +* we push three space bytes - here we'll store the original second rtl +* address, and rtl out of our patch + + phb ; 11,s ; three bytes of storage + pha ; 9,s for calling the old RM routine + + php ; 8,s + phb ; 7,s + phk + plb + phx ; 5,s + phy ; 3,s + pha ; 1,s + +* last bit of the patch + lda >curProcInd + tax + lda #0 + sta >resapp,X + + +waserr lda rmStackPtr + dec a + sta rmStackPtr + bne noSwitch2 + ldx curProcInd + lda oldOpenFiles + sta openFiles,x + lda oldOpenFiles+2 + sta openFiles+2,x + lda rmStackPtr +noSwitch2 anop + asl a + asl a + tax + lda rmStack+1,x + sta 10,s + lda rmStack,x + sta 9,s + pla + ply + plx + plb + plp + rtl + END diff --git a/kern/gno/select.asm b/kern/gno/select.asm new file mode 100644 index 0000000..d8c69e0 --- /dev/null +++ b/kern/gno/select.asm @@ -0,0 +1,583 @@ +* $Id: select.asm,v 1.1 1998/02/02 08:19:46 taubert Exp $ +* +* select.asm +* +* modified socket stuff - Derek Taubert - 12/13/94 +* added GS/OS file support and proper return value - DT - 2/6/96 +* added timeout support - DT - 2/13/96 +* + + mcopy m/select.mac + case on + copy inc/tty.inc + copy inc/gsos.inc + copy inc/kern.inc + copy global.equates + +IncBusyFlag gequ $E10064 +DecBusyFlag gequ $E10068 + +DebugNames gequ 1 + +* +* +* + +TIselect START KERN2 +TIselect name + using pipeRecord + using KernelStruct + using SelTimStruct + +* locals +mask equ 1 1 used? +pPtr equ mask+4 5 +fdtptr equ pPtr+4 9 +fdPtr equ fdtptr+4 13 used? +slept equ fdPtr+4 17 +r_mask equ slept+2 19 +w_mask equ r_mask+4 23 +x_mask equ w_mask+4 27,28,29,30 +space equ x_mask+4-1 + +* intermediates +bsp equ x_mask+4 31 +dsp equ bsp+1 32 +rtl2 equ dsp+2 34 +rtl1 equ rtl2+3 37 + +* args +errnoptr equ rtl1+3 40 +timeout equ errnoptr+4 44 +exceptfds equ timeout+4 48 +writefds equ exceptfds+4 52 +readfds equ writefds+4 56 +width equ readfds+4 60 +retval equ width+2 62 + + phd + phb + + phk + plb + tsc + sec + sbc #space + tcd + tcs + + stz retval + + lda >procPtr + sta pPtr + lda >procPtr+2 + sta pPtr+2 + + ldy #openFiles-CKernData + lda [pPtr],y + sta fdtptr + ldy #(openFiles-CKernData+2) + lda [pPtr],y + sta fdtptr+2 + + lda readfds + ora readfds+2 + beq checkwr1 + pei (readfds+2) + pei (readfds) + pei (fdtptr+2) + pei (fdtptr) + jsl validate_mask + cmp #0 + bne err_mask + +checkwr1 lda writefds + ora writefds+2 + beq checkex1 + pei (writefds+2) + pei (writefds) + pei (fdtptr+2) + pei (fdtptr) + jsl validate_mask + cmp #0 + bne err_mask + +checkex1 lda exceptfds + ora exceptfds+2 + beq enter_loop + pei (exceptfds+2) + pei (exceptfds) + pei (fdtptr+2) + pei (fdtptr) + jsl validate_mask + cmp #0 + beq enter_loop +err_mask lda #EBADF + sta [errnoptr] + lda #-1 + sta retval + jmp goaway + +enter_loop anop + stz slept + jsr getSelTimIndex + lda #0 + sta >SelTimExpired,x + lda >curProcInd + tax + lda #0 + sta >p_waitvec,x ; just for kicks.. + sta >p_waitvec+2,x + +select_loop anop +* First, reset the local select masks we're using + lda #0 + sta r_mask + sta r_mask+2 + sta w_mask + sta w_mask+2 + sta x_mask + sta x_mask+2 + +* Set Process' "selecting" flag + ldy #flags-KernelStruct + lda [pPtr],y + ora #FL_SELECTING + sta [pPtr],y + +* For each FD, poll the device by calling its select routine +* If the descriptor can't do the operation, select must record that +* this process wants to do I/O. + lda readfds + ora readfds+2 + beq checkwr2 + pea SEL_READ + pei (readfds+2) + pei (readfds) + pei (fdtptr+2) + pei (fdtptr) + pea 0 + tdc + clc + adc #retval + pha + jsl poll_mask + sta r_mask + stx r_mask+2 + +checkwr2 lda writefds + ora writefds+2 + beq checkex2 + pea SEL_WRITE + pei (writefds+2) + pei (writefds) + pei (fdtptr+2) + pei (fdtptr) + pea 0 + tdc + clc + adc #retval + pha + jsl poll_mask + sta w_mask + stx w_mask+2 + +checkex2 lda exceptfds + ora exceptfds+2 + beq endpoll + pea SEL_EXCEPT + pei (exceptfds+2) + pei (exceptfds) + pei (fdtptr+2) + pei (fdtptr) + pea 0 + tdc + clc + adc #retval + pha + jsl poll_mask + sta x_mask + stx x_mask+2 + +endpoll php + sei + lda >curProcInd + tax + lda >flags,x + bit #FL_SELECTING + bne noloop +* Somebody cleared FL_SELECTING, we better check again + plp + jmp select_loop + +noloop and #FL_SELECTING.EOR.$FFFF + sta >flags,x + +; retval slept timeout SelTimExpired +; 0 0 0 X sleep +; 0 0 1 X set alarm, sleep +; 0 1 0 X return -1, EINTR +; 0 1 1 0 return -1, EINTR +; 0 1 1 1 return 0 +; 1 X X X return retval + lda retval + bne done1 ; we have a fd, kaptain! + lda slept + beq tosleep +; check to see how k_sleep woke up + lda timeout + ora timeout+2 + beq interup + jsr getSelTimIndex + lda >SelTimExpired,x + beq interup + lda #0 + sta >SelTimExpired,x +done1 bra done ; we timed out! +interup plp + lda #EINTR + sta [errnoptr] + lda #-1 + sta retval + jmp goaway + +timeoutTMP dc i4'0' +; set up alarm here +tosleep lda timeout + ora timeout+2 + beq noalrm +setalrm anop + MUL4 [timeout],#10,timeoutTMP +; FIXME: add microseconds to timeoutTMP too + jsr getSelTimIndex + lda timeoutTMP + bne nofudge + inc A ; so SelTimTimeout never starts at zero +nofudge sta >SelTimTimeout,x + lda timeoutTMP+2 + sta >SelTimTimeout+2,x + lda >curProcInd + sta >SelTimPID,x + +noalrm lda >truepid + pha + pea 0 + ph4 #selwait + jsl k_sleep + + inc slept + lda timeout + ora timeout+2 + beq noalrm2 +; remove alarm here + jsr getSelTimIndex + lda #0 + sta >SelTimTimeout,x + sta >SelTimTimeout+2,x + +noalrm2 plp + jmp select_loop + +done plp + ldy #2 + lda r_mask + sta [readfds] + lda r_mask+2 + sta [readfds],y + lda w_mask + sta [writefds] + lda w_mask+2 + sta [writefds],y + lda x_mask + sta [exceptfds] + lda x_mask+2 + sta [exceptfds],y + +goaway anop + tsc + clc + adc #space + tcs + plb + pld + ldx #0 + ldy #22 + jmp >tool_exit + + END + + +poll_mask START KERN2 +poll_mask name + using KernelStruct +words_left equ 0 +cur_fd equ 2 +bitcount equ 4 +wordind equ 6 +fdPtr equ 8 +outmask equ 12 + + subroutine (2:which,4:mask,4:fdtptr,4:fdsrdyptr),16 + + stz outmask + stz outmask+2 + + ldy #FDTfdTableSize + lda [fdtptr],y ; table size, divide by 16 + lsr a + lsr a + lsr a + lsr a + sta words_left + stz cur_fd + stz wordind +val_loop1 lda #16 + sta bitcount + ldy wordind + lda [mask],y +val_loop2 ror a ; rotate into carry flag + bcc dontcheck1 ; do not check this fd + pha + + pei (cur_fd) + jsl getFDptr + sta fdPtr + stx fdPtr+2 + +; dispatch to the driver's select routine, which will tell us whether there's +; data and do other sundry stuff + + lda [fdPtr] ; get device number + dec a ; dec to get device index + pha + pei (which) ; tell the driver which I/O operation +; had to add this parm - DT + lda >curProcInd ; current pid + pha +; + ldy #FDrefType + lda [fdPtr],y + cmp #FDsocket + beq selsok1 + cmp #FDgsos + beq selsok2 +; otherwise, it is #FDtty +; need to load A with dev type here, not ref type - DT + lda [fdPtr] ; get device number + dec a ; dec to get device index + ldy #t_select + jsl LineDiscDispatch + bra donesel1 + +; we can always read and write #FDgsos, never except +selsok2 anop + pla ; current pid + pla ; which operation + plx ; device number + cmp #SEL_EXCEPT + beq gsos_nox + sec + bra donesel2 +gsos_nox clc + bra donesel2 + +selsok1 anop + jsl SOCKselect + +donesel1 cmp #1 ; set carry properly +donesel2 bcc notready + lda [fdsrdyptr] + adc #0 + sta [fdsrdyptr] + sec +notready ldx wordind + ror p_waitvec,x + cmp #selwait + bne ck_coll + lda >p_waitvec+2,x + cmp #^selwait + bne ck_coll + lda >ProcessState,x + cmp #PS_SLEEP + bne ck_coll + + ph4 #selwakeupdefer + lda pid + lsr a + lsr a + lsr a + lsr a + lsr a + lsr a + lsr a + pha + pea 1 + jsl defer + bra goaway + +ck_coll lda >flags,x + and #FL_SELECTING.EOR.$FFFF + sta >flags,x + +goaway return + END + + +SelTimStruct DATA +SelTimTimeout dc i4'0' ; timeout in tenths of seconds +SelTimPID dc i2'0' ; pid argument to call selwakeup with +SelTimExpired dc i2'0' ; set by the HB routine when she blows + ds 8*(NPROC-1) ; space for 31 more entries + END + + +getSelTimIndex START KERN2 +getSelTimIndex name + using KernelStruct + lda >truepid + asl a + asl a + asl a + tax + rts + END + + +;KERNgetdtablesize START KERN2 +; using KernelStruct +; +;pPtr equ 0 +;fdPtr equ 4 +;ret equ 8 +; +; subroutine (4:errptr),10 +; +; mv4 >procPtr,pPtr +; ldy #openFiles-CKernData +; lda [pPtr],y +; sta fdPtr +; ldy #(openFiles-CKernData-2) +; lda [pPtr],y +; sta fdPtr+2 +; +; lda #0 +; sta [errptr] +; +; ldy #FDTfdTableSize +; lda [fdPtr],y +; sta ret +; return 2:ret +; END +; +;STACK START ~_STACK +; KIND $12 +; ds 1024 +; END diff --git a/kern/gno/sem.c b/kern/gno/sem.c new file mode 100644 index 0000000..f19c102 --- /dev/null +++ b/kern/gno/sem.c @@ -0,0 +1,228 @@ +/* $Id: sem.c,v 1.1 1998/02/02 08:18:51 taubert Exp $ */ + +/* _sem.c - semaphore functions + +SYSCALL swait() - make current process wait on a semaphore +SYSCALL ssignal() - signal a semaphore, releasing one waiting process +SYSCALL screate() - create and initialize a semaphore, returning its id +SYSCALL sdelete() - delete a semaphore by releasing its table entry + +_seminit() - initialize semaphore system + +newsem() - allocate an unused semaphore and return its index +*/ + +#pragma optimize 79 +segment "KERN3 "; + +#include "conf.h" +#if NSEM +#include "kernel.h" +#include "proc.h" +#include "sys.h" +#include "q.h" +#include "sem.h" +#include "gno.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include + +static int nextsem = NSEM-1; +extern kernelStructPtr kp; +extern void sleepbusy(void); + +static int newsem() +{ +int sem; +int i; + + for (i=0;isstate = SFREE; + /* sptr->sqtail = 1 + ( sptr->sqhead = _newqueue() ); */ + /* don't allocate queues until we need them, but init them + here */ + } +} + +/* make current process wait on a semaphore */ +SYSCALL commonSwait(int *ERRNO, int sem, int blockas, int waitdone) +{ +struct sentry *sptr; +struct pentry *pptr; + + if (blockas != procBLOCKED) + PANIC("commonSwait() only supports procBLOCKED now"); + + disableps(); + if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { + enableps(); + *ERRNO = EINVAL; + return SYSERR; + } + if (--(sptr->semcnt) < 0) { + PROC->processState = blockas; + if (blockas == procBLOCKED) PROC->waitdone = waitdone; + PROC->psem = sem; + _enqueue(Kgetpid(),sptr->squeue); + + sleepbusy(); + + if (blockas == procBLOCKED && PROC->waitdone == waitdone) goto gotit; + if (sptr->sstate != SFREE) { + if (_dequeueitem(Kgetpid(),sptr->squeue) != SYSERR) + PANIC("pentry still on queue in commonSwait()"); + } /* else sem was deallocated */ + + enableps(); + *ERRNO = EINTR; + return SYSERR; + } +gotit: + PROC->psem = 0; + enableps(); + return OK; +} + +/* Cleanup semaphore due to signal causing EINTR */ +void semINTR(int sem, int mpid) +{ +struct sentry *sptr; + + if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) + return; + _dequeueitem(mpid, sptr->squeue); + sptr->semcnt++; + PROC->psem = -1; +} + +/* create and initialize a semaphore, returning its id */ +/* initial count (>=0) */ +SYSCALL Kscreate(int *ERRNO, int count) +{ +int sem; + + disableps(); + if (count < 0 || (sem=newsem()) == SYSERR) { + enableps(); + *ERRNO = ENOMEM; + return SYSERR; + } + _semaph[sem].semcnt = count; + enableps(); + return sem; +} + +SYSCALL Kscount(int *ERRNO, int sem) +{ +struct sentry *sptr; +int c; + + disableps(); + if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { + enableps(); + *ERRNO = EINVAL; + return SYSERR; + } + c = sptr->semcnt; + enableps(); + return c; /* BAH! This could be == SYSERR */ +} + +#pragma databank 1 +#pragma toolparms 1 + +SYSCALL KERNswait(int *ERRNO,int sem) +{ + return commonSwait(ERRNO,sem,procBLOCKED,BLOCKED_SWAIT); +} + +SYSCALL KERNscreate(int *ERRNO, int count) +{ + return Kscreate(ERRNO, count); +} + +SYSCALL KERNscount(int *ERRNO, int sem) +{ + return Kscount(ERRNO, sem); +} + +/* signal a semaphore, releasing one waiting process */ +SYSCALL KERNssignal(int *ERRNO, int sem) +{ +struct sentry *sptr; +int mpid; + + disableps(); + if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { + enableps(); + *ERRNO = EINVAL; + return SYSERR; + } + if ((sptr->semcnt++) < 0) { + if ((mpid = _getfirst(sptr->squeue)) == SYSERR) + PANIC("ssignal: _getfirst FAILED!"); + + /* _ready(kp->procTable[mpid].flpid,RESCHNO); */ + if (kp->procTable[mpid].processState != procUNUSED) + kp->procTable[mpid].processState = procREADY; + + } + enableps(); + return OK; +} + +/* delete a semaphore by releasing its table entry */ +SYSCALL KERNsdelete(int *ERRNO, int sem) +{ +int mpid; +struct sentry *sptr; /* address of sem to free */ + + disableps(); + if (isbadsem(sem) || (sptr = &_semaph[sem])->sstate == SFREE) { + enableps(); + *ERRNO = EINVAL; + return SYSERR; + } + sptr->sstate = SFREE; + if (nonempty(sptr->squeue)) { + while ((mpid = _getfirst(sptr->squeue)) != SYSERR) { + /* _ready(kp->procTable[mpid].flpid,RESCHNO); */ + if (kp->procTable[mpid].processState != procUNUSED) + kp->procTable[mpid].processState = procREADY; + } + Qdispose(sptr->squeue); + enableps(); + _resched(); + return OK; + } + Qdispose(sptr->squeue); + enableps(); + return OK; +} + +#pragma databank 0 +#pragma toolparms 0 +#endif + diff --git a/kern/gno/sem.h b/kern/gno/sem.h new file mode 100644 index 0000000..d0e388c --- /dev/null +++ b/kern/gno/sem.h @@ -0,0 +1,20 @@ +/* $Id: sem.h,v 1.1 1998/02/02 08:18:54 taubert Exp $ */ + +/* sem.h - semaphore definitions */ + +#if NSEM +#define SFREE 1 /* free semaphore */ +#define SUSED 2 /* semaphore in use */ + +struct sentry { /* semaphore table entry */ + char sstate; /* SFREE or SUSED */ + short semcnt; /* semaphore count, (i.e. value) */ + unsigned squeue; /* process queue id */ +}; +extern struct sentry *_semaph; +/*extern struct sentry _semaph[];*/ + +#define isbadsem(s) (s<0 || s>=NSEM) + +void semINTR(int sem, int mpid); +#endif diff --git a/kern/gno/shellcall.asm b/kern/gno/shellcall.asm new file mode 100644 index 0000000..1051ad8 --- /dev/null +++ b/kern/gno/shellcall.asm @@ -0,0 +1,1897 @@ +* $Id: shellcall.asm,v 1.1 1998/02/02 08:19:48 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* SHELLCALL.ASM +* By Tim Meekins +* +* This file contains routines for patching GS/OS to intercept Shell +* calls and do special things with certain GS/OS calls. +* +* Phase 1 Modifications to Orca 2.0 compat: (11/18/91) +* removal of old c-style calls, and fixing all routines to work +* directly from pBlock rather than a copy. +* Phase 2: (11/19-20/91) +* Addition of most pCount checking, and addition of routines +* that don't take strings as parameters +* Phase 3: (11/20/91) +* String manipulation changes/additions +* Phase 4: (11/21/91) +* The variable pCount calls (FastFile, etc) and calls that differ +* greatly from Orca 1.x. +************************************************************************** + + case on + copy global.equates + mcopy m/shellcall.mac + +shellLoc gequ 12 + +; +; Table of commands +; +ShellCallTbl DATA + dc a2'_Get_L_Info' ;$101 - GetLInfo + dc a2'_Set_L_Info' ;$102 - SetLInfo + dc a2'_GetLang' ;$103 + dc a2'_SetLang' ;$104 + dc a2'_Error' ;* $105 - Error + dc a2'_Set' ;* $106 - Set + dc a2'_Version' ;* $107 - Version + dc a2'_Read_Indexed' ;* $108 - ReadIndexed + dc a2'_Init_Wildcard' ;$109 - InitWildcard + dc a2'_Next_Wildcard' ;$10A - NextWildcard + dc a2'_Read_Variable' ;* $10B - ReadVariable + dc a2'NotImp' ;$10C + dc a2'_Execute' ;* $10D - Execute + dc a2'_FastFile' ;$10E - FastFile + dc a2'_Direction' ;* $10F - Direction + dc a2'_Redirect' ;* $110 - Redirect + dc a2'NotImp' ;$111 + dc a2'NotImp' ;$112 + dc a2'_Stop' ;* $113 - Stop + dc a2'_ExpandDevices' ;* $114 - ExpandDevices + dc a2'_UnsetVariable' ;* $115 - UnsetVariable + dc a2'_Export' ;* $116 - Export + dc a2'_PopVariables' ;* $117 - PopVariables + dc a2'_PushVariables' ;* $118 - PushVariables + dc a2'_SetStopFlag' ;* $119 - SetStopFlag + dc a2'_ConsoleOut' ;* $11A - ConsoleOut + dc a2'NotImp' ;$11B + dc a2'NotImp' ;$11C + dc a2'NotImp' ;$11D + dc a2'_KeyPress' ;$11E + dc a2'_ReadKey' ;$11F + END + +;========================================================================= +; +; ($101) GetLInfo +; +;========================================================================= + +_Get_L_Info START +_Get_L_Info name + + ph2 cmdNum + ph4 pBlock + jsl cGetLInfo + jmp GSOSReturn + END + +;========================================================================= +; +; ($102) SetLInfo +; +;========================================================================= + +_Set_L_Info START +_Set_L_Info name + + ph2 cmdNum + ph4 pBlock + jsl cSetLInfo + jmp GSOSReturn + END + +;========================================================================= +; +; ($103) GetLang +; +;========================================================================= + +_GetLang START +_GetLang name +PBLang equ 0 + + lda curLangNum + ldy #PBLang + sta [pBlock],y + lda #0 + jmp GSOSReturn + +;========================================================================= +; +; ($104) SetLang +; +;========================================================================= + +_SetLang ENTRY + + ldy #PBLang + lda [pBlock],y + sta curLangNum + lda #0 + jmp GSOSReturn +curLangNum dc i2'1' + END + + +;========================================================================= +; +; ($105) Error +; +;========================================================================= + +_Error START +_Error name + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #1 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 lda [pBlock] + jsl printError + + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($106) Set +; +;========================================================================= + +_Set START +_Set name +PBexport equ 8 + +varC equ shellLoc+0 +valC equ shellLoc+4 + + lda cmdNum + and #$40 ;If bit $40 then c strings + beq orca_1 + + lda pCount + cmp #3 + beq orca_2 + lda #4 + jmp GSOSReturn + +orca_2 anop + ldy #2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl gs2cstr + phx + pha + sta varC + stx varC+2 + + ldy #6 ;$ + lda [pBlock],y ;$ + pha ;$ + ldy #4 ;$ + lda [pBlock],y ;$ + pha ;$ + + jsl gs2cstr + phx + pha + sta valC + stx valC+2 + jsl setvar + + pei (varC+2) ; set the export flag according + pei (varC) + ldy #PBexport ; to the new parm in Orca 2.0 + lda [pBlock],y + pha + jsl exportvar + bra orca_com + +orca_1 ldy #2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl p2cstr + phx + pha + sta varC + stx varC+2 + + ldy #6 ;$ + lda [pBlock],y ;$ + pha ;$ + ldy #4 ;$ + lda [pBlock],y ;$ + pha ;$ + + jsl p2cstr + phx + pha + sta valC + stx valC+2 + + jsl setvar + +orca_com pei (varC+2) + pei (varC) + jsl ~NDISPOSE + pei (valC+2) + pei (valC) + jsl ~NDISPOSE + + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($107) Version +; +;========================================================================= + +_Version START +_Version name + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #1 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 ldy #2 + lda #$2020 + sta [pBlock],y + lda #$3032 ;version (3031 = 1.0) (3032 = 2.0) + sta [pBlock] + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($108) Read_Indexed +; +;========================================================================= + +_Read_Indexed START +_Read_Indexed name + +var_name equ 0 +value equ 4 +index equ 8 +PBexport equ $A + +var equ shellLoc+0 +vn_tmp equ shellLoc+4 + + ldy #index ;$ + lda [pBlock],y ;$ + pha ;$ + jsl indexvar + stx var+2 + sta var + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #4 + beq orca_2 + lda #4 + jmp GSOSReturn +orca_2 anop + ldy #2 + lda var + ora var+2 + bne orca21 + jmp nomore +orca21 anop + ldy #12 ; copy the export flag + lda [var],y ; to the parameter block + ldy #PBexport + sta [pBlock],y + + ldy #4+2 + lda [var],y + pha + dey2 + lda [var],y + pha + ldy #var_name+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl copyc2res + ldy #8+2 + lda [var],y + pha + dey2 + lda [var],y + pha + ldy #value+2 ;$ + lda [pBlock],y ;$ + pha ;$ + ldy #value ;$ + lda [pBlock],y ;$ + pha ;$ + jsl copyc2res + lda #0 + jmp GSOSReturn + +orca_1 anop + ldy #0 + lda var + ora var+2 + beq nomore + + ldy #4+2 + lda [var],y + pha + dey2 + lda [var],y + pha + ldy #var_name+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl c2pstr + ldy #8+2 + lda [var],y + pha + dey2 + lda [var],y + pha + ldy #value+2 ;$ + lda [pBlock],y ;$ + pha ;$ + ldy #value ;$ + lda [pBlock],y ;$ + pha ;$ + jsl c2pstr + lda #0 + jmp GSOSReturn + +nomore phy + ldy #var_name+2 ;$ + lda [pBlock],y ;$ + sta vn_tmp+2 ;$ + lda [pBlock] ;$ + sta vn_tmp ;$ + ldy #value+2 + lda [pBlock],y + sta var+2 + ldy #value + lda [pBlock],y + sta var + ply + lda #0 + sta [vn_tmp],y + sta [var],y + jmp GSOSReturn + + END + +;========================================================================= +; +; ($109) Init_Wildcard +; +;========================================================================= + +_Init_Wildcard START +_Init_Wildcard name + using globals + using KernelStruct + +wildcard equ 0 +iw_flags equ 4 ;I'm ignoring the flags (no prompting) + +tbl equ shellLoc +ptr equ shellLoc+4 +w_file equ shellLoc+8 +w_dirpath equ shellLoc+12 +w_pfx equ shellLoc+16 + +; DebugStr #debug + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #2 + beq orca_2 + lda #4 + jmp GSOSReturn +orca_2 anop + ldy #wildcard+2 + lda [pBlock],y + sta w_file+2 + lda [pBlock] + sta w_file + lda [w_file] + inc a + inc a ; add two to get length of ds + pea 0 + pha ; make a copy of the gs string + jsl ~NEW + pei (w_file+2) + pei (w_file) + stx w_file+2 + sta w_file + phx + pha + jsl copygsstr + bra common +orca_1 anop + ldy #wildcard+2 + lda [pBlock],y + sta w_file+2 + pha ; push addr of p string for + lda [pBlock] + sta w_file + pha ; use later (by copy) + pea 0 + lda [w_file] ; get length + and #$ff + inc a + inc a ; add two to get length of gs string + pha + jsl ~NEW + stx w_file+2 + sta w_file + phx + pha + jsl copyp2gs ; convert to a GS string + +common anop + stz WC_PathBuf + stz WC_Patt + lda [w_file] +; and #$FF + jeq done +; +; Find last separator and separate the file pattern from the path +; + tay + iny +strippat lda [w_file],y + and #$FF + cmp #':' + beq gotpat + cmp #'/' + beq gotpat + dey + cpy #1 + bne strippat +; +; No path, so grab the current prefix +; +; Copy the pointer to prefix 0 straight out of the process structure + + phy + ldx curProcInd + lda prefixh,x + sta w_pfx + lda prefixh+2,x + sta w_pfx+2 + ldy #4 + lda [w_pfx],y + sta WC_PathPtr + sta w_dirpath + ldy #6 + lda [w_pfx],y + sta WC_PathPtr+2 + sta w_dirpath+2 + ply + bra gotpat2 +; +; Copy the path and pattern +; +gotpat ld4 WC_PathBuf,(WC_PathPtr,w_dirpath) +gotpat2 sty tmp + ldx #0 + iny + lda [w_file] + beq copiedpat + inc a ; +1, because y is postindexed + sta chk+1 + short m +copypat anop + lda [w_file],y + cmp #'=' + bne putpat + lda #'*' +putpat sta WC_Patt,x + inx + iny +chk cpy #0 + bcc copypat + beq copypat +copiedpat lda #0 + sta WC_Patt,x + ldx tmp + dex ; argh! this is nasty! + beq copiedpath + ldy #2 +copypath lda [w_file],y + sta WC_PathBuf,y + iny + dex + bne copypath +copiedpath dey + dey + sty WC_PathBuf + long ai + +; +; Expand the device +; +; lda tmp ;skip this +; beq fixGSOS +; ExpandDevices ExpParm +; jcs err + +;fixGSOS lda WC_PathBuf +; xba +; sta WC_PathBuf + + Open WC_OpenParms + jcs err + mv2 WC_OpenRef,(GDERef,CloseRef) + stz GDEbase + stz GDEdisp + ld2 6,GDEParm + GetDirEntry GDEParm + jcs err + pea 0 + lda GDEentry + inc a + asl2 a + pha + jsl ~NEW + sta tbl + stx tbl+2 + + stz tbloff ; initialize offset to zero + ldx GDEentry + bne itsAlright + jmp nofiles ; there are no files in this directory! + +itsAlright ldy #0 + tya +clrtbl sta [tbl],y + iny2 + sta [tbl],y + iny2 + dex + bne clrtbl + + ld2 5,GDEParm + ld2 1,(GDEbase,GDEdisp) +searchloop GetDirEntry GDEParm + jcs GDEerr + ldy buf + lda #0 + sta buf+2,y +; WriteCString #buf+2 +; WriteChar #13 +; WriteChar #10 +; WriteCString #WC_Patt +; WriteChar #13 +; WriteChar #10 + ph4 #WC_Patt + ph4 #buf+2 + ph2 #0 ; case insensitive + jsl RegExp + cmp #0 + beq searchloop +; WriteChar #10 + +* allocate space for the file/pathname. If bit 0 of flags is set, only +* use the filename, otherwise include the whole pathname. + + ldy #iw_flags + lda [pBlock],y + and #1 + bne fnameonly + pea 0 + lda buf + inc a + inc a + clc + adc [w_dirpath] ; pointer to directory entry + pha + jsl ~NEW + sta ptr + stx ptr+2 + ph4 WC_PathPtr + ph4 ptr + jsl copygsstr + ph4 #buf + ph4 ptr + jsl gsstrcat + bra commonptr + +fnameonly pea 0 + lda buf + inc a + inc a + pha + + jsl ~NEW + sta ptr + stx ptr+2 + ph4 #buf + ph4 ptr + jsl copygsstr + +commonptr ldy tbloff + lda ptr + sta [tbl],y + iny2 + lda ptr+2 + sta [tbl],y + iny2 + sty tbloff + + jmp searchloop + +GDEerr cmp #$61 ;End of directory? + bne err +nofiles ldy tbloff + lda #0 + sta [tbl],y + iny2 + sta [tbl],y + Close CloseParm +; +; do we need to delete the old table +; + lda truepid + asl2 a + tax + lda WCtbl,x + ora WCtbl+2,x + beq settbl +; +; delete old table +; + lda WCtbl,x + sta ptr + lda WCtbl+2,x + sta ptr+2 + ldy #0 +clrit lda [ptr],y + tax + iny2 + lda [ptr],y + iny2 + cmp #0 + bne disp + cpx #0 + beq nodisp +disp phy + pha + phx + jsl ~NDISPOSE + ply + bra clrit +nodisp pei (ptr+2) + pei (ptr) + jsl ~NDISPOSE + +settbl lda truepid + asl a + tax + asl a + tay + lda #0 + sta WCidx,x + lda tbl + sta WCtbl,y + lda tbl+2 + sta WCtbl+2,y + +done lda #0 +err pha + pei (w_file+2) + pei (w_file) + jsl ~NDISPOSE + pla + jmp GSOSReturn + +tmp ds 2 + +tbloff ds 2 + +CloseParm dc i'1' +CloseRef ds 2 + +GDEParm dc i'6' +GDERef ds 2 + ds 2 +GDEbase dc i'1' +GDEdisp dc i'1' + dc a4'GDBuf' +GDEentry ds 2 + +GDBuf dc i'67' +buf ds 65 + +WC_PathBuf ds 129 +WC_Patt ds 40 + + +WC_OpenParms dc i'2' +WC_OpenRef ds 2 +WC_PathPtr ds 4 + +;debug str 'init_wilcard' + + END + +globals DATA + +WCidx dc 32i2'0' +WCtbl dc 32i4'0' + + END + +;========================================================================= +; +; ($10A) Next_Wildcard +; +;========================================================================= + +_Next_Wildcard START +_Next_Wildcard name + using globals + using KernelStruct + +PBnextfile equ 0 + +tbl equ shellLoc +ptr equ shellLoc+4 +nextfile equ shellLoc+8 + + ldy #PBnextfile+2 ;$ + lda [pBlock],y ;$ + sta nextfile+2 ;$ + lda [pBlock] ;$ + sta nextfile ;$ + lda truepid + asl a + tay + asl a + tax + lda WCtbl,x + sta tbl + lda WCtbl+2,x + sta tbl+2 + ora tbl + bne alloced + jmp erruer +alloced tyx + lda WCidx,x + tay + lda [tbl],y + iny2 + ora [tbl],y + bne stillmore + jmp erruer +stillmore anop + iny2 + tya + sta WCidx,x + dey2 + dey2 + lda [tbl],y + sta ptr + iny2 + lda [tbl],y + sta ptr+2 + +* insert nextfile/nextfileGS check here + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #13 + bcs badpcount + cmp #0 + bne orca_2 +badpcount lda #4 + jmp GSOSReturn +orca_2 anop + ph4 ptr + ph4 nextfile + jsl copygs2res + lda ptr + ldy #PBnextfile + sta [pBlock],y + lda ptr+2 + ldy #PBnextfile+2 + sta [pBlock],y + lda pCount + cmp #1 + bne doGFI + lda #0 + bra doneNW +doGFI lda pBlock + sec + sbc #2 + tax + lda pBlock+2 + sbc #0 + pha + phx + pea $2006 ; GetFileInfoGS + jsl $E100B0 ; GS/OS stack entry point +doneNW pha + lda nextfile + ldy #PBnextfile + sta [pBlock],y + lda nextfile+2 + ldy #PBnextfile+2 + sta [pBlock],y + pla + jmp GSOSReturn + +* Copy the GSString to a PString in the form required by Next_Wildcard +* (the old P16 version), converting :'s to /'s along the way + +orca_1 lda [ptr] ; copy a GS string + sta [nextfile] ; to the P-string output buffer + tay + iny + short a +copy lda [ptr],y + dey + cmp #':' + bne nocolon + lda #'/' +nocolon sta [nextfile],y + cpy #1 + bne copy + long a + lda #0 + jmp GSOSReturn + +erruer anop + lda cmdNum + and #$40 + beq orca_1a + ldy #2 + lda #0 + sta [nextfile],y + jmp GSOSReturn +orca_1a lda #0 + short m + sta [nextfile] + long m + jmp GSOSReturn + + END + +;========================================================================= +; +; ($10B) Read_Variable +; +;========================================================================= + +_Read_Variable START +_Read_Variable name +PBvar_name equ 0 +PBvalue equ 4 +PBexport equ 8 + +var_name equ shellLoc+0 +value equ shellLoc+4 +var equ shellLoc+8 + + lda cmdNum + and #$40 ;If bit $40 then c strings + beq orca_1 + lda pCount + cmp #3 + beq orca_2 + lda #4 + jmp GSOSReturn + +orca_2 anop + ldy #PBvar_name+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl gs2cstr + phx + pha + phx + pha + jsl readvarrec + sta var + stx var+2 + jsl ~NDISPOSE ; get rid of the temp C string + + ldy #PBvalue+2 ;$ + lda [pBlock],y ;$ + sta value+2 ;$ + ldy #PBvalue ;$ + lda [pBlock],y ;$ + sta value ;$ + + lda var + ora var+2 + beq novar2 + + ldy #8 + lda [var],y + sta var_name + ldy #10 + lda [var],y + sta var_name+2 + + pei (var_name+2) + pei (var_name) + ph4 value + jsl copyc2res + ldy #12 + lda [var],y + ldy #PBexport + sta [pBlock],y + lda #0 + jmp GSOSReturn +novar2 anop + ldy #2 + lda #0 + sta [value],y + jmp GSOSReturn + +orca_1 anop +; pei (var_name+2) +; pei (var_name) + ldy #PBvalue+2 ;$ + lda [pBlock],y ;$ + sta value+2 ;$ + ldy #PBvalue ;$ + lda [pBlock],y ;$ + sta value ;$ + + ldy #PBvar_name+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl p2cstr + phx + pha + phx + pha + jsl readvar + sta var_name + stx var_name+2 + jsl ~NDISPOSE + lda var_name + ora var_name+2 + beq novar + + pei (var_name+2) + pei (var_name) + pei (value+2) + pei (value) + jsl c2pstr + + lda #0 + jmp GSOSReturn + +novar anop + lda #0 + sta [value] + jmp GSOSReturn + + END + +;========================================================================= +; +; ($10D) Execute +; +;========================================================================= + +_Execute START +_Execute name + using KernelStruct + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #2 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 jsl decBusy +; jsr decMutex + + ldx curProcInd + lda executeHook,x + ora executeHook+2,x + bne validHook + lda #26 + jsl incBusy +; jsr incMutex + jmp GSOSReturn +validHook anop + lda [pBlock] + bne nonewvar + PushVariables 0 +nonewvar ldy #4 + lda [pBlock],y + pha + dey2 + lda [pBlock],y + pha + push3 #returnadr-1 + ldx curProcInd + lda executeHook+2,x + short m + pha + long m + lda executeHook,x + dec a + pha + rtl ; jump to the routine +returnadr anop + pha + lda [pBlock] + bne nokillvar + PopVariables 0 +nokillvar anop + jsl incBusy + pla + jmp GSOSReturn + + END + +;========================================================================= +; +; ($10E) FastFile +; +;========================================================================= +; fastfile.c does all the work + +_FastFile START +_FastFile name + + ph2 pCount + lda cmdNum + and #$40 + pha ; osFlag (0 = P16, !0 = GSOS) + ph4 pBlock ; pointer to pBlock + jsl fastEntry ; har! + jmp GSOSReturn + END + +;========================================================================= +; +; ($10F) Direction +; +;========================================================================= + +_Direction START +_Direction name + using KernelStruct + using TextToolsInfo + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #2 + beq orca_1 + lda #4 + jmp GSOSReturn + +* redirection mapping +* 0,1 = none 0 +* unless xxSlot != kernelStruct.ttyID, which is 1 (.printer) +* 2 = none 0 (no Orca-based redirection) +* 3 = disk 2 +* 4 = pipe 2 +* any others are 1 (generalized communication) + +orca_1 lda [pBlock] + cmp #3 + bcc noerr + lda #$53 + jmp GSOSReturn ; Parameter out of range +noerr anop + lda truepid + asl a + asl a + asl a + asl a + asl a + asl a + pha + lda [pBlock] + asl a + clc + adc 1,s + tax + lda InDeviceType,x + cmp #2 + bcc Rconsole + beq Rram + cmp #3 + beq Rdisk + cmp #4 + beq Rdisk +Rcomm ldy #2 + lda #1 + sta [pBlock],y + pla + lda #0 + jmp GSOSReturn +Rram ldy #2 + lda #0 + sta [pBlock],y + pla + lda #0 + jmp GSOSReturn +Rdisk ldy #2 + lda #2 + sta [pBlock],y + pla + lda #0 + jmp GSOSReturn +Rconsole lda [pBlock] + asl a + asl a + clc + adc 1,s + tax + lda InSlot,x + ldx curProcInd + cmp ttyID,x + beq Rram ; no redirection + bra Rcomm + END + +;========================================================================= +; +; ($110) Redirect +; +;========================================================================= + +_Redirect START +_Redirect name + + using KernelStruct + using TextToolsInfo +PBdevice equ 0 +PBappend equ 2 +PBfile equ 4 + +file equ shellLoc+0 + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #3 + beq orca_2 + lda #4 + jmp GSOSReturn +orca_2 ldy #PBfile+2 + lda [pBlock],y + sta CRpathname+2 + ldy #PBfile + lda [pBlock],y + sta CRpathname + mv4 CRpathname,(OPENpathname,destPathname) + bra redirectCom + +orca_1 ldy #PBfile+2 ;$ + lda [pBlock],y ;$ + sta file+2 ;$ + ldy #PBfile ;$ + lda [pBlock],y ;$ + sta file ;$ + + lda [file] + and #$00ff + cmp #65 + bcc strokay + lda #$0053 ; oops- decimal error #s are boo-boo + jmp GSOSReturn +strokay ph4 file ; convert thingy to a GS string + ph4 #gspath+1 + jsl copypstr + lda gspath+1 + and #$00FF + sta gspath + ld4 gspath,(CRpathname,OPENpathname,destPathname) +redirectCom anop +; lda device + lda [pBlock] ;$ + beq doOpen +; lda append + ldy #PBappend + lda [pBlock],y ;$ + bne doOpen +doCreate anop + Create CRparm + bcc doOpen + cmp #$47 ; duplicate pathname? + beq delFile + cmp #$58 + beq doOpen ; not a block device- Char device + jmp GSOSReturn +delFile Destroy destParm + bcc doCreate + jmp GSOSReturn +doOpen anop + ldx #1 ;$ +; lda device + lda [pBlock] ;$ + beq storeAccess + ldx #2 ;$ +storeAccess stx OPENreqAccess ;$ + lda [pBlock] ; get 'device' parameter + inc a ; I/O channel before we open + sta CLOSEparm+2 + Close CLOSEparm ; the new one. + bcs openError1 + Open OPENParm + bcc okay +openError1 jmp GSOSReturn ; error if >> on nonexistent file +okay anop +; lda append ; move mark to eof? + ldy #PBappend ;$ move mark to eof? + lda [pBlock],y ;$ + beq noAppend + lda OPENrefNum + sta EOFref + sta MARKref + GetEOF EOFpb + bcs nonOkey + movelong EOFeof,MARKdisp + SetMark MARKpb + bcs nonOkey + bra noAppend +EOFpb dc i2'2' +EOFref dc i2'0' +EOFeof dc i4'0' +MARKpb dc i2'3' +MARKref dc i2'0' +MARKbase dc i2'0' +MARKdisp dc i4'0' + +noAppend anop + pea $3 ; file redirection + pea $0 + ph2 OPENrefNum + lda #$0F + clc +; adc device + adc [pBlock] ;$ + xba + ora #$0C + tax + jsl $E10000 ; make the tool call + lda #0 +nonOkey jmp GSOSReturn + +gspath ds 66 +CRparm dc i2'4' +CRpathname dc i4'gspath' + dc i2'$C3' + dc i2'$04' + dc i4'0' +destParm dc i2'1' +destPathname dc i4'gspath' +OPENParm dc i2'3' +OPENrefNum dc i2'0' +OPENpathname dc i4'gspath' +OPENreqAccess dc i2'0' +CLOSEparm dc i2'1' + dc i2'0' + END + +;========================================================================= +; +; ($113) Stop +; +;========================================================================= + + +_Stop START +_Stop name + using KernelStruct + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #1 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 lda >truepid + asl a + tax + lda StopFlags,x + sta [pBlock] + jmp GSOSReturn +StopFlags ENTRY + dc 32i2'0' + END + +;========================================================================= +; +; ($114) ExpandDevices +; +;========================================================================= + +_ExpandDevices START +_ExpandDevices name +PBpathname equ 0 +PBoutname equ 4 + +pathname equ shellLoc+0 + + lda cmdNum + and #$40 + beq orca_1 + ldy #PBpathname+2 + lda [pBlock],y + sta inputPath+2 + lda [pBlock] + sta inputPath + ldy #PBoutname+2 + lda [pBlock],y + sta outputPath+2 + ldy #PBoutname + lda [pBlock],y + sta outputPath + ExpandPath epParm + jmp GSOSReturn + +orca_1 anop + ldy #PBpathname+2 ;$ + lda [pBlock],y ;$ + sta pathname+2 ;$ + lda [pBlock] ;$ + sta pathname ;$ + + lda [pathname] + and #$00FF + tay + sta inputbuf + beq nocopy1 + short m +loop1 lda [pathname],y + sta inputbuf+1,y + dey + bne loop1 +nocopy1 long m + ld4 inputbuf,inputPath + ld4 outputbuf,outputPath + + ExpandPath epParm + bcs error + + lda outputbuf+2 + and #$00ff + tay + sta [pathname] + beq nocopy2 + short a +loop2 lda outputbuf+3,y + sta [pathname],y + dey + bne loop2 +nocopy2 long a + lda #0 +error anop + jmp GSOSReturn + + +epParm anop + dc i2'3' +inputPath dc i4'inputbuf' +outputPath dc i4'outputbuf' +ed_flags dc i2'0' +inputbuf ds 66 +outputbuf dc i2'68' + ds 66 + END + +;========================================================================= +; +; ($115) UnsetVariable +; +;========================================================================= + +_UnsetVariable START +_UnsetVariable name + +PBname equ 0 +name equ shellLoc+0 + + lda cmdNum + and #$40 + beq orca_1 + +orca_2 anop + ldy #PBname+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl gs2cstr + sta name + stx name+2 + bra orca_com + +orca_1 anop + ldy #PBname+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + + jsl p2cstr + sta name + stx name+2 +orca_com anop + pei (name+2) + pei (name) + jsl unsetvar + pei (name+2) + pei (name) + jsl ~NDISPOSE + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($116) Export +; +;========================================================================= + +_Export START +_Export name + +PBname equ 0 +PBflags equ 4 + +name equ shellLoc+0 + + lda cmdNum + and #$40 ;If bit $40 then c strings + beq orca_1 + lda pCount + cmp #2 + beq orca_2 + lda #4 + jmp GSOSReturn + +orca_2 anop + ldy #PBname+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl gs2cstr + sta name + stx name+2 + bra orca_com +orca_1 anop +; pei (name+2) +; pei (name) + ldy #PBname+2 ;$ + lda [pBlock],y ;$ + pha ;$ + lda [pBlock] ;$ + pha ;$ + jsl p2cstr + sta name + stx name+2 +orca_com anop + pei (name+2) + pei (name) +; pei (flags) + ldy #PBflags ;$ + lda [pBlock],y ;$ + pha ;$ + jsl exportvar + pei (name+2) + pei (name) + jsl ~NDISPOSE + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($117) PopVariables +; +;========================================================================= + +_PopVariables START +_PopVariables name + using KernelStruct + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #0 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 lda truepid + jsl popvartbl + + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($118) PushVariables +; +;========================================================================= + +_PushVariables START +_PushVariables name + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #0 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 jsl initvar + + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($119) SetStopFlag +; +;========================================================================= + +_SetStopFlag START +_SetStopFlag name + using KernelStruct + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #1 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 lda >truepid + asl a + tax + lda [pBlock] + sta StopFlags,x + jmp GSOSReturn + END + +;========================================================================= +; +; ($11A) ConsoleOut +; +;========================================================================= +; does nothing if process is in the background (1/21/93 jb) + +_ConsoleOut START +_ConsoleOut name + using KernelStruct + +char equ 0 + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #1 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 anop + jsr isBGProcess + bcs goaway + +* Instead of calling the console's COUT, call down to the character device +* dispatcher with a write request. + + jsl decBusy + pea 1 + ph4 pBlock + ldx curProcInd + lda ttyID,x +; dec a don't need this since this is the actual + pha + jsl ttwrite value + jsl incBusy + +goaway lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($11E) KeyPress +; New ORCA/Shell (2.0.1) call to see if input is pending, and if so +; what the input is. +; This routine is the compromise Mike W. and I worked out regarding +; directly accessing the keyboard from his compilers. +; +;========================================================================= +; Due to the fact that there's no way to 'unget' a character from +; a tty and that the only way to get the data this call wants is to +; read it via ioctl(FIONREAD) & read (which removes the char, making +; a subsequent _KeyRead work improperly), we have to peek at the +; console's input buffer directly to get our data. This is really icky, +; but we have sufficient checks to prevent the routine from snagging +; a foreground process' input. + +_KeyPress START +_KeyPress name + using ADBData + using KernelStruct + +key equ 0 key & mod. reg of keypress. Not valid +modifiers equ 2 if available == 0 +available equ 4 == 1 if key avail, == 0 if not + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #3 + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 anop + ldx curProcInd + lda ttyID,x + cmp #3 ; is controlling tty the console? + bne goaway ; leave w/o doing anything + + jsr isBGProcess + bcs goaway ; ignore progs in the bg + + php + sei ; temporarily shut off interrupts + 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. + ldy #key ; store them in the parameter + sta [pBlock],y ; block after masking unneeded + lda modbuf,x ; portions out + and #$00FF + jsl ConvKMR2EM + ldy #modifiers + sta [pBlock],y + lda #1 + ldy #available + sta [pBlock],y + + plp ; restore interrupts + lda #0 + jmp GSOSReturn + +noKeyWaiting plp +goaway lda #0 + ldy #available + sta [pBlock],y + lda #0 + jmp GSOSReturn + + END + +;========================================================================= +; +; ($11F) ReadKey +; New ORCA/Shell (2.0.1) call to wait for an input character and +; return the key and modifiers in Event Manager format. +; +;========================================================================= +; ReadKey does a number of checks to maintain sanity. Currently, if the +; caller is in the BG no action occurs. If the process' controlling TTY +; is not the console, we do a ReadChar to get pause keys, at least (we +; can't get modifiers from a serial port!). If the tty is the console, +; we make a direct (fast) call to KEYIN in inout.asm + +_ReadKey START +_ReadKey name + using KernelStruct + +key equ 0 key & mod. reg of keypress. Not valid +modifiers equ 2 if available == 0 + + lda cmdNum + and #$40 + beq orca_1 + lda pCount + cmp #2 ; check the pCount + beq orca_1 + lda #4 + jmp GSOSReturn + +orca_1 anop + jsr isBGProcess + bcs isbg + + ldx curProcInd + lda ttyID,x +* cmp #3 +* beq isConsole ; it's the console + + pha ; do something sensible for non-console + pea 0 + ldx #$220C ; TextTools/ReadChar + jsl $E10000 + pla + and #$00FF + bra setKey + +*isConsole anop +; phd +; lda InOutDP +; tcd +* jsl KEYIN +; pld +setKey pha + and #$00FF + + ldy #key + sta [pBlock],y + pla + xba + and #$00FF + jsl ConvKMR2EM + ldy #modifiers + sta [pBlock],y + + lda #0 + jmp GSOSReturn + +* We eventually might want to go ahead and suspend the background +* process for trying to read; this could be useful if some dork +* ever writes a program that uses these routines for input (God help +* us). + +isbg lda #0 + ldy #key + sta [pBlock],y + ldy #modifiers + sta [pBlock],y + +* Convert the keyboard modifier reg. format to the Event Manager modifiers +* format. + +ConvKMR2EM ENTRY + tay ; store the old value + ldx #0 ; initial modifier value + bit #%10000000 ; open apple? + beq x1 + txa + ora #%0000000100000000 + tax +x1 tya + bit #%01000000 + beq x2 + txa + ora #%0000100000000000 + tax +x2 tya + bit #%00010000 + beq x3 + txa + ora #%0010000000000000 + tax +x3 tya + bit #%00000100 + beq x4 + txa + ora #%0000010000000000 + tax +x4 tya + bit #%00000010 + beq x5 + txa + ora #%0001000000000000 + tax +x5 tya + bit #%00000001 + beq xdone + txa + ora #%0000001000000000 + tax +xdone txa + rtl + +isBGProcess ENTRY + ldx curProcInd + lda ttyID,x + asl a + tax + lda ttyStruct,x + beq nopgrp + ldx curProcInd + cmp pgrp,x + beq nopgrp ; it's the foreground process + sec + rts +nopgrp clc + rts + END diff --git a/kern/gno/signal.c b/kern/gno/signal.c new file mode 100644 index 0000000..927113c --- /dev/null +++ b/kern/gno/signal.c @@ -0,0 +1,725 @@ +/* $Id: signal.c,v 1.1 1998/02/02 08:18:56 taubert Exp $ */ + +/* Signals work like this. + The following paragraphs only describe calling a handler routine, as + ignore and default are trivial operations in all situations. kill(x,9) + supercedes all this and just blasts the process to hell. + Mutex should of course be in effect during any of this. + + 1) A process sends a signal to itself + Set the sigmasks appropriately, then pushes the context on the stack + and jsl's the handler routine. The handler RTLs to the context restore + routine, and another rtl occurs to resume execution right after the sig + call. + 2) A process sends a signal to another process + a) if there are signals pending, just set the bits and what-not and + return (the context restore routine will run the next handler if + necessary) + b) get the process context from the process table, and build stuff + on the process' stack, so that the next time the proc is executed, + it will be executing the signal handler. + c) in either case, the restore context routine checks to see whether + there are any more signals pending, and if so, sets it up immediately. + + The only difference between 1 and 2 is that 1 gets the 'current context' + by shoving registers on the stack, and 2 gets it from the target process' + + Note that the signal code need not worry about the various machine states + (shadow, statereg, etc) because those would only be modified by routines + in emulation mode, which should by all accounts be mutexed. +*/ +#pragma optimize 79 +segment "KERN2 "; + +#include "conf.h" +#include "kernel.h" +#include "proc.h" +#include "sys.h" +#include "gno.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include +#include +#include +#include +#include +#include + +extern kernelStructPtr kp; +extern void selwakeup(int col_flag, int pid); +extern void selwait(void); + +enqueueWait(int targetpid, int pid, union wait status) +{ +chldInfoPtr walk; +chldInfoPtr nwait; + +/* printf("enqueueWait: tpid %d pid %d status %04X\n",targetpid,pid,status); +*/ + if (targetpid == 0) return; /* don't queue up for Null Process */ + nwait = malloc(sizeof(chldInfo)); + nwait->next = NULL; + nwait->pid = pid; + nwait->status = status; + + walk = kp->procTable[targetpid].waitq; + if (walk == NULL) { kp->procTable[targetpid].waitq = nwait; return; } + while (walk->next != NULL) walk = walk->next; + walk->next = nwait; +} + +word numInWaitQueue(int pid) +{ +chldInfoPtr w; +word x; + + w = kp->procTable[pid].waitq; + while (w != NULL) { + w = w->next; + x++; + } + return x; +} + +int dequeueWait(chldInfoPtr status, int pid) +{ +chldInfoPtr item; + + /*printf("dequeueWait: %06lX, pid %d ",kp->procTable[pid].waitq, + pid); */ + if ((item = kp->procTable[pid].waitq) == NULL) return -1; + if (status != NULL) + memcpy(status,item,sizeof(chldInfo)); + kp->procTable[pid].waitq = item->next; + /* printf("status: %04X, tpid: %d\n",item->status,item->pid); */ + nfree(item); + return 0; +} + +#pragma databank 1 +#pragma toolparms 1 + +extern void addsig(int, int); + +/* + * This MUST be in a function by itself so the kp-> dereference will have + * an allocated DP to use. + */ +static void proc_free(struct pentry *tosig) +{ + if (tosig->flags & FL_FORKED) { + DisposeAll(tosig->userID); /* process was fork()ed, don't USD */ + DeleteID(tosig->userID); + } else { + UserShutDown(tosig->userID, + ((tosig->flags & FL_RESTART) && + !(tosig->flags & FL_NORESTART)) ? 0x4000 : 0); + } + + kp->numProcs--; + if (kp->numProcs == 1) kp->shutdown = 1; +} + +int KERNkill(int *ERRNO, int signum, int pid) +{ +struct pentry *tosig; +struct sigrec *sig; +int i,j,mpid; +longword wait; +word ClosePB[2]; +union wait status; +extern int OLDGSOSST(word callnum, void *pBlock); +extern void ctxtRestore(void); +extern void enableBuf(void); +extern pgrp pgrpInfo[]; +extern void disposevar(int); + + if (kp->gsosDebug & 8) + kern_printf("kill (-%d):pid %d\n\r",signum,pid); +/* $$$ if (pid == 0) pid = -(kp->procTable[Kgetpid()].pgrp); */ + if (pid == 0) pid = -(PROC->pgrp); + if (pid < 0) { + pid = 0-pid; + for (i = 0; i < NPROC; i++) { + if ((kp->procTable[i].processState) && + (kp->procTable[i].pgrp == pid)) + addsig(i,signum); + } + _resched(); /* allow signals to be processed before we go on */ + return 0; + } + mpid = mapPID(pid); + if (mpid == 0) return -1; /* can't signal the kernel null process */ + if (mpid == -1) { *ERRNO = ESRCH; return -1; } + if (!signum) return 0; + if ((signum < 1) || (signum > 32)) { *ERRNO = EINVAL; return -1; } + tosig = &(kp->procTable[mpid]); + sig = tosig->siginfo; + disableps(); + if (sig->signalmask & sigmask(signum)) { + sig->sigpending |= sigmask(signum); + enableps(); + return 0; + } + + /* if we were BLOCKED, then restart the operation */ + if (tosig->processState == procBLOCKED) { +#if 1 + /* if (sig interrupt bit is set) */ + if ((sig->v_signal[signum] != SIG_DFL) && + (sig->v_signal[signum] != SIG_IGN)) + { tosig->waitdone = -1; tosig->processState = procREADY; } +#else + { tosig->waitdone = 1; tosig->processState = procREADY; } +#endif + + /* Semaphore cleanup for preceive(), swait() */ + if (tosig->psem && tosig->psem != -1) + semINTR(tosig->psem, mpid); + } + + /* if we were waiting for a signal, restart the process after we + execute any signal handler (including killing the puppy if necessary) */ + if (tosig->processState == procPAUSED) + tosig->processState = procREADY; + else if (tosig->processState == procWAITSIGCH) { + if (signum == SIGCHLD) tosig->waitdone = 1; + else { + if (sig->v_signal[signum] != SIG_DFL) + tosig->waitdone = -1; + } + tosig->processState = procREADY; /* restart the process, bloke! */ + } + + /* ignore the signal? */ + if (sig->v_signal[signum] == SIG_IGN) { enableps(); return 0; } + else if (sig->v_signal[signum] == SIG_DFL) { /* default actions */ + switch (signum) { + case SIGCONT: + if (tosig->processState != procSUSPENDED) + { enableps(); return 0; } + if ((tosig->stoppedState == procRUNNING) || + (tosig->stoppedState == procBLOCKED)) + tosig->processState = procREADY; + else tosig->processState = tosig->stoppedState; + /* if (tosig->stoppedState == procBLOCKED) + tosig->irq_A = 0xFF; *//* restart I/O operation */ + + enableps(); + return 0; + case SIGURG: + case SIGCHLD: enableps(); return 0; + case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + /* if the process is already suspended, ignore these signals */ + + if (tosig->processState != procSUSPENDED) { + status.w_stopsig = signum; + status.w_stopval = WSTOPPED; + enqueueWait(tosig->parentpid,pid,status); + /* this seems to be a definite no-no; the parent will restart on receipt + of the SIGCHLD */ + /* kp->procTable[tosig->parentpid].processState = procREADY; */ + tosig->stoppedState = tosig->processState; + tosig->processState = procSUSPENDED; + addsig(tosig->parentpid,SIGCHLD); + } + enableps(); + if (mpid == Kgetpid()) _resched(); + return 0; + } + +/* this is the old 'kill' code + This portion is repsponsible for terminating processes +*/ + +/*printf("kill (-%d):pid %d (userID %04X)",signum,pid,tosig->userID);*/ + +#if 0 + if (kp->gsosDebug & 8) { + int i; + for (i=0;iparentpid != 0) { + if (tosig->flags & FL_NORMTERM) { + status.w_termsig = 0; + status.w_coredump = 0; + status.w_retcode = tosig->exitCode; + } else { + status.w_termsig = signum; + status.w_coredump = 0; + status.w_retcode = 0; + } + enqueueWait(tosig->parentpid,pid,status); + addsig(tosig->parentpid,SIGCHLD); + /* update children time accounting stuff for times() */ + if (tosig->parentpid) + kp->procTable[tosig->parentpid].childTicks += + tosig->ticks + tosig->childTicks; + } + if (!(tosig->flags & FL_COMPLIANT)) { + int c = 5; + enableBuf(); + } + /* If the process was in a sleep queue, remove it - do not ready */ + if (tosig->p_waitvec) k_remove(tosig->p_waitvec, mpid, 0); + + if (tosig->flags & FL_QDSTARTUP) *((byte *)0xE0C029l) &= 0x7F; + + /* if the process has active children, have INIT (pid 0) inherit them */ + /* printf("reassigning active children\n"); */ + for (i = 1; i < NPROC; i++) { + if (kp->procTable[i].processState != procUNUSED) + if (kp->procTable[i].parentpid == mpid) + kp->procTable[i].parentpid = 0; + } + disposevar(mpid); + /*printf("dequeueing all wait info\n"); */ + while (dequeueWait(NULL,mpid) != -1); /* unallocate all the wait info */ + + /*printf("freeing prefix recs\n");*/ + for (i = 0; i < 33; i++) + if (tosig->prefix[i] != NULL) + nfree(tosig->prefix[i]); + + /*printf("freeing prefix rec\n");*/ + nfree(tosig->prefix); + /*printf("freeing args\n");*/ + if (tosig->args) nfree(tosig->args); + /*printf("freeing sig\n");*/ + nfree(sig); /* dealloc the signal record */ + /*printf("deallocating pgrp\n"); */ + if (tosig->pgrp != 0) pgrpInfo[tosig->pgrp-2].pgrpref--; + tosig->alarmCount = 0l; + + switch (tosig->processState) { + case procRUNNING: /* suicide */ + tosig->openFiles->fdLevel = + tosig->openFiles->fdLevelMode = 0; + ClosePB[0] = 1; ClosePB[1] = 0; + CloseGS(ClosePB); + nfree(tosig->openFiles); /* since we alloc'ed this- fix this later */ + tosig->processState = procUNUSED; + + /* + * Switch to the nullproc's stack so we won't be running on a + * deallocated stack. + */ + { + Word nullproc_S = kp->procTable[0].irq_S; + + asm { + lda nullproc_S + tcs + } + } + /* STACK REPAIR MUST BE OFF TO CALL proc_free() */ + proc_free(tosig); + /* DON'T USE ANY DP AFTER THIS until _resched() */ + +#if 1 + /* do this in case program crashed in the kernel */ + asm { lda #0 + sta 0xE100FF + } +#else + enableps(); +#endif + _resched(); + PANIC("KILL OVERRUN #1"); + /* not reached */ + default: + { + fdtablePtr tmpof; + /* $$$ tmpof = kp->procTable[Kgetpid()].openFiles; */ + tmpof = PROC->openFiles; + /* $$$ kp->procTable[Kgetpid()].openFiles = tosig->openFiles; */ + PROC->openFiles = tosig->openFiles; + /* make sure we close _all_ files */ + tosig->openFiles->fdLevel = + tosig->openFiles->fdLevelMode = 0; + ClosePB[0] = 1; ClosePB[1] = 0; + CloseGS(ClosePB); + /* $$$ kp->procTable[Kgetpid()].openFiles = tmpof; */ + PROC->openFiles = tmpof; + tosig->processState = procUNUSED; + + nfree(tosig->openFiles); /* since we alloc'ed this- fix this later */ + break; + } + } + proc_free(tosig); + enableps(); + return SYSOK; + } + + if (mpid == Kgetpid()) { + int tmpwaitdone; + + /* this is implemented as a function call- is there a reason not to? */ + sig->signalmask |= sigmask(signum); /* block the signal */ + tmpwaitdone = tosig->waitdone; + enableps(); + (*sig->v_signal[signum])(signum,0); + tosig->waitdone = tmpwaitdone; + Ksigsetmask(ERRNO, sig->signalmask & ~sigmask(signum)); + return 0; + } /* process signalling itself */ + else { /* signalling another process */ + sig->signalmask |= sigmask(signum); /* block the signal */ + +/* fake the RTL address of the 'jsl' to the signal handler */ + *((longword *) (tosig->irq_S-30)) = (longword) (((byte *)ctxtRestore)-1); + +/* fake the two parameters - first 'code', then 'signum' */ + *((longword *) (tosig->irq_S-27)) = (longword) signum; + +/* fake the parameter to cSignalHook */ + *((word *) (tosig->irq_S-23)) = (word) signum; + +/* store the waitdone flag */ + *((word *) (tosig->irq_S-21)) = (word) tosig->waitdone; + +/* copy the process' context record to the stack for restoration in + CTXTRESTORE */ + memcpy((void *) ((tosig->irq_S-19)),((byte *) tosig)+8,20l); + +/* use the stack pointer context field to store the old process state, + since the Stack is implicit */ + + /* Interrupt select() */ +#if 0 + /* selwakeup(1, mpid2KToff(mpid)); + FIXME: why does this break init? */ +#else + if (tosig->p_waitvec == (unsigned long)selwait) + k_remove(tosig->p_waitvec, mpid, 1); +#endif + switch(i = tosig->processState) { + /* case procRUNNING: */ + case procBLOCKED: /* read(), preceive(), swait(), procreceive() */ + /* + * We need to stay awake after the signal handler so + * the system call can return EINTR + */ + i = procREADY; + break; + } + + *((word *) (tosig->irq_S-13)) = i; + +/* we want the signal handler to run even if the process was not READY */ + tosig->processState = procREADY; + + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + tosig->irq_B = tosig->irq_B1 = + tosig->irq_K = (sig->v_signal[signum] >> 16); +#else + tosig->irq_K = (sig->v_signal[signum] >> 16); + tosig->irq_B1 = tosig->irq_K; + tosig->irq_B = tosig->irq_B1; +#endif + + /* the PC field isn't used right now. fix it */ + tosig->irq_PC = (word) sig->v_signal[signum]; + tosig->irq_P = 0x04; /* leave interrupts off you idiot */ + + /* this RTI info simulation goes away at the next context switch, + and the other, actual interrupt info from the last context + switch out of the process gets RTId in ctxtRestore */ + *((word *) (tosig->irq_S-33)) = (word) tosig->irq_PC; + *((byte *) (tosig->irq_S-34)) = 0; /*(byte) tosig->irq_P;*/ /* handler should run with interrupts on */ + *((byte *) (tosig->irq_S-31)) = (byte) tosig->irq_K; + + tosig->irq_S -= 35; + enableps(); + return 0; + } +/* we won't actually get here ... */ + PANIC("we shouldn't be here in signal"); + enableps(); + return 0; +} + +void *KERNsignal(int *ERRNO, void (*func)(), int sig ) +{ + return Ksignal(ERRNO, func, sig); +} + +longword KERNsigsetmask(int *ERRNO, longword mask) +{ + return Ksigsetmask(ERRNO, mask); +} + +longword KERNsigblock(int *ERRNO, longword mask) +{ + return Ksigblock(ERRNO, mask); +} + +/* wait() code- use with caution, this stuff is heinous! */ + +int KERNwait(int *ERRNO, union wait *stat) +{ +/* $$$ struct pentry *p; */ +unsigned i; +chldInfo waitinfo; + + + disableps(); + for (i = 0; i < NPROC; i++) { + if (kp->procTable[i].processState) { + if (kp->procTable[i].parentpid == Kgetpid()) break; + } + } + if ((i == NPROC) && (PROC->waitq == NULL)) { + *ERRNO = ECHILD; enableps(); return -1; + } + + /* $$$ p = &(kp->procTable[Kgetpid()]); */ + while (dequeueWait(&waitinfo,Kgetpid()) == -1) { + PROC->waitdone = 0; + + /* WAITSIGCH returns when a SIGCHLD or caught signal is sent + to the process */ + /* $$$ kp->procTable[Kgetpid()].processState = procWAITSIGCH; */ + PROC->processState = procWAITSIGCH; + enableps(); + _resched(); + if (PROC->waitdone == -1) { /* interrupted by a caught signal */ + *ERRNO = EINTR; return -1; + } + disableps(); + } + enableps(); + if (stat != NULL) + *stat = waitinfo.status; + return (waitinfo.pid); +} + +longword KERNalarm(int *ERRNO, longword seconds) +{ +longword old; + + asm { + php + sei + } + /* $$$ old = kp->procTable[Kgetpid()].alarmCount; */ + old = PROC->alarmCount; + /* $$$ kp->procTable[Kgetpid()].alarmCount = seconds * 10; */ + PROC->alarmCount = seconds * 10; + asm { plp } + return (old - (old % 10)) / 10; +} + +longword KERNalarm10(int *ERRNO, longword seconds10) +{ +longword old; + asm { + php + sei + } + /* $$$ old = kp->procTable[Kgetpid()].alarmCount; */ + old = PROC->alarmCount; + /* $$$ kp->procTable[Kgetpid()].alarmCount = seconds * 10; */ + PROC->alarmCount = seconds10; + asm { plp } + return old; +} + +int KERNsigpause(int *ERRNO, longword mask) +{ +longword oldmask; + + disableps(); + oldmask = Ksigsetmask(ERRNO, mask); + /* $$$ kp->procTable[Kgetpid()].processState = procPAUSED; */ + PROC->processState = procPAUSED; + enableps(); + _resched(); + Ksigsetmask(ERRNO, oldmask); + return -1; +} + +#pragma toolparms 0 + +#if 0 +longword Kreceive(int *ERRNO) +{ +longword tmp; +struct pentry *p; +extern void sleepbusy(void); + + disableps(); + p = PROC; + + p->waitdone = BLOCKED_RECEIVE; + if (!(p->flags & FL_MSGRECVD)) { + p->processState = procBLOCKED; + sleepbusy(); + } + if (p->waitdone == BLOCKED_RECEIVE) { + tmp = p->msg; + p->flags &= ~FL_MSGRECVD; + } + else tmp = -1l; + + enableps(); + return tmp; /* return the value of the message */ +} +#else +extern longword Kreceive(int *); +#endif + +void rcvttrap(int sig, int code) +{ + /* foobar! */ +} + +#pragma toolparms 1 + +longword KERNreceive(int *ERRNO) +{ + return Kreceive(ERRNO); +} + +longword KERNrecvclr(int *ERRNO) +{ +longword tmp; +struct pentry *p; + + p = PROC; + disableps(); + + if (p->flags & FL_MSGRECVD) tmp = p->msg; + else tmp = -1l; + p->flags &= ~FL_MSGRECVD; + + enableps(); + return tmp; +} + +longword KERNrecvtim(int *ERRNO, int timeout) +{ +void *oldsig; +longword oldalrm, oldmask, tmp; +struct pentry *p; + + oldmask = Ksigblock(ERRNO, SIGALRM); + oldsig = Ksignal(ERRNO, rcvttrap, SIGALRM); + /* $$$ p = &(kp->procTable[Kgetpid()]); */ + p = PROC; + oldalrm = p->alarmCount; + p->alarmCount = timeout; + Ksigsetmask(ERRNO, oldmask & ~sigmask(SIGALRM)); + tmp = Kreceive(ERRNO); + Ksigsetmask(ERRNO, oldmask); + p->alarmCount = oldalrm; + Ksignal(ERRNO, oldsig, SIGALRM); + return tmp; +} + +int KERNsend(int *ERRNO, longword msg, int pid) +{ +struct pentry *targetp; +int mpid; + + mpid = mapPID(pid); + if ((mpid == 0) || (mpid == -1)) { + *ERRNO = ESRCH; return -1; + } + targetp = &(kp->procTable[mpid]); + disableps(); + if (targetp->flags & FL_MSGRECVD) { + *ERRNO = EIO; enableps(); return -1; + } + targetp->msg = msg; + targetp->flags |= FL_MSGRECVD; + if ((targetp->waitdone == BLOCKED_RECEIVE) && + (targetp->processState == procBLOCKED)) { + targetp->processState = procREADY; + } + enableps(); + return 0; +} + +#pragma toolparms 0 + +void cSignalHook(int signum) +{ +struct sigrec *siginf; + + disableps(); + /* $$$ siginf = kp->procTable[Kgetpid()].siginfo; */ + siginf = PROC->siginfo; + Ksigsetmask(&errno, siginf->signalmask &= ~sigmask(signum)); + enableps(); +} + +#pragma databank 0 + +void *Ksignal(int *ERRNO, void (*func)(), int sig ) +{ +void (*old)(); +struct sigrec *siginf; + + if (kp->gsosDebug & 16) + kern_printf("signal(sig: %d, func:%06lX)\n\r",sig,func); +/* $$$ siginf = kp->procTable[Kgetpid()].siginfo; */ + siginf = PROC->siginfo; +/* printf("siginf: %08lX\n",siginf); */ + old = siginf->v_signal[sig]; + /* silently enforce restriction on signal handling */ + if ((sig != SIGKILL) && (sig != SIGSTOP)) { + if (func == SIG_IGN) siginf->sigpending &= ~sigmask(sig); +/* siginf->sigpending |= sigmask(sig); */ + siginf->v_signal[sig] = func; + } + return old; +} + +longword Ksigblock(int *ERRNO, longword mask) +{ +struct sigrec *siginf; +longword oldmask; + + /* $$$ siginf = kp->procTable[Kgetpid()].siginfo; */ + siginf = PROC->siginfo; + oldmask = siginf->signalmask; +/* install new mask, but don't allow blocking of SIGKILL, SIGSTOP, or SIGCONT */ + siginf->signalmask |= (mask & 0xFFFAFEFFl); + return oldmask; +} + +longword Ksigsetmask(int *ERRNO, longword mask) +{ +struct sigrec *siginf; +longword oldmask,ready; +int i; + + disableps(); + /* $$$ siginf = kp->procTable[Kgetpid()].siginfo; */ + siginf = PROC->siginfo; + oldmask = siginf->signalmask; + mask &= 0xFFFAFEFFl;/* don't allow blocking of SIGKILL, SIGSTOP, or SIGCONT */ + ready = siginf->sigpending & ~mask; + if (ready) { + for (i = 1; i < 32; i++) + if (ready & sigmask(i)) { + addsig(Kgetpid(), i); + siginf->sigpending &= ~sigmask(i); + } + } + siginf->signalmask = mask; + enableps(); + return oldmask; +} + diff --git a/kern/gno/sleep.c b/kern/gno/sleep.c new file mode 100644 index 0000000..a47be54 --- /dev/null +++ b/kern/gno/sleep.c @@ -0,0 +1,180 @@ +/* $Id: sleep.c,v 1.1 1998/02/02 08:19:00 taubert Exp $ */ + +/* + * sleep.c + * + * sleep/wakeup handling routines + */ + +extern void sleepbusy(void); + +#ifndef KERNEL +#include "tests/testsleep.c" +#else + +/* Building it into the kernel */ + +#pragma databank 1 +#pragma optimize 79 + +/*segment "KERN2 ";*/ +#include "proc.h" +#include "sys.h" +#include "kernel.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +extern kernelStructPtr kp; + +void dosleep(int pid) +{ + kp->procTable[pid].processState = procSLEEP; +} + +static void ready(int pid, int resch) +{ + kp->procTable[pid].processState = procREADY; + if (resch) _resched(); +} + +#endif + +typedef struct hash_entry { + unsigned pid; /* first pool entry on the wait list */ +} hash_entry; + +#define NUM_HVENTRIES 64 +hash_entry hv_tab[NUM_HVENTRIES]; + +#if 0 +void init_sleep_hash(void) +{ +unsigned i; + + for (i = 0; i < NUM_HVENTRIES; i++) { + hv_tab[i].vector = 0l; + hv_tab[i].pid = 0; + } +} +#endif + +static unsigned hash_vector(unsigned long vec) +{ + return (unsigned)(vec & 0x3F); +} + +#define BUSY_FLAG ((byte *)0xE100FFl) + +/* no longer used; this code is now in assembly language */ +#if 0 +int k_sleepold(unsigned long vec, int pri, int pid) +{ +unsigned hv; +struct proc *p; +unsigned last; +unsigned cur; +byte oldBusy; + + disableps(); + hv = hash_vector(vec); + /*PROC->p_pri = pri;*/ + /*PROC->p_waitvec = vec;*/ + kp->procTable[pid].p_waitvec = vec; + + /* Add this process to the END of this wait queue. This gives us a + FIFO action on the sleep queues */ + last = hv_tab[hv].pid; + if (last == 0) { + hv_tab[hv].pid = pid; + } else { + while (kp->procTable[last].p_slink != 0) { + last = kp->procTable[last].p_slink; + } + kp->procTable[last].p_slink = pid; + } + kp->procTable[pid].p_slink = 0; + /*fprintf(stderr,"process %d going to sleep on vec %06lX\n",pid,vec);*/ + dosleep(pid); + sleepbusy(); + enableps(); +} +#endif + +/* Remove a single process from a sleep vector */ +void k_remove(unsigned long vec, int pid, int readyq) +{ +unsigned last = 0; +unsigned hv; +unsigned cur,link; + + /*fprintf(stderr,"removing %d from %06lX\n",pid,vec);*/ + disableps(); + hv = hash_vector(vec); + cur = hv_tab[hv].pid; + while (cur != 0) { + link = kp->procTable[cur].p_slink; + if ((kp->procTable[cur].p_waitvec == vec) && (cur == pid)) { + /* Remove an item from the list. If the item is the first, + last == 0, and we set the hash vector to the follower + of the item */ + if (last == 0) { + hv_tab[hv].pid = link; + } + /* Otherwise, the item is not the first; last != 0; we set + last's link to the current link, removing the curproc + from the list */ + else { + kp->procTable[last].p_slink = kp->procTable[cur].p_slink; + last = cur; + } + if (readyq) ready(cur,0); + kp->procTable[cur].p_waitvec = 0l; + cur = link; + } else { + last = cur; + cur = link; + } + } + enableps(); + /* if priority of a proc we awakened was higher than current priority + we need to _resched() */ +} + +/* Remove all processes from a sleep vector */ +void k_wakeup(unsigned long vec) +{ +unsigned last = 0; +unsigned hv; +unsigned cur,link; + + /*fprintf(stderr,"waking up %06lX\n",vec);*/ + disableps(); + hv = hash_vector(vec); + cur = hv_tab[hv].pid; + while (cur != 0) { + link = kp->procTable[cur].p_slink; + if (kp->procTable[cur].p_waitvec == vec) { + /* Remove an item from the list. If the item is the first, + last == 0, and we set the hash vector to the follower + of the item */ + if (last == 0) { + hv_tab[hv].pid = link; + } + /* Otherwise, the item is not the first; last != 0; we set + last's link to the current link, removing the curproc + from the list */ + else { + kp->procTable[last].p_slink = kp->procTable[cur].p_slink; + last = cur; + } + ready(cur,0); + kp->procTable[cur].p_waitvec = 0l; + cur = link; + } else { + last = cur; + cur = link; + } + } + enableps(); + /* if priority of a proc we awakened was higher than current priority + we need to _resched() */ +} + diff --git a/kern/gno/stat.c b/kern/gno/stat.c new file mode 100644 index 0000000..559ec73 --- /dev/null +++ b/kern/gno/stat.c @@ -0,0 +1,250 @@ +/* $Id: stat.c,v 1.1 1998/02/02 08:19:02 taubert Exp $ */ + +/* + + stat.c + + Copyright 1992-1998, Procyon Inc. + + Many generations ago, Derek Taubert wrote the original version of + this code. There is still a family resemblance, but this great-great- + great-grandchild also bears a striking resemblance to Jawaid Bazyar. + I.e., this is a bastard piece of code. + + The many changes were made to facilitate its merge into the GNO Kernel, + mostly dealing with reporting of pipes. +*/ + +segment "KERN2 "; +#pragma optimize 79 + +#include "proc.h" +#include "sys.h" +#include "kernel.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include +#include +#include +#include +#include + +extern kernelStructPtr kp; +int inoPool = 1; + +int +_mapErr (int err) +{ + int ret; + + if (!err) { + return 0; + } + if ((err & 0xff00) == 0x4300) { + /* GNO already mapped the error */ + return (err & 0x00ff); + } + switch (err) { + case 0x43: ret = EBADF; break; + + case 0x44: + case 0x45: + case 0x46: ret = ENOENT; break; + + case 0x47: + case 0x50: ret = EEXIST; break; + + case 0x48: + case 0x49: ret = ENOSPC; break; + case 0x4A: ret = ENOTDIR; break; + + case 0x4B: + case 0x4F: + case 0x53: ret = EINVAL; break; + case 0x54: ret = ENOMEM; break; + case 0x4E: ret = EACCES; break; + case 0x58: ret = ENOTBLK; break; + default: ret = EIO; break; + } + return ret; +} + +#pragma databank 1 +int statCommon(const char *filename, struct stat *s_buf) +{ +FileInfoRecGS fi; +DevNumRecGS getdev; +int e,entcount; +int dtype = 0; +GSString255Ptr fullpath,path; +extern void COPYC2GS(void*,void*); +extern GSString255Ptr gno_ExpandPath(GSString255Ptr, int, word); +unsigned long lsec; + + disableps(); + path = malloc(strlen(filename)+2); + COPYC2GS(path,filename); + fullpath = gno_ExpandPath(path,0,0); + + fi.pCount = 10; + fi.optionList = NULL; + fi.pathname = fullpath; + GetFileInfoGS(&fi); + if (_toolErr) { + if (_toolErr == 0x58) dtype = 1; + else { + nfree(path); + enableps(); + return _mapErr(_toolErr); + } + } + + if (fullpath->text[0] == '.') { + getdev.devName = (GSString32Ptr) fullpath; + if (findDevice(fullpath)) { + memset(s_buf,0,sizeof(struct stat)); + s_buf->st_mode = S_IFCHR; + nfree(path); return 0; + } + } + else { + fullpath->text[fullpath->length] = 0; + e = strpos(fullpath->text+1,':'); + if (e != -1) { + if (e < fullpath->length) e++; + fullpath->length = e; + } + getdev.devName = (GSString32Ptr) fullpath; + } + getdev.pCount = 2; + GetDevNumberGS(&getdev); + + if (_toolErr) { + enableps(); + return _mapErr(_toolErr); + } + s_buf->st_dev = getdev.devNum; + + /* this fakes an inode number. For applications like diff, + this will work since there are no file links under either + ProDOS or HFS */ + + s_buf->st_ino = inoPool++; + + if (!dtype) { + s_buf->st_mode = + ((fi.fileType == 0x0f) ? (S_IFDIR|S_IEXEC) : S_IFREG) | + ((fi.access & 0x01) ? S_IREAD : 0) | + ((fi.access & 0x02) ? S_IWRITE : 0) | + (((fi.fileType == 0xff) || (fi.fileType == 0xb5) || + (fi.fileType == 0xb3)) ? S_IEXEC : 0); + s_buf->st_nlink = 0; + s_buf->st_uid = 0; + s_buf->st_gid = 0; + s_buf->st_rdev = 0; /* device type */ + s_buf->st_size = fi.eof; + + lsec = ConvSeconds(1,0l,(Pointer)&fi.modDateTime); + /* 2083363200. seconds difference */ + /*s_buf->st_atime = s_buf->st_mtime = lsec - 2756021998ul;*/ + + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + s_buf->st_atime = s_buf->st_mtime = lsec - 2078611200ul; +#else + s_buf->st_mtime = lsec - 2078611200ul; + s_buf->st_atime = s_buf->st_mtime; +#endif + lsec = ConvSeconds(1,0l,(Pointer)&fi.createDateTime); + s_buf->st_ctime = lsec - 2078611200ul; + + s_buf->st_blksize = STAT_BSIZE; + s_buf->st_blocks = fi.blocksUsed; + } else { + memset(s_buf,0,sizeof(struct stat)); + s_buf->st_dev = getdev.devNum; + s_buf->st_mode = S_IFCHR; + } + enableps(); + return(0); +} + +#pragma databank 1 +#pragma toolparms 1 + +int KERNfstat(int *ERRNO, struct stat *s_buf, int fd) +{ +RefInfoRecGS refInfo; +ResultBuf255Ptr gstring; +fdentryPtr fp; +int rc; +extern fdentryPtr getFDptr(int); + + disableps(); + if (kp->gsosDebug & 16) + fprintf(stderr,"fstat: fd: %d s_buf: %06lX\n",fd,s_buf); + if ((fd == 0) || ((fp = getFDptr(fd)) == NULL) || (fp->refNum == 0)) { + *ERRNO = EBADF; + enableps(); + return -1; + } + if (fp->refType == rtPIPE) { + memset(s_buf,0,sizeof(struct stat)); + s_buf->st_mode = S_IFSOCK; + enableps(); return 0; + } else if (fp->refType == rtTTY) { + memset(s_buf,0,sizeof(struct stat)); + s_buf->st_mode = S_IFCHR; + enableps(); return 0; + } + gstring = malloc(sizeof(ResultBuf255)); + + refInfo.pCount = 3; + refInfo.refNum = fd; + gstring->bufSize = 254; + refInfo.pathname = gstring; +tryGet: + GetRefInfoGS(&refInfo); + if (_toolErr == 0x4F) { + gstring = realloc(gstring,gstring->bufString.length+5); + gstring->bufSize = gstring->bufString.length; + goto tryGet; + } + if (_toolErr) { + *ERRNO = _mapErr(_toolErr); + enableps(); + return(-1); + } + gstring->bufString.text[gstring->bufString.length]=0; + rc = statCommon(gstring->bufString.text,s_buf); + if (rc) *ERRNO = rc; + nfree(gstring); + enableps(); + return (rc) ? -1 : 0; +} + +int KERNlstat(int *ERRNO,struct stat *s_buf,const char *filename) +{ +int rc; + + if (kp->gsosDebug & 16) + fprintf(stderr,"stat: lpath: %s s_buf: %06lX\n",filename,s_buf); + rc = statCommon(filename,s_buf); + if (rc) *ERRNO = rc; + return (rc) ? -1 : 0; +} + +int KERNstat(int *ERRNO,struct stat *s_buf,const char *filename) +{ +int rc; + + if (kp->gsosDebug & 16) + fprintf(stderr,"stat: path: %s s_buf: %06lX\n",filename,s_buf); + rc = statCommon(filename,s_buf); + if (rc) *ERRNO = rc; + return (rc) ? -1 : 0; +} +#pragma databank 0 +#pragma toolparms 0 + diff --git a/kern/gno/sys.c b/kern/gno/sys.c new file mode 100644 index 0000000..9cf1bee --- /dev/null +++ b/kern/gno/sys.c @@ -0,0 +1,1249 @@ +/* $Id: sys.c,v 1.1 1998/02/02 08:19:05 taubert Exp $ */ + +#pragma optimize 79 +segment "KERN2 "; + +/* + + sys.c + + GS/IX Kernel routines for process control + + Copyright 1991-1998, Procyon, Inc. + Jawaid Bazyar and Derek Taubert +*/ + +#include "conf.h" +#include "proc.h" +#include "kernel.h" +#include "gno.h" +#include "kvm.h" +#include "sys.h" +#include "/lang/orca/libraries/orcacdefs/stdio.h" +#include "/lang/orca/libraries/orcacdefs/string.h" +#include "/lang/orca/libraries/orcacdefs/stdlib.h" +#include +#include +#include +#include +#include +#include +#include +#include + +extern kernelStructPtr kp; + +/* signal context record */ +typedef struct ctxt { + word ctx_A; + word ctx_X; + word ctx_Y; + word ctx_state; + word ctx_D; + byte ctx_B; + byte ctx_B1; + word ctx_P; + word ctx_S1; + longword ctx_PC; +} ctxt, *ctxtPtr; + +struct GSString1K { + Word length; /* Number of Chars in text field */ + char text[1024]; +} ; +typedef struct GSString1K GSString1K, *GSString1KPtr; + +struct ResultBuf1K { + Word bufSize; + GSString1K bufString; +} ; +typedef struct ResultBuf1K ResultBuf1K, *ResultBuf1KPtr; + +/* + this is the info kept per-process on what sorts of shit the process + expects for I/O. This is similar to a special case of user.h fd table + including only the stdin/stdout fds (0-2). +*/ + +typedef struct ttyinf { + word InANDMask; + word InORMask; + word OutANDMask; + word OutORMask; + word ErrANDMask; + word ErrORMask; + word InDeviceType; + word OutDeviceType; + word ErrDeviceType; + longword InSlot; + longword OutSlot; + longword ErrSlot; + word dummy; +} ttyinf; + +#define NPGRP 32 + +pgrp pgrpInfo[NPGRP]; +typedef struct ttyInfo { + word pgrp; +} ttyInfo; + +extern ttyStruct; +ttyInfo *ttys = (ttyInfo *) &ttyStruct; + +#define isbadpgrp(p) ((p < 0) || (p >= NPGRP)) + +static word hiWord(longword w) +{ +word h; + + asm { + lda w+2 + sta h + } + return h; +} + +static word loWord(longword w) +{ +word l; + + asm { + lda w + sta l + } + return l; +} + +void *kmalloc(size_t size) +{ +handle h; +word p_uid; +void *x; + + /* $$$ p_uid = kp->procTable[Kgetpid()].userID; */ + p_uid = PROC->userID; + h = NewHandle(size, p_uid, 0xC008, NULL); + + if (toolerror()) { + fprintf(stderr, "kmalloc:%04X\n",toolerror()); + return NULL; + } + x = *h; + return x; +} + +void *pmalloc(size_t size, word p_uid) +{ +handle h; +void *x; + + h = NewHandle(size, p_uid, 0xC008, NULL); + + if (toolerror()) { + fprintf(stderr, "pmalloc:%04X\n",toolerror()); + return NULL; + } + x = *h; + return x; +} + +int kfree(void *mem) +{ +handle h; + + if (h = (FindHandle(mem) == NULL)) return SYSERR; + DisposeHandle(h); + return (OK); +} + +static int findEmptyProc(void) +{ +int i; + for (i = 0; i < NPROC; i++) + if (kp->procTable[i].processState == procUNUSED) return i; + return -1; +} + +#if 0 +int isbadpid( int pid ) +{ +int mpid; + + mpid = mapPID(pid); + if (mpid == -1) return SYSERR; + else return SYSOK; +} +#endif + +static int createProc(word stack, word dp, longword process) +{ +int p; + + disableps(); + /* printf("creating process stack=%04X, dp=%04X, addr=%08lX\n", + stack, dp, process); */ + p = findEmptyProc(); + if (p == -1) { enableps(); return SYSERR; } + kp->procTable[p].processState = procSUSPENDED; + kp->procTable[p].parentpid = Kgetpid(); + kp->procTable[p].irq_S = stack; + kp->procTable[p].irq_D = dp; + kp->procTable[p].irq_PC = (word) process; + kp->procTable[p].irq_B = + kp->procTable[p].irq_K = (process >> 16); + kp->procTable[p].irq_P = 4; /* interrupts must be OFF you putz */ + /* assign child same TTY as parent */ + kp->procTable[p].ttyID = PROC->ttyID; + /* $$$ kp->procTable[Kgetpid()].ttyID; */ + enableps(); + return p; +} + +#if 0 +#define BUSY_FLAG ((byte *)0xE100FFl) + +int _ready(int pid, int resch) +{ +int mpid; +unsigned x; + + mpid = mapPID(pid); + if (mpid == -1) return SYSERR; + disableps(); + if (kp->procTable[mpid].processState != procUNUSED) + kp->procTable[mpid].processState = procREADY; + if (resch) { + asm { + php + sei + } + x = *BUSY_FLAG; + *BUSY_FLAG = 0; + _resched(); + *BUSY_FLAG = x; + asm { + plp + } + } + enableps(); + return OK; +} +#endif + +/* + * Allocates a new file descriptor in this process. If the fd table is + * full, resizes the table and proceeds with the allocation. + * allocFD does NOT adjust the fdCount field, as it's possible that + * we must unallocate the fd later due to an error and it saves + * a bit of code. (i.e. the caller must inc fdCount) + */ +fdentryPtr allocFD(int *fdn) +{ +fdtablePtr ft; +int i,j; +unsigned s; + + /* $$$ ft = kp->procTable[Kgetpid()].openFiles; */ + ft = PROC->openFiles; + j = 0; /* change this when tables are dynamically allocated */ + disableps(); +retry: + while (j < ft->fdTableSize) { + if (ft->fds[j].refNum == 0) { + ft->fds[j].refNum = -1; /* just to make this item look allocated */ + enableps(); + if (fdn != NULL) *fdn = j+1; + return &(ft->fds[j]); + } else j++; + } + ft->fdTableSize += 32; + i = ft->fdTableSize; + ft = realloc(ft,sizeof(fdtable) + sizeof(fdentry)*(i-1)); + /* zero out the new entries */ + memset(&ft->fds[i-32],0,sizeof(fdentry)*32); + PROC->openFiles = ft; + goto retry; +} + +struct rc { + int rn; + int rt; + int cn; +}; + +#ifdef NOTDEFINED +void printFDS(fdtablePtr f) +{ +int i; +struct rc *r; +extern struct rc *FINDREFNUM(int,int); + + fputc('[',stderr); + for (i = 0; i < 32; i++) { + if (f->fds[i].refNum) { + fprintf(stderr,"(%d ",i); + switch (f->fds[i].refType) { + case rtGSOS: fprintf(stderr,"GSOS "); break; + case rtPIPE: fprintf(stderr,"PIPE "); break; + case rtTTY : fprintf(stderr,"TTY "); break; + default : fprintf(stderr,"%d ",f->fds[i].refType); + } + fprintf(stderr,"%d/%d ", f->fds[i].refNum,f->fds[i].refLevel); + r = FINDREFNUM(f->fds[i].refType,f->fds[i].refNum); + if (r == NULL) fprintf(stderr,"!!)"); + else fprintf(stderr,"%d)",r->cn); + } + } + fputc(']',stderr); fputc('\n',stderr); +} +#endif + +#pragma databank 1 +void endproc(void) +{ +/* + * printfs in here won't work with quiting orca/c progs because ~C_SHUTDOWN + * closes ALL open file descriptors + */ + +/* printf("end of process %d\n",Kgetpid()); */ + /* $$$ kp->procTable[Kgetpid()].flags |= FL_NORMTERM; */ + PROC->flags |= FL_NORMTERM; + /* kill(kp->procTable[Kgetpid()].flpid,9); */ + Kkill(&errno, 9, PROC->flpid); + /* not reached */ + PANIC("ENDPROC KILL OVERRUN"); +} + +int CommonQuit(char *pname, int flag) +{ +/*struct pentry *p = &kp->procTable[Kgetpid()];*/ +char *pcopy; +quitStack *qs; +GSString255Ptr gp; + + enableps(); + if (flag & 0x4000) PROC->flags |= FL_RESTART; + if (pname && *pname) { + if (flag & 0x8000) { + gp = (GSString255Ptr) LGetPathname2(PROC->userID,1); + qs = malloc(gp->length+5); + qs->next = PROC->returnStack; + memcpy(qs->data,gp->text,gp->length); + qs->data[gp->length] = 0; + PROC->returnStack = qs; + } + pcopy = kmalloc(strlen(pname)+1); + strcpy(pcopy,pname); nfree(pname); + Kexecve(&errno,pcopy,pcopy); + } + else { + if ((qs = PROC->returnStack) != NULL) { + pcopy = kmalloc(strlen(qs->data)+1); + strcpy(pcopy,qs->data); + PROC->returnStack = qs->next; nfree(qs); + Kexecve(&errno,pcopy,pcopy); + } else Kkill(&errno, 9, PROC->flpid); + } + disableps(); + return 0x27; +} + +#pragma toolparms 1 +/* subr is the address to begin the process at */ + +pascal int KERNSetGNOQuitRec(word pCount,GSString255Ptr pathname, word flags, int *ERRNO) +{ +extern QuitRecGS quitParms; + quitParms.pCount = pCount; + quitParms.pathname = pathname; + quitParms.flags = flags; +} + +int KERNgetpid() +/* get the process id of currently executing process */ +{ + /*$$$ return( kp->procTable[kp->truepid].flpid ); */ + return (PROC->flpid); +} + +int KERNgetppid(int *ERRNO) +/* get the pid of the process' parent */ +{ + return (kp->procTable[PROC->parentpid].flpid); +} + +int KERNgetpgrp(int *ERRNO, int pid) +/* get the pgrp field for a specified process */ +{ +int mpid; + mpid = mapPID(pid); + if (mpid == -1) { *ERRNO = ESRCH; return -1; } + return( kp->procTable[mpid].pgrp ); +} + +int KERNsetpgrp(int *ERRNO, int pgrp, int pid) +{ +int mpid; +int pp; + + mpid = mapPID(pid); + if (mpid == -1) { *ERRNO = ESRCH; return -1; } + if (isbadpgrp(pgrp)) { *ERRNO = ESRCH; return -1; } + if (kp->procTable[mpid].pgrp != pgrp) + { + if (pgrp != 0) pgrpInfo[pgrp-2].pgrpref++; + if ((pp = kp->procTable[mpid].pgrp) != 0) + pgrpInfo[pp-2].pgrpref--; + } + return 0; +} + +int KERNgetuid(int *ERRNO) +{ + return (PROC->p_uid); + /* $$$ return (kp->procTable[Kgetpid()].p_uid); */ +} + +int KERNgeteuid(int *ERRNO) +{ + return (PROC->p_euid); + /* $$$ return (kp->procTable[Kgetpid()].p_euid); */ +} + +int KERNgetgid(int *ERRNO) +{ + return (PROC->p_gid); + /* $$$ return (kp->procTable[Kgetpid()].p_gid); */ +} + +int KERNgetegid(int *ERRNO) +{ + return (PROC->p_egid); + /* $$$ return (kp->procTable[Kgetpid()].p_egid); */ +} + +int KERNsetreuid(int *ERRNO, int ruid, int euid) +{ + if (ruid == -1) ruid = PROC->p_uid; + if (euid == -1) euid = PROC->p_euid; + if ((PROC->p_uid != 0) && + (((euid != PROC->p_uid) && (euid != PROC->p_euid)) + || ((ruid != PROC->p_euid) && (ruid != PROC->p_uid)))) { + *ERRNO = EPERM; + return -1; + } + PROC->p_uid = ruid; + PROC->p_euid = euid; + return 0; +} + +int KERNsetuid(int *ERRNO, int uid) +{ +/* $$$ struct pentry *p; +p = &(kp->procTable[Kgetpid()]); */ + + if ((PROC->p_uid == 0) || (uid == PROC->p_uid) || (uid == PROC->p_euid)) { + PROC->p_uid = uid; + PROC->p_euid = uid; + return 0; + } + *ERRNO = EPERM; + return -1; +} + +int KERNsetregid(int *ERRNO, int rgid, int egid) +{ + if (rgid == -1) rgid = PROC->p_gid; + if (egid == -1) egid = PROC->p_egid; + if ((PROC->p_uid != 0) && + (((egid != PROC->p_gid) && (egid != PROC->p_egid)) + || ((rgid != PROC->p_egid) && (rgid != PROC->p_gid)))) { + *ERRNO = EPERM; + return -1; + } + PROC->p_gid = rgid; + PROC->p_egid = egid; + return 0; +} + +int KERNsetgid(int *ERRNO, int gid) +{ +/* $$$ struct pentry *p; +p = &(kp->procTable[Kgetpid()]); */ + + if ((PROC->p_uid == 0) || (gid == PROC->p_gid) || (gid == PROC->p_egid)) { + PROC->p_gid = gid; + PROC->p_egid = gid; + return 0; + } + *ERRNO = EPERM; + return -1; +} + +int KERNtimes(int *ERRNO, struct tms *buffer) +{ + /* $$$ buffer->tms_utime = kp->procTable[Kgetpid()].ticks; + buffer->tms_cutime = kp->procTable[Kgetpid()].childTicks; + buffer->tms_stime = buffer->tms_cstime = 0l; */ + + buffer->tms_utime = PROC->ticks; + buffer->tms_cutime = PROC->childTicks; + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + buffer->tms_stime = buffer->tms_cstime = 0l; +#else + buffer->tms_stime = 0l; buffer->tms_cstime = 0l; +#endif + + return 0; +} + +#pragma toolparms 0 +char *a_strncpy_max(char *s, word max_len) +{ +word l; +char *x; + + if (s == NULL) return NULL; + while ((l < max_len) && (s[l] != 0)) + l++; + x = malloc(l+1); + strncpy(x,s,l); + x[l] = 0; + return x; +} + +int commonFork(void (*funcptr)(), word stackSize, int prio, char *name, + word *argv, int *ERRNO) +{ +word dPageAddr, buffSize,nargs; +int newID,newPID,parentPID; +int flpid; +longword *ret; +handle fstack; +struct pentry *parent,*child; +word state; +byte statereg,slot; +int i,j,k; +extern void endproc2(void); +extern void FORKInitGlob(void); +extern void IncRefnum(int,int); +extern void incPipe(int,int); +extern int allocPID(void); + +/* printf("address = %08lX\n",subr); */ + if (kp->gsosDebug & 16) fprintf(stderr, "fork(%06lX)\n",funcptr); + newID = GetNewID(0x1000); + + fstack = NewHandle((long) stackSize,newID | 0x0100,0xC105, NULL); + if (toolerror()) { *ERRNO = ENOMEM; return -1; } + dPageAddr = (word) *fstack; + buffSize = stackSize; + + /* calculate the # of bytes of parameters */ + nargs = (*argv) * 2; + ret = (longword *) (dPageAddr+buffSize-4-nargs); + /* place this first, or it'll clobber some parameters */ + *ret = ((longword) endproc2)-1; /* go to endproc when process is done */ + + /* if they're passing in params, copy them to the target stack */ + if (nargs) + memcpy( (((byte *) ret)+3), argv+1, nargs); + + disableps(); + newPID = createProc(dPageAddr+buffSize-5-nargs,dPageAddr, (longword) funcptr); + if (newPID == SYSERR) { + *ERRNO = EAGAIN; DisposeHandle(fstack); + enableps(); return -1; + } + child = &(kp->procTable[newPID]); + parent = PROC; /* $$$ &(kp->procTable[Kgetpid()]); */ + + child->parentpid = Kgetpid(); + child->irq_A = newID; + child->irq_X = + child->irq_Y = 0; + child->userID = newID; + if (name != NULL) { + name = a_strncpy_max(name,128); + child->args = malloc(strlen(name)+9); + strcpy(child->args,"BYTEWRKS"); + strcat(child->args,name); + nfree(name); + } else child->args = NULL; + +/* make sure we keep the pgrp refcount up to date */ + child->pgrp = parent->pgrp; + if (child->pgrp != 0) pgrpInfo[child->pgrp-2].pgrpref++; + + child->siginfo = malloc(sizeof(struct sigrec)); + memcpy(child->siginfo, parent->siginfo, sizeof(struct sigrec)); + child->waitq = NULL; + + i = sizeof(fdentry)*(parent->openFiles->fdTableSize-1); + child->openFiles = malloc(sizeof(fdtable)+i); + memcpy(child->openFiles, parent->openFiles, sizeof(fdtable)+i); + + child->prefix = malloc(33*sizeof(GSString255Ptr)); + for (i = 0; i < 33; i++) { + if (parent->prefix[i] != NULL) { + child->prefix[i] = + malloc( ((GSString255Ptr) parent->prefix[i])->length+2 ); + copygsstr(child->prefix[i],parent->prefix[i]); + } else child->prefix[i] = NULL; + } + + child->LInfo = parent->LInfo; + child->ticks = 0l; + child->childTicks = 0l; + child->flags = FL_FORKED | FL_COMPLIANT; + child->ttyID = parent->ttyID; + child->executeHook = parent->executeHook; + child->returnStack = NULL; + child->p_uid = parent->p_uid; + child->p_gid = parent->p_gid; + child->p_euid = parent->p_euid; + child->p_egid = parent->p_egid; + child->SANEwap = parent->SANEwap; + child->lastTool = parent->lastTool; /* actually the resource app number */ + asm { + lda 0xE0C035 + sta state + sep #0x30 + lda 0xE0C02D + sta slot + lda 0xE0C068 + sta statereg + rep #0x30 + } + child->irq_state = state; + child->irq_SLTROM = slot; + child->irq_STATEREG = statereg; + child->alarmCount = 0l; + child->t2StackPtr = 0; + child->processState = procNEW; /* brand new! */ + + parentPID = Kgetpid(); + asm { + ldy newPID + ldx parentPID + jsl FORKInitGlob + } + +/* make sure the system knows about all of our new copies of those + file descriptors we inherited */ + + i = child->openFiles->fdCount; k = 0; + while (i) { + if (j = child->openFiles->fds[k].refNum) { + if (child->openFiles->fds[k].refType == rtPIPE) + incPipe(child->openFiles->fds[k].refFlags,j); + IncRefnum(child->openFiles->fds[k].refType,j); + i--; + } + k++; + if (k > child->openFiles->fdTableSize) + PANIC("BAD FILE DESCRIPTOR TABLE"); + } + + child->flpid = allocPID(); + kp->numProcs++; + enableps(); + return child->flpid; +} + +#pragma toolparms 1 + +int KERNfork(int *ERRNO,void *subr) +{ +word nargs = 0; + + return commonFork((void *)subr, 1024, 0, NULL, &nargs, ERRNO); +} + +pascal int KERNfork2(void (*funcptr)(), word stackSize, int prio, + char *name, word *argv, int *ERRNO) +{ + return commonFork(funcptr, stackSize, prio, name, argv, ERRNO); +} + + +typedef struct GetUserPathRec { + int pCount; + int fileSysID; + int commandNum; + GSString255Ptr prefixPtr; +} GetUserPathRec; + +/* + * This MUST be in a function by itself so the PROC-> dereference will have + * an allocated DP to use. + */ +static void kill_self(void) +{ + Kkill(&errno, 9, PROC->flpid); +} + +int KERNexecve(int *ERRNO, char *cmdline, char *filename) +{ +union { + InitialLoadOutputRec il; + RestartOutRec r; +} il_out; +#define il_rec il_out.il +#define r_rec il_out.r +int e; +word newID; +GSString255Ptr pfn; +ResultBuf1KPtr resBuf; +int ind; +longword *ret; +handle fstack; +int *optionList; +char **ourPFhand; +char *args,*argscopy; +int i,j; +struct pentry *p; +ExpandPathRecGS ep; +PrefixRecGS sp; +FileInfoRecGS fi; +int ssf = 0,restart,force_norest = 0; +word oldUserID, oldFlags, newStack; +extern ctxt ctxtstuff; +extern GSString255Ptr __C2GSMALLOC(char *); +extern void endproc2(void); +extern void execveHook(void); +extern void disableBuf(void); +extern void enableBuf(void); + +/* always disableps() when screwing with process tables */ + disableps(); + if (kp->gsosDebug & 16) fprintf(stderr,"execve(%s,%s)\n",filename,cmdline); + + p = PROC; /* $$$ &(kp->procTable[Kgetpid()]);*//* aaaaaaaaaaarrrgghhh!!!!! */ + +/* Don't do anything with the file tables- we simply pass them on to the + new process */ + +/* turn the input path into a GSString255 */ + pfn = __C2GSMALLOC(filename); + +/* do an ExpandPath on the input path */ + resBuf = malloc(sizeof(ResultBuf1K)); + ep.pCount = 2; + ep.inputPath = pfn; + resBuf->bufSize = 1024; + ep.outputPath = (ResultBuf255Ptr) resBuf; + ExpandPathGS(&ep); + + restart = 1; + newID = GetUserID2((Pointer)&resBuf->bufString); + if (toolerror() == 0x1101) { + /* allocate a new UserID for the program */ + newID = GetNewID(0x1000); + restart = 0; + } else { +/* if the 'newID' is being used by a process, force another copy from disk */ + for (i = 0; i < NPROC; i++) { + if (kp->procTable[i].processState != procUNUSED) + if (kp->procTable[i].userID == newID) { + newID = GetNewID(0x1000); + restart = 0; force_norest = 1; + break; + } + } + } + + if (restart) { + r_rec = Restart(newID); + } else { + il_rec = InitialLoad2(newID, (Pointer)&resBuf->bufString, 1, 1); + } + if ((e = toolerror())) { + switch(e) { + case volNotFound: + case pathNotFound: + case fileNotFound: + *ERRNO = ENOENT; + break; + default: + *ERRNO = EIO; + break; + } + nfree(resBuf); + enableps(); + return -1; + } + +/* get info about the executable so we know how to set up the environment */ + optionList = malloc(48l); /* should be large enough for everything */ + fi.pCount = 8; + fi.pathname = (GSString255Ptr) &(resBuf->bufString); + fi.optionList = (void *) optionList; + optionList[0] = 48; + GetFileInfoGS(&fi); + +/* if the executable had no defined stack segment, create 1K by default */ + if (il_rec.buffSize == 0) { /* no stack/dp segment- create one */ + fstack = NewHandle(4096l,newID,0xC015, NULL); + il_rec.dPageAddr = (word) *fstack; + il_rec.buffSize = 4096; + } + +/* S16s (and others) get no command line arguments, but we should put + their name in the process table anyway */ + + if (cmdline != NULL) { + size_t len = strlen(cmdline)+11; + /* build the command line by tacking the shellid() onto the real + line */ + args = (char *) malloc(len); + strcpy(args,"BYTEWRKS"); + strcat(args, cmdline); + args[((word)(len-1))] = 0; /* Orca 2.0 does this for compat */ + argscopy = pmalloc(len,newID); + memcpy(argscopy,args,len); + } else args = argscopy = NULL; + +/* tricky- shove the address of our generic RTL-exiting shutdown routine + onto the process stack so we can always keep track of processes */ + ret = (longword *) (il_rec.dPageAddr+il_rec.buffSize-4); + *ret = ((longword) endproc2)-1; /* go to endproc when process is done */ + +/* set up the registers to point to the command line/shell id combo */ + if (p->args) nfree(p->args); /* free the args string of the old executable */ + p->args = args; + if (fi.fileType != 0xB5) argscopy = NULL; + ctxtstuff.ctx_A = newID; + ctxtstuff.ctx_X = hiWord((longword) argscopy); + ctxtstuff.ctx_Y = loWord((longword) argscopy); + newStack = ctxtstuff.ctx_S1 = il_rec.dPageAddr+il_rec.buffSize-5; + ctxtstuff.ctx_D = il_rec.dPageAddr; + ctxtstuff.ctx_B = ctxtstuff.ctx_B1 = (((longword) il_rec.startAddr) >> 16); + ctxtstuff.ctx_PC = (longword) il_rec.startAddr; + + oldUserID = p->userID; + oldFlags = p->flags; + p->userID = newID; + p->ticks = 0l; + p->flags = FL_COMPLIANT; + if (force_norest) p->flags |= FL_NORESTART; + p->SANEwap = 0; /* reset to the 'not started up' state */ + p->lastTool = 0x401E; /* reset res app to standard */ + + /* is program compliant? */ + if (fi.auxType == 0xDC00l) { + p->flags &= (~FL_COMPLIANT); /* turn off compliance flag */ + disableBuf(); /* disablebuf now turns off the cursor */ + } + +/* + * Set up the prefixes for the new process image + */ + + /* modify prefixes 1 and 9 to point to the directory the appl. is in */ + ourPFhand = PROC->prefix; /* $$$ kp->procTable[Kgetpid()].prefix; */ + nfree(ourPFhand[0]); /* the '@' prefix */ + nfree(ourPFhand[1+1]); nfree(ourPFhand[9+1]); + + /* set Prefixes 1 and 9 to the directory the executable is in */ + for (ind = resBuf->bufString.length-1; ind > 0; ind--) + if (resBuf->bufString.text[ind] == ':') { + resBuf->bufString.length = ind+1; break; /* +1 -> snag the colon */ + } /* there will always be one */ + + ourPFhand[9+1] = malloc(resBuf->bufString.length+2); + copygsstr(ourPFhand[9+1],&resBuf->bufString); + if (optionList[2] == 0x0D) { /* app is on AppleShare volume - set '@' */ + GetUserPathRec gp; + gp.pCount = 3; gp.fileSysID = 0x0D; gp.commandNum = 8; + FSTSpecific(&gp); + ourPFhand[0] = malloc(gp.prefixPtr->length+3); + copygsstr(ourPFhand[0],gp.prefixPtr); + ourPFhand[0][gp.prefixPtr->length+2] = ':'; + ((GSString255Ptr)ourPFhand[0])->length++; + } else { + ourPFhand[0] = malloc(resBuf->bufString.length+2); + copygsstr(ourPFhand[0],&resBuf->bufString); + } + + /* if prefix 1 would be longer than 64 chars, set it to the NULL prefix */ + if (resBuf->bufString.length > 64) resBuf->bufString.length = 0; + ourPFhand[2] = malloc(resBuf->bufString.length+2); + copygsstr(ourPFhand[2],&resBuf->bufString); + + nfree(pfn); + nfree(resBuf); + nfree(optionList); + + /* If we're launching a S16 application, copy prefix 0 to prefix 8 */ + if (fi.fileType == 0xB3) { + pfn = (GSString255Ptr) ourPFhand[0+1]; + pfn = malloc(pfn->length+2); + copygsstr(pfn,ourPFhand[0+1]); + nfree(ourPFhand[8+1]); + ourPFhand[8+1] = (char *)pfn; + } + +/* Ignored/blocked signals remain ignored/blocked, but caught signals + are reset to their default state */ + for (i = 0; i < 32; i++) { + if (p->siginfo->v_signal[i] != SIG_IGN) + p->siginfo->v_signal[i] = SIG_DFL; + } + + SET_STOP_FLAG(&ssf); + + if (!(oldFlags & FL_COMPLIANT)) { + enableBuf(); + } + if ((fi.auxType & 0xDB02) != 0xDB02) + if (oldFlags & FL_QDSTARTUP) *((byte *)0xE0C029l) &= 0x7F; +/* switch over to the new stack before we deallocate the one we're using */ + asm { + lda newStack + tcs + } + if ((fi.auxType == 0xDC00) && (p->ttyID != 3)) { + fprintf(stderr, "Program can only run on console.\n"); + if (oldFlags & FL_FORKED) { + DisposeAll(oldUserID); /* process was fork()ed, don't USD */ + DeleteID(oldUserID); + } else { + UserShutDown(oldUserID, + ((oldFlags & FL_RESTART) && !(oldFlags & FL_NORESTART)) ? 0x4000 : 0); + } + /* don't use any local variables beyond this point */ + /* STACK REPAIR MUST BE OFF TO CALL kill_self() */ + kill_self(); + /* not reached */ + PANIC("EXECVE KILL OVERRUN"); + } else { + if (oldFlags & FL_FORKED) { + DisposeAll(oldUserID); /* process was fork()ed, don't USD */ + DeleteID(oldUserID); + } else { + UserShutDown(oldUserID, + ((oldFlags & FL_RESTART) && !(oldFlags & FL_NORESTART)) ? 0x4000 : 0); + } + /* don't use any local variables beyond this point */ + } + asm { + jmp >execveHook + } +} + +/* open the kernel to access the process structures */ + +kvmt *KERNkvm_open(int *ERRNO) +{ +kvmt *newk; + + newk = (kvmt *) kmalloc(sizeof(kvmt)); + if (newk == NULL) { *ERRNO = ENOMEM; return NULL;} + Kkvmsetproc(ERRNO, newk); + return newk; +} + +SYSCALL KERNkvm_close(int *ERRNO,kvmt *k) +{ + if (kfree(k)) return SYSERR; + return (OK); +} + +struct pentry *KERNkvmgetproc(int *ERRNO, int pid, kvmt *kd) +{ +int mpid; + mpid = mapPID(pid); + if (mpid == -1) { *ERRNO = ESRCH; return NULL; } + memcpy(&(kd->kvm_pent), &(kp->procTable[mpid]), sizeof(struct pentry)); + kd->pid = pid; + kd->kvm_pent.parentpid = kp->procTable[kp->procTable[mpid].parentpid].flpid; + return &(kd->kvm_pent); +} + +struct pentry *KERNkvmnextproc(int *ERRNO, kvmt *kd) +{ +int i; +int mpid; + + if (kd->procIndex < NPROC) + { + memcpy(&(kd->kvm_pent), &(kp->procTable[kd->procIndex]), + sizeof(struct pentry)); + kd->pid = kd->kvm_pent.flpid; + mpid = mapPID(kd->pid); + kd->kvm_pent.parentpid = + kp->procTable[kp->procTable[mpid].parentpid].flpid; + i = kd->procIndex+1; + while ((i < NPROC) && (kp->procTable[i].processState == procUNUSED)) + i++; + kd->procIndex = i; + return &kd->kvm_pent; + } + else return NULL; +} + +int KERNkvmsetproc(int *ERRNO,kvmt *kd) +{ +int i; + + for (i = 0; i < NPROC; i++) + if (kp->procTable[i].processState != procUNUSED) { + kd->procIndex = i; + return OK; + } + return SYSERR; +} + +int KERNtcnewpgrp(int *ERRNO, int fdtty) +{ +unsigned i,devNum,ttyPgrp; +fdentryPtr tty; +extern fdentryPtr getFDptr(int); + + tty = getFDptr(fdtty); + if ((tty == NULL) || (tty->refNum == 0)) { *ERRNO = EBADF; return -1; } + if (tty->refType != rtTTY) { *ERRNO = ENOTTY; return -1; } + devNum = tty->refNum-1; + disableps(); + + for (i = 0; i < NPGRP; i++) + if (!pgrpInfo[i].pgrpref) break; + + if (i == NPGRP) { enableps(); return -1; } + + /* we're leaving a PTY, decrement the refcount */ + if (ttyPgrp = ttys[devNum].pgrp) + pgrpInfo[ttyPgrp-2].pgrpref--; + if (kp->gsosDebug & 16) + fprintf(stderr, "tcnewpgrp- TTY:%d pgrp:%d\n",devNum,i+2); + ttys[devNum].pgrp = i+2; + pgrpInfo[i].pgrpref++; + enableps(); + return 0; +} + +int KERNsettpgrp(int *ERRNO, int fdtty) +{ +int p,pid = Kgetpid(); +int pp,devNum; +fdentryPtr tty; +extern fdentryPtr getFDptr(int); + + tty = getFDptr(fdtty); + if ((tty == NULL) || (tty->refNum == 0)) { *ERRNO = EBADF; return -1; } + if (tty->refType != rtTTY) { *ERRNO = ENOTTY; return -1; } + devNum = tty->refNum-1; + p = ttys[devNum].pgrp; + if (kp->gsosDebug & 16) + fprintf(stderr, "settpgrp pid: %d, oldpgrp: %d, ", + PROC->flpid, PROC->pgrp); + /* $$$ kp->procTable[pid].flpid, + kp->procTable[pid].pgrp); */ + + disableps(); +/* $$$ if (kp->procTable[pid].pgrp != p) */ + if (PROC->pgrp != p) + { + if (p != 0) pgrpInfo[p-2].pgrpref++; +/* $$$ if ((pp = kp->procTable[pid].pgrp) != 0) */ + if ((pp = PROC->pgrp) != 0) + pgrpInfo[pp-2].pgrpref--; + } + if (kp->gsosDebug & 16) fprintf(stderr,"newpgrp: %d\n",p); + /* $$$ kp->procTable[pid].pgrp = p; */ + PROC->pgrp = p; + enableps(); +} + +int KERNtctpgrp(int *ERRNO, int pid, int fdtty) +{ +int p,mpid,devNum; +fdentryPtr tty; +extern fdentryPtr getFDptr(int); + + /* should check pid to be sure it's == getpid or a child of it */ + mpid = mapPID(pid); + if (mpid == -1) { *ERRNO = ESRCH; return -1; } +/* + if (!((mpid == Kgetpid()) || (kp->procTable[mpid].parentpid == Kgetpid()))) + { *ERRNO = ERANGE; return -1; } +*/ + tty = getFDptr(fdtty); + if ((tty == NULL) || (tty->refNum == 0)) { *ERRNO = EBADF; return -1; } + devNum = tty->refNum-1; + if (tty->refType != rtTTY) { *ERRNO = ENOTTY; return -1; } + disableps(); + p = kp->procTable[mpid].pgrp; + if (p != ttys[devNum].pgrp) { + if (p != 0) pgrpInfo[p-2].pgrpref++; + if (ttys[devNum].pgrp != 0) + pgrpInfo[ttys[devNum].pgrp-2].pgrpref--; + } + if (kp->gsosDebug & 16) + fprintf(stderr,"tctpgrp TTY:%d pid:%d pgrp:%d\n",devNum,pid,p); + ttys[devNum].pgrp = p; + enableps(); +} + +int KERNsetdebug(int code) +{ +int old; + + if (kp->gsosDebug & 16) fprintf(stderr,"setdebug %d\n",code); + if ((code < 0) || (code > 63)) return SYSERR; + old = kp->gsosDebug; + kp->gsosDebug = code; + return old; +} + +void *KERNsetsystemvector(void * execvec) +{ +void *x; + x = PROC->executeHook; + PROC->executeHook = execvec; + + /* $$$ x = kp->procTable[Kgetpid()].executeHook; + kp->procTable[Kgetpid()].executeHook = execvec; */ + return x; +} + +#ifdef NOTDEFINED +struct pipest { + handle bufferH; /* the pipe data handle */ + word in; /* write pointer */ + word out; /* read pointer */ + word qflags; + word RrnCount; /* Why? Because special stuff has to */ + word WrnCount; /* happen in strange conditions */ + + int accessSem; + int readSem; + int writeSem; + int writeStatus; +} +#endif + +/* filedes[0] is read only, filedes[1] is write only */ +int KERNpipe(int *ERRNO, int filedes[2]) +{ +fdentryPtr pread,pwrite; +int fdread,fdwrite; +fdtablePtr ft; +int pipen; +extern int newPipe(void); + + if (kp->gsosDebug & 16) printf("pipe(%06lX)\n",filedes); + /* $$$ ft = kp->procTable[Kgetpid()].openFiles; */ + pipen = newPipe(); + pread = allocFD(&fdread); + if (pread == NULL) { *ERRNO = EMFILE; disposePipe(pipen); return -1; } + pwrite = allocFD(&fdwrite); + ft = PROC->openFiles; /* deref pointer after calls to allocFD */ + if (pwrite == NULL) { + pread->refNum = 0; /* deallocate the read file descriptor */ + *ERRNO = EMFILE; + disposePipe(pipen); + return -1; + } + disableps(); + filedes[0] = fdread; filedes[1] = fdwrite; + /* a->i1 = a->i2 = b BROKEN in C 2.0.3 */ +#if 0 + pread->refNum = pwrite->refNum = pipen; + pread->refType = pwrite->refType = rtPIPE; + pread->refLevel = pwrite->refLevel = ft->fdLevel | ft->fdLevelMode; + pwrite->NLenableMask = pread->NLenableMask = 0; +#else + pread->refNum = pipen; pwrite->refNum = pipen; + pread->refType = rtPIPE; pwrite->refType = rtPIPE; + pwrite->refLevel = ft->fdLevel | ft->fdLevelMode; + pread->refLevel = pwrite->refLevel; + pwrite->NLenableMask = 0; pread->NLenableMask = 0; +#endif + pread->refFlags = rfPIPEREAD; + pwrite->refFlags = rfPIPEWRITE; + + AddRefnum(rtPIPE,pipen); + IncRefnum(rtPIPE,pipen); + ft->fdCount += 2; /* we opened two new files */ + enableps(); + return 0; +} + +int KERNdup(int *ERRNO, int filedes) +{ +/* $$$ struct pentry *p; */ +fdtablePtr ft; +fdentryPtr newFD,oldFD; +int nfd; +int i,j,fd; +extern void IncRefnum(int,int); + + disableps(); + /* $$$ p = &(kp->procTable[Kgetpid()]); */ + fd = filedes-1; + ft = PROC->openFiles; + if ((filedes < 1) || (filedes > 32) || + (ft->fds[fd].refNum == 0)) { + *ERRNO = EBADF; + enableps(); + return -1; + } + + newFD = allocFD(&nfd); + ft = PROC->openFiles; + if (newFD == NULL) { *ERRNO = EMFILE; enableps(); return -1; } + oldFD = &(ft->fds[fd]); + memcpy(newFD,oldFD,sizeof(fdentry)); + IncRefnum(newFD->refType,newFD->refNum); + if (newFD->refType == rtPIPE) + incPipe(newFD->refFlags,newFD->refNum); + ft->fdCount++; /* we created a new one... */ + enableps(); + return nfd; +} + +int KERNdup2(int *ERRNO, int filedes2, int filedes) +{ +/* $$$ struct pentry *p; */ +fdtablePtr ft; +fdentryPtr newFD,oldFD; +int i,j,fd,fd2; +extern void IncRefnum(int,int); +int cl[2]; + + disableps(); + /* $$$ p = &(kp->procTable[Kgetpid()]); */ + ft = PROC->openFiles; + fd = filedes-1; fd2 = filedes2-1; + newFD = &(ft->fds[fd2]); oldFD = &(ft->fds[fd]); + if ((filedes < 1) || (filedes2 < 1) || (filedes > 32) || (filedes2 > 32) || + (oldFD->refNum == 0)) { + *ERRNO = EBADF; + enableps(); + return -1; + } + /* if they're duping a file to itself, pretend we did it */ + if (fd == fd2) { + enableps(); return 0; + } + if (newFD->refNum) { + cl[0] = 1; cl[1] = filedes2; + CloseGS(cl); + } + memcpy(newFD,oldFD,sizeof(fdentry)); + IncRefnum(newFD->refType,newFD->refNum); + if (newFD->refType == rtPIPE) + incPipe(newFD->refFlags,newFD->refNum); + ft->fdCount++; /* we created a new one... */ + enableps(); + return 0; +} + +#pragma databank 0 +#pragma toolparms 0 + diff --git a/kern/gno/sys.h b/kern/gno/sys.h new file mode 100644 index 0000000..a0782f5 --- /dev/null +++ b/kern/gno/sys.h @@ -0,0 +1,20 @@ +/* $Id: sys.h,v 1.1 1998/02/02 08:19:10 taubert Exp $ */ + +#if 0 +int createProc(word stack, word dp, longword process); +int _ready(int pid, int resch); +int isbadpid( int pid ); +/*void *mmemcpy(const void *dest, void *src, size_t len); */ +#endif +#define Kgetpid() kp->truepid + +typedef struct pgrp { + word pgrpref; /* number of references to this pgrp - tty and process */ +} pgrp; + +fdentryPtr allocFD(int *fdn); +void copygsstr(void *,void*); +void nfree(void *); + +#define PROC procPtr +extern struct pentry *procPtr; diff --git a/kern/gno/texttool.asm b/kern/gno/texttool.asm new file mode 100644 index 0000000..b090056 --- /dev/null +++ b/kern/gno/texttool.asm @@ -0,0 +1,2428 @@ +* $Id: texttool.asm,v 1.1 1998/02/02 08:19:50 taubert Exp $ +************************************************************************** +* +* The GNO Multitasking Environment Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* +************************************************************************** +* +* TEXTTOOL.ASM +* By Tim Meekins +* and Jawaid Bazyar +* GNO replacement for TextTools toolset +* Supports redirection, pipes, and loadable drivers +* +* Copyright 1991, Jawaid Bazyar +* +************************************************************************** + + case on + mcopy m/texttool.mac + copy global.equates + copy ../drivers/console.equates + +;========================================================================= +; +; Text Tool Data +; +;========================================================================= + +IgnoreInfo DATA +ignSetInDev dc i2'0' +ignSetInGlo dc i2'0' +ignSetOutDev dc i2'0' +ignSetOutGlo dc i2'0' +ignSetErrDev dc i2'0' +ignSetErrGlo dc i2'0' + END + +TextToolsInfo DATA +InANDMask dc i2'$FF' +InORMask dc i2'$80' +OutANDMask dc i2'$FF' +OutORMask dc i2'$80' +ErrANDMask dc i2'$FF' +ErrORMask dc i2'$80' +InDeviceType dc i2'1' +OutDeviceType dc i2'1' +ErrDeviceType dc i2'1' +InSlot dc i4'3' +OutSlot dc i4'3' +ErrSlot dc i4'3' +ProcessGroup dc i2'0' ; that's 64 bytes to you and me +stateFlags dc i2'0' ; info on CR/LF removal, plus ? +InVect dc i4'0' +OutVect dc i4'0' +ErrVect dc i4'0' + +InCache dc i4'0' ; stderr need not be cached +OutCache dc i4'0' + dc 5i2'0' + ds 64*(NPROC-1) ; space for other processes + END + +* Table of Installed TextTools Drivers + +ReadDDTab DATA + dc i4'0' ; null device + dc i4'sl1Read-1' ; [serial 1] + dc i4'sl2Read-1' ; [serial 2] + dc i4'0' ; console driver (COUT/KEYIN) + dc i4'NullIn-1' ; + dc i4'NullIn-1' ; + dc i4'NullIn-1' ; + dc i4'NullIn-1' ; + END +WriteDDTab DATA + dc i4'0' ; null device + dc i4'sl1Write-1' ; [serial 1] + dc i4'sl2Write-1' ; [serial 2] + dc i4'0' ; console driver (COUT/KEYIN) + dc i4'NullOut-1' ; + dc i4'NullOut-1' ; + dc i4'NullOut-1' ; + dc i4'NullOut-1' ; + END +InitDDTab DATA + dc i4'NullInit-1' ; null device + dc i4'sl1Init-1' ; [serial 1] + dc i4'sl2Init-1' ; [serial 2] + dc i4'C80Init-1' ; console driver (COUT/KEYIN) + dc i4'NullInit-1' ; + dc i4'NullInit-1' ; + dc i4'NullInit-1' ; + dc i4'NullInit-1' ; + END +StatusDDTab DATA + dc i4'NullStatus-1' + dc i4'sl1Status-1' ; [serial 1] + dc i4'sl2Status-1' + dc i4'NullStatus-1' + dc i4'NullStatus-1' + dc i4'NullStatus-1' + dc i4'NullStatus-1' + dc i4'NullStatus-1' + dc i4'NullStatus-1' + + END + +NotDone gequ 1 ; NULL entries are copied from old table + +TTtable DATA + dc i4'(TheEnd-TTtable)/4' + + dc i4'NewTextBootInit-1' ; $010C + dc i4'NewTextStartUp-1' ; $020C + dc i4'NewTextShutDown-1' ; $030C + dc i4'NotDone-1' ; $040C + dc i4'NewTextStartUp-1' ; $050C + dc i4'NotDone-1' ; $060C + + dc i4'NotDone-1' ; + dc i4'NotDone-1' ; + + dc i4'NewSetInGlob-1' ; $090C SetInGlobals + dc i4'NewSetOutGlob-1' ; $0A0C SetOutGlobals + dc i4'NewSetErrGlob-1' ; $0B0C SetErrGlobals + + dc i4'NewGetInGlob-1' ; $0C0C GetInGlobals + dc i4'NewGetOutGlob-1' ; $0D0C GetOutGlobals + dc i4'NewGetErrGlob-1' ; $0E0C GetErrGlobals + + dc i4'NewSetInDevice-1' ; $0F0C SetInputDevice + dc i4'NewSetOutDevice-1' ; $100C SetOutputDevice + dc i4'NewSetErrDevice-1' ; $110C SetErrorDevice + + dc i4'NewGetInDevice-1' ; $120C GetInputDevice + dc i4'NewGetOutDevice-1' ; $130C GetOutputDevice + dc i4'NewGetErrDevice-1' ; $140C GetErrorDevice + + dc i4'NewInitText-1' ; $150C InitTextDev + dc i4'NotDone-1' ; $160C CtlTextDev + dc i4'NewStatusDev-1' ; $170C StatusTextDev + + dc i4'NewWriteChar-1' ; $180C + dc i4'NewErrWriteChar-1' ; $190C + dc i4'NewWriteLine-1' ; $1A0C + dc i4'NewErrWriteLine-1' ; $1B0C + dc i4'NewWriteString-1' ; $1C0C + dc i4'NewErrWriteString-1' ; $1D0C + dc i4'NewTextWriteBlock-1' ; $1E0C + dc i4'NewErrWriteBlock-1' ; $1F0C + dc i4'NewWriteCString-1' ; $200C + dc i4'NewErrWriteCString-1' ; $210C + dc i4'NewReadChar-1' ; $220C + dc i4'NewTextReadBlock-1' ; $230C + dc i4'NewReadLine-1' ; $240C +TheEnd anop + END + + +;========================================================================= +; +; Patch the text tool set +; +;========================================================================= + +PatchText START + using ReadDDTab + using WriteDDTab + + pushlong #0 + pushword #$0000 + pushword #$000C + _GetTSPtr + bcc ok + jmp done + +ok pulllong >oldTextTT + + pushword #$0000 ; system tool set + pushword #$0C ; texttools + pushlong #TTtable ; thar she blows + _SetTSPtr + + movelong #KEYIN-1,ReadDDTab+12 + movelong #COUT-1,WriteDDTab+12 + movelong #NullIn-1,ReadDDTab+0 + movelong #NullOut-1,WriteDDTab+0 + ldx #0 ; null process + jsr InitGlobals + +done anop + rts +oldTextTT ENTRY + dc i4'0' + END + +;========================================================================= +; +; UnPatch the text tool set +; +;========================================================================= + +UnPatchText START + + pushword #$0000 + pushword #$000C + pushlong >oldTextTT + _SetTSPtr + + rts + END + +* We want this to do NOTHING... +NewTextBootInit START + lda #0 + clc + rtl + END + +NewTextStartUp START + using KernelStruct +* phd +* phb +* phk +* plb +* lda >truepid +* xba +* lsr a +* lsr a +* tax +* jsr InitGlobals +* plb + phd + jmp bye0 + END + +NewTextShutDown START + phd + jmp bye0 + END + +; FORKInitGlob +; KERNfork() jsl's this routine. x is source pid, y is destination pid. +; copies all the TextTools info from parent to child (source to dest) + +FORKInitGlob START + using TextToolsInfo + + phb + phk + plb + + tya + xba + lsr a + lsr a + tay + phy + + txa + xba + lsr a + lsr a + tax + lda #32 + sta left +cpTInfo anop + lda TextToolsInfo,x + sta TextToolsInfo,y + inx + inx + iny + iny + dec left + bne cpTInfo + ply + lda #0 + sta stateFlags,y + + plb + rtl +left dc i2'0' + END + +InitGlobals START + using TextToolsInfo + + phx + pea $00FF + pea $0000 + _SetInGlobals + pea $00FF + pea $0000 + _SetOutGlobals + pea $00FF + pea $0000 + _SetErrGlobals + + pea $0001 + ph4 #3 + _SetInputDevice + pea $0001 + ph4 #3 + _SetOutputDevice + pea $0001 + ph4 #3 + _SetErrorDevice + plx + + lda #0 + sta stateFlags,x + rts + END + +NewInitText START + using TextToolsInfo + using KernelStruct + using InOutData + +dev equ 10 + + phd + lda >InOutDP + tcd + + phb + phk + plb + + lda truepid + xba + lsr a + lsr a + tax + lda dev,s + beq doit + inx + inx + cmp #1 + beq doit + inx + inx +doit anop + lda InDeviceType,x + cmp #1 + bne nodice + + lda truepid + xba + lsr a + lsr a + tax + lda dev,s + beq doit2 + inx2 + inx2 + cmp #1 + beq doit2 + inx2 + inx2 +doit2 anop + lda InSlot,x + asl a + asl a + tax + + push3 #nodice-1 + short m + lda InitDDTab+2,x + pha + long m + lda InitDDTab,x + pha + rtl + +nodice plb + jmp bye2 + END + +NewStatusDev START + using TextToolsInfo + using KernelStruct + using InOutData + +dev equ 12 +req equ 10 + + phd + lda >InOutDP + tcd + + phb + phk + plb + + lda truepid + xba + lsr a + lsr a + tax + lda dev,s + beq doit + inx + inx + cmp #1 + beq doit + inx + inx +doit anop + lda InDeviceType,x + cmp #1 + bne nodice + + lda truepid + xba + lsr a + lsr a + tax + lda dev,s + beq doit2 + inx2 + inx2 + cmp #1 + beq doit2 + inx2 + inx2 +doit2 anop + lda req,s + tay + lda InSlot,x + asl a + asl a + tax + + push3 #retadr-1 + short m + lda StatusDDTab+2,x + pha + long m + lda StatusDDTab,x + pha + tya + rtl +retadr ldx #0 + bcs nodice + ldx #$0C40 +nodice plb + pld + ldy #4 + jmp tool_exit + END + +NewGetOutDevice START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda OutSlot,x + sta 7+1,s + lda OutSlot+2,x + sta 7+1+2,s + lda OutDeviceType,x + sta 7+1+4,s + plb + phd ;ack!! + jmp bye0 + + END + +NewGetInDevice START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda InSlot,x + sta 7+1,s + lda InSlot+2,x + sta 7+1+2,s + lda InDeviceType,x + sta 7+1+4,s + plb + phd ;ack!! + jmp bye0 + + END + +NewGetErrDevice START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda ErrSlot,x + sta 7+1,s + lda ErrSlot+2,x + sta 7+1+2,s + lda ErrDeviceType,x + sta 7+1+4,s + plb + phd ;ack!! + jmp bye0 + + END + +* Device numbers +* 0-1: Pascal +* 2: RAM-based +* 3: file redirection +* 4: pipe + +NewSetOutDevice START + using IgnoreInfo + using TextToolsInfo + using KernelStruct + + phb + phk + plb + lda ignSetOutDev + beq noign + stz ignSetOutDev + bra outta +noign anop + + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+1,s + sta OutSlot,x + lda 7+1+2,s + sta OutSlot+2,x + lda 7+1+4,s + sta OutDeviceType,x + cmp #2 + bcc setPascal + beq setRAM + cmp #3 + beq setFile + lda #pipeOUT-1 + sta OutVect,x + lda #^pipeOUT-1 + sta OutVect+2,x + bra outta +setFile anop + lda #fileOUT-1 + sta OutVect,x + lda #^fileOUT-1 + sta OutVect+2,x + bra outta +setPascal lda OutSlot,x + asl a + asl a + tay + lda WriteDDTab,y + sta OutVect,x + lda WriteDDTab+2,y + sta OutVect+2,x + bra outta +setRAM lda OutSlot,x + clc + adc #5 + sta OutVect,x + lda OutSlot+2,x + adc #0 + sta OutVect+2,x +outta plb + phd ;ack!! + jmp bye6 + + END + +NewSetInDevice START + using IgnoreInfo + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda ignSetInDev + beq noign + stz ignSetInDev + bra outta +noign anop + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+1,s + sta InSlot,x + lda 7+1+2,s + sta InSlot+2,x + lda 7+1+4,s + sta InDeviceType,x + cmp #2 + bcc setPascal + beq setRAM + cmp #3 + beq setFile + brk $00 + +* lda #pipeIN-1 +* sta InVect,x +* lda #^pipeIN-1 +* sta InVect+2,x +* bra outta +setFile anop + lda #fileIN-1 + sta InVect,x + lda #^fileIN-1 + sta InVect+2,x + bra outta +setPascal lda InSlot,x + asl a + asl a + tay + lda ReadDDTab,y + sta InVect,x + lda ReadDDTab+2,y + sta InVect+2,x + bra outta +setRAM lda InSlot,x + clc + adc #2 + sta InVect,x + lda InSlot+2,x + adc #0 + sta InVect+2,x +outta plb + phd ;ack!! + jmp bye6 + + END + +NewSetErrDevice START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+1,s + sta ErrSlot,x + lda 7+1+2,s + sta ErrSlot+2,x + lda 7+1+4,s + sta ErrDeviceType,x + cmp #2 + bcc setPascal + beq setRAM + lda #fileERR-1 + sta ErrVect,x + lda #^fileERR-1 + sta ErrVect+2,x + bra outta +setPascal lda ErrSlot,x + asl a + asl a + tay + lda WriteDDTab,y + sta ErrVect,x + lda WriteDDTab+2,y + sta ErrVect+2,x + bra outta +setRAM lda ErrSlot,x + clc + adc #5 + sta ErrVect,x + lda ErrSlot+2,x + adc #0 + sta ErrVect+2,x + +outta plb + phd ;ack!! + jmp bye6 + + END + +;========================================================================= +; +; _SetInGlobals +; +;========================================================================= + +NewSetInGlob START + using IgnoreInfo + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda ignSetInGlo + beq noign + stz ignSetInGlo + bra outta +noign anop + lda >truepid + xba + lsr a + lsr a + + tax + + lda 7+1,s + sta InORMask,x + lda 7+1+2,s + sta InANDMask,x + +outta plb + phd ;ack!! + jmp bye4 + + END + +NewSetOutGlob START + using IgnoreInfo + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda ignSetOutGlo + beq noign + stz ignSetOutGlo + bra outta +noign anop + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+1,s + sta OutORMask,x + lda 7+1+2,s + sta OutANDMask,x +outta plb + phd ;ack!! + jmp bye4 + + END + +NewSetErrGlob START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+1,s + sta ErrORMask,x + lda 7+1+2,s + sta ErrANDMask,x + plb + phd ;ack!! + jmp bye4 + + END + +NewGetInGlob START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda InORMask,x + sta 7+1,s + lda InANDMask,x + sta 7+1+2,s + plb + phd ;ack!! + jmp bye0 + + END + +NewGetOutGlob START + using TextToolsInfo + using KernelStruct + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda OutORMask,x + sta 7+1,s + lda OutANDMask,x + sta 7+1+2,s + plb + phd ;ack!! + jmp bye0 + + END + +NewGetErrGlob START + using KernelStruct + using TextToolsInfo + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda ErrORMask,x + sta 7+1,s + lda ErrANDMask,x + sta 7+1+2,s + plb + phd ;ack!! + jmp bye0 + + END + +;========================================================================= +; +; _WriteChar +; +;========================================================================= + +NewWriteChar START + using TextToolsInfo + using KernelStruct + using InOutData + + jsl decBusy + phd + lda >InOutDP + tcd + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+2+1,s + and OutANDMask,x + ora OutORMask,x + jsl VectOut + jsl incBusy + plb + jmp bye2 + END + +;========================================================================= +; +; _ErrWriteChar +; +;========================================================================= + +NewErrWriteChar START + using KernelStruct + using TextToolsInfo + using InOutData + + jsl decBusy + phd + lda >InOutDP + tcd + + phb + phk + plb + + lda >truepid + xba + lsr a + lsr a + tax + + lda 7+2+1,s + and ErrANDMask,x + ora ErrORMask,x + jsl VectErr + jsl incBusy + plb + jmp bye2 + END + +;========================================================================= +; +; WriteLine +; +;========================================================================= + +NewWriteLine START + using KernelStruct + using TextToolsInfo + using InOutData + +index equ 9 +count equ 7 +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 14 +strPtr equ 20 + + jsl decBusy + phd + phb + phk + plb + pea 1 + pha + lda >InOutDP + pha + pha + pha + tsc + tcd + lda [strPtr] + and #$00FF + sta count + lda truepid + xba + lsr a + lsr a + tax + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + lda count + beq done +lp ldy index + lda [strPtr],y + and #$00FF + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectOut + pld + ldy index + cpy count + beq done + inc index + bra lp + +done phd + pei (dp) + pld + lda #13 + jsl VectOut + lda #10 + jsl VectOut + pld + jsl incBusy + pla + pla + pla + pla + pla + plb + jmp bye4 + END + +;========================================================================= +; +; _ErrWriteLine +; +;========================================================================= + +NewErrWriteLine START + using KernelStruct + using TextToolsInfo + using InOutData + +index equ 9 +count equ 7 +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 14 +strPtr equ 20 + + jsl decBusy + phd + phb + phk + plb + pea 1 + pha + lda >InOutDP + pha + pha + pha + tsc + tcd + lda [strPtr] + and #$00FF + sta count + lda truepid + xba + lsr a + lsr a + tax + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + lda count + beq done + +lp ldy index + lda [strPtr],y + and #$00FF + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectErr + pld + ldy index + cpy count + beq done + inc index + bra lp + +done phd + pei (dp) + pld + lda #13 + jsl VectErr + lda #10 + jsl VectErr + pld + jsl incBusy + pla + pla + pla + pla + pla + plb + + jmp bye4 + END + +;========================================================================= +; +; _WriteString +; +;========================================================================= + +NewWriteString START + using KernelStruct + using TextToolsInfo + using InOutData + +index equ 9 +count equ 7 +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 14 +strPtr equ 20 + + jsl decBusy + phd + phb + phk + plb + pea 1 + pha + lda >InOutDP + pha + pha + pha + tsc + tcd + lda [strPtr] + and #$00FF + sta count + lda truepid + xba + lsr a + lsr a + tax + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + lda count + beq done + +lp ldy index + lda [strPtr],y + and #$00FF + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectOut + pld + ldy index + cpy count + beq done + inc index + bra lp + +done anop + jsl incBusy + pla + pla + pla + pla + pla + plb + jmp bye4 + END + +;========================================================================= +; +; _ErrWriteString +; +;========================================================================= + +NewErrWriteString START + using KernelStruct + using TextToolsInfo + using InOutData + +index equ 9 +count equ 7 +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 14 +strPtr equ 20 + + jsl decBusy + phd + phb + phk + plb + pea 1 + pha + lda >InOutDP + pha + pha + pha + tsc + tcd + lda [strPtr] + and #$00FF + sta count + lda truepid + xba + lsr a + lsr a + tax + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + lda count + beq done + +lp ldy index + lda [strPtr],y + and #$00FF + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectErr + pld + ldy index + cpy count + beq done + inc index + bra lp + +done anop + jsl incBusy + pla + pla + pla + pla + pla + plb + + jmp bye4 + END + +;========================================================================= +; +; _WriteCString +; +;========================================================================= + +NewWriteCString START + using KernelStruct + using TextToolsInfo + using InOutData + +index equ 9 +count equ 7 +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 14 +strPtr equ 20 + + jsl decBusy + phd + phb + phk + plb + pea 0 + pha + lda >InOutDP + pha + pha + pha + tsc + tcd + + lda truepid + xba + lsr a + lsr a + tax + + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + +lp ldy index + lda [strPtr],y + and #$00FF + cmp #0 + beq done + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectOut + pld + inc index + bra lp + +done anop + jsl incBusy + pla + pla + pla + pla + pla + plb + + jmp bye4 + END + +;========================================================================= +; +; _ErrWriteCString +; +;========================================================================= + +NewErrWriteCString START + using KernelStruct + using TextToolsInfo + using InOutData + +index equ 9 +count equ 7 +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 14 +strPtr equ 20 + + jsl decBusy + phd + phb + phk + plb + pea 0 + pha + lda >InOutDP + pha + pha + pha + tsc + tcd + + lda truepid + xba + lsr a + lsr a + tax + + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + +lp ldy index + lda [strPtr],y + and #$00FF + cmp #0 + beq done + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectErr + pld + inc index + bra lp + +done anop + jsl incBusy + pla + pla + pla + pla + pla + plb + + jmp bye4 + + END + +;========================================================================= +; +; _TextWriteBlock +; +;========================================================================= + +NewTextWriteBlock START + using KernelStruct + using TextToolsInfo + using InOutData + +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 10 +strPtr equ 20 +index equ 18 +count equ 16 + + jsl decBusy + phd ; 8,s + phb ; 7,s + phk + plb + lda >InOutDP + pha ; 5,s (dp) + pha ; 3,s (andmask) + pha ; 1,s (ormask) + tsc + tcd + + lda truepid + xba + lsr a + lsr a + tax + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + lda count + beq done + +lp ldy index + lda [strPtr],y + and #$00FF + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectOut + pld + dec count + beq done + inc index + bra lp + +done anop + jsl incBusy + pla + pla + pla + plb + jmp bye8 + END + +;========================================================================= +; +; _ErrWriteBlock +; +;========================================================================= + +NewErrWriteBlock START + using KernelStruct + using TextToolsInfo + using InOutData + +dp equ 5 +andmask equ 3 +ormask equ 1 +sixrtl equ 10 +strPtr equ 20 +index equ 18 +count equ 16 + + jsl decBusy + phd ; 8,s + phb ; 7,s + phk + plb + lda >InOutDP + pha ; 5,s (dp) + pha ; 3,s (andmask) + pha ; 1,s (ormask) + tsc + tcd + + lda truepid + xba + lsr a + lsr a + tax + lda OutANDMask,x + sta andmask + lda OutORMask,x + sta ormask + lda count + beq done + +lp ldy index + lda [strPtr],y + and #$00FF + and andmask + ora ormask + phd + pei (dp) + pld + jsl VectErr + pld + dec count + beq done + inc index + bra lp + +done anop + jsl incBusy + pla + pla + pla + plb + jmp bye8 + END + +;========================================================================= +; +; _ReadChar +; +;========================================================================= + +NewReadChar START + using KernelStruct + using TextToolsInfo + using InOutData + + jsl decBusy + + phd ; where does this go? + lda >InOutDP + tcd + + phb + phk + plb + +dobgcheck lda truepid + xba + lsr a + lsr a + tax + lda InDeviceType,x + cmp #1 + bne isfg + lda InSlot,x + tax + lda #21 + jsl BGCheck + cmp #0 + beq isfg + cmp #1 + beq dobgcheck ; we were suspended, try again + + jsl incBusy ; the return code was -1, which means + plb ; to abort this call with an error + ldx #$0027 ; code. + pld + ldy #2 + jmp >tool_exit + +isfg anop + + jsl VectIn + pha + lda >truepid + xba + lsr a + lsr a + tax + pla + and InANDMask,x + ora InORMask,x + sta 7+2+1+2,s + + lda 7+2+1,s + and #%1 + beq done + lda 7+2+1+2,s ;Echo the character + and OutANDMask,x + ora OutORMask,x + jsl VectOut + +done anop + jsl incBusy + plb + jmp bye2 + + END + +;========================================================================= +; +; _TextReadBlock +; +;========================================================================= + +NewTextReadBlock START + using KernelStruct + using TextToolsInfo + + jsl decBusy + phd + tsc + tcd + phb + phk + plb + +dobgcheck lda truepid + xba + lsr a + lsr a + tax + lda InDeviceType,x + cmp #1 + bne isfg + lda InSlot,x + tax + lda #21 + jsl BGCheck + cmp #0 + beq isfg + cmp #1 + beq dobgcheck ; we were suspended, try again + + jsl incBusy ; the return code was -1, which means +* ; to abort this call with an error + plb + ldx #$0027 ; code. + pld + ldy #10 + jmp >tool_exit + +isfg anop +loop anop + jsl VectIn + pha + lda >truepid + xba + lsr a + lsr a + tax + lda 1,s + and InANDMask,x + ora InORMask,x + ldy 7+2+4 + short a + sta [7+2+6],y + long a + + lda 7+2+0 + and #%1 + beq noecho + lda 1,s ;Echo the character + and OutANDMask,x + ora OutORMask,x + jsl VectOut + +noecho pla + inc 7+2+4 + lda 7+2+4 + cmp 7+2+2 + bne loop + +done anop + jsl incBusy + plb + jmp bye10 + + END + +;========================================================================= +; +; _ReadLine +; +;========================================================================= + +NewReadLine START + using KernelStruct + using TextToolsInfo + using InOutData + +cmdlen equ 1 +cmdloc equ 3 +tmp equ 5 +wordspace equ 7+2+6+10 +bufferPtr equ 7+2+6+6 +maxCount equ 7+2+6+4 +eolChar equ 7+2+6+2 +echoFlag equ 7+2+6 + + phd + pushword #0 ; space for tmp variables + pushword #0 + pushword #0 + tsc + tcd + + phb + phk + plb + jsl decBusy + +dobgcheck lda truepid + xba + lsr a + lsr a + tax + lda InDeviceType,x + cmp #1 + bne isfg + lda InSlot,x + tax + lda #21 + jsl BGCheck + cmp #0 + beq isfg + cmp #1 + beq dobgcheck ; we were suspended, try again + + jsl incBusy ; the return code was -1, which means + plb + pla + pla + pla ; to abort this call with an error + ldx #$0027 ; code. + pld + ldy #2 + jmp >tool_exit + +isfg anop + + stz 0,x + long m + and #$00FF + ora #$C100 + pea $c1 + pea $10 + pha + _FWEntry + ply + plx + pla + plp + plp + long m + jsl decBusy + rtl + END + +sl2Read START + ldx #$C20E + bra dopasc +sl2Write ENTRY + ldx #$C20F + bra dopasc +sl2Init ENTRY + ldx #$C20D + bra dopasc +sl2Status ENTRY + ldx #$C210 +dopasc jsl incBusy + pea 0 + pea 0 + pea 0 + pea 0 + pha + short m + lda >0,x + long m + and #$00FF + ora #$C200 + pea $c2 + pea $20 + pha + _FWEntry + ply + plx + pla + plp + plp + long m + jsl decBusy + rtl + END + +NullOut START KERN2 + rtl + END + +NullIn START KERN2 + lda #0 + rtl + END +NullStatus START KERN2 + lda #0 + sec + rtl + END +NullInit START KERN2 + rtl + END + +C80Init START KERN2 + using InOutData + phd + lda >InOutDP + tcd + lda #12 + jsl COUT + pld + rtl + END + +************************************************************ +* +* I/O/E vector entry points +* all TextTools calls come through these three routines +* +************************************************************ + +VectIn START KERN2 + using TextToolsInfo + using KernelStruct + + phb + pha + phx + pha + + lda >truepid + asl a + asl a + asl a + asl a + asl a + asl a + tax + short m + lda >InVect+2,x + sta 7,s + long m + lda >InVect,x + sta 5,s + pla + plx + rtl + END + +VectOut START KERN2 + using TextToolsInfo + using KernelStruct + + phb + pha + phx + pha + lda >truepid + asl a + asl a + asl a + asl a + asl a + asl a + tax + short m + lda >OutVect+2,x + sta 7,s + long m + lda >OutVect,x + sta 5,s + pla + plx + rtl + END + +VectErr START KERN2 + using TextToolsInfo + using KernelStruct + + phb + pha + phx + pha + lda >truepid + asl a + asl a + asl a + asl a + asl a + asl a + tax + short m + lda >ErrVect+2,x + sta 7,s + long m + lda >ErrVect,x + sta 5,s + pla + plx + rtl + END + +************************************************************ +* +* Pipe Driver +* +* Grabs the pipe number (from the TTY struct) and calls +* either loRead or loWrite to get a single byte +* +************************************************************ + +pipeIN START KERN2 + using TextToolsInfo + + phy + phx + jsr getTTindex + lda >InSlot,x ; something else needs to set this up + pha +* jsl loRead + plx + ply + rtl + END + +pipeOUT START KERN2 + using TextToolsInfo + + phy + phx + pha + pha + jsr getTTindex + lda >OutSlot,x ; something else needs to set this up + pha +* jsl loWrite + pla + plx + ply + rtl + END + +************************************************************ +* +* Redirection Driver +* +* Note that the redirection drivers only use the old +* entry points- this is because pipes will be handled +* entirely through our GS/OS intercept +* +************************************************************ + +fileIN START KERN2 + using TextToolsInfo + phb + phk + plb + phx + + pha ; result buffer! + tsc + pha ; transfer count + pha + pea 0 + pea 1 ; request count + pea 0 + inc a + pha ; push buffer address + + jsr getTTindex + lda >InSlot,x ; something else needs to set this up + pha ; push the refnum + pea 4 ; number of parameters + tsc + inc a + pea 0 + pha ; address of pBlock + pea $2012 ; command code + jsl StackGSOS + bcc leave + cmp #$4C + bne leave + lda #$7F00 + sta 17,s +leave anop + tsc + clc + adc #16 + tcs + pla + plx + plb + rtl + +*READPB dc i2'5' +*READrefNum dc i2'0' +* dc i4'buffer' +* dc i4'1' +*xferCount dc i4'0' +* dc i2'1' ; cache blocks! +*buffer ds 16 ; in case we decide to get clever +*char dc i2'0' + END + +* This routine temporarily turns off GS/OS debug output, to prevent +* an infinite recursion. This was done to allow pipes to be accessed +* thru the texttools file interface if desired. The pipe interface +* sports much better performance, however. + +fileOUT START KERN2 + using TextToolsInfo + using KernelStruct + + phb + phk + plb + phx + pha ; data buffer + + tsc + pha ; transfer count + pha + pea 0 + pea 1 ; request count + pea 0 + inc a + pha ; push buffer address + + jsr getTTindex + lda >OutSlot,x ; something else needs to set this up + pha +;sta WRITErefNum + lda >stateFlags,x + and #%00000001 ; 1 = stdout, 2 = stderr + bne convMode1 ; last char was a CR + lda 15,s + and #$7F + cmp #$0D + bne noConv1 + lda >stateFlags,x + ora #%00000001 + sta >stateFlags,x + bra noConv1 +convMode1 lda 15,s + and #$7F + cmp #$0A + bne noConv1 ; ignore the LF part of CRLF + lda >stateFlags,x + and #%1111111111111110 + sta >stateFlags,x + pha + bra leave1 +noConv1 anop +* lda 15,s +* sta buffer + pea 4 ; pCount + tsx ; put it in X for now + + lda >gsosDebug + pha + lda #0 + sta >gsosDebug + pea 0 + inx + phx ; push the pBlock ptr + pea $2013 ; write command code + jsl StackGSOS +*Write WRITEPB + pla + sta >gsosDebug +leave1 anop + tsc + clc + adc #16 + tcs + pla + plx + plb + rtl + +fileERR ENTRY + phb + phk + plb + phx + pha ; data buffer + + tsc + pha ; transfer count + pha + pea 0 + pea 1 ; request count + pea 0 + inc a + pha ; push buffer address + + jsr getTTindex + lda >ErrSlot,x ; something else needs to set this up + pha +*sta WRITErefNum + lda >stateFlags,x + and #%00000010 ; 1 = stdout, 2 = stderr + bne convMode2 ; last char was a CR + lda 15,s + and #$7F + cmp #$0D + bne noConv2 + lda >stateFlags,x + ora #%00000010 + sta >stateFlags,x + bra noConv2 +convMode2 lda 15,s + and #$7F + cmp #$0A + bne noConv2 ; ignore the LF part of CRLF + lda >stateFlags,x + and #%1111111111111101 + sta >stateFlags,x + pha + bra leave2 +noConv2 anop +* lda 1,s +* sta buffer + + pea 4 ; pCount + tsx ; put it in X for now + + lda >gsosDebug + pha + lda #0 + sta >gsosDebug + + pea 0 + inx + phx + pea $2013 ; write command code + jsl StackGSOS +*Write WRITEPB + pla + sta >gsosDebug +leave2 anop + tsc + clc + adc #16 + tcs + pla + plx + plb + rtl + +*WRITEPB dc i2'5' +*WRITErefNum dc i2'0' +* dc i4'buffer' +* dc i4'1' +*xferCount dc i4'0' +* dc i2'1' ; cache blocks! +*buffer ds 16 ; in case we decide to get clever + END + diff --git a/kern/gno/tty.asm b/kern/gno/tty.asm new file mode 100644 index 0000000..caa8527 --- /dev/null +++ b/kern/gno/tty.asm @@ -0,0 +1,1979 @@ +* $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 +;#include +;#include +;#include +;#include +;#include +;#include + +;#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 + diff --git a/kern/gno/tty.h b/kern/gno/tty.h new file mode 100644 index 0000000..33882ae --- /dev/null +++ b/kern/gno/tty.h @@ -0,0 +1,50 @@ +/* $Id: tty.h,v 1.1 1998/02/02 08:19:12 taubert Exp $ */ + +struct tty_s { + /*q outQ; + q inQ; */ + char sg_ispeed; /* input speed */ + char sg_ospeed; /* output speed */ + char sg_erase; /* erase character */ + char sg_kill; /* kill character */ + unsigned sg_flags; /* mode flags */ + + unsigned local; + + char t_intrc; /* interrupt */ + char t_quitc; /* quit */ + char t_startc; /* start output */ + char t_stopc; /* stop output */ + char t_eofc; /* end-of-file */ + char t_brkc; /* input delimiter (like nl) */ + + char t_suspc; /* stop process signal */ + char t_dsuspc; /* delayed stop process signal */ + char t_rprntc; /* reprint line */ + char t_flushc; /* flush output (toggles) */ + char t_werasc; /* word erase */ + char t_lnextc; /* literal next character */ + + unsigned short ws_row; /* rows, in characters */ + unsigned short ws_col; /* columns, in characters */ + unsigned short ws_xpixel; /* horizontal size, pixels */ + unsigned short ws_ypixel; /* vertical size, pixels */ + + void (*t_open)(int devnum); + void (*t_close)(int devnum); + int (*t_ioctl)(int devNum, void *dataptr, unsigned long tioc); + int (*t_read)(int devNum, void *dataptr, unsigned count); + int (*t_write)(int devNum, void *dataptr, unsigned count); + void (*mutex)(); + void (*demutex)(); + void (*out_enq)(char c); + void (*in_enq)(char c); + int (*out_deq)(); + int (*in_deq)(); + int (*size_inq)(); + int (*size_outq)(); + unsigned editInd,editBegin; + unsigned st_flags; + char *editBuf; +}; +typedef struct tty_s ttyb; diff --git a/kern/gno/util.asm b/kern/gno/util.asm new file mode 100644 index 0000000..43bf642 --- /dev/null +++ b/kern/gno/util.asm @@ -0,0 +1,708 @@ +* $Id: util.asm,v 1.1 1998/02/02 08:19:59 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* UTIL.ASM +* By Tim Meekins +* By Jawaid Bazyar +* +* Utility functions used by the kernel. Mostly string manipulation +* routines, with a strong tilt towards coversion between different types +* +************************************************************************** + + case on + mcopy m/util.mac + +;========================================================================= +; +; Convert the accumulator to lower case. +; +;========================================================================= + +TOLOWER START KERN2 + + if2 @,cc,#'A',done + if2 @,cs,#'Z'+1,done + add2 @,#'a'-'A',@ + +done rts + + END + +;========================================================================= +; +; Convert a c string to lower case +; +;========================================================================= + +lowercstr START KERN2 + +space equ 0 + + subroutine (4:p),space + + short a + + ldy #0 +loop lda [p],y + beq done + if2 @,cc,#'A',next + if2 @,cs,#'Z'+1,next + add2 @,#'a'-'A',@ + sta [p],y +next iny + bra loop + +done long a + + return + + END + +;========================================================================= +; +; Get the length of a c string. +; +;========================================================================= + +cstrlen START KERN2 + +space equ 0 + + subroutine (4:p),space + + short a + ldy #0 +loop lda [p],y + beq done + iny + bra loop + +done long a + sty p + + return 2:p + + END + +;========================================================================= +; +; Allocate memory for a c string the same length as another string. +; +;========================================================================= + +alloccstr START KERN2 + +space equ 0 + + subroutine (4:p),space + + ph4 p ;get length of string + jsl cstrlen + inc a ;for terminator + pea 0 ;allocate memory + pha + jsl ~NEW + sta p + stx p+2 + + return 4:p + + END + + +;========================================================================= +; +; Copy a GS/OS string to a GS/OS result buffer. Assumes that the result +; address points to valid memory +; +;========================================================================= + +copygs2res START KERN2 +bufString equ 0 +retval equ 4 + + subroutine (4:in,4:resultBuf),6 + lda [in] + ldy #2 + sta [resultBuf],y + clc + adc #4 ; string length, but add in buf size + cmp [resultBuf] + beq lenOkay + bcc lenOkay + lda #$004F ; bwa haha + bra goaway +lenOkay lda [in] ; we just want the length, bud + tay + iny ; copy the length word also + lda resultBuf + clc + adc #2 + sta bufString + lda resultBuf+2 + adc #0 + sta bufString+2 + short a +loop lda [in],y + sta [bufString],y + dey + bpl loop + long m + lda #0 +goaway sta retval + return 2:retval + END + +;========================================================================= +; +; appends one GS/OS string to another. assumes the destination is big +; enough to hold the result. +; +;========================================================================= +gsstrcat START KERN2 + +iind equ 0 +oind equ iind+2 +left equ oind+2 +space equ left+2 + + subroutine (4:s,4:d),space + lda [d] + inc a + inc a + sta oind + lda #2 + sta iind + lda [s] + sta left + clc + adc [d] + sta [d] + +loop short m + ldy iind + lda [s],y + ldy oind + sta [d],y + long m + inc iind + inc oind + dec left + bne loop + return + END + +;========================================================================= +; +; Copy one GS/OS string to another. Assumes an alloccstr has been +; performed on destination. +; +;========================================================================= + +copygsstr START KERN2 + +space equ 0 + + subroutine (4:p,4:q),space + + lda [p] + inc a +; clc +; adc #1 + tay + short a +loop lda [p],y + sta [q],y + dey + bpl loop +done long a + + return + + END + +;========================================================================= +; +; Copy one pascal string to another. Assumes an alloccstr has been +; performed on destination. +; +;========================================================================= + +copypstr START KERN2 + +space equ 0 + + subroutine (4:p,4:q),space + + lda [p] + and #$00FF + tay + short a +loop lda [p],y + sta [q],y + dey + bpl loop +done long a + + return + + END + +;========================================================================= +; +; Copy one string to another. Assumes an alloccstr has been performed on +; destination. +; +;========================================================================= + +copycstr START KERN2 + +space equ 0 + + subroutine (4:p,4:q),space + + short a + ldy #0 +loop lda [p],y + beq done + sta [q],y + iny + bra loop +done sta [q],y + long a + + return + + END + +;========================================================================= +; +; Converts a pascal string to a c string. This allocates memory for the +; new c string. +; +;========================================================================= + +p2cstr START KERN2 + +cstr equ 0 +space equ cstr+4 + + subroutine (4:p),space + + lda [p] + and #$FF + inc a + pea 0 + pha + jsl ~NEW + sta cstr + stx cstr+2 + lda [p] + and #$FF + tax + + short a + ldy #0 +loop cpx #0 + beq done + iny + lda [p],y + dey + sta [cstr],y + iny + dex + bra loop + +done lda #0 + sta [cstr],y + long a + + return 4:cstr + + END + +;========================================================================= +; +; Converts a GS/OS string to a c string. This allocates memory for the +; new c string. +; +;========================================================================= + +gs2cstr START KERN2 + +cstr equ 0 +space equ cstr+4 + + subroutine (4:gs),space + + lda [gs] + inc a + pea 0 + pha + jsl ~NEW + sta cstr + stx cstr+2 + lda [gs] + tax + + short a + ldy #0 +loop cpx #0 + beq done + iny + iny + lda [gs],y + dey + dey + sta [cstr],y + iny + dex + bra loop + +done lda #0 + sta [cstr],y + long a + + return 4:cstr + + END + + +;========================================================================= +; +; Converts a c string to a pascal string. Does not allocate memory. +; +;========================================================================= + +c2pstr START KERN2 + +space equ 0 + + subroutine (4:cstr,4:p),space + + short a + ldy #0 +loop lda [cstr],y + beq endstr + iny + sta [p],y + bra loop +endstr tya + sta [p] + long a + + return + + END + +;========================================================================= +; +; Compare two c strings. Return 0 if equal. +; +;========================================================================= + +cmpcstr START KERN2 + +ch equ 0 +result equ ch+2 +space equ result+2 + + subroutine (4:p,4:q),space + + ld2 1,result + + ldy #0 +strloop lda [p],y + and #$FF + beq strchk + sta ch + lda [q],y + and #$FF + cmp ch + bne done + iny + bra strloop +strchk lda [q],y + and #$FF + bne done + + stz result + +done return 2:result + + END + +writeacc START + phb + phk + plb + phy + phx + pha + sta tempacc + xba + lsr a + lsr a + lsr a + lsr a + and #$0F + jsr hexdig + lda tempacc + xba + and #$0F + jsr hexdig + lda tempacc + lsr a + lsr a + lsr a + lsr a + and #$0F + jsr hexdig + lda tempacc + and #$0F + jsr hexdig + pla ; preserve the accumulator + plx + ply + plb + rts +tempacc dc i2'0' + +hexdig entry + cmp #$A + bcc add0 + clc + adc #7 +add0 anop + clc + adc #'0' + ErrWriteChar @a + rts + END + +;========================================================================= +; +; Copy a Pascal string to a GS/OS string +; +;========================================================================= + +copyp2gs START KERN2 +slen equ 0 + subroutine (4:p,4:gs),2 + + lda [p] + and #$00FF + sta [gs] + sta slen + ldy #0 + short m +loop iny + lda [p],y + iny + sta [gs],y + dey + cpy slen + bcc loop + long m + return + END + +;========================================================================= +; +; Copy a GS/OS string to a Pascal string +; +;========================================================================= + +copygs2p START KERN2 +slen equ 0 + subroutine (4:gs,4:p),2 + + lda [gs] + and #$00FF + sta [p] + beq done ; 0 length- done! + inc a + sta slen + ldy #1 + short m +loop iny + lda [gs],y + dey + sta [p],y + iny + cpy slen + bcc loop + long m +done return + END + +;========================================================================= +; +; Copy a C string to a GS/OS result buffer +; +;========================================================================= + +copyc2res START KERN2 +bufString equ 0 +clen equ 4 +in equ 6 +out equ 8 +space equ out+2 + + subroutine (4:c,4:res),space + + ph4 c + jsl cstrlen + ldy #2 + sta [res],y + clc + adc #4 + cmp [res] + beq lenokay + bcc lenokay + lda #$4F + bra goaway +lenokay anop + lda [res],y + sta clen + ldy #0 + sty in + ldy #4 + sty out +loop anop + short m + ldy in + lda [c],y + ldy out + sta [res],y + long m + inc in + inc out + ldy in + cpy clen + bcs done + bra loop +done anop + lda #0 +goaway sta clen + return 2:clen + END + +GScaseEqual START KERN2 +retval equ 0 +lowera equ 2 + subroutine (4:a,4:b),4 + + lda [a] + cmp [b] + bne notequal + tay + iny +loop anop + cpy #1 + beq isequal ; done with comparison + lda [a],y + and #$00FF + jsr TOLOWER + sta lowera + lda [b],y + and #$00FF + jsr TOLOWER + cmp lowera + bne notequal + dey + bra loop + +isequal lda #1 + sta retval +goaway return 2:retval +notequal stz retval + bra goaway + END + +COPYC2GS START KERN2 + subroutine (4:c,4:gs),0 + + ph4 c + jsl cstrlen + sta [gs] + + tay + cpy #0 + beq done + short m +lp lda [c],y + iny2 + sta [gs],y + dey2 + dey + bpl lp +done long m + return + END + +~NDISPOSE START KERN2 +~NDISPOSE name + subroutine (4:ptr),0 + lda ptr+2 + bit #$FF80 + bne badptr + ora ptr + beq zptr + ph4 ptr + jsl ~DISPOSE + return +badptr anop + ph4 #bptrtxt + jsl PANIC + brk $00 +bptrtxt dc c'Attempt to ~dispose bogus pointer',i1'0' +zptr anop + ph4 #zptrtxt + jsl PANIC + brk $00 +zptrtxt dc c'Attempt to ~dispose null pointer',i1'0' + END + + case on +nfree START KERN2 +nfree name + subroutine (4:ptr),0 + lda ptr+2 + bit #$FF80 + bne badptr + ora ptr + beq zptr + ph4 ptr + jsl free + return +badptr anop + ph4 #bptrtxt + jsl PANIC + brk $00 +bptrtxt dc c'Attempt to free bogus pointer',i1'0' +zptr anop + ph4 #zptrtxt + jsl PANIC + brk $00 +zptrtxt dc c'Attempt to free null pointer',i1'0' + END + +gnoSetHandleID START KERN2 + subroutine (4:hand,2:id),0 + + lda id + ldy #6 + sta [hand],y + return + END diff --git a/kern/gno/var.asm b/kern/gno/var.asm new file mode 100644 index 0000000..01a3245 --- /dev/null +++ b/kern/gno/var.asm @@ -0,0 +1,1293 @@ +* $Id: var.asm,v 1.1 1998/02/02 08:20:02 taubert Exp $ +************************************************************************** +* +* The GNO Shell Project +* +* Developed by: +* Jawaid Bazyar +* Tim Meekins +* Derek Taubert +* +************************************************************************** +* +* VAR.ASM +* By Tim Meekins +* Optimized Nov 6,1991 by Jawaid Bazyar +* +* Routines for dealing with shell variables +* +* DATA STRUCTURES: +* +* varPtr points to a linked list of varNodes. Each varNode points to +* the next varNode and to the varTable for this level. When a Push Var +* is called when starting a shell file, a new varNode is added to the head +* of the list and a new varTable is created. All SETs will occur within +* this varTable. Reading variables will start by checking the current varTable. +* If not found, then the next lower varTable will be checked. This will +* insure proper scoping. +* +* A vartable is an array of size VTABSIZE. Each slot is a pointer to a +* variable itself. The variable consists of a pointer to its name, a +* pointer to its value, a pointer to the next variable in case of hash +* collisions, and finally a flag which defines if the variable should +* be exported to the previous varTable after the current varTable is popped. +* +* varPtr: +* [0] next: Ptr +* [4] varTable: Ptr +* +* varTable[VTABSIZE]: +* var: Ptr +* +* var: +* [0] next: Ptr +* [4] name: Ptr +* [8] value: Ptr +* [12] flag: word +* +* Nov 6, 1991 (jb) : I removed all references to kvm_xxxx routines. +* The variable code will probably run about twice as fast now. +* +************************************************************************** + + case on + mcopy m/var.mac + +VTABSIZE gequ 39 ;Size of variable table + +VEXPORT gequ %0001 ;This is variable is exported. + +;========================================================================= +; +; Deallocates the specified process' variable tables. After this is done +; none of the variable calls will work properly, so disposevar MUST be +; called ONLY at process shutdown time. +; +;========================================================================= + +disposevar START + using VarData + using KernelStruct + + subroutine (2:process),0 + +displp lda process + asl a + asl a + tax + lda varPtr,x + ora varPtr+2,x + beq done + lda process + jsl popvartbl + bra displp +done return + END + +;========================================================================= +; +; Initialize a new variable table. This is called at startup and also +; performs a PushStack. [THERE IS NO MEMORY ERROR CHECKING AT THIS TIME!!]! +; +;========================================================================= + +initvar START + + using VarData + using KernelStruct + +pidx128 equ 0 +count equ pidx128+2 +p equ count+2 +tbl equ p+4 +oldtbl equ tbl+4 +space equ oldtbl+4 + + subroutine (0:dummy),space + +; +; Save the current table value +; + lda truepid + beq root + asl a + tax + lda varDepth,x + bne pushptr + + lda truepid ; $$$ +folpid anop + + asl a + asl a + asl a + asl a + asl a + asl a + asl a + sta pidx128 + tax + lda ParentProc,x ; $$$ + bmi root + asl a + tax + lda varDepth,x + bne tryold + + ldx pidx128 + lda ParentProc,x + bra folpid + +root stz oldtbl + stz oldtbl+2 + bra insNode + +tryold anop + +pushptr txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + ldy #4 + lda [p],y + sta oldtbl + iny2 + lda [p],y + sta oldtbl+2 +; +; Insert a new varNode into the linked list +; +insNode ph4 #4+4 + jsl ~NEW + sta p + stx p+2 + lda truepid + asl2 a + tax + ldy #2 + lda varPtr,x + sta [p] + lda varPtr+2,x + sta [p],y + lda p + sta varPtr,x + lda p+2 + sta varPtr+2,x +; +; Create a new varTable and add to linked list +; + ph4 #VTABSIZE*4 + jsl ~NEW + sta tbl + stx tbl+2 + ldy #4 + sta [p],y + iny2 + txa + sta [p],y +; +; Set all table entries to NIL +; + ldx #VTABSIZE + ldy #0 + lda #0 +nilloop sta [tbl],y + iny2 + sta [tbl],y + iny2 + dex + bne nilloop +; +; Set the var depth before calling SETVAR below +; + lda truepid + asl a + tax + lda varDepth,x + inc a + sta varDepth,x +; +; If oldtbl == NIL then we're all done for now +; + lda oldtbl + ora oldtbl+2 + beq done +; +; scan through the old table, get any exported variables and insert them +; into the new var table. +; + ld2 VTABSIZE,count + +loop1 ldy #2 + lda [oldtbl] + sta p + lda [oldtbl],y + sta p+2 + ora p + beq nexttbl + +loop2 ldy #12 + lda [p],y + and #VEXPORT + beq nextvar + + ldy #4+2 + lda [p],y + pha + dey2 + lda [p],y + pha + ldy #8+2 + lda [p],y + pha + dey2 + lda [p],y + pha + jsl setvar ;Copy over the new variable + ldy #4+2 + lda [p],y + pha + dey2 + lda [p],y + pha + ldy #12 + lda [p],y + pha + jsl exportvar ;Copy over the var flags + +nextvar ldy #2 + lda [p] + tax + lda [p],y + sta p+2 + stx p + ora p + bne loop2 + +nexttbl add4 oldtbl,#4,oldtbl + dec count + bne loop1 + +done return + + END + +;========================================================================= +; +; Pop a variable table. +; +;========================================================================= + +popvartbl START + + using VarData + using KernelStruct + +tblptr equ 0 +pid equ tblptr+4 +count equ pid+2 +p equ count+2 +tbl equ p+4 +space equ tbl+4 + + sta >mylocalpid + subroutine (0:dummy),space + + lda mylocalpid + sta pid + + asl a + tax + lda varDepth,x + bne ok + jmp done + +ok dec a + sta varDepth,x +; +; Point to tables, assume ptrs good because varDepth is good +; + txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + + ldy #4 + lda [p],y + sta tbl + sta tblptr + iny2 + lda [p],y + sta tbl+2 + sta tblptr+2 + + ldy #2 + lda [p] + tax + lda [p],y + sta p+2 + stx p +; +; Dispose varNode pointing to table +; + lda pid + asl2 a + tax + lda varPtr+2,x + pha + lda varPtr,x + pha + jsl ~NDISPOSE + lda pid + asl2 a + tax + lda p + sta varPtr,x + lda p+2 + sta varPtr+2,x +; +; Start looping through each variable in the table and then dispose them. +; If a variable is set to export then export it. +; + ld2 VTABSIZE,count + +loop1 ldy #2 + lda [tbl] + sta p + lda [tbl],y + sta p+2 + ora p + beq nexttbl + +loop2 anop +* ldy #12 +* lda [p],y +* and #VEXPORT +* beq dispvar +* +* ldy #4+2 +* lda [p],y +* pha +* dey2 +* lda [p],y +* pha +* ldy #8+2 +* lda [p],y +* pha +* dey2 +* lda [p],y +* pha +* jsl setvar ;Copy over the new variable +* ldy #4+2 +* lda [p],y +* pha +* dey2 +* lda [p],y +* pha +* ldy #12 +* lda [p],y +* pha +* jsl exportvar ;Copy over the var flags + +dispvar ldy #4+2 ;dispose the variable + lda [p],y + pha + dey2 + lda [p],y + pha + jsl ~NDISPOSE + ldy #8+2 + lda [p],y + pha + dey2 + lda [p],y + pha + jsl ~NDISPOSE + pei (p+2) + pei (p) + ldy #2 + lda [p] + tax + lda [p],y + sta p+2 + stx p + jsl ~NDISPOSE + lda p+2 + ora p + bne loop2 + +nexttbl add4 tbl,#4,tbl + dec count + jne loop1 + + pei (tblptr+2) + pei (tblptr) + jsl ~NDISPOSE + +done return +mylocalpid dc i2'0' + END + +;========================================================================= +; +; Set a variable. +; +;========================================================================= + +setvar START + + using VarData + using KernelStruct + +pidx128 equ 0 +var equ pidx128+2 +tbl equ var+4 +p equ tbl+4 +q equ p+4 +space equ q+4 + + subroutine (4:name,4:value),space + + pei (name+2) + pei (name) + jsl lowercstr + + lda truepid + + asl a + tax + lda varDepth,x + bne pointit + + lda truepid +folpid anop + asl2 a + asl2 a + asl2 a + asl a + sta pidx128 + tax + lda ParentProc,x ;parent id + jmi done ;can't do it + asl a + tax + lda varDepth,x + bne tryit + ldx pidx128 + lda ParentProc,x + bra folpid + +tryit anop + +; +; Point to table +; +pointit txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + ldy #4 + lda [p],y + sta tbl + iny2 + lda [p],y + sta tbl+2 +; +; Point to var list in hash table +; + pei (name+2) + pei (name) + jsl hashvar + clc + adc tbl + sta p + lda tbl+2 + adc #0 + sta p+2 +; +; See if it's already defined locally +; + ldy #2 + lda [p],y + pha + lda [p] + pha + pei (name+2) + pei (name) + jsl followlocvar + cmp #0 + bne changevar + cpx #0 + beq newvar +; +; Modify an already defined variable +; +changevar anop + sta var ;point to variable + stx var+2 + ldy #8+2 ;dispose old value + lda [var],y + pha + dey2 + lda [var],y + pha + jsl ~NDISPOSE + jmp setvalue ;set the new value +; +; Create a new local variable +; +newvar anop + ph4 #14 ;get space for variable + jsl ~NEW + sta var + stx var+2 + ora var+2 + beq done + ldy #2 ;insert variable into linked list + lda [p] + sta [var] + lda [p],y + sta [var],y + lda var + sta [p] + lda var+2 + sta [p],y + ldy #12 ;initialize flag to 0 + lda #0 + sta [var],y + pei (name+2) ;get memory for the string + pei (name) + jsl alloccstr + sta q + stx q+2 + ldy #4 ;point to name + sta [var],y + txa + iny2 + sta [var],y + pei (name+2) ;copy name to variable + pei (name) + pei (q+2) + pei (q) + jsl copycstr +setvalue pei (value+2) ;get memory for the string + pei (value) + jsl alloccstr + sta q + stx q+2 + ldy #8 ;point to value + sta [var],y + txa + iny2 + sta [var],y + pei (value+2) ;copy value to variable + pei (value) + pei (q+2) + pei (q) + jsl copycstr + +done return + + END + +;========================================================================= +; +; Returns the variable record of a named variable (same as what indexvar +; returns) +; +;========================================================================= + +readvarrec START + + using VarData + using KernelStruct + +pidx128 equ 0 +hashval equ pidx128+2 +var equ hashval+2 +tbl equ var+4 +p equ tbl+4 +space equ p+4 + + subroutine (4:name),space + + pei (name+2) + pei (name) + jsl lowercstr + pei (name+2) + pei (name) + jsl hashvar + sta hashval + + lda truepid + asl a + tax + lda varDepth,x + bne pointit + + lda truepid +folpid anop + + asl2 a + asl2 a + asl2 a + asl a + sta pidx128 + tax + lda ParentProc,x ;parent id + bpl cont ;can't do it + stz p + stz p+2 + jmp done +cont asl a + tax + lda varDepth,x + bne tryit + ldx pidx128 + lda ParentProc,x + bra folpid + +tryit anop + +; +; Point to table +; +pointit txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + +loop clc + ldy #4 + lda [p],y + adc hashval + sta tbl + iny2 + lda [p],y + adc #0 + sta tbl+2 +; +; See if it's already defined locally +; + ldy #2 + lda [tbl],y + pha + lda [tbl] + pha + pei (name+2) + pei (name) + jsl followlocvar +; cmp #0 +; bne found +; cpx #0 +; bne found +; +; next table +; +; ldy #2 +; lda [p] +; tax +; lda [p],y +; sta p+2 +; stx p +; ora p +; bne loop +; bra done + +found sta var + stx var+2 + +done return 4:var + + END + + +;========================================================================= +; +; Read a variable. +; +;========================================================================= + +readvar START + + using VarData + using KernelStruct + +pidx128 equ 0 +hashval equ pidx128+2 +var equ hashval+2 +tbl equ var+4 +p equ tbl+4 +space equ p+4 + + subroutine (4:name),space + + pei (name+2) + pei (name) + jsl lowercstr + pei (name+2) + pei (name) + jsl hashvar + sta hashval + + lda truepid + asl a + tax + lda varDepth,x + bne pointit + + lda truepid +folpid anop + + asl2 a + asl2 a + asl2 a + asl a + sta pidx128 + tax + lda ParentProc,x ;parent id + bpl cont ;can't do it + stz p + stz p+2 + jmp done +cont asl a + tax + lda varDepth,x + bne tryit + ldx pidx128 + lda ParentProc,x + bra folpid + +tryit anop + +; +; Point to table +; +pointit txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + +loop clc + ldy #4 + lda [p],y + adc hashval + sta tbl + iny2 + lda [p],y + adc #0 + sta tbl+2 +; +; See if it's already defined locally +; + ldy #2 + lda [tbl],y + pha + lda [tbl] + pha + pei (name+2) + pei (name) + jsl followlocvar + cmp #0 + bne found + cpx #0 + bne found +; +; next table +; +; ldy #2 +; lda [p] +; tax +; lda [p],y +; sta p+2 +; stx p +; ora p +; bne loop + stz p + stz p+2 + bra done + +found sta var + stx var+2 + ldy #8 + lda [var],y + sta p + iny2 + lda [var],y + sta p+2 + +done return 4:p + + END + +;========================================================================= +; +; Return the nth variable by its index +; +;========================================================================= + +indexvar START + + using VarData + using KernelStruct + +pidx128 equ 0 +count equ pidx128+2 +p equ count+2 +tbl equ p+4 +space equ tbl+4 + + subroutine (2:index),space + + lda index + jeq nope + jmi nope + + lda truepid + asl a + tax + lda varDepth,x + bne pointit + + lda truepid +folpid anop + asl2 a + asl2 a + asl2 a + asl a + sta pidx128 + tax + lda ParentProc,x ;parent id + jmi nope ;can't do it + asl a + tax + lda varDepth,x + bne tryit + ldx pidx128 + lda ParentProc,x + bra folpid + +tryit anop + +; +; Point to table +; +pointit txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + + ldy #4 + lda [p],y + sta tbl + iny2 + lda [p],y + sta tbl+2 + + ld2 VTABSIZE,count + +loop1 ldy #2 + lda [tbl] + sta p + lda [tbl],y + sta p+2 + ora p + beq nexttbl + +loop2 dec index + beq found + ldy #2 + lda [p] + tax + lda [p],y + sta p+2 + stx p + ora p + bne loop2 + +nexttbl add4 tbl,#4,tbl + dec count + bne loop1 + +nope stz p + stz p+2 + +found return 4:p + + END + +;========================================================================= +; +; Unset a variable. +; +;========================================================================= + +unsetvar START + + using VarData + using KernelStruct + +pidx128 equ 0 +ch equ pidx128+2 +thisname equ ch+2 +hashval equ thisname+4 +var equ hashval+2 +tbl equ var+4 +p equ tbl+4 +q equ p+4 +space equ q+4 + + subroutine (4:name),space + + pei (name+2) + pei (name) + jsl lowercstr + pei (name+2) + pei (name) + jsl hashvar + sta hashval + + lda truepid + asl a + tax + lda varDepth,x + bne pointit + + lda truepid +folpid anop + asl2 a + asl2 a + asl2 a + asl a + sta pidx128 + tax + lda ParentProc,x ;parent id + jmi done ;can't do it + asl a + tax + lda varDepth,x + bne tryit + ldx pidx128 + lda ParentProc,x + bra folpid + +tryit anop + +; +; Point to table +; +pointit txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + + clc + ldy #4 + lda [p],y + adc hashval + sta tbl + iny2 + lda [p],y + adc #0 + sta tbl+2 +; +; See if it's defined +; + ldy #2 + lda [tbl],y + sta p+2 + lda [tbl] + sta p + + mv4 tbl,q +; +; Check if end of list +; +loop lda p + ora p+2 + beq done +; +; Point to this variable name +; + ldy #4 + lda [p],y + sta thisname + iny2 + lda [p],y + sta thisname+2 +; +; Do a string comparison +; + pei (name+2) + pei (name) + pei (thisname+2) + pei (thisname) + jsl cmpcstr + cmp #0 + beq found +; +; follow link to next variable +; +next mv4 p,q + ldy #2 + lda [p] + tax + lda [p],y + sta p+2 + stx p + bra loop +; +; We found it, now unset it +; +found ldy #4+2 ;dispose the name + lda [p],y + pha + dey2 + lda [p],y + pha + jsl ~NDISPOSE + ldy #8+2 ;dispose the value + lda [p],y + pha + dey2 + lda [p],y + pha + jsl ~NDISPOSE + ldy #2 ;move pointers to look around it + lda [p] + sta [q] + lda [p],y + sta [q],y + pei (p+2) ;dispose the var + pei (p) + jsl ~NDISPOSE + +done return + + END + +;========================================================================= +; +; Export a variable. +; +;========================================================================= + +exportvar START + + using VarData + using KernelStruct + +pidx128 equ 0 +hashval equ pidx128+2 +var equ hashval+2 +tbl equ var+4 +p equ tbl+4 +space equ p+4 + + subroutine (4:name,2:flag),space + + pei (name+2) + pei (name) + jsl lowercstr + pei (name+2) + pei (name) + jsl hashvar + sta hashval + + lda truepid + asl a + tax + lda varDepth,x + bne pointit + + lda truepid +folpid anop + asl2 a + asl2 a + asl2 a + asl a + sta pidx128 + tax + lda ParentProc,x ;parent id + jmi done ;can't do it + asl a + tax + lda varDepth,x + bne tryit + ldx pidx128 + lda ParentProc,x + bra folpid + +tryit anop + +; +; Point to table +; +pointit txa + asl a + tax + lda varPtr,x + sta p + lda varPtr+2,x + sta p+2 + + clc + ldy #4 + lda [p],y + adc hashval + sta tbl + iny2 + lda [p],y + adc #0 + sta tbl+2 +; +; See if it's defined +; + ldy #2 + lda [tbl],y + pha + lda [tbl] + pha + pei (name+2) + pei (name) + jsl followlocvar + cmp #0 + bne found + cpx #0 + beq done + +found sta var + stx var+2 + ldy #12 + lda [var],y + ora flag + sta [var],y + +done return + + END + +;========================================================================= +; +; Follows a linked list of local variables. Returns pointer to var or nil. +; +;========================================================================= + +followlocvar START + +ch equ 0 +thisname equ ch+2 +space equ thisname+4 + + subroutine (4:p,4:varname),space +; +; Check if end of list +; +loop lda p + ora p+2 + beq done +; +; Point to this variable name +; + ldy #4 + lda [p],y + sta thisname + iny2 + lda [p],y + sta thisname+2 +; +; Do a string comparison +; + pei (varname+2) + pei (varname) + pei (thisname+2) + pei (thisname) + jsl cmpcstr + cmp #0 + beq found +; +; follow link to next variable +; +next ldy #2 + lda [p] + tax + lda [p],y + sta p+2 + stx p + bra loop + +done stz p ;we didn't find it + stz p+2 +found return 4:p + + END + +;========================================================================= +; +; Hash a variable +; +;========================================================================= + +hashvar PRIVATE + +hashval equ 0 +space equ hashval+2 + + subroutine (4:p),space + + lda #11 + sta hashval + + ldy #0 +loop lda hashval + asl a + sta hashval + lda [p],y + and #$FF + beq done + clc + adc hashval + sta hashval + iny + bra loop +done UDivide (hashval,#VTABSIZE),(@a,hashval) + + asl2 a ;Make it an index. + sta hashval + + return 2:hashval + + END + +;========================================================================= +; +; Variable Data [How much does the data vary?] - TM +; (^^^ Oh, My Lord!) - jb +;========================================================================= + +VarData DATA + +varPtr dc 32i4'0' +varDepth dc 32i2'0' + END