; > HostIO ; Interface to Host system ; ------------------------ ; 08-Feb-2008: RDCH/WRCH use direct TRAP calls ; 09-Feb-2008: CLI checks for *Quit, seperate ostty and mytty settings ; 10-Feb-2008: Vectors explicity set on startup, calls chain through to ; BBC calls if BBC environment available. ; 22-Aug-2008 ?? Set up unix handlers ; Initialise Host I/O system ; ========================== ; On entry, r5=&0BBC for BBC environment or <>&0BBC otherwise ; r6=>top of memory-2, bottom of stack, startup parameters ; stacked parameters end with -1 or 0 (documented as 0, actually -1) ; On exit, r0=bottom of memory ; r1=top of memory ; Could combine this with IO_CommandLine and recover space used by parameters. ; Keeping parameters means still have startup command available. ; .IO_Init adr IO_UNIX,r0 ; Default to UNIX TRAP calls mov 6(sp),r4 ; Address of first parameter beq IO_Init1 ; =0, no parameters, use UNIX I/O calls inc r4 ; Test for -1 beq IO_Init1 ; =-1, no parameters, use UNIX I/O calls dec r4 ; Restore r4 movb (r4)+,r1 ; Get first char of first param cmp r1,#ASC"-" ; Is it a switch? bne IO_Init1 ; No, use UNIX I/O calls movb (r4),r1 ; Get first char of first param bis #&20,r1 ; Ensure lower case cmp r1,#ASC"b" ; Is it "-b"? bne IO_Init1 ; No, use UNIX I/O calls adr IO_BBC,r0 ; Force use of BBC I/O calls .IO_Init1 adr IO_BBC,r2 ; Use BBC I/O fall-through calls cmp r5,#&0BBC ; Is BBC environment available? beq IO_Init2 ; Yes, use BBC calls adr IO_NUL,r2 ; Fall-through to nulls .IO_Init2 adr QUITV,r1 ; Point to vectors adr BBCQUITV,r3 mov #16,r4 ; 16 entries to fill in .IO_InitLp1 mov (r0)+,(r1)+ ; Copy to vector tables mov (r2)+,(r3)+ dec r4 bne IO_InitLp1 ; Loop for 16 entries ; ; Catch system signals ; -------------------- jsr pc,SetupSIGINT ; Catch user interupts (Escape) jsr pc,SetupSIGEMT ; Catch EMTs jsr pc,SetupSIGSYS ; Catch bad SYS (TRAP) calls ; ; trap 54 ; not available on v6 ; equw 0 ; filedes ; equw TIOCGETP ; request ; equw SV_OSIOCTL ; argp ; ; On Unix v6, trap 54 returns to next instruction ; On Unix v7, trap 54 skips three words on return ; 'RTI' is opcode 2, 2=STDERR ; ; ; MOVB #27,SV_OSIOCTL+0 ; Interupt ; ; trap 54 ; equw 0 ; filedes ; equw TIOCSETP ; request ; equw SV_OSIOCTL ; argp ; Set up tty and keep copy to restore ; ----------------------------------- clr r0 ; 0=STDIN trap 32 ; gtty() equw SV_OSTTY ; Read host TTY setting mov SV_OSTTY+0,SV_MYTTY+0 ; Copy to mytty settings mov SV_OSTTY+2,SV_MYTTY+2 mov SV_OSTTY+4,r0 bic #8,r0 ; Echo off bis #32,r0 ; Raw on mov r0,SV_MYTTY+4 clr r0 ; 0=STDIN trap 31 ; stty() equw SV_MYTTY ; Set my TTY setting ; ; Return memory limits ; -------------------- adr BasicEnd,r0 ; r0=bottom of memory mov sp,r1 add #2,r1 ; r1=top of memory rts pc ; Copy any command line to string buffer ; ====================================== ; sp=>retaddr, argn, arg[0], arg[1], ... 0 ; .IO_CommandLine mov sp,r3 ; Point to stack frame add #6,r3 ; Point to first parameter adr SV_STRING,r1 ; Point to string buffer .IO_CmdSkip mov (r3)+,r2 ; Get address of parameter beq IO_CmdEnd ; =0 - end of parameters inc r2 beq IO_CmdEnd ; =-1 - end of parameters dec r2 movb (r2),r0 ; Check this parameter cmpb r0,#ASC"-" ; Is it an option to BASIC beq IO_CmdSkip ; Skip BASIC options sub #2,r3 ; Adjust for following increment .IO_CmdNext mov (r3)+,r2 ; Get address of parameter beq IO_CmdEnd ; End of parameters .IO_CmdCopy movb (r2)+,(r1)+ ; Copy bytes from parameter to string buffer bne IO_CmdCopy ; Loop until zero byte movb #32,&FFFF(r1) ; Replace zero byte with space br IO_CmdNext ; Jump back for next parameter .IO_CmdEnd movb #13,(r1) ; Store terminating adr SV_STRING,r4 ; r4=>command line movb (r4),r0 ; Get first byte from string cmp r0,#13 ; Is it null string - no parameters? rts pc ; Return EQ=no command line, NE=command line found ; IO jump block entries for Unix environment ; ------------------------------------------ .IO_UNIX equw UNIX_QUIT equw UNIX_CLI equw UNIX_BYTE equw UNIX_WORD equw UNIX_WRCH equw UNIX_NEWL equw UNIX_RDCH equw UNIX_FILE equw UNIX_ARGS equw UNIX_BGET equw UNIX_BPUT equw UNIX_GBPB equw UNIX_FIND equw UNIX_SYS1 equw UNIX_SYS2 equw UNIX_ERROR ; IO jump block entries for BBC environment ; ----------------------------------------- .IO_BBC equw BBC_QUIT equw BBC_CLI equw BBC_BYTE equw BBC_WORD equw BBC_WRCH equw BBC_NEWL equw BBC_RDCH equw BBC_FILE equw BBC_ARGS equw BBC_BGET equw BBC_BPUT equw BBC_GBPB equw BBC_FIND equw BBC_SYS1 equw BBC_SYS2 equw BBC_ERROR ; IO jump block entries for null returns ; -------------------------------------- .IO_NUL equw NUL_QUIT equw NUL_CLI equw NUL_BYTE equw NUL_WORD equw NUL_WRCH equw NUL_NEWL equw NUL_RDCH equw NUL_FILE equw NUL_ARGS equw NUL_BGET equw NUL_BPUT equw NUL_GBPB equw NUL_FIND equw NUL_SYS1 equw NUL_SYS2 equw NUL_ERROR ; IO entry points ; =============== .IO_QUIT0 MOV #0,R0 ; Quit with status=0 .IO_QUIT JSR PC,@QUITV ; Quit BVS IO_Error RTS PC .IO_CLI JSR PC,@CLIV ; Execute command BVS IO_Error RTS PC .IO_BYTE JSR PC,@BYTEV ; Byte operation BVS IO_Error RTS PC .IO_WORD JSR PC,@WORDV ; Control block operation BVS IO_Error RTS PC .IO_ASCI CMP R0,#13 ; Print ASCII character BEQ IO_NEWL .IO_WRCH JSR PC,@WRCHV ; Send char to output stream BVS IO_Error RTS PC .IO_NEWL JSR PC,@NEWLV ; Send NEWLINE to output stream BVS IO_Error RTS PC .IO_RDCH JSR PC,@RDCHV ; Read char from input stream BVS IO_Error RTS PC .IO_FILE JSR PC,@FILEV ; Whole file operations BVS IO_Error RTS PC .IO_ARGS JSR PC,@ARGSV ; Information on open files BVS IO_Error RTS PC .IO_BGET JSR PC,@BGETV ; Get byte from channel BVS IO_Error RTS PC .IO_BPUT JSR PC,@BPUTV ; Put byte to channel BVS IO_Error RTS PC .IO_GBPB JSR PC,@GBPBV ; Block read/write BVS IO_Error RTS PC .IO_FIND JSR PC,@FINDV ; Open or close file BVS IO_Error RTS PC .IO_SYS1 JSR PC,@sys1V BVS IO_Error RTS PC .IO_SYS2 JSR PC,@sys2V BVS IO_Error RTS PC .IO_ERROR JSR PC,@ERRV ; Generate an error BVS IO_Error RTS PC .IO_Error ; R0=>error block byte,string,zero byte clv mov r0,-(sp) jmp Error ; NUL returns ; =========== .NUL_QUIT .NUL_CLI .NUL_BYTE .NUL_WORD .NUL_WRCH .NUL_NEWL .NUL_RDCH .NUL_FILE .NUL_ARGS .NUL_BGET .NUL_BPUT .NUL_GBPB .NUL_FIND .NUL_SYS1 .NUL_SYS2 .NUL_ERROR clv rts pc ; Direct calls to BBC MOS I/O calls ; ================================= .BBC_QUIT emt 0 ; Won't actually get back! rts pc .BBC_CLI emt 1 ; r0=>command string rts pc .BBC_BYTE emt 2 ; Osbyte r0,r1,r2 rts pc .BBC_WORD emt 3 ; Osword r0,r1=>block rts pc .BBC_WRCH emt 4 ; Oswrch r0=char rts pc .BBC_NEWL emt 5 ; Print NEWLINE rts pc .BBC_RDCH emt 6 ; Osrdch r0=char rts pc .BBC_FILE emt 7 ; Osfile r0=action, r1=>block rts pc .BBC_ARGS emt 8 ; Osargs r0=action, r1=>block, r2=handle rts pc .BBC_BGET emt 9 ; Osbget r1=handle rts pc .BBC_BPUT emt 10 ; Osbput r0=byte, r1=handle rts pc .BBC_GBPB emt 11 ; Osgbpb r0=action, r1=>block rts pc .BBC_FIND emt 12 ; Osfind r0=action, r1=>filename or handle rts pc .BBC_SYS1 emt 13 rts pc .BBC_SYS2 emt 14 rts pc .BBC_ERROR emt 15 ; Generate inline error rts pc ; Calls translated to UNIX TRAPs ; ============================== ; OSNEWL - Output newline to output stream ; ======================================== .UNIX_NEWL ; Print NEWLINE mov #10,r0 jsr pc,IO_WRCH .UNIX_WRCR ; Print CR mov #13,r0 ; OSWRCH - Output character to output stream ; ========================================== ; On entry, R0=character ; On exit, all registers preserved ; .UNIX_WRCH mov r0,MOS_BUF ; Store char in buffer mov #1,r0 ; STDOUT=1 trap 4 ; write() equw MOS_BUF ; address=buffer equw 1 ; count=1 mov MOS_BUF,r0 ; Restore r0 clv ; Clear error state rts pc ; OSRDCH - Wait for character from input stream ; ============================================= ; On exit, R0=character ; CC=not escape, CS=escape ; .UNIX_RDCH clr r0 ; STDIN=0 trap 3 ; read() equw MOS_BUF ; address=buffer equw 1 ; count=1 movb MOS_BUF,r0 ; Fetch char from buffer cmp r0,#27 ; Escape character? beq UNIX_RDCH_ESC clc ; Not Escape clv ; No error rts pc .UNIX_RDCH_ESC sec ; Escape character clv ; No error rts pc ; OSQUIT - Quit execution ; ======================= ; On entry, R0=exit status ; .UNIX_QUIT mov r0,-(sp) ; Save exit status clr r0 ; 0=STDIN trap 31 ; stty() equw SV_OSTTY ; Set host TTY setting trap 48 ; signal(SIGSYS,0) equw 12 equw 0 trap 48 ; signal(SIGEMT,0) equw 7 equw 0 trap 48 ; signal(SIGINT,0) equw 2 equw 0 mov (sp)+,r0 ; Get exit status back trap 1 ; exit(r0) clv ; Clear error state rts pc ; Just in case we get back! ; OSWORD - Host calls with parameters in control block ; ==================================================== ; On entry, R0=action ; R1=>control block ; On exit, All registers undefined ; .UNIX_WORD tst r0 beq UNIX_WORD0 ; Jump for OSWORD 0, Read Line jmp @BBCWORDV ; Fall through to BBC call ; Read line of text ; ----------------- ; On entry, R1=>address of memory to read string to ; On exit, R2=length of string ; CC=ok, CS=Escape pressed ; .UNIX_WORD0 mov r1,-(sp) ; Save pointer to control block mov r3,-(sp) ; Save R3 mov (r1),r1 ; Get pointer to buffer clr r2 ; Zero number of characters read .RdLnLoop jsr pc,IO_RDCH ; Get a character bcs RdLnEsc ; Escape state cmp r0,#13 beq RdLnCR ; - End of line cmp r0,#10 beq RdLnCR ; - End of line cmp r0,#21 beq RdLnU ; Ctrl-U - delete line cmp r0,#127 beq RdLnDel ; - del a character cmp r0,#8 beq RdLnDel ; - del a character cmp r0,#ASC" " bcs RdLnLoop ; Ignore other control characters cmp r2,#240 bcc RdLnLoop ; No more room for characters movb r0,(r1)+ ; Put character into memory add #1,r2 ; Inc. number of characters jsr pc,IO_WRCH ; Output the character br RdLnLoop ; Go back for another ; .RdLnU mov r2,r3 ; We want to delete all characters br RdLnDelete .RdLnDel mov #1,r3 ; We only want to delete one char .RdLnDelete tst r2 ; Check line length beq RdLnLoop ; Length=0, jump back to main loop mov #8,r0 ; Output by backspacing jsr pc,IO_WRCH mov #32,r0 jsr pc,IO_WRCH mov #8,r0 jsr pc,IO_WRCH dec r1 ; Back address pointer dec r2 ; Dec character counter ;sob r3,RdLnDelete ; Loop for each to delete dec r3 bne RdLnDelete ; Loop for each to delete br RdLnLoop ; Go back into ReadLine loop ; .RdLnEsc jsr pc,IO_NEWL ; Print newline clr r2 ; Length = 0 mov (sp)+,r3 ; Restore R3 mov (sp)+,r1 ; Get buffer address back movb r0,(r1) ; Put terminator in sec ; Set carry - escape rts pc ; .RdLnCR mov #13,r0 ; Convert to movb r0,(r1)+ ; Put terminator in jsr pc,IO_NEWL ; Returns with r0= clc ; Clear carry - ok .RdLnEnd mov (sp)+,r3 ; Restore R3 mov (sp)+,r1 ; Get buffer address back clr r0 ; Restore R0 rts pc ; r0=0, r1=buffer, r2=length ; OSCLI - Execute command ; ======================= ; Initially, just checks for *Quit .UNIX_CLI ; r0=>command string mov r1,-(sp) mov r0,-(sp) mov r0,r1 .CLI_lp1 movb (r1)+,r0 cmp r0,#ASC"*" beq CLI_lp1 ; Skip spaces cmp r0,#ASC" " beq CLI_lp1 mov r1,-(sp) ; Save address after '*'s and ' 's bic #32,r0 cmp r0,#ASC"Q" bne CLI_not movb (r1)+,r0 bic #32,r0 cmp r0,#ASC"U" bne CLI_not movb (r1)+,r0 bic #32,r0 cmp r0,#ASC"I" bne CLI_not movb (r1)+,r0 bic #32,r0 cmp r0,#ASC"T" bne CLI_not movb (r1),r0 cmp r0,#ASC"!" bcc CLI_not jmp IO_QUIT0 .CLI_not mov (sp)+,r1 ; Get command line address back ; ; (pc+0)=>name ; (pc+2)=argv ; mov (sp)+,r0 ; Restore registers mov (sp)+,r1 jmp @BBCCLIV ; Fall through to BBC call ; OSBYTE - Host calls with byte parameters ; ======================================== .UNIX_BYTE jmp @BBCBYTEV ; Osbyte r0,r1,r2 ; Fall through to BBC calls ; ========================= .UNIX_FILE jmp @BBCFILEV ; Osfile r0=action, r1=>block .UNIX_ARGS jmp @BBCARGSV ; Osargs r0=action, r1=>block, r2=handle .UNIX_BGET jmp @BBCBGETV ; Osbget r1=handle .UNIX_BPUT jmp @BBCBPUTV ; Osbput r0=byte, r1=handle .UNIX_GBPB jmp @BBCGBPBV ; Osgbpb r0=action, r1=>block .UNIX_FIND jmp @BBCFINDV ; Osfind r0=action, r1=>filename or handle .UNIX_SYS1 jmp @BBCSYS1V .UNIX_SYS2 jmp @BBCSYS2V .UNIX_ERROR jmp @BBCERRV ; Generate error .SetupSIGINT trap 48 ; signal() equw 2 ; SIGINT - User interupt (Escape) equw CatchSIGINT rts pc .CatchSIGINT jsr pc,SetupSIGINT ; Reconnect handler ;;movb #&FF,SV_ESCAPE ; Set local Escape flag rti .SetupSIGEMT trap 48 ; signal() equw 7 ; SIGEMT - EMT call equw CatchSIGEMT rts pc .CatchSIGEMT jsr pc,SetupSIGEMT ; Reconnect handler rti .SetupSIGSYS trap 48 ; signal() equw 12 ; SIGSYS - unknown SYS (TRAP) call equw CatchSIGSYS rts pc .CatchSIGSYS jsr pc,SetupSIGSYS ; Reconnect handler rti