Microsoft (R) Macro Assembler Version 6.14.8444 07/16/15 23:17:30 unix.asm Page 1 - 1 ; **************************************************************************** ; ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) ; ---------------------------------------------------------------------------- ; ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) ; 1.44 MB Floppy Disk ; (11/03/2013) ; ; [ Last Modification: 16/07/2015 ] ; ; Derivation from UNIX Operating System (v1.0 for PDP-11) ; (Original) Source Code by Ken Thompson (1971-1972) ; ; ; ; **************************************************************************** ; 28/08/2014, 01/09/2014 ; 20/07/2014, 21/07/2014, 23/07/2014, 24/07/2014, 27/07/2014, 28/07/2014 ; 05/07/2014, 07/07/2014, 08/07/2014, 09/07/2014, 12/07/2014, 18/07/2014 ; 26/06/2014, 27/06/2014, 30/06/2014, 01/07/2014, 03/07/2014, 04/07/2014 ; 31/05/2014, 02/06/2014, 03/06/2014, 11/06/2014, 23/06/2014, 25/06/2014 ; 05/05/2014, 19/05/2014, 20/05/2014, 22/05/2014, 26/05/2014, 30/05/2014 ; 17/04/2014, 22/04/2014, 25/04/2014, 29/04/2014, 30/04/2014, 01/05/2014 ; 24/03/2014, 04/04/2014, 10/04/2014, 11/04/2014, 14/04/2014, 15/04/2014 ; 04/03/2014, 07/03/2014, 08/03/2014, 12/03/2014, 18/03/2014, 20/03/2014 ; 14/02/2014, 17/02/2014, 23/02/2014, 25/02/2014, 28/02/2014, 03/03/2014 ; 18/01/2014, 20/01/2014, 21/01/2014, 26/01/2014, 01/02/2014, 05/02/2014 ; 10/01/2014, 12/01/2014, 13/01/2014, 14/01/2014, 16/01/2014, 17/01/2014 ; 03/12/2013, 04/12/2013, 06/12/2013, 07/12/2013, 10/12/2013, 12/12/2013 ; 24/10/2013, 30/10/2013, 04/11/2013, 18/11/2013, 19/11/2013, 30/11/2013 ; 22/09/2013, 24/09/2013, 05/10/2013, 10/10/2013, 20/10/2013, 23/10/2013 ; 30/08/2013, 26/08/2013, 03/09/2013, 13/09/2013, 17/09/2013, 20/09/2013 ; 18/08/2013, 16/08/2013, 14/08/2013, 13/08/2013, 12/08/2013, 11/08/2013 ; 09/08/2013, 08/08/2013, 05/08/2013, 03/08/2013, 02/08/2013, 01/08/2013 ; 31/07/2013 user/u structure (u.rw and u.namei_r has been removed) ; 30/07/2013, 29/07/2013 ; 28/07/2013 u.rw, u.namei_r, u.ttyn, u.errn ; 26/07/2013, 25/07/2013, 24/07/2013, 17/07/2013, 16/07/2013, 14/07/2013 ; 13/07/2013 kernel initialization additions & modifications ; 09/07/2013 ; 20/06/2013 set date & time (for 'sysstime' system call) ; 04/06/2013 ecore (sysexec) ; 03/06/2013 p_time (systime, sysmdate) ; 26/05/2013 ; 24/05/2013 (end of core) ; 21/05/2013 com_stat: owner and status of COM/serial port (1&2) ; 10/05/2013 tty modifications (keyboard functions) ; 26/04/2013 device numbers, structure modifications ; 11/03/2013 = 0010 nproc equ 16 ; number of processes = 0032 nfiles equ 50 = 0008 ntty equ 8 ; 8+1 -> 8 (10/05/2013) = 0006 nbuf equ 6 = 2000 csgmnt equ 2000h ; 26/05/2013 (segment of process 1) = 0000 core equ 0 ; 19/04/2013 = 7FC0 ecore equ 32768 - 64 ; 04/06/2013 (24/05/2013) ; (if total size of argument list and arguments is 128 bytes) ; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes ; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570) ; initial value of user's stack pointer = 32768-64-128-2 = 32574 ; (sp=32768-args_space-2 at the beginning of execution) ; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes) ; 'u' structure offset (for the '/core' dump file) = 32704 ; '/core' dump file size = 32768 bytes ; 08/03/2014 = 06C0 sdsegmnt equ 6C0h ; 256*16 bytes (swap data segment size for 16 processes) ; 19/04/2013 Retro UNIX 8086 v1 feaure only ! ;sdsegmnt equ 740h ; swap data segment (for user structures and registers) ; 30/08/2013 = 0004 time_count equ 4 ; 10 --> 4 01/02/2014 ; 05/02/2014 ; process status ;SFREE equ 0 ;SRUN equ 1 ;SWAIT equ 2 ;SZOMB equ 3 ;SSLEEP equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup) 0040 user struc ; 10/10/2013 ; 11/03/2013. ;Derived from UNIX v1 source code 'user' structure (ux). ;u. 0000 0000 sp_ dw ? ; sp 0002 0000 usp dw ? 0004 0000 r0 dw ? 0006 0000 cdir dw ? 0008 000A [ fp db 10 dup(?) 00 ] 0012 0000 fofp dw ? 0014 0000 dirp dw ? 0016 0000 namep dw ? 0018 0000 off dw ? 001A 0000 base dw ? 001C 0000 count dw ? 001E 0000 nread dw ? 0020 0000 break_ dw ? ; break 0022 0000 ttyp dw ? 0024 000A [ dirbuf db 10 dup(?) 00 ] ;pri dw ? ; 14/02/2014 002E 00 quant db ? ; Retro UNIX 8086 v1 Feature only ! (uquant) 002F 00 pri db ? ; 0030 0000 intr dw ? 0032 0000 quit dw ? ; emt dw ? ; 10/10/2013 0034 0000 ilgins dw ? 0036 0000 cdrv dw ? ; cdev 0038 00 uid_ db ? ; uid 0039 00 ruid db ? 003A 00 bsys db ? 003B 00 uno db ? ; user/program segment (12/03/2013) 003C 0000 segmnt dw ? ; 12/03/2013 - Retro Unix 8086 v1 feature only ! ; tty number (rtty, rcvt, wtty) 003E 00 ttyn db ? ; 28/07/2013 - Retro Unix 8086 v1 feature only ! ; last error number (reserved) 003F 00 errn db ? ; 28/07/2013 - Retro Unix 8086 v1 feature only ! user ends 00A0 process struc ; 05/02/2014 ttys -> waitc (waiting channel, tty number) ; 17/09/2013 ttys (10 byte structure) ; 03/09/2013 ttyc (word -> byte) [ 10 bytes -> 9 bytes ] ; 14/08/2013 dska -> ttyc ; 11/03/2013. ;Derived from UNIX v1 source code 'proc' structure (ux). ;p. 0000 0010 [ pid dw nproc dup(?) 0000 ] 0020 0010 [ ppid dw nproc dup(?) 0000 ] 0040 0010 [ break dw nproc dup(?) 0000 ] 0060 0010 [ ttyc db nproc dup(?) ; console tty in Retro UNIX 8086 v1. 00 ] 0070 0010 [ waitc db nproc dup(?) ; waiting channel in Retro UNIX 8086 v1. 00 ] 0080 0010 [ link db nproc dup(?) 00 ] 0090 0010 [ stat db nproc dup(?) 00 ] process ends 0020 inode struc ; 11/03/2013. ;Derived from UNIX v1 source code 'inode' structure (ux). ;i. 0000 0000 flgs dw ? 0002 00 nlks db ? 0003 00 uid db ? 0004 0000 size_ dw ? ; size 0006 0008 [ dskp dw 8 dup(?) ; 16 bytes 0000 ] 0016 00000000 ctim dd ? 001A 00000000 mtim dd ? 001E 0000 rsvd dw ? ; Reserved (ZERO/Undefined word for UNIX v1.) inode ends 00DA systm struc ; 11/03/2013. ;Derived from UNIX v1 source code 'systm' structure (ux). ;s. 0000 0000 dw ? 0002 0080 [ db 128 dup(?) 00 ] 0082 0000 dw ? 0084 0040 [ db 64 dup (?) 00 ] 00C4 00000000 time dd ? 00C8 00000000 syst dd ? 00CC 00000000 wait_ dd ? ; wait 00D0 00000000 idlet dd ? 00D4 00000000 chrgt dd ? 00D8 0000 drerr dw ? systm ends ; fsp table entry (8 bytes) ;; 19/04/2013 ; inum dw 0 ; inode number ; devnum dw 0 ; device number ; ofsp dw 0 ; offset pointer ; oc db 0 ; open count ; df db 0 ; deleted flag ; 0024 phydrv struc ; 26/04/2013 (09/07/2013) ; Physical drv parameters of Retro UNIX 8086 v1 devices ; Retro UNIX 8086 v1 feature only ! 0000 0006 [ err db 6 dup(?) ; error status (>0 means error) 00 ] 0006 0006 [ pdn db 6 dup(?) ; physical drive number 00 ] 000C 0006 [ spt dw 6 dup(?) ; sectors per track 0000 ] 0018 0006 [ hds dw 6 dup(?) ; heads 0000 ] phydrv ends ; 14/07/2013 ; UNIX v1 system calls = 0000 _rele equ 0 = 0001 _exit equ 1 = 0002 _fork equ 2 = 0003 _read equ 3 = 0004 _write equ 4 = 0005 _open equ 5 = 0006 _close equ 6 = 0007 _wait equ 7 = 0008 _creat equ 8 = 0009 _link equ 9 = 000A _unlink equ 10 = 000B _exec equ 11 = 000C _chdir equ 12 = 000D _time equ 13 = 000E _mkdir equ 14 = 000F _chmod equ 15 = 0010 _chown equ 16 = 0011 _break equ 17 = 0012 _stat equ 18 = 0013 _seek equ 19 = 0014 _tell equ 20 = 0015 _mount equ 21 = 0016 _umount equ 22 = 0017 _setuid equ 23 = 0018 _getuid equ 24 = 0019 _stime equ 25 = 001A _quit equ 26 = 001B _intr equ 27 = 001C _fstat equ 28 = 001D _emt equ 29 = 001E _mdate equ 30 = 001F _stty equ 31 = 0020 _gtty equ 32 = 0021 _ilgins equ 33 = 0022 _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! sys macro syscallnumber ; 14/07/2013 ; Retro UNIX 8086 v1 system call. mov ax, syscallnumber int 20h endm .8086 0000 UNIX SEGMENT PUBLIC PARA 'CODE' assume cs:UNIX,ds:UNIX,es:UNIX,ss:UNIX 0000 START: ; 11/03/2013 ; include files according to original UNIX v1 (except ux.s) ; (u0.s, u1.s, u2.s, u3.s, u34.s, u5.s, u6.s, u7.s, u8.s, u9.s) ; include u0.asm ; u0.s (with major modifications for 8086 PC) C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U0.ASM (include u0.asm) //// UNIX v1 -> u0.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 28/07/2014 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 23/07/2014, 27/07/2014 C ; 07/07/2014, 08/07/2014, 12/07/2014, 20/07/2014 C ; 30/06/2014, 03/07/2014, 04/07/2014, 05/07/2014 C ; 23/06/2014, 25/06/2014, 26/06/2014, 27/06/2014 C ; 22/05/2014, 26/05/2014, 02/06/2014, 03/06/2014 C ; 01/05/2014, 05/05/2014, 19/05/2014, 20/05/2014 C ; 14/04/2014, 25/04/2014, 29/04/2014, 30/04/2014 C ; 03/03/2014, 04/03/2014, 07/03/2014, 12/03/2014 C ; 05/02/2014, 14/02/2014, 23/02/2014, 28/02/2014 C ; 17/01/2014, 18/01/2014, 20/01/2014, 01/02/2014 C ; 30/10/2013, 04/12/2013, 06/12/2013, 10/12/2013 C ; 24/09/2013, 29/09/2013, 05/10/2013, 10/10/2013 C ; 30/08/2013, 03/09/2013, 17/09/2013, 20/09/2013 C ; 23/07/2013, 29/07/2013, 11/08/2013, 12/08/2013 C ; 16/07/2013, 17/07/2013, 18/07/2013, 22/07/2013 C ; 15/07/2013, 20/05/2013, 21/05/2013, 27/05/2013 C ; 15/05/2013, 17/05/2013, 13/07/2013, 14/07/2013 C ; 11/03/2013, 11/04/2013, 09/05/2013, 10/05/2013 C C ; 29/04/2014 --> serial port (terminal) login functionality test C ; by using fake INT 14h, tty6, tty7 C ; etc/init has been modified for leaving tty6 and tty7 free C 0000 C kernel_init: C ; 07/03/2014 C ; 04/03/2013 C ; 28/02/2014 C ; 14/02/2014 C ; 05/02/2014 C ; 04/12/2013 C ; 05/10/2013 C ; 29/07/2013 C ; 18/07/2013 C ; 17/07/2013 C ; 14/07/2013 C ; 13/07/2013 C ; Retro UNIX 8086 v1 feature only ! C ; C ; Retro UNIX 8086 v1 C ; kernel relies on data from its 'boot' program ... C ; C ;;mov ax, cs C ;mov ds, ax C ;mov es, ax C ;cli C ;mov ss, ax C ;mov sp, 32766 C ;sti C ; mov bp, sp 0000 88 16 2564 R C mov byte ptr [unixbootdrive], dl 0004 8E D9 C mov ds, cx ; boot sector segment C ; bx = boot sector buffer 0006 8B 47 02 C mov ax, word ptr [BX]+2 ; 14/07/2013 0009 8B 57 04 C mov dx, word ptr [BX]+4 ; 14/07/2013 000C 0E C push cs 000D 1F C pop ds 000E 3D 5552 C cmp ax, 'UR' 0011 74 03 E9 0094 C jne kernel_init_err ; jne short kernel_init_err 0016 81 FA 5346 C cmp dx, 'SF' 001A 74 03 E9 008B C jne kernel_init_err ; jne short kernel_init_err C ; 001F E8 1930 C call drv_init 0022 73 03 E9 0083 C jc kernel_init_err ; jne short kernel_init_err C ; C ; 14/02/2014 C ; 14/07/2013 0027 B8 0029 C mov ax, 41 002A A3 2C00 R C mov word ptr [rootdir], ax 002D A3 38D2 R C mov word ptr [u.cdir], ax 0030 B0 01 C mov al, 1 0032 A2 3907 R C mov byte ptr [u.uno], al 0035 A3 2BFE R C mov word ptr [mpid], ax 0038 A3 298E R C mov word ptr [p.pid], ax 003B A2 2A1E R C mov byte ptr [p.stat], al ; SRUN, 05/02/2014 C ; 003E B0 04 C mov al, time_count ; 30/08/2013 C ;; 29/07/2013 C ;;mov byte ptr [s.wait_]+2, al C ;;mov byte ptr [s.idlet]+2, al C ; 14/02/2014 uquant -> u.quant 0040 A2 38FA R C mov byte ptr [u.quant], al ; 14/07/2013 C ; 22/07/2013 0043 8C C8 C mov ax, cs 0045 A3 3908 R C mov word ptr [u.segmnt], ax ; reset to CS C ; 0048 E8 2342 C call epoch 004B A3 262E R C mov word ptr [s.time], ax 004E 89 16 2630 R C mov word ptr [s.time]+2, dx C ; 0052 E8 0094 C call kb_init C ; ES = 0 (30/06/2014) C ; C ; 28/02/2014 INT 16h handler 0055 B8 1CDF R C mov ax, offset int_16h 0058 BF 0058 C mov di, 22*4 ; INT 16h vector - offset 005B AB C stosw 005C 8C C8 C mov ax, cs 005E AB C stosw C ;mov es, ax ; 30/06/2014) C ; C ;; 10/12/2013 C ;; INT 1Ch handling disabled here, C ;; it will be enabled by 'sys emt' C ;; system call (in 'etc/init') C ; INT 1Ch (clock/timer) transfer to unix kernel C ;; 30/06/2014 C ;;xor ax, ax C ;;mov es, ax ; 0 C ;; ES = 0 C ;mov di, 28*4 ; INT 1Ch vector - offset C ;cli C ;mov ax, offset clock C ;stosw ; offset C ;mov ax, cs C ;stosw ; segment C ;sti C ; C ; setting up syscall vector (int 20h) 005F B8 0263 R C mov ax, offset sysent 0062 BF 0080 C mov di, 32*4 ; INT 20h for system calls 0065 AB C stosw 0066 8C C8 C mov ax, cs 0068 AB C stosw C ;mov es, ax ; 14/04/2014 C ; C ; C ;; 13/07/2013 C ;; Kernel is running message ... (temporary) C ; 0069 BE 392F R C mov si, offset kernel_init_ok_msg C ; 07/03/2014 C ;call print_msg 006C AC C lodsb 006D B4 0E C mov ah, 0Eh 006F BB 0007 C mov bx, 07h 0072 C @@: 0072 CD 10 C int 10h 0074 AC C lodsb 0075 22 C0 C and al, al 0077 75 F9 C jnz short @b C ; C ; 17/01/2014 C ; ES = 0 0079 E8 0185 C call sp_init ; serial port interrupts C ; 14/04/2014 007C 8C C8 C mov ax, cs 007E 8E C0 C mov es, ax C ; C ; 05/10/2013 Temporary 0080 32 C0 C xor al, al ; mov al, 0 C ; mov byte ptr [u.ttyn], 0 0082 E8 1986 C call getc C ; 16/07/2013 C ;xor al, al C ; 04/12/2013 0085 32 DB C xor bl, bl ; video page 0 0087 C @@: ; clear video pages (reset cursor positions) 0087 E8 0115 C call vp_clr ; 17/07/2013 008A FE C3 C inc bl 008C 80 FB 08 C cmp bl, 8 008F 72 F6 C jb short @b C ; C ; 17/07/2013 C ;mov al, byte ptr [unixbootdrive] C ;cmp al, 80h ; 128 (80h->hd0) C ;jna short @f C ;sub al, 7Eh ; 126 (2->hd0) C ;@@: C ;mov byte ptr [rdev], al C ; 0091 E8 1953 C call bf_init ; buffer initialization ; 17/07/2013 C C ;; original UNIX v1 (PDP-11) code here: C ; / make current program a user C ; C ; mov $41.,r0 / rootdir set to 41 and never changed C ; mov r0,rootdir / rootdir is i-number of root directory C ; mov r0,u.cdir / u.cdir is i-number of process current directory C ; mov $1,r0 C ; movb r0,u.uno / set process table index for this process to 1 C ; mov r0,mpid / initialize mpid to 1 C ; mov r0,p.pid / p.pid identifies process C ; movb r0,p.stat / process status = 1 i.e., active C ; / = 0 free C ; / = 2 waiting for a child to die C ; / = 3 terminated but not yet waited C ; / for C ; 18/01/2014 C ;sti C ; 24/07/2013 0094 BB 00B6 R C mov bx, offset init_file 0097 B9 00B2 R C mov cx, offset init_argp C ; (([u.segmnt] = CS)) C ; BX contains 'etc/init' asciiz file name address C ; CX contains address of argument list pointer C ; 009A FE 0E 2C07 R C dec byte ptr [sysflg] ; FFh = ready for system call C ; 0 = executing a system call C ;mov ax, _exec C ;int 20h C sys _exec ; execute file 1C ; 14/07/2013 1C ; Retro UNIX 8086 v1 system call. 009E B8 000B 1C mov ax, _exec 00A1 CD 20 1C int 20h C ; 00A3 73 1B C jnc short panic C ; 00A5 BE 399B R C mov si, offset etc_init_err_msg 00A8 EB 03 C jmp short @f C C ;; original UNIX v1 (PDP-11) code here: C ; 1: C ; decb sysflg / normally sysflag=0, indicates executing in system C ; sys exec; 2f; 1f / generates trap interrupt; trap vector = C ; / sysent; 0 C ; br panic / execute file/etc/init C C ; 1: C ; 2f;0 C ; 2: C ; / UNIX looks for strings term, noted by nul\0 C 00AA C kernel_init_err: C ;; NOTE: UNix kernel will load boot sector C ;; 00AA BE 390C R C mov si, offset kernel_init_err_msg 00AD C @@: 00AD E8 0029 C call print_msg 00B0 EB 14 C jmp short key_to_reboot C C align 2 00B2 C init_argp: 00B2 00B6 R 0000 C dw offset init_file, 0 00B6 C init_file: 00B6 2F 65 74 63 2F 69 C db '/etc/init', 0 6E 69 74 00 C 00C0 C panic: C ; 07/03/2014 C ; 05/10/2013 ('call getc' instead of 'int 16h') C ; 14/07/2013 (panic_msg/print_msg) C ; 10/04/2013 C ; C ; Retro Unix 8086 v1 modification on original Unix v1 panic procedure! C ; C 00C0 BE 3980 R C mov si, offset panic_msg 00C3 E8 0013 C call print_msg 00C6 C key_to_reboot: C ;hlt C ; 05/10/2013 00C6 32 C0 C xor al, al 00C8 E8 1940 C call getc C ; 00CB B0 0A C mov al, 0Ah 00CD 8A 26 2C4A R C mov ah, byte ptr [ptty] ; [active_page] 00D1 E8 19D7 C call write_tty C C ; C ; 15/07/2013 C ;mov ah, 0Eh C ;;mov bx, 07h C ;;mov al, 0Dh C ;;int 10h C ;mov al, 0Ah C ;int 10h C 00D4 C cpu_reset: C ; 07/03/2014 C ; CPU reset (power on) address 00D4 EA C db 0EAh ; far jump (jmp 0FFFFh:0000h) 00D5 0000 C dw 0 00D7 FFFF C dw 0FFFFh ; F000:0FFF0h C C ;khere: hlt C ; jmp short khere C C ;@@: C ; 24/09/2013 C ; Reset INT 09h vector for next start-up C ;xor di, di C ;mov es, di C ;mov di, 4*9 C ;mov si, offset int09h C ;movsw C ;movsw C ; C ;int 19h C C ; hlt C ; jmp short @b C C ; clr ps C ;1: C ; dec $0 C ; bne 1b C ; dec $5 C ; bne 1b C ; jmp *$173700 / rom loader address C 00D9 C print_msg: C ; 07/03/2014 C ; (Modified registers: AX, BX, CX, DX, SI, DI) C ; 00D9 AC C lodsb 00DA C @@: 00DA 56 C push si 00DB 8A 26 2C4A R C mov ah, byte ptr [ptty] 00DF E8 19C9 C call write_tty 00E2 5E C pop si 00E3 AC C lodsb 00E4 22 C0 C and al, al 00E6 75 F2 C jnz short @b 00E8 C3 C retn C C ; 14/07/2013 C ; 13/07/2013 C ;lodsb C ;mov bx, 07h C ;mov ah, 0Eh C ;@@: C ;int 10h C ;lodsb C ;and al, al C ;jnz short @b C ;retn C 00E9 C kb_init: C ; 30/06/2014 C ; 03/03/2014 C ; 11/08/2013 C ; 16/07/2013 C ; 15/07/2013 C ; 13/07/2013 C ; 21/05/2013 C ; 17/05/2013 C ; 10/05/2013 C ; C ; Initialization of keyboard handlers C ; C ; Retro Unix 8086 v1 feature only! C ; C ; ((Modified registers: AX, CX, SI, DI, ES)) C ; 00E9 33 C0 C xor ax, ax ; 11/08/2013 00EB BF 2C30 R C mov di, offset int09h 00EE 8E D8 C mov ds, ax ; 0 00F0 B8 0024 C mov ax, 9*4 ; INT 09h vector - offset 00F3 8B F0 C mov si, ax 00F5 A5 C movsw ; offset 00F6 A5 C movsw ; segment 00F7 8B F8 C mov di, ax 00F9 8C D8 C mov ax, ds 00FB 8E C0 C mov es, ax 00FD 8C C8 C mov ax, cs 00FF 8E D8 C mov ds, ax 0101 FA C cli 0102 B8 0144 R C mov ax, offset kb_int 0105 AB C stosw 0106 8C C8 C mov ax, cs 0108 AB C stosw 0109 B8 0115 R C mov ax, offset ctrlbrk 010C BF 006C C mov di, 27*4 ; INT 1Bh vector - offset 010F AB C stosw ; offset 0110 8C C8 C mov ax, cs 0112 AB C stosw ; segment 0113 FB C sti C ;mov es, ax ; 30/06/2014 (ES = 0) C ; C ; 03/03/2014 C ; SETUP KEYBOARD PARAMETERS C ;mov si, offset KB_BUFFER C ;mov word ptr [BUFFER_HEAD], si C ;mov word ptr [BUFFER_TAIL], si C ;mov word ptr [BUFFER_START], si C ;add si, 32 ; DEFAULT BUFFER OF 32 BYTES C ;mov word ptr [BUFFER_END], si C ; 0114 C3 C retn C 0115 C ctrlbrk: C ; 06/12/2013 C ; 20/09/2013 C ; 03/09/2013 C ; 09/05/2013 C ; C ; INT 1Bh (control+break) handler C ; C ; Retro Unix 8086 v1 feature only! C ; 0115 2E: 83 3E 38FC R C cmp word ptr CS:[u.intr], 0 00 011B 77 01 C ja short cbrk1 011D CF C iret 011E C cbrk1: C ; 20/09/2013 011E 50 C push ax 011F 2E: A0 2C4A R C mov al, byte ptr CS:[ptty] 0123 FE C0 C inc al C ; 06/12/2013 0125 2E: 3A 06 38EE R C cmp al, byte ptr CS:[u.ttyp] 012A 74 07 C je short cbrk2 012C 2E: 3A 06 38EF R C cmp al, byte ptr CS:[u.ttyp]+1 0131 75 0F C jne short cbrk3 0133 C cbrk2: C ; 06/12/2013 0133 2E: A1 38FE R C mov ax, word ptr CS:[u.quit] 0137 23 C0 C and ax, ax 0139 74 07 C jz short cbrk3 013B 33 C0 C xor ax, ax ; 0 013D 48 C dec ax C ; 0FFFFh = 'ctrl+brk' keystroke 013E 2E: A3 38FE R C mov word ptr CS:[u.quit], ax 0142 C cbrk3: 0142 58 C pop ax 0143 CF C iret C C ;tty_sw: ; < tty switch > C ; 23/02/2014 C ; 04/12/2013 'act_disp_page' (U9.ASM) C ; 29/09/2013 (simplified) C ; 29/09/2013 u1.asm -> u0.asm C ; 22/09/2013 C ; 17/09/2013 C ; 03/09/2013 C ; 21/08/2013 C ; 18/08/2013 C ; 16/07/2013 C ; 15/07/2013 C ; 20/05/2013 C ; C ; Retro UNIX 8086 v1 feature only ! C ; C ; INPUTS: C ; AL = tty number to be switched on C ; OUTPUTS: C ; Keyboard buffer will be reset and C ; active video page will be changed C ; according to the requested tty number. C ; C ; ((Modified registers: AX)) C ; C ; 29/09/2013 C ; 03/09/2013 C ; C ;mov al, byte ptr [nxtty] ; tty number C ; ; video page C ;;; C ; 04/12/2013 C ;;mov ah, 5 ; Set video page C ;;int 10h C ;;mov byte ptr [ptty], al ; byte ptr [active_page], al C ;call act_disp_page C ; 23/02/2014 C ;mov byte ptr [u.quant], 0 C ;retn C 0144 C kb_int: C ; INT 09h Keyboard Handler C ; C ; 30/06/2014 C ; 12/03/2014 C ; 07/03/2014 C ; 04/03/2014 C ; 03/03/2014 major modification C ; 25/02/2013 ;; C ; 23/02/2014 C ; 14/02/2014 C ; 01/02/2014 C ; 20/01/2014 C ; 18/01/2014 C ; 17/01/2014 C ; 10/10/2013 C ; 05/10/2013 C ; 29/09/2013 C ; 24/09/2013 C ; 03/09/2013 C ; 12/08/2013 C ; 11/08/2013 C ; 20/05/2013 C ; 15/05/2013 C ; 10/05/2013 C ; C ; Retro Unix 8086 v1 feature only! C C ; 03/03/2014 C 0144 1E C push ds 0145 50 C push ax 0146 53 C push bx C ; 0147 8C C8 C mov ax, cs 0149 8E D8 C mov ds, ax C ; 014B 9C C pushf C ; 04/03/2014 C ;call dword ptr [int09h] C ; 07/03/2014 014C 0E C push cs 014D E8 1C17 C call int_09h C ; C ; 24/09/2013 0150 B4 01 C mov ah, 1 0152 CD 16 C int 16h 0154 74 45 C jz short kb_int_4 C ; C ; 04/03/2014 0156 8A 1E 2C4A R C mov bl, byte ptr [ptty] 015A 32 E4 C xor ah, ah 015C CD 16 C int 16h C ; 015E 22 C0 C and al, al 0160 75 20 C jnz short kb_int_1 C ; 0162 80 FC 68 C cmp ah, 68h ; ALT + F1 key 0165 72 1B C jb short kb_int_1 0167 80 FC 6F C cmp ah, 6Fh ; ALT + F8 key 016A 77 16 C ja short kb_int_1 C ; 016C 8A FB C mov bh, bl 016E 80 C7 68 C add bh, 68h 0171 38 E7 C cmp bh, ah 0173 74 0D C je short kb_int_1 0175 8A C4 C mov al, ah 0177 2C 68 C sub al, 68h C ; C ;mov byte ptr [ptty], al ; [active_page] C ; 0179 E8 1B0F C call tty_sw 017C 33 C0 C xor ax, ax ; 0 ; 07/03/2014 C ; 12/03/2014 017E 8A 1E 2C4A R C mov bl, byte ptr [ptty] 0182 C kb_int_1: 0182 32 FF C xor bh, bh 0184 D0 E3 C shl bl, 1 0186 81 C3 2C7A R C add bx, offset ttychr C ; 12/03/2014 018A 0B C0 C or ax, ax 018C 74 05 C jz short kb_int_2 C ; 29/09/2013 018E 83 3F 00 C cmp word ptr [BX], 0 0191 77 02 C ja short kb_int_3 0193 C kb_int_2: C ; C ; 24/09/2013 0193 89 07 C mov word ptr [BX], ax ; Save ascii code C ; and scan code of the character C ; for current tty (or last tty C ; just before tty switch). 0195 C kb_int_3: C ; 10/10/2013 0195 A0 2C4A R C mov al, byte ptr [ptty] C ; 14/02/2014 C ;mov bx, offset runq 0198 E8 0DBE C call wakeup C ; 019B C kb_int_4: 019B 5B C pop bx ; 24/09/2013 019C 58 C pop ax 019D 1F C pop ds C ; 019E CF C iret C 019F C vp_clr: C ; Reset/Clear Video Page C ; C ; 04/12/2013 scroll_up (U9.ASM) C ; C ; 30/10/2013 C ; 17/09/2013 C ; 17/07/2013 C ; 21/05/2013 C ; C ; Retro UNIX 8086 v1 feature only ! C ; C ; INPUTS -> C ; AL = video page number C ; C ; OUTPUT -> C ; none C ; ((Modified registers: AX, BH, CX, DX, SI, DI)) C ; C ; 04/12/2013 019F 2A C0 C sub al, al C ; al = 0 (clear video page) C ; bl = video page 01A1 B7 07 C mov bh, 07h C ; bh = 7 (attribute/color) 01A3 E8 1A5D C call scroll_up C ; bh = 7 C ; bl = video page 01A6 33 D2 C xor dx, dx ; 0 C ;call set_cpos C ;retn C 01A8 E9 19EA C jmp set_cpos C C ; 30/10/2013 C ;push es C ;xor ah, ah C ;;push ax C ;mov di, 0B800h C ;mov es, di C ;mov cx, 2000 C ;sub dx, dx ; 30/10/2013 C ;or al, al C ;jz short @f C ;; 30/10/2013 C ;shl al, 1 C ;; 17/09/2013 C ;push ax C ;mul cx C ;pop dx C ;@@: C ;mov di, ax ; 17/09/2013 C ;mov ah, 07h ; color C ;rep stosw C ;;pop ax C ;;mov bh, al ; video page C ;;mov ah, 2 ; set cursor position C ;;xor dx, dx C ;;int 10h C ;;xor ax, ax C ;xor ah, ah C ;;pop di ; Video page number C ;;shl di, 1 C ;mov di, dx C ;mov es, ax ; 0 C ;add di, 450h ; 40h:50h or 0h:450h C ;; di = cursor position of the video page. C ;stosw ; reset cursor position C ;pop es C ;retn C 01AB C com2_int: C ; 28/07/2014 C ; 27/07/2014 C ; 23/07/2014 C ; 20/07/2014 (null chr) C ; 07/07/2014 C ; 05/07/2014 C ; 04/07/2014 C ; < serial port 2 interrupt handler > C ; C ; Retro UNIX 8086 v1 feature only ! C ; 01AB 52 C push dx 01AC 50 C push ax 01AD BA 02FA C mov dx, 2FAh ; interrupt identification register 01B0 B8 0009 C mov ax, 9 ; tty number of com2 01B3 EB 08 C jmp short @f C 01B5 C com1_int: C ; 28/07/2014 C ; 27/07/2014 C ; 23/07/2014 C ; 20/07/2014 (null chr) C ; 07/07/2014 C ; 05/07/2014 C ; 04/07/2014 C ; < serial port 1 interrupt handler > C ; C ; Retro UNIX 8086 v1 feature only ! C ; 01B5 52 C push dx 01B6 50 C push ax 01B7 BA 03FA C mov dx, 3FAh ; interrupt identification register 01BA B8 0008 C mov ax, 8 ; tty number of com1 01BD C @@: 01BD 1E C push ds 01BE 53 C push bx 01BF 0E C push cs 01C0 1F C pop ds 01C1 50 C push ax C ; 01C2 8B D8 C mov bx, ax 01C4 EC C in al, dx ; read register 01C5 24 0F C and al, 0Fh ; leave lowernibble only C ; 28/07/2014 01C7 3C 02 C cmp al, 2 01C9 75 13 C jne short com_rdei C ; 01CB 81 C3 2CA4 R C add bx, offset tsleep - 8 01CF 38 27 C cmp byte ptr [BX], ah ; 0 01D1 76 04 C jna short @f 01D3 88 27 C mov byte ptr [BX], ah ; 0 01D5 EB 1D C jmp short com_eoi 01D7 C @@: 01D7 B0 20 C mov al, 20h 01D9 E6 20 C out 20h, al ; end of interrupt 01DB 58 C pop ax 01DC EB 1E C jmp short com_iret C 01DE C com_rdei: 01DE 3C 04 C cmp al, 4 ; is it receiver data available interrupt? 01E0 75 12 C jne short com_eoi ; no, leave interrupt handler C ; 01E2 83 EA 02 C sub dx, 3FAh-3F8h ; data register (3F8h, 2F8h) 01E5 EC C in al, dx ; read character C ; 27/07/2014 01E6 22 C0 C and al, al 01E8 75 02 C jnz short @f C ; null chr (al=0, ah=0) 01EA FE CC C dec ah ; 0FFh 01EC C @@: ; 27/07/2014 C ; 09/07/2014 01EC D0 E3 C shl bl, 1 01EE 81 C3 2C7A R C add bx, offset ttychr C ; 23/07/2014 (always overwrite) C ;;cmp word ptr [BX], 0 C ;;ja short com_eoi C ; 01F2 89 07 C mov word ptr [BX], ax ; Save ascii code C ; scan code = 0 01F4 C com_eoi: 01F4 B0 20 C mov al, 20h 01F6 E6 20 C out 20h, al ; end of interrupt C ; 01F8 58 C pop ax ; al = tty number (8 or 9) 01F9 E8 0D5D C call wakeup 01FC C com_iret: 01FC 5B C pop bx 01FD 1F C pop ds 01FE 58 C pop ax 01FF 5A C pop dx 0200 CF C iret C 0201 C sp_init: C ; 28/07/2014 C ; 27/07/2014 C ; 12/07/2014 C ; 08/07/2014 C ; 05/07/2014 C ; 03/07/2014 C ; 17/01/2014 C ; C ; Initialization of serial port interrupt handlers C ; C ; Retro Unix 8086 v1 feature only! C ; C ; ((Modified registers: AX, CX, DX, DI)) C ; C ; ES = 0 C ; C ; Set communication parameters for COM1 C ; 0201 B1 E3 C mov cl, 0E3h 0203 32 E4 C xor ah, ah 0205 8A C1 C mov al, cl ; Communication parameters (E3h) C ; 9600 baud, parity none, one stop bit 0207 33 D2 C xor dx, dx ; COM1 (DX=0) 0209 CD 14 C int 14h C ; 12/07/2014 020B F6 C4 80 C test ah, 80h 020E 75 52 C jnz short @f C ; (Note: Serial port interrupts will be disabled here...) C ; (INT 14h initialization code disables interrupts.) 0210 88 0E 2CAE R C mov byte ptr [com1p], cl ; 0E3h C ; C ;; Hook serial port (COM1) interrupt C ; 0214 BF 0030 C mov di, 12 * 4 ; 0Ch, COM1 (IRQ 4) interrupt vector C ;cli 0217 B8 01B5 R C mov ax, offset com1_int 021A AB C stosw 021B 8C C8 C mov ax, cs 021D AB C stosw C ;sti C ; C ;; COM1 - enabling IRQ 4 021E BA 03FC C mov dx, 3FCh ;modem control register 0221 EC C in al, dx ;read register 0222 0C 08 C or al, 8 ;enable bit 3 (OUT2) 0224 EE C out dx, al ;write back to register 0225 BA 03F9 C mov dx, 3F9h ;interrupt enable register 0228 EC C in al, dx ;read register C ;or al, 1 ;receiver data interrupt enable C ; 27/7/2014 ; and 0229 0C 03 C or al, 3 ;Transmitter empty interrupt enable C ; 022B EE C out dx, al ;write back to register 022C E4 21 C in al, 21h ;read interrupt mask register 022E 24 EF C and al, 0EFh ;enable IRQ 4 (COM1) 0230 E6 21 C out 21h, al ;write back to register C C ; C ; Set communication parameters for COM2 C ; 0232 BA 0001 C mov dx, 1 ; COM2 0235 2A E4 C sub ah, ah 0237 8A C1 C mov al, cl ; Communication parameters (E3h) C ; 9600 baud, parity none, one stop bit 0239 CD 14 C int 14h C ; 12/07/2014 023B F6 C4 80 C test ah, 80h 023E 75 22 C jnz short @f C ; (Note: Serial port interrupts will be disabled here...) C ; (INT 14h initialization code disables interrupts.) 0240 88 0E 2CAF R C mov byte ptr [com2p], cl ; 0E3h C ; C ;; Hook serial port (COM2) interrupt C ; 0244 BF 002C C mov di, 11 * 4 ; 0Bh, COM2 (IRQ 3) interrupt vector C ;cli 0247 B8 01AB R C mov ax, offset com2_int 024A AB C stosw 024B 8C C8 C mov ax, cs 024D AB C stosw C ;sti C ; C ;; COM2 - enabling IRQ 3 024E BA 02FC C mov dx, 2FCh ;modem control register 0251 EC C in al, dx ;read register 0252 0C 08 C or al, 8 ;enable bit 3 (OUT2) 0254 EE C out dx, al ;write back to register 0255 BA 02F9 C mov dx, 2F9h ;interrupt enable register 0258 EC C in al, dx ;read register C ;or al, 1 ;receiver data interrupt enable C ; 27/7/2014 ; and 0259 0C 03 C or al, 3 ;Transmitter empty interrupt enable C ; 025B EE C out dx, al ;write back to register 025C E4 21 C in al, 21h ;read interrupt mask register 025E 24 F7 C and al, 0F7h ;enable IRQ 3 (COM2) 0260 E6 21 C out 21h, al ;write back to register 0262 C @@: 0262 C3 C retn C include u1.asm ; u1.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U1.ASM (include u1.asm) //// UNIX v1 -> u1.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 28/06/2015 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 11/06/2014, 26/06/2014, 04/07/2014, 12/07/2014 C ; 07/03/2014, 10/04/2014, 15/04/2014, 22/04/2014, 30/04/2014 C ; 18/01/2014, 26/01/2014, 05/02/2014, 14/02/2014, 23/02/2014 C ; 12/01/2014, 13/01/2014, 14/01/2014, 16/01/2014, 17/01/2014 C ; 18/11/2013, 04/12/2013, 06/12/2013, 07/12/2013, 10/12/2013 C ; 20/10/2013, 23/10/2013, 24/10/2013, 30/10/2013, 04/11/2013 C ; 03/09/2013, 16/09/2013, 17/09/2013, 22/09/2013, 29/09/2013 C ; 14/08/2013, 18/08/2013, 19/08/2013, 21/08/2013, 30/08/2013 C ; 26/07/2013, 02/08/2013, 07/08/2013, 08/08/2013, 11/08/2013 C ; 15/07/2013, 16/07/2013, 22/07/2013, 23/07/2013, 24/07/2013 C ; 27/05/2013, 30/05/2013, 02/06/2013, 03/06/2013, 14/07/2013 C ; 20/05/2013, 22/05/2013, 23/05/2013, 24/05/2013, 26/05/2013 C ; 26/04/2013, 04/05/2013, 09/05/2013, 15/05/2013, 16/05/2013 C ; 11/03/2013, 10/04/2013, 16/04/2013, 17/04/2013, 19/04/2013 C ; C C 0263 C unkni: ; / used for all system calls 0263 C sysent: ; < enter to system call > C ; 18/01/2014 C ; 26/07/2013 C ; 24/07/2013 C ; 14/07/2013 C ; 24/05/2013 C ; 16/04/2013 C ; 10/04/2013 C ; C ; 'unkni' or 'sysent' is sytem entry from various traps. C ; The trap type is determined and an indirect jump is made to C ; the appropriate system call handler. If there is a trap inside C ; the system a jump to panic is made. All user registers are saved C ; and u.sp points to the end of the users stack. The sys (trap) C ; instructor is decoded to get the the system code part (see C ; trap instruction in the PDP-11 handbook) and from this C ; the indirect jump address is calculated. If a bad system call is C ; made, i.e., the limits of the jump table are exceeded, 'badsys' C ; is called. If the call is legitimate control passes to the C ; appropriate system routine. C ; C ; Calling sequence: C ; Through a trap caused by any sys call outside the system. C ; Arguments: C ; Arguments of particular system call. C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; System call number is in AX register. C ; C ; Other parameters are in DX, BX, CX, SI, DI, BP registers C ; depending of function details. C ; C C ; 16/04/2013 segment changing 0263 0E C push cs 0264 1F C pop ds C ; 0265 FE 06 2C07 R C inc byte ptr [sysflg] C ; incb sysflg / indicate a system routine is in progress 0269 FB C sti ; 18/01/2014 026A 74 03 E9 FE51 C jnz panic ; 24/05/2013 C ;jz short @f C ; beq 1f C ;jmp short panic C ; jmp panic ; / called if trap inside system 026F C @@: ;1: C ; 24/05/2013 026F A3 38D0 R C mov word ptr [u.r0], ax 0272 89 26 38CE R C mov word ptr [u.usp], sp C C ; 16/04/2013 stack segment changing C ;mov ax, ss C ;mov word ptr [u.segmnt], ax 0276 8C C8 C mov ax, cs C ; 24/05/2013 C ;;;mov es, ax ; 14/07/2013 0278 FA C cli C ; 24/07/2013 0279 BC 3A74 R C mov sp, sstack ; offset sstack ; swap stack C ; (System/Kernel stack in Retro UNIX 8086 v1 !) 027C 8E D0 C mov ss, ax 027E FB C sti C ; 24/05/2013 027F FF 36 38CE R C push word ptr [u.usp] ; user's stack pointer (old sp) C ; which points to top of user's stack C ; (Retro UNIX 8086 v1 modification!) C ; 0283 52 C push dx 0284 51 C push cx 0285 53 C push bx 0286 56 C push si 0287 57 C push di 0288 55 C push bp C ; 0289 89 26 38CC R C mov word ptr [u.sp_], sp C ;;mov ax, word ptr [s.syst+2] C ;;mov word ptr [clockp], ax C ; mov $s.syst+2,clockp C ; mov r0,-(sp) / save user registers C ; mov sp,u.r0 / pointer to bottom of users stack C ; / in u.r0 C ; mov r1,-(sp) C ; mov r2,-(sp) C ; mov r3,-(sp) C ; mov r4,-(sp) C ; mov r5,-(sp) C ; mov ac,-(sp) / "accumulator" register for extended C ; / arithmetic unit C ; mov mq,-(sp) / "multiplier quotient" register for the C ; / extended arithmetic unit C ; mov sc,-(sp) / "step count" register for the extended C ; / arithmetic unit C ; mov sp,u.sp / u.sp points to top of users stack C ; mov 18.(sp),r0 / store pc in r0 C ; mov -(r0),r0 / sys inst in r0 10400xxx C ; sub $sys,r0 / get xxx code 028D A1 38D0 R C mov ax, word ptr [u.r0] 0290 D1 E0 C shl ax, 1 C ; asl r0 / multiply by 2 to jump indirect in bytes 0292 3D 0046 C cmp ax, offset @f - offset syscalls C ; cmp r0,$2f-1f / limit of table (35) exceeded C ;jnb short badsys C ; bhis badsys / yes, bad system call C ; 16/04/2013 0295 F5 C cmc 0296 9C C pushf 0297 50 C push ax C ; 24/05/2013 0298 8B 2E 38CE R C mov bp, word ptr [u.usp] C ; 26/07/2013 C ;mov ax, 0FFFEh 029C B0 FE C mov al, 0FEh ; 11111110b 029E 14 00 C adc al, 0 ; al = al + cf C ;and word ptr ES:[BP]+4, ax ; flags C ;;mov ax, word ptr [u.segmnt] C ;;mov es, ax 02A0 26: 20 46 04 C and byte ptr ES:[BP]+4, al ; flags (reset carry flag) C ; bic $341,20.(sp) / set users processor priority to 0 C ; / and clear carry bit 02A4 8C D8 C mov ax, ds ; 14/07/2013 02A6 8E C0 C mov es, ax ; 17/07/2013 C ;pop ax C ;mov bp, ax C ;shr ax, 1 02A8 5D C pop bp ; ax C ;mov ax, word ptr [u.r0] 02A9 9D C popf 02AA 73 03 E9 00D0 C jc badsys 02AF A1 38D0 R C mov ax, word ptr [u.r0] C ; system call registers: AX, DX, CX, BX, SI, DI 02B2 FF A6 02B6 R C jmp word ptr [BP]+syscalls C ; jmp *1f(r0) / jump indirect thru table of addresses C ; / to proper system routine. 02B6 C syscalls: ; 1: 02B6 0353 R C dw offset sysrele ; / 0 02B8 03EF R C dw offset sysexit ; / 1 02BA 04C0 R C dw offset sysfork ; / 2 02BC 0596 R C dw offset sysread ; / 3 02BE 05A6 R C dw offset syswrite ; / 4 02C0 05CB R C dw offset sysopen ; / 5 02C2 067D R C dw offset sysclose ; / 6 02C4 046D R C dw offset syswait ; / 7 02C6 0639 R C dw offset syscreat ; / 8 02C8 08B3 R C dw offset syslink ; / 9 02CA 0915 R C dw offset sysunlink ; / 10 02CC 0999 R C dw offset sysexec ; / 11 02CE 0C65 R C dw offset syschdir ; / 12 02D0 0CDC R C dw offset systime ; / 13 02D2 0659 R C dw offset sysmkdir ; / 14 02D4 0C8B R C dw offset syschmod ; / 15 02D6 0CC2 R C dw offset syschown ; / 16 02D8 0D03 R C dw offset sysbreak ; / 17 02DA 0B0E R C dw offset sysstat ; / 18 02DC 0D83 R C dw offset sysseek ; / 19 02DE 0D8F R C dw offset systell ; / 20 02E0 147F R C dw offset sysmount ; / 21 02E2 14E2 R C dw offset sysumount ; / 22 02E4 0DDE R C dw offset syssetuid ; / 23 02E6 0DF9 R C dw offset sysgetuid ; / 24 02E8 0CEF R C dw offset sysstime ; / 25 02EA 0DD7 R C dw offset sysquit ; / 26 02EC 0DD0 R C dw offset sysintr ; / 27 02EE 0AFA R C dw offset sysfstat ; / 28 02F0 068A R C dw offset sysemt ; / 29 02F2 06B6 R C dw offset sysmdate ; / 30 02F4 06E4 R C dw offset sysstty ; / 31 02F6 07ED R C dw offset sysgtty ; / 32 02F8 06B3 R C dw offset sysilgins ; / 33 02FA 1CCF R C dw offset syssleep ; 34 ; Retro UNIX 8086 v1 feature only ! C ; 11/06/2014 02FC C @@: ;2: C 02FC C error: C ; 07/08/2013 C ; 26/05/2013 C ; 24/05/2013 C ; 22/05/2013 C ; 04/05/2013 C ; 18/04/2013 C ; 16/04/2013 C ; 10/04/2013 C ; 'error' merely sets the error bit off the processor status (c-bit) C ; then falls right into the 'sysret', 'sysrele' return sequence. C ; C ; INPUTS -> none C ; OUTPUTS -> C ; processor status - carry (c) bit is set (means error) C ; C C ; 26/05/2013 (Stack pointer must be reset here! C ; Because, jumps to error procedure C ; disrupts push-pop nesting balance) 02FC 8B 26 38CC R C mov sp, word ptr [u.sp_] 0300 8B EC C mov bp, sp C ; mov u.sp,r1 0302 8B 5E 0C C mov bx, word ptr [BP]+12 ; user's stack pointer C ; 0305 A1 3908 R C mov ax, word ptr [u.segmnt] 0308 8E C0 C mov es, ax C ;;push ds C ;;mov ds, ax C ; C ;;; word ptr ES:[BX] -> IP C ;;; word ptr ES:[BX]+2 -> CS C ;;; word ptr ES:[BX]+4 -> FLAGS C C ;;or byte ptr [BX]+4, 1 030A 26: 80 4F 04 01 C or byte ptr ES:[BX]+4, 1 ; set carry bit of flags register C ; in user's stack C ; bis $1,20.(r1) / set c bit in processor status word below C ; / users stack C ;;pop ds 030F 8C C8 C mov ax, cs 0311 8E C0 C mov es, ax C ; 07/08/2013 0313 C7 06 2C09 R 0000 C mov word ptr [namei_r], 0 ; namei_r, mkdir_w reset C 0319 C sysret: ; < return from system call> C ; 23/02/2014 C ; 07/08/2013 C ; 24/05/2013 C ; 04/05/2013 C ; 26/04/2013 C ; 10/04/2013 C ; C ; 'sysret' first checks to see if process is about to be C ; terminated (u.bsys). If it is, 'sysexit' is called. C ; If not, following happens: C ; 1) The user's stack pointer is restored. C ; 2) r1=0 and 'iget' is called to see if last mentioned C ; i-node has been modified. If it has, it is written out C ; via 'ppoke'. C ; 3) If the super block has been modified, it is written out C ; via 'ppoke'. C ; 4) If the dismountable file system's super block has been C ; modified, it is written out to the specified device C ; via 'ppoke'. C ; 5) A check is made if user's time quantum (uquant) ran out C ; during his execution. If so, 'tswap' is called to give C ; another user a chance to run. C ; 6) 'sysret' now goes into 'sysrele'. C ; (See 'sysrele' for conclusion.) C ; C ; Calling sequence: C ; jump table or 'br sysret' C ; Arguments: C ; - C ; ............................................................... C ; C ; ((AX=r1 for 'iget' input)) C ; 0319 33 C0 C xor ax, ax ; 04/05/2013 031B FE C0 C inc al ; 04/05/2013 031D 38 06 3906 R C cmp byte ptr [u.bsys], al ; 1 C ; tstb u.bsys / is a process about to be terminated because 0321 72 03 E9 00C9 C jnb sysexit ; 04/05/2013 C ; bne sysexit / of an error? yes, go to sysexit C ;mov sp, word ptr [u.sp_] ; 24/05/2013 (that is not needed here) C ; mov u.sp,sp / no point stack to users stack 0326 FE C8 C dec al ; mov ax, 0 C ; clr r1 / zero r1 to check last mentioned i-node 0328 E8 0DAF C call iget C ; jsr r0,iget / if last mentioned i-node has been modified C ; / it is written out 032B 33 C0 C xor ax, ax ; 0 032D 38 06 2C05 R C cmp byte ptr [smod], al ; 0 C ; tstb smod / has the super block been modified 0331 76 0D C jna short @f C ; beq 1f / no, 1f 0333 A2 2C05 R C mov byte ptr [smod], al ; 0 C ; clrb smod / yes, clear smod 0336 BB 2566 R C mov bx, offset sb0 ;; 07/08//2013 0339 81 0F 0200 C or word ptr [BX], 200h ;; C ;or word ptr [sb0], 200h ; write bit, bit 9 C ; bis $1000,sb0 / set write bit in I/O queue for super block C ; / output C ; AX = 0 033D E8 14D5 C call poke ; 07/08/2013 C ; call ppoke C ; AX = 0 C ; jsr r0,ppoke / write out modified super block to disk 0340 C @@: ;1: 0340 38 06 2C06 R C cmp byte ptr [mmod], al ; 0 C ; tstb mmod / has the super block for the dismountable file C ; / system 0344 76 0D C jna short @f ; 23/02/2014 (@f location has been changed to u.quant check) C ; beq 1f / been modified? no, 1f 0346 A2 2C06 R C mov byte ptr [mmod], al ; 0 C ; clrb mmod / yes, clear mmod C ;mov ax, word ptr [mntd] C ;;mov al, byte ptr [mdev] ; 26/04/2013 0349 BB 276A R C mov bx, offset sb1 ;; 07/08//2013 C ;;mov byte ptr [BX], al C ;mov byte ptr [sb1], al C ; movb mntd,sb1 / set the I/O queue 034C 81 0F 0200 C or word ptr [BX], 200h C ;or word ptr [sb1], 200h ; write bit, bit 9 C ; bis $1000,sb1 / set write bit in I/O queue for detached sb 0350 E8 14C2 C call poke ; 07/08/2013 C ;call ppoke C ; jsr r0,ppoke / write it out to its device C ;xor al, al ; 26/04/2013 C ;@@: ;1: C ; cmp byte ptr [uquant], al ; 0 C ; ; tstb uquant / is the time quantum 0? C ; ja short @f C ; ;ja short swapret C ; bne 1f / no, don't swap it out C 0353 C sysrele: ; < release > C ; 07/03/2014 C ; 23/02/2014 C ; 14/02/2014 uquant -> u.quant C ; 18/01/2014 C ; 07/12/2013 C ; 20/10/2013 C ; 22/09/2013 C ; 16/05/2013 C ; 08/05/2013 C ; 16/04/2013 C ; 11/04/2013 C ; 10/04/2013 C ; C ; 'sysrele' first calls 'tswap' if the time quantum for a user is C ; zero (see 'sysret'). It then restores the user's registers and C ; turns off the system flag. It then checked to see if there is C ; an interrupt from the user by calling 'isintr'. If there is, C ; the output gets flashed (see isintr) and interrupt action is C ; taken by a branch to 'intract'. If there is no interrupt from C ; the user, a rti is made. C ; C ; Calling sequence: C ; Fall through a 'bne' in 'sysret' & ? C ; Arguments: C ; - C ; ............................................................... C ; C ; 23/02/2014 (@@) C ; 22/09/2013 0353 C @@: ;1: 0353 80 3E 38FA R 00 C cmp byte ptr [u.quant], 0 ; 16/05/2013 C ; tstb uquant / is the time quantum 0? 0358 77 03 C ja short @f C ;ja short swapret C ; bne 1f / no, don't swap it out 035A C sysrelease: ; 07/12/2013 (jump from 'clock ') C ; 035A E8 0AD7 C call tswap C ; jsr r0,tswap / yes, swap it out C ; C ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address. 035D C @@: C ;swapret: ;1: C ; 26/05/2013 C ; 'sp' must be already equal to 'word ptr [u.sp_]' here ! C ;mov sp, word ptr [u.sp_] ; Retro Unix 8086 v1 modification! C ; 10/04/2013 C ; (If an I/O error occurs during disk I/O, C ; related procedures will jump to 'error' C ; procedure directly without returning to C ; the caller procedure. So, stack pointer C ; must be restored here.) 035D 5D C pop bp 035E 5F C pop di 035F 5E C pop si 0360 5B C pop bx 0361 59 C pop cx 0362 5A C pop dx C ; mov (sp)+,sc / restore user registers C ; mov (sp)+,mq C ; mov (sp)+,ac C ; mov (sp)+,r5 C ; mov (sp)+,r4 C ; mov (sp)+,r3 C ; mov (sp)+,r2 C ; 22/09/2013 0363 E8 0C45 C call isintr C ; 20/10/2013 0366 74 03 C jz short @f 0368 E8 0072 C call intract C ; jsr r0,isintr / is there an interrupt from the user C ; br intract / yes, output gets flushed, take interrupt C ; / action 036B C @@: C ; mov (sp)+,r1 036B 58 C pop ax ; user's stack pointer C ; (was pushed on system stack by 'sysenter'.) C ; mov (sp)+,r0 C ; 24/05/2013 C ; 18/01/2014 C ;cli ; disable (hardware) interrupts 036C 8B E0 C mov sp, ax ; user's stack pointer 036E A1 3908 R C mov ax, word ptr [u.segmnt] 0371 8E D0 C mov ss, ax ; user's stack segment C ; 18/01/2014 C ;;sti ; enable interrupts ;; 07/03/2014 C ; 'sti' is not needed here C ; (because 'iret' will restore interrupt flag) 0373 8E C0 C mov es, ax C ;;;mov ax, word ptr [s.chrgt]+2 C ;;;mov word ptr [clockp], ax C ; 20/10/2013 0375 A1 38D0 R C mov ax, word ptr [u.r0] ; ((return value in AX)) 0378 FE 0E 2C07 R C dec byte ptr [sysflg] C ; decb sysflg / turn system flag off 037C 06 C push es 037D 1F C pop ds 037E CF C iret C ; rti / no, return from interrupt C 037F C badsys: C ; 27/05/2013 C ; 11/04/2013 037F FE 06 3906 R C inc byte ptr [u.bsys] C ; incb u.bsys / turn on the user's bad-system flag 0383 C7 06 38E2 R 03D6 R C mov word ptr [u.namep], offset badsys_3 ; 3f C ; mov $3f,u.namep / point u.namep to "core\0\0" 0389 E8 080F C call namei C ; jsr r0,namei / get the i-number for the core image file C ;or ax, ax ; Retro UNIX 8086 v1 modification ! C ; ax = 0 -> file not found C ;jz short badsys_1 038C 72 0A C jc short badsys_1 ; 27/05/2013 C ; br 1f / error 038E F7 D8 C neg ax ; AX = r1 C ; neg r1 / negate the i-number to open the core image file C ; / for writing 0390 E8 118E C call iopen C ; jsr r0,iopen / open the core image file 0393 E8 0E2F C call itrunc C ; jsr r0,itrunc / free all associated blocks 0396 EB 09 C jmp short badsys_2 C ; br 2f 0398 C badsys_1: ;1: 0398 B8 000F C mov ax, 15 ; mode 17 C ; mov $17,r1 / put i-node mode (17) in r1 039B E8 0991 C call maknod C ; jsr r0,maknod / make an i-node 039E A1 38F0 R C mov ax, word ptr [u.dirbuf] ; i-number C ; mov u.dirbuf,r1 / put i-node number in r1 03A1 C badsys_2: ;2: C ; 19/04/2013 03A1 BE 0000 C mov si, offset user 03A4 BF 7FC0 C mov di, ecore 03A7 8B 0E 3908 R C mov cx, word ptr [u.segmnt] 03AB 8E C1 C mov es, cx 03AD B9 0020 C mov cx, 32 03B0 F3/ A5 C rep movsw 03B2 8C DA C mov dx, ds 03B4 8E C2 C mov es, dx C 03B6 C7 06 38E6 R 0000 C mov word ptr [u.base], core C ; mov $core,u.base / move address core to u.base 03BC C7 06 38E8 R 8000 C mov word ptr [u.count], ecore - core + 64 C ; mov $ecore-core,u.count / put the byte count in u.count 03C2 C7 06 38DE R 38E4 R C mov word ptr [u.fofp], offset u.off C ; mov $u.off,u.fofp / more user offset to u.fofp 03C8 89 0E 38E4 R C mov word ptr [u.off], cx ; 0 C ; clr u.off / clear user offset 03CC E8 0F6B C call writei C ; jsr r0,writei / write out the core image to the user C ;mov word ptr [u.base], offset user C ; mov $user,u.base / pt. u.base to user C ;mov word ptr [u.count], 64 C ; mov $64.,u.count / u.count = 64 C ;call writei C ; jsr r0,writei / write out all the user parameters 03CF F7 D8 C neg ax ; r1 C ; neg r1 / make i-number positive 03D1 E8 1287 C call iclose C ; jsr r0,iclose / close the core image file 03D4 EB 19 C jmp short sysexit C ; br sysexit / 03D6 C badsys_3: ;3: 03D6 63 6F 72 65 00 00 C db 'core',0,0 C ; C 03DC C @@: ; 22/09/2013 03DC C3 C retn C 03DD C intract: ; / interrupt action C ; 07/12/2013 C ; 06/12/2013 C ; 20/10/2013 C ; 22/09/2013 C ; 03/09/2013 C ; 16/05/2013 task/process/tty switch C ; 15/05/2013 (ptty, set video page) C ; 09/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; (Process/task switching and quit routine by using C ; Retro UNIX 8086 v1 keyboard interrupt output.)) C ; C ; input -> 'u.quit' (also value of 'u.intr' > 0) C ; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign) C ; 'intract' will jump to 'sysexit'. C ; Intract will return to the caller C ; if value of 'u.quit' <> FFFFh. C ; 07/12/2013 03DD FF 06 38FE R C inc word ptr [u.quit] 03E1 74 06 C jz short @f ; FFFFh -> 0 03E3 FF 0E 38FE R C dec word ptr [u.quit] 03E7 EB F3 C jmp short @b 03E9 C @@: C ; 20/10/2013 03E9 58 C pop ax ; call intract -> retn 03EA 58 C pop ax ; user's stack pointer ('sysrele') C ; 03EB 33 C0 C xor ax, ax 03ED FE C0 C inc al ; mov ax, 1 C ; 06/12/2013 C ;mov word ptr [u.quit], ax ; reset to C ; 'ctrl+brk' enabled C ;jmp sysexit C ;;; C ; UNIX v1 original 'intract' routine... C ; / interrupt action C ;cmp *(sp),$rti / are you in a clock interrupt? C ; bne 1f / no, 1f C ; cmp (sp)+,(sp)+ / pop clock pointer C ; 1: / now in user area C ; mov r1,-(sp) / save r1 C ; mov u.ttyp,r1 C ; / pointer to tty buffer in control-to r1 C ; cmpb 6(r1),$177 C ; / is the interrupt char equal to "del" C ; beq 1f / yes, 1f C ; clrb 6(r1) C ; / no, clear the byte C ; / (must be a quit character) C ; mov (sp)+,r1 / restore r1 C ; clr u.quit / clear quit flag C ; bis $20,2(sp) C ; / set trace for quit (sets t bit of C ; / ps-trace trap) C ; rti ; / return from interrupt C ; 1: / interrupt char = del C ; clrb 6(r1) / clear the interrupt byte C ; / in the buffer C ; mov (sp)+,r1 / restore r1 C ; cmp u.intr,$core / should control be C ; / transferred to loc core? C ; blo 1f C ; jmp *u.intr / user to do rti yes, C ; / transfer to loc core C ; 1: C ; sys 1 / exit C 03EF C sysexit: ; C ; 14/02/2014 C ; 05/02/2014 C ; 17/09/2013 C ; 30/08/2013 C ; 19/04/2013 C ; C ; 'sysexit' terminates a process. First each file that C ; the process has opened is closed by 'flose'. The process C ; status is then set to unused. The 'p.pid' table is then C ; searched to find children of the dying process. If any of C ; children are zombies (died by not waited for), they are C ; set free. The 'p.pid' table is then searched to find the C ; dying process's parent. When the parent is found, it is C ; checked to see if it is free or it is a zombie. If it is C ; one of these, the dying process just dies. If it is waiting C ; for a child process to die, it notified that it doesn't C ; have to wait anymore by setting it's status from 2 to 1 C ; (waiting to active). It is awakened and put on runq by C ; 'putlu'. The dying process enters a zombie state in which C ; it will never be run again but stays around until a 'wait' C ; is completed by it's parent process. If the parent is not C ; found, process just dies. This means 'swap' is called with C ; 'u.uno=0'. What this does is the 'wswap' is not called C ; to write out the process and 'rswap' reads the new process C ; over the one that dies..i.e., the dying process is C ; overwritten and destroyed. C ; C ; Calling sequence: C ; sysexit or conditional branch. C ; Arguments: C ; - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; System call number (=1) is in AX register. C ; C ; Other parameters are in DX, BX, CX, SI, DI, BP registers C ; depending of function details. C ; C ; ('swap' procedure is mostly different than original UNIX v1.) C ; C ; / terminate process C ; AX = 1 03EF 48 C dec ax ; 0 03F0 A3 38FC R C mov word ptr [u.intr], ax ; 0 C ; clr u.intr / clear interrupt control word C ; clr r1 / clear r1 C ; AX = 0 03F3 C sysexit_1: ; 1: C ; AX = File descriptor C ; / r1 has file descriptor (index to u.fp list) C ; / Search the whole list 03F3 E8 0741 C call fclose C ; jsr r0,fclose / close all files the process opened C ;; ignore error return C ; br .+2 / ignore error return C ;inc ax 03F6 FE C0 C inc al C ; inc r1 / increment file descriptor C ;cmp ax, 10 03F8 3C 0A C cmp al, 10 C ; cmp r1,$10. / end of u.fp list? 03FA 72 F7 C jb short sysexit_1 C ; blt 1b / no, go back 03FC 32 FF C xor bh, bh ; 0 03FE 8A 1E 3907 R C mov bl, byte ptr [u.uno] C ; movb u.uno,r1 / yes, move dying process's number to r1 0402 88 A7 2A1D R C mov byte ptr [BX]+p.stat-1, ah ; 0, SFREE, 05/02/2014 C ; clrb p.stat-1(r1) / free the process C ;shl bx, 1 0406 D0 E3 C shl bl, 1 C ; asl r1 / use r1 for index into the below tables 0408 8B 8F 298C R C mov cx, word ptr [BX]+p.pid-2 C ; mov p.pid-2(r1),r3 / move dying process's name to r3 040C 8B 97 29AC R C mov dx, word ptr [BX]+p.ppid-2 C ; mov p.ppid-2(r1),r4 / move its parents name to r4 C ; xor bx, bx ; 0 0410 32 DB C xor bl, bl ; 0 C ; clr r2 0412 33 F6 C xor si, si ; 0 C ; clr r5 / initialize reg 0414 C sysexit_2: ; 1: C ; / find children of this dying process, C ; / if they are zombies, free them C ;add bx, 2 0414 80 C3 02 C add bl, 2 C ; add $2,r2 / search parent process table C ; / for dying process's name 0417 39 8F 29AC R C cmp word ptr [BX]+p.ppid-2, cx C ; cmp p.ppid-2(r2),r3 / found it? 041B 75 0F C jne short sysexit_4 C ; bne 3f / no C ;shr bx, 1 041D D0 EB C shr bl, 1 C ; asr r2 / yes, it is a parent 041F 80 BF 2A1D R 03 C cmp byte ptr [BX]+p.stat-1, 3 ; SZOMB, 05/02/2014 C ; cmpb p.stat-1(r2),$3 / is the child of this C ; / dying process a zombie 0424 75 04 C jne short sysexit_3 C ; bne 2f / no 0426 88 A7 2A1D R C mov byte ptr [BX]+p.stat-1, ah ; 0, SFREE, 05/02/2014 C ; clrb p.stat-1(r2) / yes, free the child process 042A C sysexit_3: ; 2: C ;shr bx, 1 042A D0 E3 C shl bl, 1 C ; asl r2 042C C sysexit_4: ; 3: C ; / search the process name table C ; / for the dying process's parent 042C 39 97 298C R C cmp word ptr [BX]+p.pid-2, dx ; 17/09/2013 C ; cmp p.pid-2(r2),r4 / found it? 0430 75 02 C jne short sysexit_5 C ; bne 3f / no 0432 8B F3 C mov si, bx C ; mov r2,r5 / yes, put index to p.pid table (parents C ; / process # x2) in r5 0434 C sysexit_5: ; 3: C ;cmp bx, nproc + nproc 0434 80 FB 20 C cmp bl, nproc + nproc C ; cmp r2,$nproc+nproc / has whole table been searched? 0437 72 DB C jb short sysexit_2 C ; blt 1b / no, go back C ; mov r5,r1 / yes, r1 now has parents process # x2 0439 23 F6 C and si, si ; r5=r1 043B 74 25 C jz short sysexit_6 C ; beq 2f / no parent has been found. C ; / The process just dies 043D D1 EE C shr si, 1 C ; asr r1 / set up index to p.stat 043F 8A 84 2A1D R C mov al, byte ptr [SI]+p.stat-1 C ; movb p.stat-1(r1),r2 / move status of parent to r2 0443 22 C0 C and al, al 0445 74 1B C jz short sysexit_6 C ; beq 2f / if its been freed, 2f 0447 3C 03 C cmp al, 3 C ; cmp r2,$3 / is parent a zombie? 0449 74 17 C je short sysexit_6 C ; beq 2f / yes, 2f C ; BH = 0 044B 8A 1E 3907 R C mov bl, byte ptr [u.uno] C ; movb u.uno,r3 / move dying process's number to r3 044F C6 87 2A1D R 03 C mov byte ptr [BX]+p.stat-1, 3 C ; movb $3,p.stat-1(r3) / make the process a zombie C ; 05/02/2014 0454 3C 01 C cmp al, 1 ; SRUN 0456 74 0A C je short sysexit_6 C ;cmp al, 2 C ; cmp r2,$2 / is the parent waiting for C ; / this child to die C ;jne short sysexit_6 C ; bne 2f / yes, notify parent not to wait any more C ; 05/02/2014 C ; p.stat = 2 --> waiting C ; p.stat = 4 --> sleeping 0458 C6 84 2A1D R 01 C mov byte ptr [SI]+p.stat-1, 1 ; SRUN ; 05/02/2014 C ;dec byte ptr [SI]+p.stat-1 C ; decb p.stat-1(r1) / awaken it by putting it (parent) 045D 8B C6 C mov ax, si ; r1 (process number in AL) C ; 14/02/2014 C ;mov bx, offset runq + 4 C ; mov $runq+4,r2 / on the runq 045F E8 0A6C C call putlu C ; jsr r0, putlu 0462 C sysexit_6: ; 2: C ; / the process dies 0462 C6 06 3907 R 00 C mov byte ptr [u.uno], 0 C ; clrb u.uno / put zero as the process number, C ; / so "swap" will 0467 E8 09D0 C call swap C ; jsr r0,swap / overwrite process with another process C ; 30/08/2013 C ;mov sp, word ptr [u.sp_] ; Retro Unix 8086 v1 modification! C ;jmp @b C ;;jmp swapret ; Retro UNIX 8086 v1 modification ! 046A C hlt_sys: C ;sti ; 18/01/2014 046A C @@: 046A F4 C hlt C ;jmp short hlt_sys 046B EB FD C jmp short @b C ; 0 / and thereby kill it; halt? C 046D C syswait: ; < wait for a processs to die > C ; 05/02/2014 C ; 10/12/2013 C ; 04/11/2013 C ; 30/10/2013 C ; 23/10/2013 C ; 24/05/2013 C ; 'syswait' waits for a process die. C ; It works in following way: C ; 1) From the parent process number, the parent's C ; process name is found. The p.ppid table of parent C ; names is then searched for this process name. C ; If a match occurs, r2 contains child's process C ; number. The child status is checked to see if it is C ; a zombie, i.e; dead but not waited for (p.stat=3) C ; If it is, the child process is freed and it's name C ; is put in (u.r0). A return is then made via 'sysret'. C ; If the child is not a zombie, nothinh happens and C ; the search goes on through the p.ppid table until C ; all processes are checked or a zombie is found. C ; 2) If no zombies are found, a check is made to see if C ; there are any children at all. If there are none, C ; an error return is made. If there are, the parent's C ; status is set to 2 (waiting for child to die), C ; the parent is swapped out, and a branch to 'syswait' C ; is made to wait on the next process. C ; C ; Calling sequence: C ; ? C ; Arguments: C ; - C ; Inputs: - C ; Outputs: if zombie found, it's name put in u.r0. C ; ............................................................... C ; C C ; / wait for a process to die 046D C syswait_0: 046D 32 FF C xor bh, bh 046F 8A 1E 3907 R C mov bl, byte ptr [u.uno] C ; movb u.uno,r1 / put parents process number in r1 0473 D0 E3 C shl bl, 1 C ;shl bx, 1 C ; asl r1 / x2 to get index into p.pid table 0475 8B 87 298C R C mov ax, word ptr [BX]+p.pid-2 C ; mov p.pid-2(r1),r1 / get the name of this process 0479 33 F6 C xor si, si C ; clr r2 047B 33 C9 C xor cx, cx ; 30/10/2013 C ;xor cl, cl C ; clr r3 / initialize reg 3 047D C syswait_1: ; 1: 047D 83 C6 02 C add si, 2 C ; add $2,r2 / use r2 for index into p.ppid table C ; / search table of parent processes C ; / for this process name 0480 3B 84 29AC R C cmp ax, word ptr [SI]+p.ppid-2 C ; cmp p.ppid-2(r2),r1 / r2 will contain the childs C ; / process number 0484 75 1D C jne short syswait_3 C ;bne 3f / branch if no match of parent process name C ;inc cx 0486 FE C1 C inc cl C ;inc r3 / yes, a match, r3 indicates number of children 0488 D1 EE C shr si, 1 C ; asr r2 / r2/2 to get index to p.stat table C ; The possible states ('p.stat' values) of a process are: C ; 0 = free or unused C ; 1 = active C ; 2 = waiting for a child process to die C ; 3 = terminated, but not yet waited for (zombie). 048A 80 BC 2A1D R 03 C cmp byte ptr [SI]+p.stat-1, 3 ; SZOMB, 05/02/2014 C ; cmpb p.stat-1(r2),$3 / is the child process a zombie? 048F 75 10 C jne short syswait_2 C ; bne 2f / no, skip it 0491 88 BC 2A1D R C mov byte ptr [SI]+p.stat-1, bh ; 0 C ; clrb p.stat-1(r2) / yes, free it 0495 D1 E6 C shl si, 1 C ; asl r2 / r2x2 to get index into p.pid table 0497 8B 84 298C R C mov ax, word ptr [SI]+p.pid-2 049B A3 38D0 R C mov word ptr [u.r0], ax C ; mov p.pid-2(r2),*u.r0 C ; / put childs process name in (u.r0) 049E E9 FE78 C jmp sysret C ; br sysret1 / return cause child is dead 04A1 C syswait_2: ; 2: 04A1 D1 E6 C shl si, 1 C ; asl r2 / r2x2 to get index into p.ppid table 04A3 C syswait_3: ; 3: 04A3 83 FE 20 C cmp si, nproc+nproc C ; cmp r2,$nproc+nproc / have all processes been checked? 04A6 72 D5 C jb syswait_1 C ; blt 1b / no, continue search C ;and cx, cx 04A8 22 C9 C and cl, cl C ; tst r3 / one gets here if there are no children C ; / or children that are still active C ; 30/10/2013 04AA 75 07 C jnz short @f C ;jz error C ; beq error1 / there are no children, error 04AC 89 0E 38D0 R C mov word ptr [u.r0], cx ; 0 04B0 E9 FE49 C jmp error 04B3 C @@: 04B3 8A 1E 3907 R C mov bl, byte ptr [u.uno] C ; movb u.uno,r1 / there are children so put C ; / parent process number in r1 04B7 FE 87 2A1D R C inc byte ptr [BX]+p.stat-1 ; 2, SWAIT, 05/02/2014 C ; incb p.stat-1(r1) / it is waiting for C ; / other children to die C ; 04/11/2013 04BB E8 097C C call swap C ; jsr r0,swap / swap it out, because it's waiting 04BE EB AD C jmp syswait_0 C ; br syswait / wait on next process C 04C0 C sysfork: ; < create a new process > C ; 14/02/2014 C ; 05/02/2014 C ; 07/12/2013 C ; 06/12/2013 C ; 18/11/2013 C ; 17/09/2013 C ; 16/09/2013 C ; 30/08/2013 C ; 08/08/2013 C ; 22/07/2013 C ; 26/05/2013 C ; 24/05/2013 C ; 'sysfork' creates a new process. This process is referred C ; to as the child process. This new process core image is C ; a copy of that of the caller of 'sysfork'. The only C ; distinction is the return location and the fact that (u.r0) C ; in the old process (parent) contains the process id (p.pid) C ; of the new process (child). This id is used by 'syswait'. C ; 'sysfork' works in the following manner: C ; 1) The process status table (p.stat) is searched to find C ; a process number that is unused. If none are found C ; an error occurs. C ; 2) when one is found, it becomes the child process number C ; and it's status (p.stat) is set to active. C ; 3) If the parent had a control tty, the interrupt C ; character in that tty buffer is cleared. C ; 4) The child process is put on the lowest priority run C ; queue via 'putlu'. C ; 5) A new process name is gotten from 'mpid' (actually C ; it is a unique number) and is put in the child's unique C ; identifier; process id (p.pid). C ; 6) The process name of the parent is then obtained and C ; placed in the unique identifier of the parent process C ; name is then put in 'u.r0'. C ; 7) The child process is then written out on disk by C ; 'wswap',i.e., the parent process is copied onto disk C ; and the child is born. (The child process is written C ; out on disk/drum with 'u.uno' being the child process C ; number.) C ; 8) The parent process number is then restored to 'u.uno'. C ; 9) The child process name is put in 'u.r0'. C ; 10) The pc on the stack sp + 18 is incremented by 2 to C ; create the return address for the parent process. C ; 11) The 'u.fp' list as then searched to see what files C ; the parent has opened. For each file the parent has C ; opened, the corresponding 'fsp' entry must be updated C ; to indicate that the child process also has opened C ; the file. A branch to 'sysret' is then made. C ; C ; Calling sequence: C ; from shell ? C ; Arguments: C ; - C ; Inputs: - C ; Outputs: *u.r0 - child process name C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; AX = r0 = PID (>0) (at the return of 'sysfork') C ; = process id of child a parent process returns C ; = process id of parent when a child process returns C ; C ; In original UNIX v1, sysfork is called and returns as C ; in following manner: (with an example: c library, fork) C ; C ; 1: C ; sys fork C ; br 1f / child process returns here C ; bes 2f / parent process returns here C ; / pid of new process in r0 C ; rts pc C ; 2: / parent process condionally branches here C ; mov $-1,r0 / pid = -1 means error return C ; rts pc C ; C ; 1: / child process brances here C ; clr r0 / pid = 0 in child process C ; rts pc C ; C ; In UNIX v7x86 (386) by Robert Nordier (1999) C ; // pid = fork(); C ; // C ; // pid == 0 in child process; C ; // pid == -1 means error return C ; // in child, C ; // parents id is in par_uid if needed C ; C ; _fork: C ; mov $.fork,eax C ; int $0x30 C ; jmp 1f C ; jnc 2f C ; jmp cerror C ; 1: C ; mov eax,_par_uid C ; xor eax,eax C ; 2: C ; ret C ; C ; In Retro UNIX 8086 v1, C ; 'sysfork' returns in following manner: C ; C ; mov ax, sys_fork C ; mov bx, offset @f ; routine for child C ; int 20h C ; jc error C ; C ; ; Routine for parent process here (just after 'jc') C ; mov word ptr [pid_of_child], ax C ; jmp next_routine_for_parent C ; C ; @@: ; routine for child process here C ; .... C ; NOTE: 'sysfork' returns to specified offset C ; for child process by using BX input. C ; (at first, parent process will return then C ; child process will return -after swapped in- C ; 'syswait' is needed in parent process C ; if return from child process will be waited for.) C ; C C ; / create a new process C ; BX = return address for child process C ; (Retro UNIX 8086 v1 modification !) 04C0 33 F6 C xor si, si C ; clr r1 04C2 C sysfork_1: ; 1: / search p.stat table for unused process number 04C2 46 C inc si C ; inc r1 04C3 80 BC 2A1D R 00 C cmp byte ptr [SI]+p.stat-1, 0 ; SFREE, 05/02/2014 C ; tstb p.stat-1(r1) / is process active, unused, dead 04C8 76 08 C jna short sysfork_2 C ; beq 1f / it's unused so branch 04CA 83 FE 10 C cmp si, nproc C ; cmp r1,$nproc / all processes checked 04CD 72 F3 C jb short sysfork_1 ; 08/08/2013 C ; blt 1b / no, branch back C ; Retro UNIX 8086 v1. modification: C ; Parent process returns from 'sysfork' to address C ; which is just after 'sysfork' system call in parent C ; process. Child process returns to address which is put C ; in BX register by parent process for 'sysfork' C ; system call. C ; so, it is not needed to increment return address C ; of system call on the top of the user's stack. C ; If the routine would be same with original UNIX v1 C ; 'sysfork' routine, 'add word ptr [SP]+12, 2' C ; instruction would be put here. C ;; add word ptr [SP]+12, 2 C ;; jmp error C ;add $2,18.(sp) / add 2 to pc when trap occured, points C ; / to old process return C ; br error1 / no room for a new process 04CF E9 FE2A C jmp error ; 08/08/2013 04D2 C sysfork_2: ; 1: C ; Retro UNIX 8086 v1. modification ! C ; 08/08/2013 04D2 B8 0319 R C mov ax, offset sysret 04D5 50 C push ax ; * 04D6 89 26 38CE R C mov word ptr [u.usp], sp C ; C ;;push es C ; 08/08/2013 C ; Return address for the parent process is already set C ; by sysenter routine. C ;mov ax, word ptr [u.segmnt] C ;mov es, ax C ;mov bp, sp C ;mov di, word ptr [BP]+12 ; user's stack pointer C ;;pop es C ;push word ptr ES:[DI] C ;;;mov ax, word ptr ES:[DI] ; return address (IP) C ;;;push ax ; **** return address for the parent process C ;;mov ax, cs C ;;mov es, ax C ;; 04DA FF 36 3908 R C push word ptr [u.segmnt] ; ** C ; Retro UNIX 8086 v1 feature only ! C ; C ; 06/12/2013 C ;push word ptr [u.uno] ; *** C ; movb u.uno,-(sp) / save parent process number 04DE 32 E4 C xor ah, ah 04E0 A0 3907 R C mov al, byte ptr [u.uno] ; parent process number 04E3 50 C push ax ; *** 04E4 8B F8 C mov di, ax C ; 07/12/2013 04E6 8A 85 29ED R C mov al, byte ptr [DI]+p.ttyc-1 ; console tty (parent) 04EA 88 84 29ED R C mov byte ptr [SI]+p.ttyc-1, al ; set child's console tty C ; 05/02/2014 (p.ttys has been removed) C ;mov byte ptr [SI]+p.ttys-1, al ; set parent's console tty 04EE 88 84 29FD R C mov byte ptr [SI]+p.waitc-1, al ; set parent's console tty C ; 22/07/2013 04F2 8B C6 C mov ax, si 04F4 A2 3907 R C mov byte ptr [u.uno], al C ; C ;mov word ptr [u.uno], si C ;movb r1,u.uno / set child process number to r1 04F7 FE 84 2A1D R C inc byte ptr [SI]+p.stat-1 ; 1, SRUN, 05/02/2014 C ; incb p.stat-1(r1) / set p.stat entry for child C ; / process to active status C ; mov u.ttyp,r2 / put pointer to parent process' C ; / control tty buffer in r2 C ;;and di, di C ;;jz short sysfork_3 C ; beq 2f / branch, if no such tty assigned C ;; ???? C ; clrb 6(r2) / clear interrupt character in tty buffer 04FB C sysfork_3: ; 2: 04FB 53 C push bx ; * return address for the child process C ; * Retro UNIX 8086 v1 feature only ! C ;;mov ax, si ;; 22/07/2013 C ; 14/02/2014 C ;mov bx, offset runq + 2 ; middle priority ! C ; (Retro UNIX 8086 v1 modification!) C ; mov $runq+4,r2 04FC E8 09CF C call putlu C ; jsr r0,putlu / put child process on lowest priority C ; / run queue 04FF D1 E6 C shl si, 1 C ; asl r1 / multiply r1 by 2 to get index C ; / into p.pid table 0501 FF 06 2BFE R C inc word ptr [mpid] C ; inc mpid / increment m.pid; get a new process name 0505 A1 2BFE R C mov ax, word ptr [mpid] 0508 89 84 298C R C mov word ptr [SI]+p.pid-2, ax C ;mov mpid,p.pid-2(r1) / put new process name C ; / in child process' name slot 050C 5A C pop dx ; * return address for the child process C ; * Retro UNIX 8086 v1 feature only ! C C ; 08/08//2013 050D 5B C pop bx ; *** 050E 53 C push bx ; *** C ;mov bp, sp C ;mov bx, word ptr [BP] ; *** C ; movb (sp),r2 / put parent process number in r2 050F 32 FF C xor bh, bh ; 08/08/2013 0511 D1 E3 C shl bx, 1 C ;asl r2 / multiply by 2 to get index into below tables 0513 8B 87 298C R C mov ax, word ptr [BX]+p.pid-2 C ; mov p.pid-2(r2),r2 / get process name of parent C ; / process 0517 89 84 29AC R C mov word ptr [SI]+p.ppid-2, ax C ; mov r2,p.ppid-2(r1) / put parent process name C ; / in parent process slot for child 051B A3 38D0 R C mov word ptr [u.r0], ax C ; mov r2,*u.r0 / put parent process name on stack C ; / at location where r0 was saved C ; 22/07/2013 051E E8 0063 C call segm_sw ; User segment switch C ; BX = New user segment ; 24/07/2013 C ; 0521 A1 3908 R C mov ax, word ptr [u.segmnt] ; 08/08/2013 0524 89 1E 3908 R C mov word ptr [u.segmnt], bx ; 24/07/2013 0528 8E C3 C mov es, bx 052A 33 F6 C xor si, si 052C 33 FF C xor di, di 052E B9 4000 C mov cx, 16384 0531 8E D8 C mov ds, ax ; 08/08/2013 0533 F3/ A5 C rep movsw ; copy process (in current segment) to C ; new process segment C ; 08/08/2013 0535 8C C8 C mov ax, cs 0537 8E D8 C mov ds, ax 0539 8B C3 C mov ax, bx ; new user segment 053B 8B 2E 38CC R C mov bp, word ptr [u.sp_] 053F 8B 5E 0C C mov bx, word ptr [BP]+12 ; user's stack pointer 0542 26: 89 17 C mov word ptr ES:[BX], dx ; *, CS:IP -> IP C ; * return address for the child process 0545 26: 89 47 02 C mov word ptr ES:[BX]+2, ax ; CS:IP -> CS C ; * return address for the child process C ;mov ax, cs C ;mov es, ax C ;* C ;;mov ax, offset sysret C ;;push ax ; * C ; mov $sysret1,-(sp) / C ;mov word ptr [u.usp], sp C ; mov sp,u.usp / contents of sp at the time when C ; / user is swapped out C ; mov $sstack,sp / point sp to swapping stack space C ; ES = u.segmnt C ; 06/12/2013 C ;push word ptr [u.intr] ; **** C ; 30/08/2013 0549 FF 36 38EE R C push word ptr [u.ttyp] ; ***** 054D 33 C0 C xor ax, ax 054F A3 38EE R C mov word ptr [u.ttyp], ax ; 0 C ; 0552 E8 092C C call wswap ; Retro UNIX 8086 v1 modification ! C ;jsr r0,wswap / put child process out on drum C ;jsr r0,unpack / unpack user stack C ;mov u.usp,sp / restore user stack pointer C ; ES = DS C ;;mov sp, word ptr [u.usp] C ; 30/08/2013 0555 8F 06 38EE R C pop word ptr [u.ttyp] ; ***** C ; 06/12/2013 C ;pop word ptr [u.intr] ; **** C ;;pop ax ; * C ; tst (sp)+ / bump stack pointer C ;pop word ptr [u.uno] ; *** 0559 58 C pop ax ; *** 22/07/2013 055A A2 3907 R C mov byte ptr [u.uno], al C ;movb (sp)+,u.uno / put parent process number in u.uno C ; 055D 8F 06 3908 R C pop word ptr [u.segmnt] ; ** C ; Retro UNIX 8086 v1 feature only ! C ; 0561 A1 2BFE R C mov ax, word ptr [mpid] 0564 A3 38D0 R C mov word ptr [u.r0], ax C ; mov mpid,*u.r0 / put child process name on stack C ; / where r0 was saved C ; 08/08/2013 C ; Return address for the parent process is already set C ; by sysenter routine. C ;pop dx ; **** return address for the parent process C ;mov ax, word ptr [u.segmnt] C ;mov es, ax C ;mov word ptr ES:[BX]+2, ax ; user's CS for iret <- ax C ;mov word ptr ES:[BX], dx ; user's IP for iret <- dx C ; add $2,18.(sp) / add 2 to pc on stack; gives parent C ; / process return C ;pop ax ; * 08/08/2013 C ; 0567 33 F6 C xor si, si C ;clr r1 0569 C sysfork_4: ; 1: / search u.fp list to find the files C ; / opened by the parent process 0569 8A 9C 38D4 R C mov bl, byte ptr [SI]+u.fp C ; movb u.fp(r1),r2 / get an open file for this process 056D 0A DB C or bl, bl 056F 74 0C C jz short sysfork_5 C ; beq 2f / file has not been opened by parent, C ; / so branch 0571 32 FF C xor bh, bh ; 18/11/2013 0573 D1 E3 C shl bx, 1 C ; asl r2 / multiply by 8 0575 D1 E3 C shl bx, 1 C ; asl r2 / to get index into fsp table 0577 D1 E3 C shl bx, 1 C ; asl r2 0579 FF 87 2A2C R C inc byte ptr [BX]+fsp-2 C ; incb fsp-2(r2) / increment number of processes C ; / using file, because child will now be C ; / using this file 057D C sysfork_5: ; 2: 057D 46 C inc si C ; inc r1 / get next open file 057E 83 FE 0A C cmp si, 10 C ; cmp r1,$10. / 10. files is the maximum number which C ; / can be opened 0581 72 E6 C jb short sysfork_4 C ; blt 1b / check next entry C ; 08/08/2013 0583 C3 C retn ; * -> sysret C ;jmp sysret C ; br sysret1 C 0584 C segm_sw: C ; 24/07/2013 C ; 23/07/2013 C ; 22/07/2013 C ; Retro UNIX 8086 v1 feature only ! C ; (User segment switch) C ; INPUT -> none C ; OUTPUT -> bx = new user segment C ; (word ptr [u.segmnt] = ax) C ; ((Modified registers: cx)) C ; 0584 8A 0E 3907 R C mov cl, byte ptr [u.uno] ; 23/07/2013 0588 BB 2000 C mov bx, csgmnt ; segment of process 1 058B C @@: 058B FE C9 C dec cl 058D 74 06 C jz short @f 058F 81 C3 0800 C add bx, 2048 ; (32768/16) 0593 EB F6 C jmp short @b 0595 C @@: C ;;mov word ptr [u.segmnt], bx ;; 24/07/2013 0595 C3 C retn C C 0596 C sysread: ; < read from file > C ; 23/05/2013 C ; 'sysread' is given a buffer to read into and the number of C ; characters to be read. If finds the file from the file C ; descriptor located in *u.r0 (r0). This file descriptor C ; is returned from a successful open call (sysopen). C ; The i-number of file is obtained via 'rw1' and the data C ; is read into core via 'readi'. C ; C ; Calling sequence: C ; sysread; buffer; nchars C ; Arguments: C ; buffer - location of contiguous bytes where C ; input will be placed. C ; nchars - number of bytes or characters to be read. C ; Inputs: *u.r0 - file descriptor (& arguments) C ; Outputs: *u.r0 - number of bytes read. C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysread' system call has three arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 3 is used C ; to get sysread system call arguments from the user; C ; * 1st argument, file descriptor is in BX register C ; * 2nd argument, buffer address/offset in CX register C ; * 3rd argument, number of bytes is in DX register C ; C ; AX register (will be restored via 'u.r0') will return C ; to the user with number of bytes read. C ; C ; NOTE: Retro UNIX 8086 v1 'arg' routine gets these C ; arguments in these registers; C ; (BX= file descriptor) C ; (CX= buffer address in user's program segment) C ; (DX= number of bytes) C ; then C ; * file descriptor (in BX) is moved into AX C ; * buffer address (in CX) is moved into 'u.base'. C ; * byte count (in DX) is moved into 'u.count'. C ; 0596 E8 0026 C call rw1 C ; jsr r0,rw1 / get i-number of file to be read into r1 0599 F6 C4 80 C test ah, 80h C ; tst r1 / negative i-number? 059C 74 03 E9 FD5B C jnz error C ; ble error1 / yes, error 1 to read C ; / it should be positive 05A1 E8 0C9B C call readi C ; jsr r0,readi / read data into core 05A4 EB 10 C jmp short @f C ; br 1f 05A6 C syswrite: ; < write to file > C ; 23/05/2013 C ; 'syswrite' is given a buffer to write onto an output file C ; and the number of characters to write. If finds the file C ; from the file descriptor located in *u.r0 (r0). This file C ; descriptor is returned from a successful open or create call C ; (sysopen or syscreat). The i-number of file is obtained via C ; 'rw1' and buffer is written on the output file via 'write'. C ; C ; Calling sequence: C ; syswrite; buffer; nchars C ; Arguments: C ; buffer - location of contiguous bytes to be writtten. C ; nchars - number of characters to be written. C ; Inputs: *u.r0 - file descriptor (& arguments) C ; Outputs: *u.r0 - number of bytes written. C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'syswrite' system call has three arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 3 is used C ; to get syswrite system call arguments from the user; C ; * 1st argument, file descriptor is in BX register C ; * 2nd argument, buffer address/offset in CX register C ; * 3rd argument, number of bytes is in DX register C ; C ; AX register (will be restored via 'u.r0') will return C ; to the user with number of bytes written. C ; C ; NOTE: Retro UNIX 8086 v1 'arg' routine gets these C ; arguments in these registers; C ; (BX= file descriptor) C ; (CX= buffer address in user's program segment) C ; (DX= number of bytes) C ; then C ; * file descriptor (in BX) is moved into AX C ; * buffer address (in CX) is moved into 'u.base'. C ; * byte count (in DX) is moved into 'u.count'. C ; 05A6 E8 0016 C call rw1 C ; jsr r0,rw1 / get i-number in r1 of file to write 05A9 F6 C4 80 C test ah, 80h C ; tst r1 / positive i-number ? 05AC 75 03 E9 FD4B C jz error C ; bge error1 / yes, error 1 C ; / negative i-number means write 05B1 F7 D8 C neg ax C ; neg r1 / make it positive 05B3 E8 0D84 C call writei C ; jsr r0,writei / write data 05B6 C @@: ; 1: 05B6 A1 38EA R C mov ax, word ptr [u.nread] 05B9 A3 38D0 R C mov word ptr [u.r0], ax C ; mov u.nread,*u.r0 / put no. of bytes transferred C ; / into (u.r0) 05BC E9 FD5A C jmp sysret C ; br sysret1 C 05BF C rw1: ; 23/05/2013 C ; 'rw1' returns i-number of the file for 'sysread' & 'syswrite'. C ; Retro UNIX 8086 v1 modification: C ; 'arg' routine is different than 'arg' in original Unix v1. C ;mov ax, 3 ; number of arguments C ;call arg C ; 24/05/2013 C ; System call registers: bx, cx, dx (through 'sysenter') 05BF 89 0E 38E6 R C mov word ptr [u.base], cx ; buffer address/offset C ; (in the user's program segment) 05C3 89 16 38E8 R C mov word ptr [u.count], dx C ; C ; jsr r0,arg; u.base / get buffer pointer C ; jsr r0,arg; u.count / get no. of characters C ;;mov ax, bx ; file descriptor C ; mov *u.r0,r1 / put file descriptor C ; / (index to u.fp table) in r1 C ;; call getf C ; BX = File descriptor 05C7 E8 05A4 C call getf1 ; calling point in 'getf' from 'rw1' C ; jsr r0,getf / get i-number of the file in r1 C ; AX = I-number of the file ; negative i-number means write C 05CA C3 C retn C ; rts r0 C 05CB C sysopen: ; C ; 27/05/2013 C ; 24/05/2013 C ; 22/05/2013 C ; 'sysopen' opens a file in following manner: C ; 1) The second argument in a sysopen says whether to C ; open the file ro read (0) or write (>0). C ; 2) I-node of the particular file is obtained via 'namei'. C ; 3) The file is opened by 'iopen'. C ; 4) Next housekeeping is performed on the fsp table C ; and the user's open file list - u.fp. C ; a) u.fp and fsp are scanned for the next available slot. C ; b) An entry for the file is created in the fsp table. C ; c) The number of this entry is put on u.fp list. C ; d) The file descriptor index to u.fp list is pointed C ; to by u.r0. C ; C ; Calling sequence: C ; sysopen; name; mode C ; Arguments: C ; name - file name or path name C ; mode - 0 to open for reading C ; 1 to open for writing C ; Inputs: (arguments) C ; Outputs: *u.r0 - index to u.fp list (the file descriptor) C ; is put into r0's location on the stack. C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysopen' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get sysopen system call arguments from the user; C ; * 1st argument, name is pointed to by BX register C ; * 2nd argument, mode is in CX register C ; C ; AX register (will be restored via 'u.r0') will return C ; to the user with the file descriptor/number C ; (index to u.fp list). C ; C ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment.) C C ;call arg2 C ; * name - 'u.namep' points to address of file/path name C ; in the user's program segment ('u.segmnt') C ; with offset in BX register (as sysopen argument 1). C ; * mode - sysopen argument 2 is in CX register C ; which is on top of stack. C ; C ; jsr r0,arg2 / get sys args into u.namep and on stack C ; 24/05/2013 C ; system call registers: bx, cx (through 'sysenter') C 05CB 89 1E 38E2 R C mov word ptr [u.namep], bx 05CF 51 C push cx 05D0 E8 05C8 C call namei C ; jsr r0,namei / i-number of file in r1 C ;and ax, ax C ;jz error ; File not found 05D3 73 03 E9 FD24 C jc error ; 27/05/2013 C ; br error2 / file not found 05D8 5A C pop dx ; mode 05D9 52 C push dx C ;or dx, dx 05DA 0A D2 C or dl, dl C ; tst (sp) / is mode = 0 (2nd arg of call; C ; / 0 means, open for read) 05DC 74 02 C jz short @f C ; beq 1f / yes, leave i-number positive 05DE F7 D8 C neg ax C ; neg r1 / open for writing so make i-number negative 05E0 C @@: ;1: 05E0 E8 0F3E C call iopen C ;jsr r0,iopen / open file whose i-number is in r1 05E3 5A C pop dx C ;and dx, dx 05E4 22 D2 C and dl, dl C ; tst (sp)+ / pop the stack and test the mode 05E6 74 02 C jz short @f C ; beq op1 / is open for read op1 05E8 C op0: 05E8 F7 D8 C neg ax C ; neg r1 C ;/ make i-number positive if open for writing [???] C ;; NOTE: iopen always make i-number positive. C ;; Here i-number becomes negative again C ;; perhaps iclose then makes it positive ??? E. Tan [22/05/2013] 05EA C @@: ;op1: 05EA 33 F6 C xor si, si C ; clr r2 / clear registers 05EC 33 DB C xor bx, bx C ; clr r3 05EE C @@: ;1: / scan the list of entries in fsp table 05EE 38 9C 38D4 R C cmp byte ptr [SI]+u.fp, bl ; 0 C ; tstb u.fp(r2) / test the entry in the u.fp list 05F2 76 09 C jna short @f C ; beq 1f / if byte in list is 0 branch 05F4 46 C inc si C ; inc r2 / bump r2 so next byte can be checked 05F5 83 FE 0A C cmp si, 10 C ; cmp r2,$10. / reached end of list? 05F8 72 F4 C jb short @b C ; blt 1b / no, go back 05FA E9 FCFF C jmp error C ; br error2 / yes, error (no files open) 05FD C @@: ; 1: 05FD 83 BF 2A2E R 00 C cmp word ptr [BX]+fsp, 0 C ; tst fsp(r3) / scan fsp entries 0602 76 0C C jna short @f C ; beq 1f / if 0 branch 0604 83 C3 08 C add bx, 8 C ; add $8.,r3 / add 8 to r3 C ; / to bump it to next entry mfsp table 0607 81 FB 0190 C cmp bx, nfiles*8 C ; cmp r3,$[nfiles*8.] / done scanning 060B 72 F0 C jb short @b C ; blt 1b / no, back 060D E9 FCEC C jmp error C ; br error2 / yes, error 0610 C @@: ; 1: / r2 has index to u.fp list; r3, has index to fsp table 0610 89 87 2A2E R C mov word ptr [BX]+fsp, ax C ; mov r1,fsp(r3) / put i-number of open file C ; / into next available entry in fsp table, 0614 8B 3E 2BD2 R C mov di, word ptr [cdev] ; word ? byte ? 0618 89 BF 2A30 R C mov word ptr [BX]+fsp+2, di C ; mov cdev,fsp+2(r3) / put # of device in next word 061C 33 FF C xor di, di 061E 89 BF 2A32 R C mov word ptr [BX]+fsp+4, di C ; clr fsp+4(r3) 0622 89 BF 2A34 R C mov word ptr [BX]+fsp+6, di C ; clr fsp+6(r3) / clear the next two words 0626 D1 EB C shr bx, 1 C ; asr r3 0628 D1 EB C shr bx, 1 C ; asr r3 / divide by 8 062A D1 EB C shr bx, 1 C ; asr r3 ; / to get number of the fsp entry-1 C ;inc bx 062C FE C3 C inc bl C ; inc r3 / add 1 to get fsp entry number 062E 88 9C 38D4 R C mov byte ptr [SI]+u.fp, bl C ; movb r3,u.fp(r2) / move entry number into C ; / next available slot in u.fp list 0632 89 36 38D0 R C mov word ptr [u.r0], si C ; mov r2,*u.r0 / move index to u.fp list C ; / into r0 loc on stack 0636 E9 FCE0 C jmp sysret C ; br sysret2 C 0639 C syscreat: ; < create file > C ; 27/05/2013 C ; 'syscreat' called with two arguments; name and mode. C ; u.namep points to name of the file and mode is put C ; on the stack. 'namei' is called to get i-number of the file. C ; If the file aready exists, it's mode and owner remain C ; unchanged, but it is truncated to zero length. If the file C ; did not exist, an i-node is created with the new mode via C ; 'maknod' whether or not the file already existed, it is C ; open for writing. The fsp table is then searched for a free C ; entry. When a free entry is found, proper data is placed C ; in it and the number of this entry is put in the u.fp list. C ; The index to the u.fp (also know as the file descriptor) C ; is put in the user's r0. C ; C ; Calling sequence: C ; syscreate; name; mode C ; Arguments: C ; name - name of the file to be created C ; mode - mode of the file to be created C ; Inputs: (arguments) C ; Outputs: *u.r0 - index to u.fp list C ; (the file descriptor of new file) C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'syscreate' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get syscreate system call arguments from the user; C ; * 1st argument, name is pointed to by BX register C ; * 2nd argument, mode is in CX register C ; C ; AX register (will be restored via 'u.r0') will return C ; to the user with the file descriptor/number C ; (index to u.fp list). C ; C ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment. C C ;call arg2 C ; * name - 'u.namep' points to address of file/path name C ; in the user's program segment ('u.segmnt') C ; with offset in BX register (as sysopen argument 1). C ; * mode - sysopen argument 2 is in CX register C ; which is on top of stack. C ; C ; jsr r0,arg2 / put file name in u.namep put mode C ; / on stack 0639 89 1E 38E2 R C mov word ptr [u.namep], bx ; file name address 063D 51 C push cx ; mode 063E E8 055A C call namei C ; jsr r0,namei / get the i-number C ;and ax, ax C ;jz short @f 0641 72 0B C jc short @f C ; br 2f / if file doesn't exist 2f 0643 F7 D8 C neg ax C ; neg r1 / if file already exists make i-number C ; / negative (open for writing) 0645 E8 0ED9 C call iopen C ; jsr r0,iopen / 0648 E8 0B7A C call itrunc C ; jsr r0,itrunc / truncate to 0 length 064B 59 C pop cx ; pop mode (did not exist in original Unix v1 !?) 064C EB 9A C jmp short op0 C ; br op0 064E C @@: ; 2: / file doesn't exist 064E 58 C pop ax C ; mov (sp)+,r1 / put the mode in r1 064F 32 E4 C xor ah, ah C ; bic $!377,r1 / clear upper byte 0651 E8 06DB C call maknod C ; jsr r0,maknod / make an i-node for this file 0654 A1 38F0 R C mov ax, word ptr [u.dirbuf] C ; mov u.dirbuf,r1 / put i-number C ; / for this new file in r1 0657 EB 8F C jmp short op0 C ; br op0 / open the file C 0659 C sysmkdir: ; < make directory > C ; 02/08/2013 C ; 27/05/2013 C ; 'sysmkdir' creates an empty directory whose name is C ; pointed to by arg 1. The mode of the directory is arg 2. C ; The special entries '.' and '..' are not present. C ; Errors are indicated if the directory already exists or C ; user is not the super user. C ; C ; Calling sequence: C ; sysmkdir; name; mode C ; Arguments: C ; name - points to the name of the directory C ; mode - mode of the directory C ; Inputs: (arguments) C ; Outputs: - C ; (sets 'directory' flag to 1; C ; 'set user id on execution' and 'executable' flags to 0) C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysmkdir' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get sysmkdir system call arguments from the user; C ; * 1st argument, name is pointed to by BX register C ; * 2nd argument, mode is in CX register C ; C ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment. C C ; / make a directory C C ;call arg2 C ; * name - 'u.namep' points to address of file/path name C ; in the user's program segment ('u.segmnt') C ; with offset in BX register (as sysopen argument 1). C ; * mode - sysopen argument 2 is in CX register C ; which is on top of stack. C C ; jsr r0,arg2 / put file name in u.namep put mode C ; / on stack 0659 89 1E 38E2 R C mov word ptr [u.namep], bx 065D 51 C push cx 065E E8 053A C call namei C ; jsr r0,namei / get the i-number C ; br .+4 / if file not found branch around error C ;xor ax, ax C ;jnz error 0661 72 03 E9 FC96 C jnc error C ; br error2 / directory already exists (error) 0666 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 ; 02/08/2013 C ;tstb u.uid / is user the super user 066B 77 03 E9 FC8C C jna error C ;bne error2 / no, not allowed 0670 58 C pop ax C ;mov (sp)+,r1 / put the mode in r1 0671 83 E0 CF C and ax, 0FFCFh ; 1111111111001111b C ;bic $!317,r1 / all but su and ex C ;or ax , 4000h ; 1011111111111111b 0674 80 CC 40 C or ah, 40h ; Set bit 14 to 1 C ;bis $40000,r1 / directory flag 0677 E8 06B5 C call maknod C ;jsr r0,maknod / make the i-node for the directory 067A E9 FC9C C jmp sysret C ;br sysret2 / C 067D C sysclose: ; C ; 26/05/2013 C ; 22/05/2013 C ; 'sysclose', given a file descriptor in 'u.r0', closes the C ; associated file. The file descriptor (index to 'u.fp' list) C ; is put in r1 and 'fclose' is called. C ; C ; Calling sequence: C ; sysclose C ; Arguments: C ; - C ; Inputs: *u.r0 - file descriptor C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; The user/application program puts file descriptor C ; in BX register as 'sysclose' system call argument. C ; (argument transfer method 1) C C ; / close the file C ;;mov ax, 1 ; one/single argument, put argument in BX C ;;call arg C ;mov bx, word ptr [u.sp_] ; points to user's BP register C ;add bx, 6 ; bx now points to BX on stack C ;mov ax, word ptr [BX] C ; mov *u.r0,r1 / move index to u.fp list into r1 067D 8B C3 C mov ax, bx ; 26/05/2013 067F E8 04B5 C call fclose C ; jsr r0,fclose / close the file 0682 73 03 E9 FC75 C jc error C ; br error2 / unknown file descriptor 0687 E9 FC8F C jmp sysret C ; br sysret2 C 068A C sysemt: C ; 10/04/2014 Bugfix [u.uid --> u.uid_] C ; 18/01/2014 C ; 10/12/2013 C ; Retro UNIX 8086 v1 modification: C ; 'Enable Multi Tasking' system call instead C ; of 'Emulator Trap' in original UNIX v1 for PDP-11. C ; C ; Retro UNIX 8086 v1 feature only! C ; Using purpose: Kernel will start without time-out C ; (internal clock/timer) functionality. C ; Then etc/init will enable clock/timer for C ; multi tasking. (Then it will not be disabled again C ; except hardware reset/restart.) C ; C 068A 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 ; BugFix u.uid --> u.uid_ 068F 76 03 E9 FC68 C ja error C 0694 06 C push es C 0695 33 C0 C xor ax, ax 0697 8E C0 C mov es, ax ; 0 0699 BF 0070 C mov di, 28*4 ; INT 1Ch vector - offset C C ; 18/01/2014 069C FA C cli C 069D 23 DB C and bx, bx 069F 74 0C C jz short emt_2 C C ; Enable INT 1Ch time-out functionality. 06A1 B8 0F0F R C mov ax, offset clock 06A4 C emt_1: 06A4 AB C stosw ; offset 06A5 8C C8 C mov ax, cs 06A7 AB C stosw ; segment C C ; 18/01/2014 06A8 FB C sti C 06A9 07 C pop es 06AA E9 FC6C C jmp sysret 06AD C emt_2: C ; Disable INT 1Ch time-out functionality. 06AD B8 06B2 R C mov ax, offset emt_iret 06B0 EB F2 C jmp short emt_1 C C 06B2 C emt_iret: 06B2 CF C iret C C C ; Original UNIX v1 'sysemt' routine C ;sysemt: C ; C ;jsr r0,arg; 30 / put the argument of the sysemt call C ; / in loc 30 C ;cmp 30,$core / was the argument a lower address C ; / than core C ;blo 1f / yes, rtssym C ;cmp 30,$ecore / no, was it higher than "core" C ; / and less than "ecore" C ;blo 2f / yes, sysret2 C ;1: C ;mov $rtssym,30 C ;2: C ;br sysret2 C 06B3 C sysilgins: C ; 03/06/2013, C ; Retro UNIX 8086 v1 modification: C ; not a valid system call ! (not in use) C ; 06B3 E9 FC46 C jmp error C ;jmp sysret C C ; Original UNIX v1 'sysemt' routine C ;sysilgins: / calculate proper illegal instruction trap address C ;jsr r0,arg; 10 / take address from sysilgins call C ;/ put it in loc 8., C ;cmp 10,$core / making it the illegal instruction C ; / trap address C ;blo 1f / is the address a user core address? C ; / yes, go to 2f C ;cmp 10,$ecore C ;blo 2f C ;1: C ;mov $fpsym,10 / no, make 'fpsum' the illegal C ; / instruction trap address for the system C ;2: C ;br sysret2 / return to the caller via 'sysret' C 06B6 C sysmdate: ; < change the modification time of a file > C ; 02/08/2013 C ; 03/06/2013 C ; 'sysmdate' is given a file name. It gets inode of this C ; file into core. The user is checked if he is the owner C ; or super user. If he is neither an error occurs. C ; 'setimod' is then called to set the i-node modification C ; byte and the modification time, but the modification time C ; is overwritten by whatever get put on the stack during C ; a 'systime' system call. This calls are restricted to C ; the super user. C ; C ; Calling sequence: C ; sysmdate; name C ; Arguments: C ; name - points to the name of file C ; Inputs: (arguments) C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; The user/application program puts address C ; of the file name in BX register C ; as 'sysmdate' system call argument. C ; C ; / change the modification time of a file C ; jsr r0,arg; u.namep / point u.namep to the file name 06B6 89 1E 38E2 R C mov word ptr [u.namep], bx 06BA E8 04DE C call namei C ; jsr r0,namei / get its i-number 06BD 73 03 E9 FC3A C jc error C ; br error2 / no, such file 06C2 E8 0A15 C call iget C ; jsr r0,iget / get i-node into core 06C5 A0 3904 R C mov al, byte ptr [u.uid_] ; 02/08/2013 06C8 3A 06 2971 R C cmp al, byte ptr [i.uid] C ; cmpb u.uid,i.uid / is user same as owner 06CC 74 07 C je short @f C ; beq 1f / yes 06CE 22 C0 C and al, al C ; tstb u.uid / no, is user the super user 06D0 74 03 E9 FC27 C jnz error C ; bne error2 / no, error 06D5 C @@: ;1: 06D5 E8 0AC8 C call setimod C ; jsr r0,setimod / fill in modification data, C ; / time etc. C ; Retro UNIX 8086 v1 modification ! 06D8 BE 2C34 R C mov si, offset p_time 06DB BF 2988 R C mov di, offset i.mtim 06DE A5 C movsw 06DF A5 C movsw C ; mov 4(sp),i.mtim / move present time to C ; mov 2(sp),i.mtim+2 / modification time 06E0 E9 FC36 C jmp sysret C ; br sysret2 C 06E3 C @@: 06E3 C3 C retn C 06E4 C sysstty: ; < set tty status and mode > C ; 12/07/2014 C ; 04/07/2014 C ; 26/06/2014 C ; 15/04/2014 C ; 18/01/2014 C ; 17/01/2014 C ; 16/01/2014 C ; 14/01/2014 C ; 13/01/2014 C ; 12/01/2014 C ; 07/12/2013 C ; 04/12/2013 C ; 30/10/2013 C ; 24/10/2013 C ; 03/09/2013 C ; 19/08/2013 C ; 15/08/2013 (set console tty) C ; 11/08/2013 C ; 16/07/2013 C ; 15/07/2013 C ; 02/06/2013 C ; C ; 'sysstty' sets the status and mode of the typewriter C ; whose file descriptor is in (u.r0). C ; C ; Calling sequence: C ; sysstty; arg C ; Arguments: C ; arg - address of 3 consequitive words that contain C ; the source of status data C ; Inputs: ((*u.r0 - file descriptor & argument)) C ; Outputs: ((status in address which is pointed to by arg)) C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysstty' system call will set the tty C ; (clear keyboard buffer and set cursor position) C ; in following manner: C ; NOTE: All of tty setting functions are here (16/01/2014) C ; C ; Inputs: C ; BX = 0 --> means C ; If CH = 0 C ; set console tty for (current) process C ; CL = tty number (0 to 9) C ; (If ch = 0, character will not be written) C ; If CH > 0 C ; set cursor position or comm. parameters only C ; If CL = FFh C ; set cursor position for console tty C ; or CL = tty number (0 to 9) C ; CH = character will be written C ; at requested cursor position (in DX) C ; (For tty numbers 0 to 7, if CH = FFh, character C ; will not be written) C ; DX = cursor position for tty number 0 to 7. C ; (only tty number 0 to 7) C ; DL = communication parameters (for serial ports) C ; (only for COM1 and COM2 serial ports) C ; DH < 0FFh -> DL is valid, initialize serial port C ; or set cursor position C ; DH = 0FFh -> DL is not valid C ; do not set serial port parameters C ; or do not set cursor position C ; C ; BX > 0 --> points to name of tty C ; CH > 0 --> C ; CL = character will be written in current C ; cursor position (for tty number from 0 to 7) C ; or character will be sent to serial port C ; (for tty number 8 or 9) C ; CH = color of the character if tty number < 8. C ; CH = 0 --> Do not write a character, C ; set mode (tty 8 to 9) or C ; set current cursor positions (tty 0 to 7) only. C ; DX = cursor position for tty number 0 to 7. C ; DH = FFh --> Do not set cursor pos (or comm. params.) C ; (DL is not valid) C ; DL = communication parameters C ; for tty number 8 or 9 (COM1 or COM2). C ; Outputs: C ; cf = 0 -> OK C ; AL = tty number (0 to 9) C ; AH = line status if tty number is 8 or 9 C ; AH = process number (of the caller) C ; cf = 1 means error (requested tty is not ready) C ; AH = FFh if the tty is locked C ; (owned by another process) C ; = process number (of the caller) C ; (if < FFh and tty number < 8) C ; AL = tty number (0FFh if it does not exist) C ; AH = line status if tty number is 8 or 9 C ; NOTE: Video page will be cleared if cf = 0. C ; C ; 14/01/2014 06E4 C7 06 38D0 R FFFF C mov word ptr [u.r0], 0FFFFh 06EA 23 DB C and bx, bx 06EC 74 03 E9 0089 C jnz sysstty_6 C ; set console tty C ; 17/01/2014 06F1 80 F9 09 C cmp cl, 9 06F4 76 17 C jna short sysstty_0 06F6 0A ED C or ch, ch 06F8 75 03 E9 FBFF C jz error 06FD 80 F9 FF C cmp cl, 0FFh 0700 73 03 E9 FBF7 C jb error 0705 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 0709 8A 8F 29ED R C mov cl, byte ptr [BX]+p.ttyc-1 ; current/console tty 070D C sysstty_0: 070D 80 F9 08 C cmp cl, 8 0710 72 10 C jb short sysstty_2 C ; 0712 80 FE FF C cmp dh, 0FFh 0715 74 0B C je short sysstty_2 C ; set communication parameters for serial ports 0717 BE 2CAE R C mov si, offset com1p C ; 12/07/2014 071A 80 F9 09 C cmp cl, 9 071D 72 01 C jb short sysstty_1 071F 46 C inc si 0720 C sysstty_1: 0720 88 14 C mov byte ptr [SI], dl ; comm. parameters 0722 C sysstty_2: 0722 52 C push dx 0723 51 C push cx 0724 32 D2 C xor dl, dl ; sysstty call sign 0726 8A C1 C mov al, cl 0728 A2 38D0 R C mov byte ptr [u.r0], al C ; AH = 0 C ;cbw C ; ah = 0 072B E8 0E55 C call ottyp 072E 59 C pop cx 072F 5A C pop dx C ; 0730 73 03 E9 FBC7 C jc error C ; 0735 32 FF C xor bh, bh C ; 17/01/2014 0737 22 ED C and ch, ch ; set cursor position C ; or comm. parameters ONLY 0739 75 08 C jnz short sysstty_3 073B 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 073F 88 8F 29ED R C mov byte ptr [BX]+p.ttyc-1, cl ; current/console tty 0743 C sysstty_3: C ; 16/01/2014 0743 8A C5 C mov al, ch ; character ; 0 to FFh 0745 80 F9 07 C cmp cl, 7 0748 76 7B C jna short sysstty_9 074A C sysstty_12: C ;; BX = 0, CL = 8 or CL = 9 C ; (Set specified serial port as console tty port) C ; CH = character to be written C ; 15/04/2014 C ; CH = 0 --> initialization only C ; AL = character C ; 26/06/2014 074A 88 0E 390A R C mov byte ptr [u.ttyn], cl C ; 12/07/2014 074E 8A E1 C mov ah, cl ; tty number (8 or 9) 0750 22 C0 C and al, al 0752 74 05 C jz short sysstty_4 ; al = ch = 0 C ; 04/07/2014 0754 E8 130E C call sndc C ; 12/07/2014 0757 EB 0A C jmp short sysstty_5 0759 C sysstty_4: C ; 12/07/2014 0759 86 E0 C xchg ah, al ; al = 0 -> al = ah, ah = 0 075B 2C 08 C sub al, 8 075D 8B D0 C mov dx, ax ; 0 or 1 075F B4 03 C mov ah, 3 ; Get serial port status 0761 CD 14 C int 14h 0763 C sysstty_5: 0763 88 26 38D1 R C mov byte ptr [u.r0]+1, ah ; line status 0767 9C C pushf 0768 32 D2 C xor dl, dl ; sysstty call sign 076A A0 390A R C mov al, byte ptr [u.ttyn] ; 26/06/2014 076D 98 C cbw ; ax = tty number (ah=0) 076E E8 0F39 C call cttyp 0771 9D C popf 0772 73 03 E9 FB85 C jc error 0777 E9 FB9F C jmp sysret C 077A C sysstty_6: 077A 52 C push dx 077B 51 C push cx 077C 89 1E 38E2 R C mov word ptr [u.namep], bx 0780 E8 0418 C call namei 0783 59 C pop cx 0784 5A C pop dx 0785 73 03 E9 FB72 C jc error 078A 83 F8 13 C cmp ax, 19 ; inode number of /dev/COM2 078D 76 03 E9 FB6A C ja error 0792 3C 0A C cmp al, 10 ; /dev/tty0 .. /dev/tty7 C ; /dev/COM1, /dev/COM2 0794 72 04 C jb short sysstty_7 0796 2C 0A C sub al, 10 0798 EB 11 C jmp short sysstty_8 C 079A C sysstty_7: 079A 3C 01 C cmp al, 1 ; /dev/tty 079C 74 03 E9 FB5B C jne error 07A1 32 FF C xor bh, bh 07A3 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 07A7 8A 87 29ED R C mov al, byte ptr [BX]+p.ttyc-1 ; current/console tty 07AB C sysstty_8: 07AB A2 38D0 R C mov byte ptr [u.r0], al 07AE 52 C push dx 07AF 50 C push ax 07B0 51 C push cx 07B1 E8 0DCF C call ottyp 07B4 59 C pop cx 07B5 58 C pop ax 07B6 5A C pop dx 07B7 73 03 E9 FB40 C jc error C ; 12/07/2014 07BC 86 C1 C xchg al, cl 07BE 80 F9 07 C cmp cl, 7 07C1 77 87 C ja sysstty_12 C ; C ; 16/01/2014 07C3 32 FF C xor bh, bh C ; 07C5 C sysstty_9: ; tty 0 to tty 7 C ; al = character 07C5 80 FE FF C cmp dh, 0FFh ; Do not set cursor position 07C8 74 09 C je short sysstty_10 07CA 51 C push cx 07CB 50 C push ax 07CC 8A D9 C mov bl, cl ; (tty number = video page number) C ;xor bh, bh 07CE E8 13C4 C call set_cpos 07D1 58 C pop ax 07D2 59 C pop cx 07D3 C sysstty_10: C ; 17/01/2014 07D3 FE C5 C inc ch 07D5 74 0B C jz short sysstty_11 ; ch = FFh 07D7 FE CD C dec ch 07D9 74 07 C jz short sysstty_11 ; ch = 0 C ; ch > 0 and ch < FFh C ; write a character at current cursor position 07DB B4 07 C mov ah, 07h ; ah = 7 (color/attribute), al = char C ; 12/07/2014 07DD 51 C push cx 07DE E8 1481 C call write_c_current 07E1 59 C pop cx 07E2 C sysstty_11: C ; 14/01/2014 07E2 32 D2 C xor dl, dl ; sysstty call sign C ; 18/01/2014 07E4 8A C1 C mov al, cl 07E6 98 C cbw 07E7 E8 0EC0 C call cttyp 07EA E9 FB2C C jmp sysret C C ; Original UNIX v1 'sysstty' routine: C ; gtty: C ;sysstty: / set mode of typewriter; 3 consequtive word arguments C ;jsr r0,gtty / r1 will have offset to tty block, C ; / r2 has source C ;mov r2,-(sp) C ;mov r1,-(sp) / put r1 and r2 on the stack C ;1: / flush the clist wait till typewriter is quiescent C ;mov (sp),r1 / restore r1 to tty block offset C ;movb tty+3(r1),0f / put cc offset into getc argument C ;mov $240,*$ps / set processor priority to 5 C ;jsr r0,getc; 0:../ put character from clist in r1 C ; br .+4 / list empty, skip branch C ;br 1b / get another character until list is empty C ;mov 0b,r1 / move cc offset to r1 C ;inc r1 / bump it for output clist C ;tstb cc(r1) / is it 0 C ;beq 1f / yes, no characters to output C ;mov r1,0f / no, put offset in sleep arg C ;jsr r0,sleep; 0:.. / put tty output process to sleep C ;br 1b / try to calm it down again C ;1: C ;mov (sp)+,r1 C ;mov (sp)+,r2 / restore registers C ;mov (r2)+,r3 / put reader control status in r3 C ;beq 1f / if 0, 1f C ;mov r3,rcsr(r1) / move r.c. status to reader C ; / control status register C ;1: C ;mov (r2)+,r3 / move pointer control status to r3 C ;beq 1f / if 0 1f C ;mov r3,tcsr(r1) / move p.c. status to printer C ; / control status reg C ;1: C ;mov (r2)+,tty+4(r1) / move to flag byte of tty block C ;jmp sysret2 / return to user C 07ED C sysgtty: ; < get tty status > C ; 28/06/2015 C ; 12/07/2014 C ; 22/04/2014 C ; 26/01/2014 C ; 17/01/2014 C ; 16/01/2014 C ; 07/12/2013 C ; 04/12/2013 C ; 03/09/2013 C ; 15/08/2013 C ; 16/07/2013 C ; 02/06/2013 C ; 30/05/2013 C ; 'sysgtty' gets the status of tty in question. C ; It stores in the three words addressed by it's argument C ; the status of the typewriter whose file descriptor C ; in (u.r0). C ; C ; Calling sequence: C ; sysgtty; arg C ; Arguments: C ; arg - address of 3 words destination of the status C ; Inputs: ((*u.r0 - file descriptor)) C ; Outputs: ((status in address which is pointed to by arg)) C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysgtty' system call will return status of tty C ; (keyboard, serial port and video page status) C ; in following manner: C ; C ; Inputs: C ; BX = 0 --> means C ; CH = 0 --> 'return status of the console tty' C ; for (current) process C ; CL = 0 --> return keyboard status (tty 0 to 7) C ; CL = 1 --> return video page status (tty 0 to 7) C ; CH > 0 --> tty number + 1 C ; C ; BX > 0 --> points to name of tty C ; CL = 0 --> return keyboard status C ; CL = 1 --> return video page status C ; CH = undefined C ; C ; Outputs: C ; cf = 0 -> C ; C ; AL = tty number from 0 to 9 C ; (0 to 7 is also the video page of the tty) C ; AH = 0 if the tty is free/unused C ; AH = the process number of the caller C ; AH = FFh if the tty is locked by another process C ; C ; (if calling is for serial port status) C ; BX = serial port status if tty number is 8 or 9 C ; (BH = modem status, BL = Line status) C ; CX = 0FFFFh (if data is ready) C ; CX = 0 (if data is not ready or undefined) C ; C ; (if calling is for keyboard status) C ; BX = current character in tty/keyboard buffer C ; (BH = scan code, BL = ascii code) C ; (BX=0 if there is not a waiting character) C ; CX is undefined C ; C ; (if calling is for video page status) C ; BX = cursor position on the video page C ; if tty number < 8 C ; (BH = row, BL = column) C ; CX = current character (in cursor position) C ; on the video page of the tty C ; if tty number < 8 C ; (CH = color, CL = character) C ; C ; cf = 1 means error (requested tty is not ready) C ; C ; AH = FFh if the caller is not owner of C ; specified tty or console tty C ; AL = tty number (0FFh if it does not exist) C ; BX, CX are undefined if cf = 1 C ; C ; (If tty number is 8 or 9) C ; AL = tty number C ; AH = the process number of the caller C ; BX = serial port status C ; (BH = modem status, BL = Line status) C ; CX = 0 C ; C 07ED C sysgtty_0: 07ED C gtty: ; get (requested) tty number C ; 28/06/2015 C ; 12/07/2014 C ; 22/04/2014 C ; 15/04/2014 C ; 26/01/2014 C ; 17/01/2014 C ; 16/01/2014 C ; 07/12/2013 C ; 04/12/2013 C ; 03/09/2013 C ; 19/08/2013 C ; 16/07/2013 C ; 02/06/2013 C ; 30/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; C ; ((Modified registers: AX, BX, CX, DX, SI, DI, BP)) C ; C ; 16/01/2014 07ED C7 06 38D0 R FFFF C mov word ptr [u.r0], 0FFFFh 07F3 80 F9 01 C cmp cl, 1 07F6 76 03 E9 FB01 C ja error C ; 07FB 23 DB C and bx, bx 07FD 74 22 C jz short sysgtty_1 C ; 07FF 89 1E 38E2 R C mov word ptr [u.namep], bx 0803 E8 0395 C call namei 0806 73 03 E9 FAF1 C jc error C ; 080B 32 FF C xor bh, bh 080D 83 F8 01 C cmp ax, 1 0810 76 1B C jna short sysgtty_2 0812 83 E8 0A C sub ax, 10 0815 83 F8 09 C cmp ax, 9 0818 76 03 E9 FADF C ja error 081D 8A E8 C mov ch, al 081F EB 18 C jmp short sysgtty_4 0821 C sysgtty_1: C ; 16/01/2014 0821 80 FD 0A C cmp ch, 10 0824 76 03 E9 FAD3 C ja error 0829 FE CD C dec ch ; 0 -> FFh (negative) 082B 79 0A C jns short sysgtty_3 ; not negative C ; 082D C sysgtty_2: C ; get tty number of console tty 082D 8A 26 3907 R C mov ah, byte ptr [u.uno] 0831 8A DC C mov bl, ah C ;xor bh, bh 0833 8A AF 29ED R C mov ch, byte ptr [BX]+p.ttyc-1 0837 C sysgtty_3: 0837 8A C5 C mov al, ch 0839 C sysgtty_4: 0839 A2 38D0 R C mov byte ptr [u.r0], al C ;cmp ch, 9 C ;ja error 083C 8B 2E 38CC R C mov bp, word ptr [u.sp_] ; 28/06/2015 0840 80 FD 08 C cmp ch, 8 ; cmp al, 8 0843 72 31 C jb short sysgtty_6 C ; C ; 12/07/2014 0845 BA 0000 C mov dx, 0 0848 74 02 C je short sysgtty_5 084A FE C2 C inc dl 084C C sysgtty_5: C ; 12/07/2014 084C B4 03 C mov ah, 3 ; get serial port status 084E CD 14 C int 14h 0850 86 E0 C xchg ah, al 0852 89 46 06 C mov word ptr [BP]+6, ax ; serial port status 0855 8A 26 3907 R C mov ah, byte ptr [u.uno] 0859 88 26 38D1 R C mov byte ptr [u.r0]+1, ah 085D C7 46 08 0000 C mov word ptr [BP]+8, 0 ; data status (0 = not ready) 0862 A8 80 C test al, 80h 0864 74 03 E9 FA93 C jnz error 0869 A8 01 C test al, 1 086B 75 03 E9 FAA9 C jz sysret 0870 FF 4E 08 C dec word ptr [BP]+8 ; data status (FFFFh = ready) 0873 E9 FAA3 C jmp sysret 0876 C sysgtty_6: 0876 A2 390A R C mov byte ptr [u.ttyn], al ; tty number C ;xor bh, bh 0879 8A D8 C mov bl, al ; tty number (0 to 7) 087B D0 E3 C shl bl, 1 ; aligned to word C ; 22/04/2014 087D 81 C3 2C8E R C add bx, offset ttyl 0881 8A 27 C mov ah, byte ptr [BX] 0883 3A 26 3907 R C cmp ah, byte ptr [u.uno] 0887 74 04 C je short sysgtty_7 0889 22 E4 C and ah, ah C ;jz short sysgtty_7 088B 75 04 C jnz short sysgtty_8 C ;mov ah, 0FFh 088D C sysgtty_7: 088D 88 26 38D1 R C mov byte ptr [u.r0]+1, ah 0891 C sysgtty_8: 0891 0A C9 C or cl, cl 0893 75 0B C jnz short sysgtty_9 0895 B0 01 C mov al, 1 ; test a key is available 0897 E8 1171 C call getc 089A 89 46 06 C mov word ptr [BP]+6, ax ; bx, character 089D E9 FA79 C jmp sysret 08A0 C sysgtty_9: 08A0 8A 1E 390A R C mov bl, byte ptr [u.ttyn] C ; bl = video page number 08A4 E8 140E C call get_cpos C ; dx = cursor position 08A7 89 56 06 C mov word ptr [BP]+6, dx ; bx C ;mov bl, byte ptr [u.ttyn] C ; bl = video page number 08AA E8 1415 C call read_ac_current C ; ax = character and attribute/color 08AD 89 46 08 C mov word ptr [BP]+8, ax ; cx 08B0 E9 FA66 C jmp sysret C C ; Original UNIX v1 'sysgtty' routine: C ; sysgtty: C ;jsr r0,gtty / r1 will have offset to tty block, C ; / r2 has destination C ;mov rcsr(r1),(r2)+ / put reader control status C ; / in 1st word of dest C ;mov tcsr(r1),(r2)+ / put printer control status C ; / in 2nd word of dest C ;mov tty+4(r1),(r2)+ / put mode in 3rd word C ;jmp sysret2 / return to user C C ; Original UNIX v1 'gtty' routine: C ; gtty: C ;jsr r0,arg; u.off / put first arg in u.off C ;mov *u.r0,r1 / put file descriptor in r1 C ;jsr r0,getf / get the i-number of the file C ;tst r1 / is it open for reading C ;bgt 1f / yes C ;neg r1 / no, i-number is negative, C ; / so make it positive C ;1: C ;sub $14.,r1 / get i-number of tty0 C ;cmp r1,$ntty-1 / is there such a typewriter C ;bhis error9 / no, error C ;asl r1 / 0%2 C ;asl r1 / 0%4 / yes C ;asl r1 / 0%8 / multiply by 8 so r1 points to C ; ; / tty block C ;mov u.off,r2 / put argument in r2 C ;rts r0 / return C include u2.asm ; u2.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U2.ASM (include u2.asm) //// UNIX v1 -> u2.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 24/03/2014 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 24/03/2014 sysbreak C ; 12/01/2014 fclose C ; 06/12/2013 sysexec C ; 19/11/2013 sysbreak C ; 18/11/2013 getf (getf1) C ; 24/10/2013 sysexec C ; 03/09/2013 sysexec (u.intr, u.quit reset -> enabled) C ; 05/08/2013 fclose, seektell C ; 02/08/2013 maknod, (u.uid -> u.uid_) C ; 01/08/2013 mkdir C ; 31/07/2013 u.namei_r -> namei_r, maknod C ; 30/07/2013 fclose C ; 28/07/2013 namei (u.namei_r) C ; 26/07/2013 namei (namei_r) C ; 25/07/2013 sysexec (arguments) C ; 24/07/2013 sysexec C ; 22/07/2013 sysexec, namei C ; 18/07/2013 sysexec, namei C ; 17/07/2013 maknod (inode->i) C ; 09/07/2013 namei (rootdir) C ; 07/07/2013 sysseek, systell, sysintr, sysquit, syssetuid, sysgetuid C ; 07/07/2013 syschmod, syschown C ; 20/06/2013 syschmod, syschown, systime, sysstime, sysbreak C ; 19/06/2013 syslink, sysunlink, sysstat, sysfstat, syschdir C ; 04/06/2013 sysexec C ; 03/06/2013 sysexec C ; 27/05/2013 namei (stc) C ; 23/05/2013 getf1 C ; 02/05/2013 maknod C ; 29/04/2013 mkdir C ; 25/04/2013 anyi C ; 24/04/2013 namei C ; 19/04/2013 fclose C ; 11/03/2013 C 08B3 C syslink: C ; 19/06/2013 C ; 'syslink' is given two arguments, name 1 and name 2. C ; name 1 is a file that already exists. name 2 is the name C ; given to the entry that will go in the current directory. C ; name2 will then be a link to the name 1 file. The i-number C ; in the name 2 entry of current directory is the same C ; i-number for the name 1 file. C ; C ; Calling sequence: C ; syslink; name 1; name 2 C ; Arguments: C ; name 1 - file name to which link will be created. C ; name 2 - name of entry in current directory that C ; links to name 1. C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'syslink' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get syslink system call arguments from the user; C ; * 1st argument, name 1 is pointed to by BX register C ; * 2nd argument, name 2 is pointed to by CX register C ; C ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment.) C C ; / name1, name2 C ;call arg2 C ; jsr r0,arg2 / u.namep has 1st arg u.off has 2nd 08B3 89 1E 38E2 R C mov word ptr [u.namep], bx 08B7 51 C push cx 08B8 E8 02E0 C call namei C ; jsr r0,namei / find the i-number associated with C ; / the 1st path name C ;and ax, ax C ;jz error ; File not found 08BB 73 03 E9 FA3C C jc error C ; br error9 / cannot be found 08C0 E8 0817 C call iget C ; jsr r0,iget / get the i-node into core 08C3 8F 06 38E2 R C pop word ptr [u.namep] ; cx C ; mov (sp)+,u.namep / u.namep points to 2nd name 08C7 50 C push ax C ; mov r1,-(sp) / put i-number of name1 on the stack C ; / (a link to this file is to be created) 08C8 FF 36 2BD2 R C push word ptr [cdev] C ; mov cdev,-(sp) / put i-nodes device on the stack 08CC E8 0028 C call isdir C ; jsr r0,isdir / is it a directory 08CF E8 02C9 C call namei C ; jsr r0,namei / no, get i-number of name2 08D2 72 03 E9 FA25 C jnc error C ; br .+4 / not found C ; / so r1 = i-number of current directory C ; / ii = i-number of current directory C ; br error9 / file already exists., error 08D7 59 C pop cx 08D8 3B 0E 2BD2 R C cmp cx, word ptr [cdev] C ; cmp (sp)+,cdev / u.dirp now points to C ; / end of current directory 08DC 74 03 E9 FA1B C jne error C ; bne error9 08E1 58 C pop ax 08E2 50 C push ax 08E3 A3 38F0 R C mov word ptr [u.dirbuf], ax C ; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf 08E6 E8 005F C call mkdir C ; jsr r0,mkdir / make directory entry for name2 C ; / in current directory 08E9 58 C pop ax C ; mov (sp)+,r1 / r1 has i-number of name1 08EA E8 07ED C call iget C ; jsr r0,iget / get i-node into core 08ED FE 06 2970 R C inc byte ptr [i.nlks] C ; incb i.nlks / add 1 to its number of links 08F1 E8 08AC C call setimod C ; jsr r0,setimod / set the i-node modified flag 08F4 E9 FA22 C jmp sysret C 08F7 C isdir: C ; 02/08/2013 C ; 04/05/2013 C ; 'isdir' check to see if the i-node whose i-number is in r1 C ; is a directory. If it is, an error occurs, because 'isdir' C ; called by syslink and sysunlink to make sure directories C ; are not linked. If the user is the super user (u.uid=0), C ; 'isdir' does not bother checking. The current i-node C ; is not disturbed. C ; C ; INPUTS -> C ; r1 - contains the i-number whose i-node is being checked. C ; u.uid - user id C ; OUTPUTS -> C ; r1 - contains current i-number upon exit C ; (current i-node back in core) C ; C ; ((AX = R1)) C ; C ; ((Modified registers: AX, DX, BX, CX, SI, DI, BP)) C ; C C ; / if the i-node whose i-number is in r1 is a directory C ; / there is an error unless super user made the call C 08F7 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 C ; tstb u.uid / super user 08FC 76 16 C jna short @f C ; beq 1f / yes, don't care 08FE FF 36 2BCE R C push word ptr [ii] C ; mov ii,-(sp) / put current i-number on stack 0902 E8 07D5 C call iget C ; jsr r0,iget / get i-node into core (i-number in r1) 0905 F7 06 296E R 4000 C test word ptr [i.flgs], 4000h ; Bit 14 : Directory flag C ; bit $40000,i.flgs / is it a directory 090B 74 03 E9 F9EC C jnz error C ; bne error9 / yes, error 0910 58 C pop ax C ; mov (sp)+,r1 / no, put current i-number in r1 (ii) 0911 E8 07C6 C call iget C ; jsr r0,iget / get it back in 0914 C @@: ; 1: 0914 C3 C retn C ; rts r0 C 0915 C sysunlink: C ; 19/06/2013 C ; 'sysunlink' removes the entry for the file pointed to by C ; name from its directory. If this entry was the last link C ; to the file, the contents of the file are freed and the C ; file is destroyed. If, however, the file was open in any C ; process, the actual destruction is delayed until it is C ; closed, even though the directory entry has disappeared. C ; C ; The error bit (e-bit) is set to indicate that the file C ; does not exist or that its directory can not be written. C ; Write permission is not required on the file itself. C ; It is also illegal to unlink a directory (except for C ; the superuser). C ; C ; Calling sequence: C ; sysunlink; name C ; Arguments: C ; name - name of directory entry to be removed C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; The user/application program puts address of the name C ; in BX register as 'sysunlink' system call argument. C ; (argument transfer method 1) C C ; / name - remove link name C ;;mov ax, 1 ; one/single argument, put argument in BX C ;;call arg C ;mov bp, word ptr [u.sp_] ; points to user's BP register C ;add bp, 6 ; bx now points to BX on stack C ;mov bx, word ptr [BP] 0915 89 1E 38E2 R C mov word ptr [u.namep], bx C ;jsr r0,arg; u.namep / u.namep points to name 0919 E8 027F C call namei C ; jsr r0,namei / find the i-number associated C ; / with the path name 091C 73 03 E9 F9DB C jc error C ; br error9 / not found 0921 50 C push ax C ; mov r1,-(sp) / put its i-number on the stack 0922 E8 FFD2 C call isdir C ; jsr r0,isdir / is it a directory 0925 33 C0 C xor ax, ax 0927 A3 38F0 R C mov word ptr [u.dirbuf], ax ; 0 C ; clr u.dirbuf / no, clear the location that will C ; / get written into the i-number portion C ; / of the entry 092A 83 2E 38E4 R 0A C sub word ptr [u.off], 10 C ; sub $10.,u.off / move u.off back 1 directory entry 092F E8 004B C call wdir C ; jsr r0,wdir / free the directory entry 0932 58 C pop ax C ; mov (sp)+,r1 / get i-number back 0933 E8 07A4 C call iget C ; jsr r0,iget / get i-node 0936 E8 0867 C call setimod C ; jsr r0,setimod / set modified flag 0939 FE 0E 2970 R C dec byte ptr [i.nlks] C ; decb i.nlks / decrement the number of links 093D 74 03 E9 F9D7 C jnz sysret C ; bgt sysret9 / if this was not the last link C ; / to file return C ; AX = r1 = i-number 0942 E8 04BD C call anyi C ; jsr r0,anyi / if it was, see if anyone has it open. C ; / Then free contents of file and destroy it. 0945 E9 F9D1 C jmp sysret C ; br sysret9 C 0948 C mkdir: C ; 01/08/2013 C ; 29/04/2013 C ; 'mkdir' makes a directory entry from the name pointed to C ; by u.namep into the current directory. C ; C ; INPUTS -> C ; u.namep - points to a file name C ; that is about to be a directory entry. C ; ii - current directory's i-number. C ; OUTPUTS -> C ; u.dirbuf+2 - u.dirbuf+10 - contains file name. C ; u.off - points to entry to be filled C ; in the current directory C ; u.base - points to start of u.dirbuf. C ; r1 - contains i-number of current directory C ; C ; ((AX = R1)) output C ; C ; (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM) C ; ((Modified registers: AX, DX, BX, CX, SI, DI, BP)) C ; C 0948 B9 0004 C mov cx, 4 094B 33 C0 C xor ax, ax 094D BF 38F2 R C mov di, offset u.dirbuf+2 0950 8B F7 C mov si, di 0952 F3/ AB C rep stosw C ; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this 0954 8B FE C mov di, si 0956 8B 36 38E2 R C mov si, word ptr [u.namep] C ; mov u.namep,r2 / r2 points to name of directory entry C ; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 095A C mkdir_1: ; 1: C ; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 C ; 01/08/2013 095A 0E C push cs ; push ds 095B A1 3908 R C mov ax, word ptr [u.segmnt] 095E 8E D8 C mov ds, ax 0960 C @@: 0960 AC C lodsb C ; movb (r2)+,r1 / move character in name to r1 0961 22 C0 C and al, al 0963 74 11 C jz short mkdir_2 C ; beq 1f / if null, done 0965 3C 2F C cmp al, '/' C ; cmp r1,$'/ / is it a "/"? 0967 74 09 C je short @f C ;je error C ; beq error9 / yes, error 0969 81 FF 38FA R C cmp di, offset u.dirbuf+10 C ; cmp r3,$u.dirbuf+10. / have we reached the last slot for C ; / a char? 096D 74 F1 C je short @b C ;je short mkdir_1 C ; beq 1b / yes, go back 096F AA C stosb C ; movb r1,(r3)+ / no, put the char in the u.dirbuf C ; 01/08/2013 0970 EB EE C jmp short @b C ; jmp short mkdir_1 C ; br 1b / get next char 0972 C @@: C ; 01/08/2013 0972 1F C pop ds 0973 E9 F986 C jmp error C 0976 C mkdir_2: ; 1: C ; 01/08/2013 0976 1F C pop ds C ; 0977 A1 38E0 R C mov ax, word ptr [u.dirp] 097A A3 38E4 R C mov word ptr [u.off], ax C ; mov u.dirp,u.off / pointer to empty current directory C ; / slot to u.off 097D C wdir: ; 29/04/2013 097D C7 06 38E6 R 38F0 R C mov word ptr [u.base], offset u.dirbuf C ; mov $u.dirbuf,u.base / u.base points to created file name 0983 C7 06 38E8 R 000A C mov word ptr [u.count], 10 C ; mov $10.,u.count / u.count = 10 0989 A1 2BCE R C mov ax, word ptr [ii] C ; mov ii,r1 / r1 has i-number of current directory 098C B2 01 C mov dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification ! 098E E8 07EC C call access C ; jsr r0,access; 1 / get i-node and set its file up C ; / for writing C ; AX = i-number of current directory C ; 01/08/2013 0991 FE 06 2C0A R C inc byte ptr [mkdir_w] ; the caller is 'mkdir' sign 0995 E8 09A2 C call writei C ; jsr r0,writei / write into directory 0998 C3 C retn C ; rts r0 C 0999 C sysexec: C ; 06/12/2013 C ; 24/10/2013 C ; 22/09/2013 C ; 03/09/2013 C ; 02/08/2013 C ; 25/07/2013 C ; 24/07/2013 C ; 22/07/2013 C ; 18/07/2013 C ; 03/06/2013 C ; 'sysexec' initiates execution of a file whose path name if C ; pointed to by 'name' in the sysexec call. C ; 'ssysexec' performs the following operations: C ; 1. obtains i-number of file to be executed via 'namei'. C ; 2. obtains i-node of file to be exceuted via 'iget'. C ; 3. sets trap vectors to system routines. C ; 4. loads arguments to be passed to executing file into C ; highest locations of user's core C ; 5. puts pointers to arguments in locations immediately C ; following arguments. C ; 6. saves number of arguments in next location. C ; 7. intializes user's stack area so that all registers C ; will be zeroed and the PS is cleared and the PC set C ; to core when 'sysret' restores registers C ; and does an rti. C ; 8. inializes u.r0 and u.sp C ; 9. zeros user's core down to u.r0 C ; 10. reads executable file from storage device into core C ; starting at location 'core'. C ; 11. sets u.break to point to end of user's code with C ; data area appended. C ; 12. calls 'sysret' which returns control at location C ; 'core' via 'rti' instruction. C ; C ; Calling sequence: C ; sysexec; namep; argp C ; Arguments: C ; namep - points to pathname of file to be executed C ; argp - address of table of argument pointers C ; argp1... argpn - table of argument pointers C ; argp1:<...0> ... argpn:<...0> - argument strings C ; Inputs: (arguments) C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; user/application segment and system/kernel segment C ; are different and sysenter/sysret/sysrele routines C ; are different (user's registers are saved to C ; and then restored from system's stack.) C ; C ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment.) C C ;call arg2 C ; * name - 'u.namep' points to address of file/path name C ; in the user's program segment ('u.segmnt') C ; with offset in BX register (as sysopen argument 1). C ; * argp - sysexec argument 2 is in CX register C ; which is on top of stack. C ; C ; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack 0999 89 1E 38E2 R C mov word ptr [u.namep], bx ; argument 1 099D 51 C push cx ; argument 2 099E E8 01FA C call namei C ; jsr r0,namei / namei returns i-number of file C ; / named in sysexec call in r1 09A1 73 03 E9 F956 C jc error C ; br error9 09A6 E8 0731 C call iget C ; jsr r0,iget / get i-node for file to be executed 09A9 F7 06 296E R 0010 C test word ptr [i.flgs], 10h C ; bit $20,i.flgs / is file executable 09AF 75 03 E9 F948 C jz error C ; beq error9 C ;; 09B4 E8 0B6A C call iopen C ; jsr r0,iopen / gets i-node for file with i-number C ; / given in r1 (opens file) C ; AX = i-number of the file 09B7 F7 06 296E R 0020 C test word ptr [i.flgs], 20h C ; bit $40,i.flgs / test user id on execution bit 09BD 74 0F C jz short sysexec_1 C ; beq 1f 09BF 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 ; 02/08/2013 C ; tstb u.uid / test user id 09C4 76 08 C jna short sysexec_1 C ; beq 1f / super user 09C6 8A 0E 2971 R C mov cl, byte ptr [i.uid] 09CA 88 0E 3904 R C mov byte ptr [u.uid_], cl ; 02/08/2013 C ; movb i.uid,u.uid / put user id of owner of file C ; / as process user id 09CE C sysexec_1: ; 1: C ; 22/07/2013 09CE E8 FBB3 C call segm_sw ; User segment switch C ; BX = New user segment ; 24/07/2013 C ; 09D1 59 C pop cx C ; mov (sp)+,r5 / r5 now contains address of list of C ; / pointers to arguments to be passed C ; mov $1,u.quit / u.quit determines handling of quits; C ; / u.quit = 1 take quit C ; mov $1,u.intr / u.intr determines handling of C ; / interrupts; u.intr = 1 take interrupt C ; mov $rtssym,30 / emt trap vector set to take C ; / system routine C ; mov $fpsym,*10 / reserved instruction trap vector C ; / set to take system routine C ; 24/07/2013 09D2 BC 3A74 R C mov sp, sstack ; offset sstack C ; mov $sstack,sp / stack space used during swapping C ;push cx C ; mov r5,-(sp) / save arguments pointer on stack 09D5 BF 7FC0 C mov di, ecore C ; mov $ecore,r5 / r5 has end of core C ;mov bp, core 09D8 33 ED C xor bp, bp ; core = 0 C ; mov $core,r4 / r4 has start of users core 09DA 89 2E 38E6 R C mov word ptr [u.base], bp C ; mov r4,u.base / u.base has start of users core C ; C ; 24/07/2013 09DE 8E C3 C mov es, bx ; new user segment C ; If the caller is a user, es = word ptr [u.segmnt] C ; If the caller is system (sysexec for '/etc/init') C ; es = csgmnt and word ptr [u.segmnt] = cs 09E0 8B 16 3908 R C mov dx, word ptr [u.segmnt] 09E4 8E DA C mov ds, dx C ; 09E6 8B D9 C mov bx, cx C ; mov (sp),r2 / move arguments list pointer into r2 09E8 C sysexec_2: ; 1: C ; AX = i-number of the file (at return of 'iopen' call) 09E8 8B 17 C mov dx, word ptr [BX] 09EA 23 D2 C and dx, dx 09EC 74 04 C jz short @f C ; tst (r2)+ / argument char = "nul" C ; bne 1b 09EE 43 C inc bx 09EF 43 C inc bx 09F0 EB F6 C jmp short sysexec_2 09F2 C @@: C ; tst -(r2) / decrement r2 by 2; r2 has addr of end of C ; / argument pointer list 09F2 C sysexec_3: ; 1: C ; / move arguments to bottom of users core 09F2 4B C dec bx 09F3 4B C dec bx C ;mov si, word ptr [BX] C ;; mov -(r2),r3 / (r3) last non zero argument ptr 09F4 3B D9 C cmp bx, cx C ; cmp r2,(sp) / is r2 = beginning of argument C ; / ptr list 09F6 72 20 C jb short sysexec_6 C ; blo 1f / branch to 1f when all arguments C ; / are moved 09F8 8B 37 C mov si, word ptr [BX] C ; mov -(r2),r3 / (r3) last non zero argument ptr 09FA C sysexec_4: ; 2: 09FA 8A 14 C mov dl, byte ptr [SI] 09FC 22 D2 C and dl, dl C ; tstb (r3)+ 09FE 74 03 C jz short sysexec_5 0A00 46 C inc si 0A01 EB F7 C jmp short sysexec_4 C ; bne 2b / scan argument for \0 (nul) 0A03 C sysexec_5: ; 2: 0A03 4F C dec di 0A04 26: 88 15 C mov byte ptr ES:[DI], dl ; 24/07/2013 C ; movb -(r3),-(r5) / move argument char C ; / by char starting at "ecore" 0A07 3B 37 C cmp si, word ptr [BX] C ; cmp r3,(r2) / moved all characters in C ; / this argument C ; bhi 2b / branch 2b if not 0A09 76 05 C jna short @f 0A0B 4E C dec si 0A0C 8A 14 C mov dl, byte ptr [SI] 0A0E EB F3 C jmp short sysexec_5 0A10 C @@: 0A10 26: 89 7E 00 C mov word ptr ES:[BP], di ; 24/07/2013 0A14 45 C inc bp 0A15 45 C inc bp C ; mov r5,(r4)+ / move r5 into top of users core; C ; / r5 has pointer to nth arg 0A16 EB DA C jmp sysexec_3 C ; br 1b / string 0A18 C sysexec_6: ; 1: 0A18 4F C dec di 0A19 4F C dec di ; 24/10/2013 C ;mov byte ptr ES:[DI], 0 ; 24/07/2013 C ; clrb -(r5) 0A1A D1 EF C shr di, 1 0A1C D1 E7 C shl di, 1 C ; bic $1,r5 / make r5 even, r5 points to C ; / last word of argument strings C ;mov si, core 0A1E 33 F6 C xor si, si ; core = 0 C ; mov $core,r2 0A20 26: 89 35 C mov word ptr ES:[DI], si ; 24/07/2013 0A23 C sysexec_7: ; 1: / move argument pointers into core following C ; / argument strings 0A23 3B F5 C cmp si, bp C ; cmp r2,r4 0A25 73 0C C jnb short sysexec_8 C ; bhis 1f / branch to 1f when all pointers C ; / are moved 0A27 26: 8B 14 C mov dx, word ptr ES:[SI] ; 25/07/2013 0A2A 46 C inc si 0A2B 4F C dec di 0A2C 46 C inc si 0A2D 4F C dec di 0A2E 26: 89 15 C mov word ptr ES:[DI], dx ; 24/07/2013 C ; mov (r2)+,-(r5) 0A31 EB F0 C jmp short sysexec_7 C ; br 1b 0A33 C sysexec_8: ; 1: C ;sub bp, core ; core = 0 C ; sub $core,r4 / gives number of arguments *2 0A33 D1 ED C shr bp, 1 C ; asr r4 / divide r4 by 2 to calculate C ; / the number of args stored 0A35 4F C dec di 0A36 4F C dec di 0A37 26: 89 2D C mov word ptr ES:[DI], bp ; 24/07/2013 C ; mov r4,-(r5) / save number of arguments ahead C ; / of the argument pointers 0A3A 33 C9 C xor cx, cx 0A3C 9C C pushf 0A3D 5A C pop dx 0A3E 4F C dec di 0A3F 4F C dec di C ; 24/07/2013 (ES:[DI]) 0A40 26: 89 15 C mov word ptr ES:[DI], dx ; FLAGS (for 'IRET') C ; clr -(r5) / popped into ps when rti in C ; / sysrele is executed 0A43 8C C3 C mov bx, es ; 24/07/2013 0A45 4F C dec di 0A46 4F C dec di 0A47 26: 89 1D C mov word ptr ES:[DI], bx ; CS (for 'IRET') C ;mov cx, core ; core = 0 0A4A 4F C dec di 0A4B 4F C dec di 0A4C 26: 89 0D C mov word ptr ES:[DI], cx ; IP (for 'IRET') C ; mov $core,-(r5) / popped into pc when rti C ; / in sysrele is executed C ;mov r5,0f / load second copyz argument C ;tst -(r5) / decrement r5 C ; 0A4F 8C CB C mov bx, cs 0A51 8E DB C mov ds, bx C ; 0A53 89 0E 38D0 R C mov word ptr [u.r0], cx ; ax = 0 0A57 89 3E 38CE R C mov word ptr [u.usp], di 0A5B 57 C push di ; user's stack pointer 0A5C 51 C push cx ; dx = 0 0A5D 51 C push cx ; cx = 0 0A5E 51 C push cx ; bx = 0 0A5F 51 C push cx ; si = 0 0A60 51 C push cx ; di = 0 0A61 51 C push cx ; bp = 0 0A62 89 26 38CC R C mov word ptr [u.sp_], sp 0A66 8B CF C mov cx, di C ; 24/07/2013 0A68 33 FF C xor di, di ; 0 0A6A 50 C push ax ; i-number 0A6B 33 C0 C xor ax, ax ; 0 0A6D D1 E9 C shr cx, 1 ; cx/2 -> word count C ; ES = word ptr [u.segmnt] or csgmnt 0A6F F3/ AB C rep stosw ; clear user's core/memory segment 0A71 8C C0 C mov ax, es ; 24/07/2013 0A73 A3 3908 R C mov word ptr [u.segmnt], ax ; 24/07/2013 0A76 8E C3 C mov es, bx ; es = ds = cs 0A78 58 C pop ax ; i-number C ; mov r5,u.r0 / C ; sub $16.,r5 / skip 8 words C ; mov r5,u.sp / assign user stack pointer value, C ; / effectively zeroes all regs C ; / when sysrele is executed C ; jsr r0,copyz; core; 0:0 / zero user's core 0A79 89 0E 38EC R C mov word ptr [u.break_], cx ; 0 C ; clr u.break C ; mov r5,sp / point sp to user's stack 0A7D C7 06 38E8 R 000C C mov word ptr [u.count], 12 C ; mov $14,u.count 0A83 C7 06 38DE R 38E4 R C mov word ptr [u.fofp], offset u.off C ; mov $u.off,u.fofp 0A89 89 0E 38E4 R C mov word ptr [u.off], cx ; 0 C ; clr u.off / set offset in file to be read to zero C ; AX = i-number of the executable file 0A8D E8 07AF C call readi C ; jsr r0,readi / read in first six words of C ; / user's file, starting at $core 0A90 8B 0E 38CE R C mov cx, word ptr [u.usp] C ; mov sp,r5 / put users stack address in r5 0A94 83 E9 28 C sub cx, core+40 ; 40 bytes will be reserved C ; for user stack C ; sub $core+40.,r5 / subtract $core +40, C ; / from r5 (leaves number of words C ; / less 26 available for C ; / program in user core 0A97 89 0E 38E8 R C mov word ptr [u.count], cx C ; mov r5,u.count / 0A9B 8B 1E 3908 R C mov bx, word ptr [u.segmnt] 0A9F 8E C3 C mov es, bx C ;mov bx, core ; 0 0AA1 33 DB C xor bx, bx ; 0 0AA3 26: 81 3F 0AEB C cmp word ptr ES:[BX], 0AEBh ; EBh, 0Ah -> jump to +12 C ; cmp core,$405 / br .+14 is first instruction C ; / if file is standard a.out format 0AA8 75 32 C jne short sysexec_9 C ; bne 1f / branch, if not standard format 0AAA 80 C3 02 C add bl, 2 C ;add cx, word ptr ES:[BX]+2 0AAD 26: 03 0F C add cx, word ptr ES:[BX] C ; mov core+2,r5 / put 2nd word of users program in r5; C ; / number of bytes in program text 0AB0 8C DA C mov dx, ds 0AB2 8E C2 C mov es, dx C ; 0AB4 83 E9 0C C sub cx, 12 C ; sub $14,r5 / subtract 12 0AB7 3B 0E 38E8 R C cmp cx, word ptr [u.count] C ; cmp r5,u.count / 0ABB 7F 1F C jg short sysexec_9 C ; bgt 1f / branch if r5 greater than u.count 0ABD 89 0E 38E8 R C mov word ptr [u.count], cx C ; mov r5,u.count 0AC1 53 C push bx 0AC2 E8 077A C call readi C ; jsr r0,readi / read in rest of user's program text 0AC5 8B 1E 3908 R C mov bx, word ptr [u.segmnt] 0AC9 8E C3 C mov es, bx 0ACB 5B C pop bx C ;mov cx, word ptr ES:[BX]+8 0ACC 80 C3 06 C add bl, 6 ; 2+6 = 8 0ACF 26: 8B 0F C mov cx, word ptr ES:[BX] C ; 0AD2 8C DB C mov bx, ds 0AD4 8E C3 C mov es, bx C ; 0AD6 89 0E 38EA R C mov word ptr [u.nread], cx C ; add core+10,u.nread / add size of user data area C ; / to u.nread 0ADA EB 03 C jmp short sysexec_10 C ; br 2f 0ADC C sysexec_9: ; 1: 0ADC E8 0760 C call readi C ; jsr r0,readi / read in rest of file 0ADF C sysexec_10: ; 2: 0ADF 8B 0E 38EA R C mov cx, word ptr [u.nread] 0AE3 83 C1 0C C add cx, core+12 ; 18/07/2013 C ;mov word ptr [u.break_], cx C ; mov u.nread,u.break / set users program break to end of C ; / user code C ;add word ptr [u.break_], core+12 ; 12 C ; add $core+14,u.break / plus data area 0AE6 89 0E 38EC R C mov word ptr [u.break_], cx ; 18/07/2013 0AEA E8 0B6E C call iclose C ; jsr r0,iclose / does nothing C ;; mov sp , word ptr [u.sp_] C ; C ; 06/12/2013 0AED 33 C0 C xor ax, ax 0AEF FE C0 C inc al 0AF1 A3 38FC R C mov word ptr [u.intr], ax ; 1 (interrupt/time-out is enabled) 0AF4 A3 38FE R C mov word ptr [u.quit], ax ; 1 ('crtl+brk' signal is enabled) C ; 0AF7 E9 F81F C jmp sysret C ; br sysret3 / return to core image at $core C C 0AFA C sysfstat: C ; 19/06/2013 C ; 'sysfstat' is identical to 'sysstat' except that it operates C ; on open files instead of files given by name. It puts the C ; buffer address on the stack, gets the i-number and C ; checks to see if the file is open for reading or writing. C ; If the file is open for writing (i-number is negative) C ; the i-number is set positive and a branch into 'sysstat' C ; is made. C ; C ; Calling sequence: C ; sysfstat; buf C ; Arguments: C ; buf - buffer address C ; C ; Inputs: *u.r0 - file descriptor C ; Outputs: buffer is loaded with file information C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysfstat' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get sysfstat system call arguments from the user; C ; * 1st argument, file descriptor is in BX register C ; * 2nd argument, buf is pointed to by CX register C C ; / set status of open file C ;call arg2 C ; jsr r0,arg; u.off / put buffer address in u.off 0AFA 51 C push cx C ; mov u.off,-(sp) / put buffer address on the stack C ; mov ax, word ptr [u.r0] C ; mov *u.r0,r1 / put file descriptor in r1 C ;jsr r0,getf / get the files i-number C ; BX = file descriptor (file number) 0AFB E8 0070 C call getf1 0AFE 23 C0 C and ax, ax ; i-number of the file C ; tst r1 / is it 0? 0B00 75 03 E9 F7F7 C jz error C ; beq error3 / yes, error 0B05 80 FC 80 C cmp ah, 80h 0B08 72 11 C jb short @f C ; bgt 1f / if i-number is negative (open for writing) 0B0A F7 D8 C neg ax C ; neg r1 / make it positive, then branch 0B0C EB 0D C jmp short @f C ; br 1f / to 1f 0B0E C sysstat: C ; 19/06/2013 C ; 'sysstat' gets the status of a file. Its arguments are the C ; name of the file and buffer address. The buffer is 34 bytes C ; long and information about the file placed in it. C ; sysstat calls 'namei' to get the i-number of the file. C ; Then 'iget' is called to get i-node in core. The buffer C ; is then loaded and the results are given in the UNIX C ; Programmers Manual sysstat (II). C ; C ; Calling sequence: C ; sysstat; name; buf C ; Arguments: C ; name - points to the name of the file C ; buf - address of a 34 bytes buffer C ; Inputs: - C ; Outputs: buffer is loaded with file information C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysstat' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get sysstat system call arguments from the user; C ; * 1st argument, name is pointed to by BX register C ; * 2nd argument, buf is pointed to by CX register C ; C ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment.) C C ; / ; name of file; buffer - get files status C ;call arg2 C ; jsr r0,arg2 / get the 2 arguments 0B0E 89 1E 38E2 R C mov word ptr [u.namep], bx 0B12 51 C push cx 0B13 E8 0085 C call namei C ; jsr r0,namei / get the i-number for the file 0B16 73 03 E9 F7E1 C jc error C ; br error3 / no such file, error 0B1B C @@: ; 1: 0B1B E8 05BC C call iget C ; jsr r0,iget / get the i-node into core 0B1E 8B 36 3908 R C mov si, word ptr [u.segmnt] 0B22 5F C pop di C ; mov (sp)+,r3 / move u.off to r3 (points to buffer) 0B23 8E C6 C mov es, si 0B25 AB C stosw C ; mov r1,(r3)+ / put i-number in 1st word of buffer C ;mov si, offset inode 0B26 BE 296E R C mov si, offset i C ; mov $inode,r2 / r2 points to i-node 0B29 C @@: ; 1: 0B29 A5 C movsw C ; mov (r2)+,(r3)+ / move rest of i-node to buffer 0B2A 81 FE 298E R C cmp si, offset i + 32 C ; cmp r2,$inode+32 / done? 0B2E 75 F9 C jne short @b C ; bne 1b / no, go back 0B30 8C D8 C mov ax, ds 0B32 8E C0 C mov es, ax 0B34 E9 F7E2 C jmp sysret C ; br sysret3 / return through sysret C 0B37 C fclose: C ; 12/01/2014 C ; 05/08/2013 C ; 30/07/2013 C ; 19/04/2013 C ; Given the file descriptor (index to the u.fp list) C ; 'fclose' first gets the i-number of the file via 'getf'. C ; If i-node is active (i-number > 0) the entry in C ; u.fp list is cleared. If all the processes that opened C ; that file close it, then fsp etry is freed and the file C ; is closed. If not a return is taken. C ; If the file has been deleted while open, 'anyi' is called C ; to see anyone else has it open, i.e., see if it is appears C ; in another entry in the fsp table. Upon return from 'anyi' C ; a check is made to see if the file is special. C ; C ; INPUTS -> C ; r1 - contains the file descriptor (value=0,1,2...) C ; u.fp - list of entries in the fsp table C ; fsp - table of entries (4 words/entry) of open files. C ; OUTPUTS -> C ; r1 - contains the same file descriptor C ; r2 - contains i-number C ; C ; ((AX = R1)) C ; ((Modified registers: DX, BX, CX, SI, DI, BP)) C ; C ; Retro UNIX 8086 v1 modification : CF = 1 C ; if i-number of the file is 0. (error) C ; 0B37 8B D0 C mov dx, ax ; ** 0B39 50 C push ax ; *** C ; mov r1,-(sp) / put r1 on the stack (it contains C ; / the index to u.fp list) 0B3A E8 002F C call getf C ; jsr r0,getf / r1 contains i-number, C ; / cdev has device =, u.fofp C ; / points to 3rd word of fsp entry 0B3D 83 F8 01 C cmp ax, 1 ; r1 C ; tst r1 / is inumber 0? 0B40 72 28 C jb short fclose_2 C ; beq 1f / yes, i-node not active so return C ; tst (r0)+ / no, jump over error return 0B42 8B DA C mov bx, dx ; ** 0B44 8B D0 C mov dx, ax ; * C ; mov r1,r2 / move i-number to r2 ;* C ; mov (sp),r1 / restore value of r1 from the stack C ; / which is index to u.fp ; ** 0B46 C6 87 38D4 R 00 C mov byte ptr [BX]+u.fp, 0 ; 30/07/2013 C ; clrb u.fp(r1) / clear that entry in the u.fp list 0B4B 8B 1E 38DE R C mov bx, word ptr [u.fofp] C ; mov u.fofp,r1 / r1 points to 3rd word in fsp entry 0B4F C @@: 0B4F FE 4F 02 C dec byte ptr [BX]+2 C ; decb 2(r1) / decrement the number of processes C ; / that have opened the file 0B52 79 16 C jns short fclose_2 ; jump if not negative (jump if bit 7 is 0) C ; bge 1f / if all processes haven't closed the file, return C ; 0B54 52 C push dx ;* C ; mov r2,-(sp) / put r2 on the stack (i-number) 0B55 33 C0 C xor ax, ax ; 0 0B57 89 47 FC C mov word ptr [BX]-4, ax ; 0 C ; clr -4(r1) / clear 1st word of fsp entry C ; 12/1/2014 (removing Retro UNIX 8086 v1 modification, 30/7/2013) C ; (returning to original unix v1 code) 0B5A 8A 47 03 C mov al, byte ptr [BX]+3 C ; tstb 3(r1) / has this file been deleted 0B5D 22 C0 C and al, al 0B5F 74 05 C jz short fclose_1 C ; beq 2f / no, branch 0B61 8B C2 C mov ax, dx ; * C ; mov r2,r1 / yes, put i-number back into r1 C ; AX = inode number 0B63 E8 029C C call anyi C ; jsr r0,anyi / free all blocks related to i-number C ; / check if file appears in fsp again 0B66 C fclose_1: ; 2: 0B66 58 C pop ax ; * C ; mov (sp)+,r1 / put i-number back into r1 0B67 E8 0AF1 C call iclose ; close if it is special file C ; jsr r0,iclose / check to see if its a special file 0B6A C fclose_2: ; 1: 0B6A 58 C pop ax ; *** C ; mov (sp)+,r1 / put index to u.fp back into r1 0B6B C3 C retn C ; rts r0 C 0B6C C getf: ; 18/11/2013 (mov ax, bx) C ; 19/04/2013 C ; / get the device number and the i-number of an open file 0B6C 8B D8 C mov bx, ax 0B6E C getf1: ;; Calling point from 'rw1' (23/05/2013) 0B6E 83 FB 0A C cmp bx, 10 C ; cmp r1,$10. / user limited to 10 open files 0B71 72 03 E9 F786 C jnb error C ; bhis error3 / u.fp is table of users open files, C ; / index in fsp table 0B76 8A 9F 38D4 R C mov bl, byte ptr [BX]+u.fp C ; movb u.fp(r1),r1 / r1 contains number of entry C ; / in fsp table 0B7A 0A DB C or bl, bl 0B7C 75 03 C jnz short @f ; 18/11/2013 C ;jz short @f C ; beq 1f / if its zero return C ; 18/11/2013 0B7E 8B C3 C mov ax, bx ; 0 0B80 C3 C retn 0B81 C @@: 0B81 D1 E3 C shl bx, 1 C ; asl r1 0B83 D1 E3 C shl bx, 1 C ; asl r1 / multiply by 8 to get index into C ; / fsp table entry 0B85 D1 E3 C shl bx, 1 C ; asl r1 0B87 81 C3 2A2A R C add bx, offset fsp - 4 C ; add $fsp-4,r1 / r1 is pointing at the 3rd word C ; / in the fsp entry 0B8B 89 1E 38DE R C mov word ptr [u.fofp], bx C ; mov r1,u.fofp / save address of 3rd word C ; / in fsp entry in u.fofp 0B8F 4B C dec bx 0B90 4B C dec bx 0B91 8B 07 C mov ax, word ptr [BX] C ;mov byte ptr [cdev], al ; ;;Retro UNIX 8086 v1 ! 0B93 A3 2BD2 R C mov word ptr [cdev], ax ; ;;in fact (!) C ; ;;dev number is in 1 byte C ; mov -(r1),cdev / remove the device number cdev 0B96 4B C dec bx 0B97 4B C dec bx 0B98 8B 07 C mov ax, word ptr [BX] C ; mov -(r1),r1 / and the i-number r1 C ;@@: ; 1: 0B9A C3 C retn C ; rts r0 C 0B9B C namei: C ; 31/07/2013 C ; 28/07/2013 C ; 26/07/2013 (namei_r) C ; 22/07/2013 C ; 18/07/2013 C ; 09/07/2013 mov ax, word ptr [rootdir] C ; 27/05/2013 (cf=1 return for indicating 'file not found') C ; 24/04/2013 C ; 'namei' takes a file path name and returns i-number of C ; the file in the current directory or the root directory C ; (if the first character of the pathname is '/'). C ; C ; INPUTS -> C ; u.namep - points to a file path name C ; u.cdir - i-number of users directory C ; u.cdev - device number on which user directory resides C ; OUTPUTS -> C ; r1 - i-number of file C ; cdev C ; u.dirbuf - points to directory entry where a match C ; occurs in the search for file path name. C ; If no match u.dirb points to the end of C ; the directory and r1 = i-number of the current C ; directory. C ; ((AX = R1)) C ; C ; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM) C ; ((Modified registers: DX, BX, CX, SI, DI, BP)) C ; C C ;;push es ; Retro UNIX 8086 v1 Feature only ! 0B9B A1 3908 R C mov ax, word ptr [u.segmnt] ; Retro UNIX 8086 v1 Feature only ! 0B9E 8E C0 C mov es, ax ; Retro UNIX 8086 v1 Feature only ! C 0BA0 A1 38D2 R C mov ax, word ptr [u.cdir] C ; mov u.cdir,r1 / put the i-number of current directory C ; / in r1 0BA3 8B 16 3902 R C mov dx, word ptr [u.cdrv] 0BA7 89 16 2BD2 R C mov word ptr [cdev], dx ; NOTE: Retro UNIX 8086 v1 C ; device/drive number is in 1 byte, C ; not in 1 word! C ; mov u.cdev,cdev / device number for users directory C ; / into cdev 0BAB 33 D2 C xor dx, dx ; 18/07/2013 0BAD 8B 36 38E2 R C mov si, word ptr [u.namep] 0BB1 26: 80 3C 2F C cmp byte ptr ES:[SI], '/' C ; cmpb *u.namep,$'/ / is first char in file name a / 0BB5 75 0C C jne short namei_1 C ; bne 1f 0BB7 46 C inc si ; go to next char 0BB8 89 36 38E2 R C mov word ptr [u.namep], si C ; inc u.namep / go to next char 0BBC A1 2C00 R C mov ax, word ptr [rootdir] ; 09/07/2013 (mov ax, rootdir) C ; mov rootdir,r1 / put i-number of rootdirectory in r1 C ;xor dx, dx 0BBF 89 16 2BD2 R C mov word ptr [cdev], dx C ; clr cdev / clear device number 0BC3 C namei_1: ; 1: C ;; 18/07/2013 0BC3 26: 8A 14 C mov dl, byte ptr ES:[SI] 0BC6 8C C9 C mov cx, cs 0BC8 8E C1 C mov es, cx 0BCA 22 D2 C and dl, dl 0BCC 74 55 C jz short nig C ;; C ;cmp byte ptr ES:[SI], dl ; 0 C ; tstb *u.namep / is the character in file name a nul C ;;jna nig C ; beq nig / yes, end of file name reached; C ; / branch to "nig" 0BCE C namei_2: ; 1: C ;mov dx, 2 0BCE B2 02 C mov dl, 2 ; user flag (read, non-owner) 0BD0 E8 05AA C call access C ; jsr r0,access; 2 / get i-node with i-number r1 C ; 'access' will not return here if user has not "r" permission ! 0BD3 F7 06 296E R 4000 C test word ptr [i.flgs], 4000h C ; bit $40000,i.flgs / directory i-node? 0BD9 75 03 E9 F71E C jz error C ; beq error3 / no, got an error 0BDE A1 2972 R C mov ax, word ptr [i.size_] 0BE1 A3 38E0 R C mov word ptr [u.dirp], ax C ; mov i.size,u.dirp / put size of directory in u.dirp 0BE4 33 C0 C xor ax, ax 0BE6 A3 38E4 R C mov word ptr [u.off], ax ; 0 C ; clr u.off / u.off is file offset used by user 0BE9 C7 06 38DE R 38E4 R C mov word ptr [u.fofp], offset u.off C ; mov $u.off,u.fofp / u.fofp is a pointer to C ; / the offset portion of fsp entry 0BEF C namei_3: ; 2: 0BEF C7 06 38E6 R 38F0 R C mov word ptr [u.base], offset u.dirbuf C ; mov $u.dirbuf,u.base / u.dirbuf holds a file name C ; / copied from a directory 0BF5 C7 06 38E8 R 000A C mov word ptr [u.count], 10 C ; mov $10.,u.count / u.count is byte count C ; / for reads and writes 0BFB A1 2BCE R C mov ax, word ptr [ii] C ; 31/07/2013 0BFE FE 06 2C09 R C inc byte ptr [namei_r] ; the caller is 'namei' sign C ; 28/07/2013 nameir -> u.nameir C ; 26/07/2013 C ;;inc byte ptr [u.namei_r] ; the caller is 'namei' sign 0C02 E8 063A C call readi C ; ES = DS after 'readi' ! C ; jsr r0,readi / read 10. bytes of file C ; with i-number (r1); i.e. read a directory entry 0C05 8B 0E 38EA R C mov cx, word ptr [u.nread] 0C09 0B C9 C or cx, cx C ; tst u.nread 0C0B 74 13 C jz short nib C ; ble nib / gives error return C ; 0C0D 8B 1E 38F0 R C mov bx, word ptr [u.dirbuf] 0C11 23 DB C and bx, bx C ; tst u.dirbuf / 0C13 75 0F C jnz short namei_4 C ; bne 3f / branch when active directory entry C ; / (i-node word in entry non zero) 0C15 A1 38E4 R C mov ax, word ptr [u.off] 0C18 83 E8 0A C sub ax, 10 0C1B A3 38E0 R C mov word ptr [u.dirp], ax C ; mov u.off,u.dirp C ; sub $10.,u.dirp 0C1E EB CF C jmp short namei_3 C ; br 2b C ; 18/07/2013 0C20 C nib: 0C20 33 C0 C xor ax, ax 0C22 F9 C stc 0C23 C nig: 0C23 C3 C retn C 0C24 C namei_4: ; 3: 0C24 A1 3908 R C mov ax, word ptr [u.segmnt] ; Retro UNIX 8086 v1 Feature only ! C ; 0C27 8B 36 38E2 R C mov si, word ptr [u.namep] C ; mov u.namep,r2 / u.namep points into a file name string 0C2B BF 38F2 R C mov di, offset u.dirbuf + 2 C ; mov $u.dirbuf+2,r3 / points to file name of directory entry 0C2E BA 38FA R C mov dx, offset u.dirbuf + 10 C ; AX = user segment 0C31 8E D8 C mov ds, ax ; Retro UNIX 8086 v1 Feature only ! 0C33 C namei_5: ; 3: 0C33 AC C lodsb ; mov al, byte ptr [SI] ; inc si (al = r4) C ; movb (r2)+,r4 / move a character from u.namep string into r4 0C34 0A C0 C or al, al 0C36 74 11 C jz short namei_6 C ; beq 3f / if char is nul, then the last char in string C ; / has been moved 0C38 3C 2F C cmp al, '/' C ; cmp r4,$'/ / is char a 0C3A 74 0D C je short namei_6 C ; beq 3f 0C3C 3B FA C cmp di, dx ; offset u_dirbuf + 10 C ; cmp r3,$u.dirbuf+10. / have I checked C ; / all 8 bytes of file name 0C3E 74 F3 C je short namei_5 C ; beq 3b 0C40 AE C scasb C ; cmpb (r3)+,r4 / compare char in u.namep string to file name C ; / char read from directory 0C41 74 F0 C je short namei_5 C ; beq 3b / branch if chars match 0C43 8C C8 C mov ax, cs ; Retro UNIX 8086 v1 Feature only ! 0C45 8E D8 C mov ds, ax ; Retro UNIX 8086 v1 Feature only ! 0C47 EB A6 C jmp short namei_3 ; 2b C ; br 2b / file names do not match go to next directory entry 0C49 C namei_6: ; 3: C ; 22/07/2013 0C49 8C C9 C mov cx, cs ; Retro UNIX 8086 v1 Feature only ! 0C4B 8E D9 C mov ds, cx ; Retro UNIX 8086 v1 Feature only ! C ; 0C4D 3B FA C cmp di, dx C ; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched 0C4F 74 06 C je short namei_7 C ; beq 3f 0C51 8A 25 C mov ah, byte ptr [DI] C ;inc di 0C53 22 E4 C and ah, ah C ; tstb (r3)+ / 0C55 75 98 C jnz short namei_3 C ; bne 2b 0C57 C namei_7: ; 3 0C57 89 36 38E2 R C mov word ptr [u.namep], si C ; mov r2,u.namep / u.namep points to char C ; / following a / or nul C ;mov bx, word ptr [u.dirbuf] C ; mov u.dirbuf,r1 / move i-node number in directory C ; / entry to r1 0C5B 22 C0 C and al, al C ; tst r4 / if r4 = 0 the end of file name reached, C ; / if r4 = then go to next directory 0C5D 8B C3 C mov ax, bx 0C5F 74 03 E9 FF6A C jnz namei_2 C ; bne 1b C ; AX = i-number of the file C ;;nig: C ;;pop es ; Retro UNIX 8086 v1 Feature only ! 0C64 C3 C retn C ; tst (r0)+ / gives non-error return C ;;nib: C ;; xor ax, ax ; Retro UNIX 8086 v1 modification ! C ; ax = 0 -> file not found C ;;pop es ; Retro UNIX 8086 v1 Feature only ! C ;; stc ; 27/05/2013 C ;; retn C ; rts r0 C 0C65 C syschdir: C ; 19/06/2013 C ; 'syschdir' makes the directory specified in its argument C ; the current working directory. C ; C ; Calling sequence: C ; syschdir; name C ; Arguments: C ; name - address of the path name of a directory C ; terminated by nul byte. C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; The user/application program puts address of C ; the path name in BX register as 'syschdir' C ; system call argument. C ; (argument transfer method 1) C C ; / makes the directory specified in the argument C ; / the current directory C ;;mov ax, 1 ; one/single argument, put argument in BX C ;;call arg C ;mov bp, word ptr [u.sp_] ; points to user's BP register C ;add bp, 6 ; bx now points to BX on stack C ;mov bx, word ptr [BP] 0C65 89 1E 38E2 R C mov word ptr [u.namep], bx C ;jsr r0,arg; u.namep / u.namep points to path name 0C69 E8 FF2F C call namei C ; jsr r0,namei / find its i-number 0C6C 73 03 E9 F68B C jc error C ; br error3 0C71 E8 0509 C call access C ; jsr r0,access; 2 / get i-node into core 0C74 F7 06 296E R 4000 C test word ptr [i.flgs], 4000h C ; bit $40000,i.flgs / is it a directory? 0C7A 75 03 E9 F67D C jz error C ; beq error3 / no error 0C7F A3 38D2 R C mov word ptr [u.cdir], ax C ; mov r1,u.cdir / move i-number to users C ; / current directory 0C82 A1 2BD2 R C mov ax, word ptr [cdev] 0C85 A3 3902 R C mov word ptr [u.cdrv], ax C ; mov cdev,u.cdev / move its device to users C ; / current device 0C88 E9 F68E C jmp sysret C ; br sysret3 C 0C8B C syschmod: ; < change mode of file > C ; 07/07/2013 C ; 20/06/2013 C ; 'syschmod' changes mode of the file whose name is given as C ; null terminated string pointed to by 'name' has it's mode C ; changed to 'mode'. C ; C ; Calling sequence: C ; syschmod; name; mode C ; Arguments: C ; name - address of the file name C ; terminated by null byte. C ; mode - (new) mode/flags < attributes > C ; C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'syschmod' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get syschmod system call arguments from the user; C ; * 1st argument, name is pointed to by BX register C ; * 2nd argument, mode is in CX register C ; C ; Mode bits (Flags): C ; bit 0 - write permission for non-owner (1) C ; bit 1 - read permission for non-owner (2) C ; bit 2 - write permission for owner (4) C ; bit 3 - read permission for owner (8) C ; bit 4 - executable flag (16) C ; bit 5 - set user ID on execution flag (32) C ; bit 6,7,8,9,10,11 are not used (undefined) C ; bit 12 - large file flag (4096) C ; bit 13 - file has modified flag (always on) (8192) C ; bit 14 - directory flag (16384) C ; bit 15 - 'i-node is allocated' flag (32768) C C ; / name; mode 0C8B E8 000F C call isown C ;jsr r0,isown / get the i-node and check user status 0C8E F7 06 296E R 4000 C test word ptr [i.flgs], 4000h C ; bit $40000,i.flgs / directory? 0C94 74 02 C jz short @f C ; beq 2f / no C ; AL = (new) mode 0C96 24 CF C and al, 0CFh ; 11001111b (clears bit 4 & 5) C ; bic $60,r2 / su & ex / yes, clear set user id and C ; / executable modes 0C98 C @@: ; 2: 0C98 A2 296E R C mov byte ptr [i.flgs], al C ; movb r2,i.flgs / move remaining mode to i.flgs 0C9B EB 20 C jmp short @f C ; br 1f C 0C9D C isown: C ; 07/07/2013 C ; 27/05/2013 C ; 04/05/2013 C ; 'isown' is given a file name (the 1st argument). C ; It find the i-number of that file via 'namei' C ; then gets the i-node into core via 'iget'. C ; It then tests to see if the user is super user. C ; If not, it cheks to see if the user is owner of C ; the file. If he is not an error occurs. C ; If user is the owner 'setimod' is called to indicate C ; the inode has been modificed and the 2nd argument of C ; the call is put in r2. C ; C ; INPUTS -> C ; arguments of syschmod and syschown calls C ; OUTPUTS -> C ; u.uid - id of user C ; imod - set to a 1 C ; r2 - contains second argument of the system call C ; C ; ((AX=R2) output as 2nd argument)) C ; C ; ((Modified registers: AX, DX, BX, CX, SI, DI, BP)) C ; C ;;call arg2 C ;; ; jsr r0,arg2 / u.namep points to file name C ;; ! 2nd argument on top of stack ! C ;; 07/07/2013 0C9D 89 1E 38E2 R C mov word ptr [u.namep], bx ;; 1st argument 0CA1 51 C push cx ;; 2nd argument C ;; 0CA2 E8 FEF6 C call namei C ; jsr r0,namei / get its i-number C ; Retro UNIX 8086 v1 modification ! C ; ax = 0 -> file not found C ;and ax, ax C ;jz error 0CA5 73 03 E9 F652 C jc error ; 27/05/2013 C ; br error3 0CAA E8 042D C call iget C ; jsr r0,iget / get i-node into core 0CAD A0 3904 R C mov al, byte ptr [u.uid_] ; 02/08/2013 0CB0 0A C0 C or al, al C ; tstb u.uid / super user? 0CB2 74 09 C jz short @f C ; beq 1f / yes, branch 0CB4 3A 06 2971 R C cmp al, byte ptr [i.uid] C ; cmpb i.uid,u.uid / no, is this the owner of C ; / the file 0CB8 74 03 E9 F63F C jne error C ; beq 1f / yes C ; jmp error3 / no, error 0CBD C @@: ; 1: 0CBD E8 04E0 C call setimod C ; jsr r0,setimod / indicates C ; ; / i-node has been modified 0CC0 58 C pop ax ; 2nd argument C ; mov (sp)+,r2 / mode is put in r2 C ; / (u.off put on stack with 2nd arg) 0CC1 C3 C retn C ; rts r0 C 0CC2 C syschown: ; < change owner of file > C ; 02/08/2013 C ; 07/07/2013 C ; 20/06/2013 C ; 'syschown' changes the owner of the file whose name is given C ; as null terminated string pointed to by 'name' has it's owner C ; changed to 'owner' C ; C ; Calling sequence: C ; syschown; name; owner C ; Arguments: C ; name - address of the file name C ; terminated by null byte. C ; owner - (new) owner (number/ID) C ; C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'syschown' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get syschown system call arguments from the user; C ; * 1st argument, name is pointed to by BX register C ; * 2nd argument, owner number is in CX register C ; C ; / name; owner 0CC2 E8 FFD8 C call isown C ; jsr r0,isown / get the i-node and check user status 0CC5 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 ; 02/08/2013 C ; tstb u.uid / super user 0CCA 74 0A C jz short @f C ; beq 2f / yes, 2f 0CCC F6 06 296E R 20 C test byte ptr [i.flgs], 20h ; 32 C ; bit $40,i.flgs / no, set userid on execution? 0CD1 74 03 E9 F626 C jnz error C ; bne 3f / yes error, could create Trojan Horses 0CD6 C @@: ; 2: C ; AL = owner (number/ID) 0CD6 A2 3904 R C mov byte ptr [u.uid_], al ; 02/08/2013 C ; movb r2,i.uid / no, put the new owners id C ; / in the i-node 0CD9 E9 F63D C jmp sysret C ; 1: C ; jmp sysret4 C ; 3: C ; jmp error C C ;;arg: ; < get system call arguments > C ; 22/05/2013 'method 4' has been modified (corrected) C ; 04/05/2013 C ; 'arg' extracts an argument for a routine whose call is C ; of form: C ; sys 'routine' ; arg1 C ; or C ; sys 'routine' ; arg1 ; arg2 C ; or C ; sys 'routine' ; arg1;...;arg10 (sys exec) C ; C ; RETRO UNIX 8086 v1 Modification ! C ; Retro Unix 8086 v1 system call argument C ; transfer methods: C ; 1) Single argument in BX register C ; ('arg' routine is called with AX=1) C ; 2) Two arguments, C ; 1st argument in BX register C ; 2nd argument in CX register C ; ('arg' routine is called with AX=2) C ; 3) Three arguments C ; 3rd argument in DX register C ; ('arg' routine is called with AX=3) C ; 4) Argument list address in BP register C ; ('arg' routine is called with AX=0) C ; 'arg' routine will return arguments in same registers C ; except method 4 will return current argument C ; which is pointed by BP register and 'arg' will C ; increase value of (user's) BP register (on stack) C ; in order to point next argument. AX register will C ; return address of current argument. C ; C ; INPUTS -> C ; u.sp+18 - contains a pointer to one of arg1..argn C ; This pointers's value is actually the value of C ; update pc at the the trap to sysent (unkni) is C ; made to process the sys instruction C ; r0 - contains the return address for the routine C ; that called arg. The data in the word pointer C ; to by the return address is used as address C ; in which the extracted argument is stored C ; C ; OUTPUTS -> C ; 'address' - contains the extracted argument C ; u.sp+18 - is incremented by 2 C ; r1 - contains the extracted argument C ; r0 - points to the next instruction to be C ; executed in the calling routine. C ; C ; ((Modified registers: AX, DX, CX, BX)) C C ; Retro UNIX 8086 v1 modification ! C ; [ sysunlink, sysfstat, syschdir, sysbreak, sysseek (seektell), C ; sysintr, sysquit, rw1 (sysread, syswrite), sysemt, sysilgins C ; sysmdate, gtty (sysgtty) etc. call arg.] C ; C ; Note: If all of system calls which call 'arg' routine will have C ; only 1 argument, this 'arg' routine may be simplified C ; and system calls with 2 arguments may be changed to use 'arg1' C ; instead of 'arg' (04/05/2013). C C ;; mov bx, word ptr [u.sp_] ; points to user's BP register C ;; mov cx, ax C ;; or cx, cx C ;; jnz short @f C ;arg_bp: ; method 4 C ;; mov ax, word ptr [BX] ; value of BP register on stack C ; (sAX = uBP) C ;; mov dx, ax C ; AX = 1st argument or current argument (method 4) C ;; inc dx C ;; inc dx C ;; mov word ptr [BX], dx ; BP will point to next argument C ; (uBP = uBP+2) C ;; retn C ; method 1, 2, 3 C ;;@@: C ;; add bx, 6 ; bx now points to BX on stack C ;,@@: C ;; mov dx, word ptr [BX] C ;; push dx ; 1st or 2nd or 3rd argument (depends on CX) C ;; dec cx C ;; jz short @f C ;; inc bx C ;; inc bx C ;; jmp short @b C ;;@@: C ;; dec ax C ;; jz short @f C ;; pop cx ; 2nd or 3rd argument (depends on value in AX) C ;; dec ax C ;; jz short @f C ;; mov dx, cx ; 3rd argument C ;; pop cx ; 2nd argument C ;;@@: C ;; pop bx ; 1st argument C ;; retn C C ; UNIX v1 original 'arg' routine here: C ; mov u.sp,r1 C ; mov *18.(r1),*(r0)+ / put argument of system call C ; / into argument of arg2 C ; add $2,18.(r1) / point pc on stack C ; / to next system argument C ; rts r0 C C ;;arg2: ; < get system calls arguments - with file name pointer> C ; 22/05/2013 arg1 modified (corrected) C ; 04/05/2013 C ; 'arg2' takes first argument in system call C ; (pointer to name of the file) and puts it in location C ; u.namep; takes second argument and puts it in u.off C ; and on top of the stack C ; C ; RETRO UNIX 8086 v1 Modification ! C ; Retro Unix 8086 v1 system call argument C ; transfer methods: C ; 1) Single argument in BX register C ; ('arg' routine is called with AX=1) C ; 2) Two arguments, C ; 1st argument in BX register C ; 2nd argument in CX register C ; ('arg' routine is called with AX=2) C ; 3) Three arguments C ; 3rd argument in DX register C ; ('arg' routine is called with AX=3) C ; 4) Argument list address in BP register C ; ('arg' routine is called with AX=0) C ; 'arg2' routine uses method 2 when calling 'arg' routine C ; then puts 1st argument (BX) in u.namep and pushes C ; 2nd argument (CX) on stack. C ; (Retro UNIX 8086 v1 does not put 2nd argument in u.off) C ; C ; INPUTS -> C ; u.sp, r0 C ; C ; OUTPUTS -> C ; u.namep C ; u.off C ; u.off pushed on stack C ; r1 C ; C ; ((Modified registers: AX, DX, CX, BX)) C ; C ; arg2 (1) -- 04/05/2013 (1) C ; mov ax, 2 ; two arguments, method 2 C ; call arg C ; ; BX = 1st argument C ; ; CX = 2nd argument C C ; arg2 (modified for arg1 call) -- 04/05/2013 (2) C C ; Retro UNIX 8086 v1 modification ! C ; Direct argument handling instead of using 'arg' call. C ; [ sysexec, sysmount, sysopen, syslink, sysstat, C ; isown (syschmod, syschown),sysopen, syscreat, sysmkdir, sysmount C ; call arg2 ] C C ;; call arg1 ; 04/05/2013 C ;; mov word ptr [u.namep], ax ; 1st argument C ;; pop dx ; return address C ;; push cx ; 2nd argument C ;; push dx C ; warning ! C ; ! Caller must pop 2nd argument on stack ! C ;; retn C C ;;arg1: ; Retro UNIX 8086 v1 feature only ! C ; 22/05/2013 modified (corrected) C ;; mov bx, word ptr [u.sp_] ; points to user's BP register C ;; add bx, 6 C ;, mov ax, [BX] ; points to user's BX register C ;(sAX = uBX) C ;; inc bx C ;; inc bx C ;, mov cx, [BX] ; points to user's CX register C ;(sCX = uCX) C ; retn C C ;; arg2 (2) -- 04/05/2013 (1) C ; mov word ptr [u.namep], bx ; file name pointer C ; ;mov word ptr [u.off], cx ; 2nd argument C ; pop dx ; return address C ; push cx C ; push dx C ; ; warning ! C ; ; ! Caller must pop 2nd argument on stack ! C ; retn C C ; UNIX v1 original 'arg2' routine here: C ; jsr r0,arg; u.namep / u.namep contains value of C ; / first arg in sys call C ; jsr r0,arg; u.off / u.off contains value of C ; / second arg in sys call C ; mov r0,r1 / r0 points to calling routine C ; mov (sp),r0 / put operation code back in r0 C ; mov u.off,(sp) / put pointer to second argument C ; / on stack C ; jmp (r1) / return to calling routine C 0CDC C systime: C ; 20/06/2013 C ; 'systime' gets the time of the year. C ; The present time is put on the stack. C ; C ; Calling sequence: C ; systime C ; Arguments: - C ; C ; Inputs: - C ; Outputs: sp+2, sp+4 - present time C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'systime' system call will return to the user C ; with unix time (epoch) in DX:AX register pair C ; C ; !! Major modification on original Unix v1 'systime' C ; system call for PC compatibility !! C ; / get time of year 0CDC E8 16AE C call epoch 0CDF A3 38D0 R C mov word ptr [u.r0], ax 0CE2 8B 2E 38CC R C mov bp, word ptr [u.sp_] 0CE6 83 C5 0A C add bp, 10 ; points to the user's DX register 0CE9 89 56 00 C mov word ptr [BP], dx C ; mov s.time,4(sp) C ; mov s.time+2,2(sp) / put the present time C ; / on the stack C ; br sysret4 0CEC E9 F62A C jmp sysret C 0CEF C sysstime: C ; 02/08/2013 C ; 20/06/2013 C ; 'sysstime' sets the time. Only super user can use this call. C ; C ; Calling sequence: C ; sysstime C ; Arguments: - C ; C ; Inputs: sp+2, sp+4 - time system is to be set to. C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; the user calls 'sysstime' with unix (epoch) time C ; (to be set) is in CX:BX register pair as two arguments. C ; C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get sysstime system call arguments from the user; C ; * 1st argument, lowword of unix time is in BX register C ; * 2nd argument, highword of unix time is in CX register C ; C ; !! Major modification on original Unix v1 'sysstime' C ; system call for PC compatibility !! C ; / set time 0CEF 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 ; 02/08/2013 C ; tstb u.uid / is user the super user 0CF4 76 03 E9 F603 C ja error C ; bne error4 / no, error C ; CX:BX = unix (epoch) time (from user) 0CF9 8B D1 C mov dx, cx 0CFB 8B C3 C mov ax, bx C ; DX:AX = unix (epoch) time (to subroutine) 0CFD E8 1790 C call set_date_time C ;call convert_from_epoch C ;call set_date_time C ; mov 4(sp),s.time C ; mov 2(sp),s.time+2 / set the system time 0D00 E9 F616 C jmp sysret C ; br sysret4 C 0D03 C sysbreak: C ; 24/03/2014 C ; 19/11/2013 C ; 20/06/2013 C ; 'sysbreak' sets the programs break points. C ; It checks the current break point (u.break) to see if it is C ; between "core" and the stack (sp). If it is, it is made an C ; even address (if it was odd) and the area between u.break C ; and the stack is cleared. The new breakpoint is then put C ;in u.break and control is passed to 'sysret'. C ; C ; Calling sequence: C ; sysbreak; addr C ; Arguments: - C ; C ; Inputs: u.break - current breakpoint C ; Outputs: u.break - new breakpoint C ; area between old u.break and the stack (sp) is cleared. C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; The user/application program puts breakpoint address C ; in BX register as 'sysbreak' system call argument. C ; (argument transfer method 1) C ; C ; NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 ! C ; ((!'sysbreak' is not needed in Retro UNIX 8086 v1!)) C ; NOTE: C ; 'sysbreak' clears extended part (beyond of previous C ; 'u.break' address) of user's memory for original unix's C ; 'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013) C C ;cmp word ptr [u.break], core C ; mov u.break,r1 / move users break point to r1 C ; cmp r1,$core / is it the same or lower than core? C ;ja short sysbreak_3 C ; blos 1f / yes, 1f 0D03 8B 3E 390C R C mov di, word ptr [u.break] 0D07 3B 3E 38CE R C cmp di, word ptr [u.usp] C ; cmp r1,sp / is it the same or higher C ; / than the stack? 0D0B 73 1B C jnb short sysbreak_3 C ; bhis 1f / yes, 1f 0D0D A1 3908 R C mov ax, word ptr [u.segmnt] 0D10 8E C0 C mov es, ax 0D12 33 C0 C xor ax, ax 0D14 F7 C7 0001 C test di, 1 C ; bit $1,r1 / is it an odd address 0D18 74 07 C jz short sysbreak_1 C ; beq 2f / no, its even 0D1A AA C stosb C ; clrb (r1)+ / yes, make it even 0D1B C sysbreak_0: ; 2: / clear area between the break point and the stack 0D1B 3B 3E 38CE R C cmp di, word ptr [u.usp] ; 24/03/2014 C ; cmp r1,sp / is it higher or same than the stack 0D1F 73 03 C jnb short sysbreak_2 C ; bhis 1f / yes, quit 0D21 C sysbreak_1: 0D21 AB C stosw C ; clr (r1)+ / clear word 0D22 EB F7 C jmp short sysbreak_0 C ; br 2b / go back 0D24 C sysbreak_2: ; 1: 0D24 8C D8 C mov ax, ds 0D26 8E C0 C mov es, ax 0D28 C sysbreak_3: 0D28 89 1E 390C R C mov word ptr [u.break], bx C ; jsr r0,arg; u.break / put the "address" C ; / in u.break (set new break point) 0D2C E9 F5EA C jmp sysret C ; br sysret4 / br sysret C 0D2F C maknod: C ; 02/08/2013 C ; 31/07/2013 C ; 17/07/2013 C ; 02/05/2013 C ; 'maknod' creates an i-node and makes a directory entry C ; for this i-node in the current directory. C ; C ; INPUTS -> C ; r1 - contains mode C ; ii - current directory's i-number C ; C ; OUTPUTS -> C ; u.dirbuf - contains i-number of free i-node C ; i.flgs - flags in new i-node C ; i.uid - filled with u.uid C ; i.nlks - 1 is put in the number of links C ; i.ctim - creation time C ; i.ctim+2 - modification time C ; imod - set via call to setimod C ; C ; ((AX = R1)) input C ; C ; (Retro UNIX Prototype : C ; 30/10/2012 - 01/03/2013, UNIXCOPY.ASM) C ; ((Modified registers: AX, DX, BX, CX, SI, DI, BP)) C C ; / r1 contains the mode 0D2F 80 CC 80 C or ah, 80h ; 10000000b C ; bis $100000,r1 / allocate flag set 0D32 50 C push ax C ; mov r1,-(sp) / put mode on stack C ; 31/07/2013 0D33 A1 2BCE R C mov ax, word ptr [ii] ; move current i-number to AX/r1 C ; mov ii,r1 / move current i-number to r1 0D36 B2 01 C mov dl, 1 ; owner flag mask 0D38 E8 0442 C call access C ; jsr r0,access; 1 / get its i-node into core 0D3B 50 C push ax C ; mov r1,-(sp) / put i-number on stack 0D3C B8 0028 C mov ax, 40 C ; mov $40.,r1 / r1 = 40 0D3F C @@: ; 1: / scan for a free i-node (next 4 instructions) 0D3F 40 C inc ax C ; inc r1 / r1 = r1 + 1 0D40 E8 04D0 C call imap C ; jsr r0,imap / get byte address and bit position in C ; / inode map in r2 & m C ; DX (MQ) has a 1 in the calculated bit position C ; BX (R2) has byte address of the byte with allocation bit 0D43 84 17 C test byte ptr [BX], dl C ; bitb mq,(r2) / is the i-node active 0D45 75 F8 C jnz short @b C ; bne 1b / yes, try the next one 0D47 08 17 C or byte ptr [BX], dl C ; bisb mq,(r2) / no, make it active C ; / (put a 1 in the bit map) 0D49 E8 038E C call iget C ; jsr r0,iget / get i-node into core 0D4C F7 06 296E R 8000 C test word ptr [i.flgs], 8000h C ; tst i.flgs / is i-node already allocated 0D52 75 EB C jnz short @b C ; blt 1b / yes, look for another one 0D54 A3 38F0 R C mov word ptr [u.dirbuf], ax C ; mov r1,u.dirbuf / no, put i-number in u.dirbuf 0D57 58 C pop ax C ; mov (sp)+,r1 / get current i-number back 0D58 E8 037F C call iget C ; jsr r0,iget / get i-node in core 0D5B E8 FBEA C call mkdir C ; jsr r0,mkdir / make a directory entry C ; / in current directory 0D5E A1 38F0 R C mov ax, word ptr [u.dirbuf] C ; mov u.dirbuf,r1 / r1 = new inode number 0D61 E8 0376 C call iget C ; jsr r0,iget / get it into core C ;jsr r0,copyz; inode; inode+32. / 0 it out 0D64 B9 0010 C mov cx, 16 0D67 33 C0 C xor ax, ax ; 0 C ;mov di, offset inode 0D69 BF 296E R C mov di, offset i ; 17/07/2013 0D6C F3/ AB C rep stosw C ; 0D6E 8F 06 296E R C pop word ptr [i.flgs] C ; mov (sp)+,i.flgs / fill flags 0D72 8A 0E 3904 R C mov cl, byte ptr [u.uid_] ; 02/08/2013 0D76 88 0E 2971 R C mov byte ptr [i.uid], cl C ; movb u.uid,i.uid / user id 0D7A C6 06 2970 R 01 C mov byte ptr [i.nlks], 1 C ; movb $1,i.nlks / 1 link C ;call epoch ; Retro UNIX 8086 v1 modification ! C ;mov ax, word ptr [s.time] C ;mov dx, word ptr [s.time]+2 C ;mov word ptr [i.ctim], ax C ;mov word ptr [i.ctim]+2, dx C ; mov s.time,i.ctim / time created C ; mov s.time+2,i.ctim+2 / time modified C ; Retro UNIX 8086 v1 modification ! C ; i.ctime=0, i.ctime+2=0 and C ; 'setimod' will set ctime of file via 'epoch' 0D7F E8 041E C call setimod C ; jsr r0,setimod / set modified flag 0D82 C3 C retn C ; rts r0 / return C 0D83 C sysseek: ; / moves read write pointer in an fsp entry C ; 05/08/2013 C ; 07/07/2013 C ; 'sysseek' changes the r/w pointer of (3rd word of in an C ; fsp entry) of an open file whose file descriptor is in u.r0. C ; The file descriptor refers to a file open for reading or C ; writing. The read (or write) pointer is set as follows: C ; * if 'ptrname' is 0, the pointer is set to offset. C ; * if 'ptrname' is 1, the pointer is set to its C ; current location plus offset. C ; * if 'ptrname' is 2, the pointer is set to the C ; size of file plus offset. C ; The error bit (e-bit) is set for an undefined descriptor. C ; C ; Calling sequence: C ; sysseek; offset; ptrname C ; Arguments: C ; offset - number of bytes desired to move C ; the r/w pointer C ; ptrname - a switch indicated above C ; C ; Inputs: r0 - file descriptor C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysseek' system call has three arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 3 is used C ; to get sysseek system call arguments from the user; C ; * 1st argument, file descriptor is in BX (BL) register C ; * 2nd argument, offset is in CX register C ; * 3rd argument, ptrname/switch is in DX (DL) register C ; C 0D83 E8 0017 C call seektell C ; jsr r0,seektell / get proper value in u.count C ; AX = u.count C ; BX = *u.fofp C ; add u.base,u.count / add u.base to it 0D86 03 06 38E6 R C add ax, word ptr [u.base] ; add offset (u.base) to base 0D8A 89 07 C mov word ptr [BX], ax C ; mov u.count,*u.fofp / put result into r/w pointer 0D8C E9 F58A C jmp sysret C ; br sysret4 C 0D8F C systell: ; / get the r/w pointer C ; 05/08/2013 C ; 07/07/2013 C ; Retro UNIX 8086 v1 modification: C ; ! 'systell' does not work in original UNIX v1, C ; it returns with error ! C ; Inputs: r0 - file descriptor C ; Outputs: r0 - file r/w pointer C C ;xor cx, cx ; 0 0D8F BA 0001 C mov dx, 1 ; 05/08/2013 C ;call seektell 0D92 E8 000C C call seektell0 ; 05/08/2013 C ;mov bx, word ptr [u.fofp] 0D95 8B 07 C mov ax, word ptr [BX] 0D97 A3 38D0 R C mov word ptr [u.r0], ax 0D9A E9 F57C C jmp sysret C C ; Original unix v1 'systell' system call: C ; jsr r0,seektell C ; br error4 C 0D9D C seektell: C ; 05/08/2013 (return AX as base for offset) C ; 07/07/2013 C ; 'seektell' puts the arguments from sysseek and systell C ; call in u.base and u.count. It then gets the i-number of C ; the file from the file descriptor in u.r0 and by calling C ; getf. The i-node is brought into core and then u.count C ; is checked to see it is a 0, 1, or 2. C ; If it is 0 - u.count stays the same C ; 1 - u.count = offset (u.fofp) C ; 2 - u.count = i.size (size of file) C ; C ; !! Retro UNIX 8086 v1 modification: C ; Argument 1, file descriptor is in BX; C ; Argument 2, offset is in CX; C ; Argument 3, ptrname/switch is in DX register. C ; C ; mov ax, 3 ; Argument transfer method 3 (three arguments) C ; call arg C ; C ; ((Return -> ax = base for offset (position= base+offset)) C ; 0D9D 89 0E 38E6 R C mov word ptr [u.base], cx ; offset C ; jsr r0,arg; u.base / puts offset in u.base 0DA1 C seektell0: 0DA1 89 16 38E8 R C mov word ptr [u.count], dx C ; jsr r0,arg; u.count / put ptr name in u.count C ; mov ax, bx C ; mov *u.r0,r1 / file descriptor in r1 C ; / (index in u.fp list) C ; call getf C ; jsr r0,getf / u.fofp points to 3rd word in fsp entry C ; BX = file descriptor (file number) 0DA5 E8 FDC6 C call getf1 0DA8 0B C0 C or ax, ax ; i-number of the file C ; mov r1,-(sp) / r1 has i-number of file, C ; / put it on the stack 0DAA 75 03 E9 F54D C jz error C ; beq error4 / if i-number is 0, not active so error C ;push ax 0DAF 80 FC 80 C cmp ah, 80h 0DB2 72 02 C jb short @f C ; bgt .+4 / if its positive jump 0DB4 F7 D8 C neg ax C ; neg r1 / if not make it positive 0DB6 C @@: 0DB6 E8 0321 C call iget C ; jsr r0,iget / get its i-node into core 0DB9 8B 1E 38DE R C mov bx, word ptr [u.fofp] ; 05/08/2013 0DBD 80 3E 38E8 R 01 C cmp byte ptr [u.count], 1 C ; cmp u.count,$1 / is ptr name =1 0DC2 77 05 C ja short @f C ; blt 2f / no its zero 0DC4 74 07 C je short seektell_1 C ; beq 1f / yes its 1 0DC6 33 C0 C xor ax, ax C ;jmp short seektell_2 0DC8 C3 C retn 0DC9 C @@: 0DC9 A1 2972 R C mov ax, word ptr [i.size_] C ; mov i.size,u.count / put number of bytes C ; / in file in u.count C ;jmp short seektell_2 C ; br 2f 0DCC C3 C retn 0DCD C seektell_1: ; 1: / ptrname =1 C ;mov bx, word ptr [u.fofp] 0DCD 8B 07 C mov ax, word ptr [BX] C ; mov *u.fofp,u.count / put offset in u.count C ;seektell_2: ; 2: / ptrname =0 C ;mov word ptr [u.count], ax C ;pop ax C ; mov (sp)+,r1 / i-number on stack r1 0DCF C3 C retn C ; rts r0 C 0DD0 C sysintr: ; / set interrupt handling C ; 07/07/2013 C ; 'sysintr' sets the interrupt handling value. It puts C ; argument of its call in u.intr then branches into 'sysquit' C ; routine. u.tty is checked if to see if a control tty exists. C ; If one does the interrupt character in the tty buffer is C ; cleared and 'sysret'is called. If one does not exits C ; 'sysret' is just called. C ; C ; Calling sequence: C ; sysintr; arg C ; Argument: C ; arg - if 0, interrupts (ASCII DELETE) are ignored. C ; - if 1, intterupts cause their normal result C ; i.e force an exit. C ; - if arg is a location within the program, C ; control is passed to that location when C ; an interrupt occurs. C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysintr' system call sets u.intr to value of BX C ; then branches into sysquit. C ; 0DD0 89 1E 38FC R C mov word ptr [u.intr], bx C ;jmp short @f C ;jsr r0,arg; u.intr / put the argument in u.intr C ; br 1f / go into quit routine 0DD4 E9 F542 C jmp sysret C 0DD7 C sysquit: C ; 07/07/2013 C ; 'sysquit' turns off the quit signal. it puts the argument of C ; the call in u.quit. u.tty is checked if to see if a control C ; tty exists. If one does the interrupt character in the tty C ; buffer is cleared and 'sysret'is called. If one does not exits C ; 'sysret' is just called. C ; C ; Calling sequence: C ; sysquit; arg C ; Argument: C ; arg - if 0, this call diables quit signals from the C ; typewriter (ASCII FS) C ; - if 1, quits are re-enabled and cause execution to C ; cease and a core image to be produced. C ; i.e force an exit. C ; - if arg is an addres in the program, C ; a quit causes control to sent to that C ; location. C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysquit' system call sets u.quit to value of BX C ; then branches into 'sysret'. C ; 0DD7 89 1E 38FE R C mov word ptr [u.quit], bx 0DDB E9 F53B C jmp sysret C ; jsr r0,arg; u.quit / put argument in u.quit C ;1: C ; mov u.ttyp,r1 / move pointer to control tty buffer C ; / to r1 C ; beq sysret4 / return to user C ; clrb 6(r1) / clear the interrupt character C ; / in the tty buffer C ; br sysret4 / return to user C 0DDE C syssetuid: ; / set process id C ; 02/08/2013 C ; 07/07/2013 C ; 'syssetuid' sets the user id (u.uid) of the current process C ; to the process id in (u.r0). Both the effective user and C ; u.uid and the real user u.ruid are set to this. C ; Only the super user can make this call. C ; C ; Calling sequence: C ; syssetuid C ; Arguments: - C ; C ; Inputs: (u.r0) - contains the process id. C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; BL contains the (new) user ID of the current process C C ; movb *u.r0,r1 / move process id (number) to r1 0DDE 3A 1E 3905 R C cmp bl, byte ptr [u.ruid] C ; cmpb r1,u.ruid / is it equal to the real user C ; / id number 0DE2 74 0E C je short @f C ; beq 1f / yes 0DE4 80 3E 3904 R 00 C cmp byte ptr [u.uid_], 0 ; 02/08/2013 C ; tstb u.uid / no, is current user the super user? 0DE9 76 03 E9 F50E C ja error C ; bne error4 / no, error 0DEE 88 1E 3905 R C mov byte ptr [u.ruid], bl 0DF2 C @@: ; 1: 0DF2 88 1E 3904 R C mov byte ptr [u.uid_], bl ; 02/08/2013 C ; movb r1,u.uid / put process id in u.uid C ; movb r1,u.ruid / put process id in u.ruid 0DF6 E9 F520 C jmp sysret C ; br sysret4 / system return C 0DF9 C sysgetuid: ; < get user id > C ; 07/07/2013 C ; 'sysgetuid' returns the real user ID of the current process. C ; The real user ID identifies the person who is logged in, C ; in contradistinction to the effective user ID, which C ; determines his access permission at each moment. It is thus C ; useful to programs which operate using the 'set user ID' C ; mode, to find out who invoked them. C ; C ; Calling sequence: C ; syssetuid C ; Arguments: - C ; C ; Inputs: - C ; Outputs: (u.r0) - contains the real user's id. C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; AL contains the real user ID at return. C ; C ;xor ah, ah 0DF9 A0 3905 R C mov al, byte ptr [u.ruid] 0DFC A3 38D0 R C mov word ptr [u.r0], ax C ; movb u.ruid,*u.r0 / move the real user id to (u.r0) 0DFF E9 F517 C jmp sysret C ; br sysret4 / systerm return, sysret 0E02 C anyi: C ; 25/04/2013 C ; 'anyi' is called if a file deleted while open. C ; "anyi" checks to see if someone else has opened this file. C ; C ; INPUTS -> C ; r1 - contains an i-number C ; fsp - start of table containing open files C ; C ; OUTPUTS -> C ; "deleted" flag set in fsp entry of another occurrence of C ; this file and r2 points 1st word of this fsp entry. C ; if file not found - bit in i-node map is cleared C ; (i-node is freed) C ; all blocks related to i-node are freed C ; all flags in i-node are cleared C ; ((AX = R1)) input C ; C ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C ; C ; / r1 contains an i-number 0E02 BB 2A2E R C mov bx, offset fsp C ; mov $fsp,r2 / move start of fsp table to r2 0E05 C anyi_1: ; 1: 0E05 3B 07 C cmp ax, word ptr [BX] C ; cmp r1,(r2) / do i-numbers match? 0E07 74 27 C je short anyi_2 C ; beq 1f / yes, 1f 0E09 F7 D8 C neg ax C ; neg r1 / no complement r1 0E0B 3B 07 C cmp ax, word ptr [BX] C ; cmp r1,(r2) / do they match now? 0E0D 74 21 C je short anyi_2 C ; beq 1f / yes, transfer C ; / i-numbers do not match 0E0F 83 C3 08 C add bx, 8 C ; add $8,r2 / no, bump to next entry in fsp table 0E12 81 FB 2BBE R C cmp bx, offset fsp + (nfiles*8) C ; cmp r2,$fsp+[nfiles*8] C ; / are we at last entry in the table 0E16 72 ED C jb short anyi_1 C ; blt 1b / no, check next entries i-number C ;cmp ax, 32768 0E18 80 FC 80 C cmp ah, 80h ; negative number check C ; tst r1 / yes, no match C ; bge .+4 0E1B 72 02 C jb short @f 0E1D F7 D8 C neg ax C ; neg r1 / make i-number positive 0E1F C @@: 0E1F E8 03F1 C call imap C ; jsr r0,imap / get address of allocation bit C ; / in the i-map in r2 C ;; DL/DX (MQ) has a 1 in the calculated bit position C ;; BX (R2) has address of the byte with allocation bit C ; not dx 0E22 F6 D2 C not dl ;; 0 at calculated bit position, other bits are 1 C ;and word ptr [BX], dx 0E24 20 17 C and byte ptr [BX], dl C ; bicb mq,(r2) / clear bit for i-node in the imap 0E26 E8 039C C call itrunc C ; jsr r0,itrunc / free all blocks related to i-node 0E29 C7 06 296E R 0000 C mov word ptr [i.flgs], 0 C ; clr i.flgs / clear all flags in the i-node 0E2F C3 C retn C ;rts r0 / return 0E30 C anyi_2: ; 1: / i-numbers match 0E30 FE 47 07 C inc byte ptr [BX]+7 C ;incb 7(r2) / increment upper byte of the 4th word C ; / in that fsp entry (deleted flag of fsp entry) 0E33 C3 C retn C ; rts r0 C include u3.asm ; u3.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U3.ASM (include u0.asm) //// UNIX v1 -> u3.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 08/03/2014 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 08/03/2014 wswap, rswap, swap C ; 25/02/2014 swap C ; 23/02/2014 putlu, swap C ; 14/02/2014 swap ('SRUN' check), putlu (single level runq) C ; 05/02/2014 swap (SSLEEP/SWAIT/SRUN, p.waitc) C ; 23/10/2013 swap (consistency check), idle C ; 10/10/2013 idle C ; 24/09/2013 swap, wswap, rswap, tswap (consistency check) C ; 20/09/2013 swap C ; 30/08/2013 swap C ; 09/08/2013 swap C ; 08/08/2013 putlu, wswap, rswap C ; 03/08/2013 C ; 01/08/2013 C ; 29/07/2013 C ; 24/07/2013 C ; 23/07/2013 C ; 09/07/2013 C ; 26/05/2013 C ; 24/05/2013 C ; 21/05/2013 C ; 17/05/2013 C ; 16/05/2013 swap C ; 19/04/2013 swap, wrswap C ; 14/04/2013 tswap, swap C ; 10/04/2013 C ; 11/03/2013 C 0E34 C tswap: C ; 14/02/2014 single level runq C ; 24/09/2013 consistency check -> ok C ; 26/05/2013 (swap, putlu modifications) C ; 14/04/2013 C ; time out swap, called when a user times out. C ; the user is put on the low priority queue. C ; This is done by making a link from the last user C ; on the low priority queue to him via a call to 'putlu'. C ; then he is swapped out. C ; C ; RETRO UNIX 8086 v1 modification -> C ; 'swap to disk' is replaced with 'change running segment' C ; according to 8086 cpu (x86 real mode) architecture. C ; pdp-11 was using 64KB uniform memory while IBM PC C ; compatibles was using 1MB segmented memory C ; in 8086/8088 times. C ; C ; INPUTS -> C ; u.uno - users process number C ; runq+4 - lowest priority queue C ; OUTPUTS -> C ; r0 - users process number C ; r2 - lowest priority queue address C ; C ; ((AX = R0, BX = R2)) output C ; ((Modified registers: DX, BX, CX, SI, DI)) C ; 0E34 A0 3907 R C mov al, byte ptr [u.uno] C ; movb u.uno,r1 / move users process number to r1 C ;mov bx, offset runq + 4 C ; mov $runq+4,r2 C ; / move lowest priority queue address to r2 0E37 E8 0094 C call putlu C ; jsr r0,putlu / create link from last user on Q to C ; / u.uno's user 0E3A C swap: C ; 08/03/2014 C ; 25/02/2014 C ; 23/02/2014 C ; 14/02/2014 single level runq C ; 05/02/2014 SSLEEP/SWAIT/SRUN, p.waitc C ; 23/10/2013 consistency check -> ok C ; 24/09/2013 consistency check -> ok C ; 20/09/2013 ('call idle' enabled again) C ; 30/08/2013 C ; 09/08/2013 C ; 29/07/2013 C ; 24/07/2013 sstack (= file size + 256) C ; 26/05/2013 wswap and rswap (are come back!) C ; 24/05/2013 (u.usp -> sp modification) C ; 21/05/2013 C ; 16/05/2013 C ; 19/04/2013 wrswap (instead of wswap and rswap) C ; 14/04/2013 C ; 'swap' is routine that controls the swapping of processes C ; in and out of core. C ; C ; RETRO UNIX 8086 v1 modification -> C ; 'swap to disk' is replaced with 'change running segment' C ; according to 8086 cpu (x86 real mode) architecture. C ; pdp-11 was using 64KB uniform memory while IBM PC C ; compatibles was using 1MB segmented memory C ; in 8086/8088 times. C ; C ; INPUTS -> C ; runq table - contains processes to run. C ; p.link - contains next process in line to be run. C ; u.uno - process number of process in core C ; s.stack - swap stack used as an internal stack for swapping. C ; OUTPUTS -> C ; (original unix v1 -> present process to its disk block) C ; (original unix v1 -> new process into core -> C ; Retro Unix 8086 v1 -> segment registers changed C ; for new process) C ; u.quant = 3 (Time quantum for a process) C ; ((INT 1Ch count down speed -> 18.2 times per second) C ; RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second) C ; for now, it will swap the process if there is not C ; a keyboard event (keystroke) (Int 15h, function 4Fh) C ; or will count down from 3 to 0 even if there is a C ; keyboard event locking due to repetitive key strokes. C ; u.quant will be reset to 3 for RETRO UNIX 8086 v1. C ; C ; u.pri -points to highest priority run Q. C ; r2 - points to the run queue. C ; r1 - contains new process number C ; r0 - points to place in routine or process that called C ; swap all user parameters C ; C ; ((Modified registers: AX, DX, BX, CX, SI, DI)) C ; 0E3A C swap_0: C ;mov $300,*$ps / processor priority = 6 C ; 14/02/2014 0E3A BE 2C02 R C mov si, offset runq ; 23/02/2014 BX -> DI -> SI C ; mov $runq,r2 / r2 points to runq table 0E3D C swap_1: ; 1: / search runq table for highest priority process 0E3D 8B 04 C mov ax, word ptr [SI] 0E3F 23 C0 C and ax, ax C ; tst (r2)+ / are there any processes to run C ; / in this Q entry 0E41 75 05 C jnz short swap_2 C ; bne 1f / yes, process 1f C ; cmp r2,$runq+6 / if zero compare address C ; / to end of table C ; bne 1b / if not at end, go back C C ;; 25/02/2014 C ;;mov al, byte ptr [ptty] C ;;call wakeup C ;;or al, al C ;;jnz short swap_1 C ; C ;;mov cx, word ptr [s.idlet]+2 ;; 29/07/2013 C ;;; 30/08/2013 C ; 20/09/2013 0E43 E8 00AC C call idle ; 23/10/2013 (consistency check !) C ; jsr r0,idle; s.idlet+2 / wait for interrupt; C ; / all queues are empty C ; 14/02/2014 0E46 EB F5 C jmp short swap_1 C ; br swap 0E48 C swap_2: ; 1: C ; tst -(r2) / restore pointer to right Q entry C ; mov r2,u.pri / set present user to this run queue C ;mov ax, word ptr [SI] C ; movb (r2)+,r1 / move 1st process in queue to r1 C ; 0E48 38 E0 C cmp al, ah ; 16/05/2013 C ; cmpb r1,(r2)+ / is there only 1 process C ; / in this Q to be run 0E4A 74 0C C je short swap_3 C ; beq 1f / yes C ; tst -(r2) / no, pt r2 back to this Q entry C ; 0E4C 8A D8 C mov bl, al 0E4E 32 FF C xor bh, bh 0E50 8A A7 2A0D R C mov ah, byte ptr [BX]+p.link-1 0E54 88 24 C mov byte ptr [SI], ah C ; movb p.link-1(r1),(r2) / move next process C ; / in line into run queue 0E56 EB 04 C jmp short swap_4 C ; br 2f 0E58 C swap_3: ; 1: 0E58 33 D2 C xor dx, dx C ; 23/02/2014 BX -> SI 0E5A 89 14 C mov word ptr [SI], dx ;16/05/2013 C ; clr -(r2) / zero the entry; no processes on the Q C ; C ; 26/05/2013 (swap_4 and swap_5) 0E5C C swap_4: ; / write out core to appropriate disk area and read C ; / in new process if required C ; clr *$ps / clear processor status C ; 09/08/2013 0E5C 8A 26 3907 R C mov ah, byte ptr [u.uno] 0E60 38 C4 C cmp ah, al C ;cmp byte ptr [u.uno], al C ; cmpb r1,u.uno / is this process the same as C ; / the process in core? 0E62 74 17 C je short swap_6 C ; beq 2f / yes, don't have to swap C ; mov r0,-(sp) / no, write out core; save r0 C ; / (address in routine that called swap) 0E64 89 26 38CE R C mov word ptr [u.usp], sp C ; mov sp,u.usp / save stack pointer C ; 09/08/2013 C ; 24/07/2013 C ;mov sp, sstack ; offset sstack C ; mov $sstack,sp / move swap stack pointer C ; / to the stack pointer C ;push ax C ; mov r1,-(sp) / put r1 (new process #) on the stack C ; 09/08/2013 0E68 0A E4 C or ah, ah C ;cmp byte ptr [u.uno], dl ; 0 C ; tstb u.uno / is the process # = 0 0E6A 74 03 C jz short swap_5 C ;jna short swap_5 C ; beq 1f / yes, kill process by overwriting 0E6C E8 0012 C call wswap C ;jsr r0,wswap / write out core to disk 0E6F C swap_5: ;1: C ; pop ax C ; mov (sp)+,r1 / restore r1 to new process number C ; 08/03/2014 C ; (protect 'rswap' return address from stack overwriting) 0E6F FA C cli 0E70 BC 39B6 R C mov sp, sstack - 190 ; (SizeOfFile + 2) C ; 0E73 E8 0032 C call rswap C ; jsr r0,rswap / read new process into core C ; jsr r0,unpack / unpack the users stack from next C ; / to his program to its normal 0E76 8B 26 38CE R C mov sp, word ptr [u.usp] C ; mov u.usp,sp / location; restore stack pointer to C ; / new process stack C ; mov (sp)+,r0 / put address of where the process C ; / that just got swapped in, left off., C ; / i.e., transfer control to new process 0E7A FB C sti 0E7B C swap_6: ;2: C ; 14/02/2014 uquant -> u.quant C ; 30/08/2013 C ; RETRO UNIX 8086 v1 modification ! 0E7B C6 06 38FA R 04 C mov byte ptr [u.quant], time_count C ;mov byte ptr [uquant], 3 C ; movb $30.,uquant / initialize process time quantum 0E80 C3 C retn C ; rts r0 / return C 0E81 C wswap: ; < swap out, swap to disk > C ; 08/03/2014 major modification C ; 24/09/2013 consistency check -> ok C ; 08/08/2013 C ; 24/07/2013 C ; 26/05/2013 C ; 'wswap' writes out the process that is in core onto its C ; appropriate disk area. C ; C ; Retro UNIX 8086 v1 modification -> C ; 'swap to disk' is replaced with 'change running segment' C ; according to 8086 cpu (x86 real mode) architecture. C ; pdp-11 was using 64KB uniform memory while IBM PC C ; compatibles was using 1MB segmented memory C ; in 8086/8088 times. C ; C ; INPUTS -> C ; u.break - points to end of program C ; u.usp - stack pointer at the moment of swap C ; core - beginning of process program C ; ecore - end of core C ; user - start of user parameter area C ; u.uno - user process number C ; p.dska - holds block number of process C ; OUTPUTS -> C ; swp I/O queue C ; p.break - negative word count of process C ; r1 - process disk address C ; r2 - negative word count C ; C ; RETRO UNIX 8086 v1 input/output: C ; C ; INPUTS -> C ; u.uno - process number (to be swapped out) C ; OUTPUTS -> C ; none C ; C ; ((Modified registers: CX, SI, DI)) C 0E81 BF 06C0 C mov di, sdsegmnt 0E84 8E C7 C mov es, di 0E86 32 C9 C xor cl, cl 0E88 8A 2E 3907 R C mov ch, byte ptr [u.uno] 0E8C FE CD C dec ch ; 0 based process number C ;; 08/03/2014 (swap data space is 256 bytes for every process) C ;;shr cx, 1 ; swap data space is 128 bytes for every process 0E8E 8B F9 C mov di, cx C ; 08/03/2014 0E90 B9 0020 C mov cx, 32 0E93 BE 38CC R C mov si, offset u ; user structure 0E96 F3/ A5 C rep movsw C ; 0E98 8B 36 38CE R C mov si, word ptr [u.usp] ; sp (system stack pointer) 0E9C B9 3A74 R C mov cx, sstack 0E9F 2B CE C sub cx, si ; NOTE: system stack size = 256-64 = 192 bytes 0EA1 F3/ A4 C rep movsb C ; 0EA3 8C D9 C mov cx, ds 0EA5 8E C1 C mov es, cx 0EA7 C3 C retn C ; C ; 08/08/2013, 14 -> 16, 7 -> 8 C ;mov si, sstack - 16 ; 24/07/2013 C ; offset sstack - 16 ;; = word ptr [u.sp_] - 2 C ;mov cx, 8 C ;rep movsw C ;mov cl, 32 C ;mov si, offset u ; user structure C ;rep movsw C ;mov cx, ds C ;mov es, cx C ;retn C C ; Original UNIX v1 'wswap' routine: C ; wswap: C ; mov *$30,u.emt / determines handling of emts C ; mov *$10,u.ilgins / determines handling of C ; / illegal instructions C ; mov u.break,r2 / put process program break address in r2 C ; inc r2 / add 1 to it C ; bic $1,r2 / make it even C ; mov r2,u.break / set break to an even location C ; mov u.usp,r3 / put users stack pointer C ; / at moment of swap in r3 C ; cmp r2,$core / is u.break less than $core C ; blos 2f / yes C ; cmp r2,r3 / no, is (u.break) greater than stack ptr. C ; bhis 2f / yes C ; 1: C ; mov (r3)+,(r2)+ / no, pack stack next to users program C ; cmp r3,$ecore / has stack reached end of core C ; bne 1b / no, keep packing C ; br 1f / yes C ; 2: C ; mov $ecore,r2 / put end of core in r2 C ; 1: C ; sub $user,r2 / get number of bytes to write out C ; / (user up to end of stack gets written out) C ; neg r2 / make it negative C ; asr r2 / change bytes to words (divide by 2) C ; mov r2,swp+4 / word count C ; movb u.uno,r1 / move user process number to r1 C ; asl r1 / x2 for index C ; mov r2,p.break-2(r1) / put negative of word count C ; / into the p.break table C ; mov p.dska-2(r1),r1 / move disk address of swap area C ; / for process to r1 C ; mov r1,swp+2 / put processes dska address in swp+2 C ; / (block number) C ; bis $1000,swp / set it up to write (set bit 9) C ; jsr r0,ppoke / write process out on swap area of disk C ; 1: C ; tstb swp+1 / is lt done writing? C ; bne 1b / no, wait C ; rts r0 / yes, return to swap C 0EA8 C rswap: ; < swap in, swap from disk > C ; 08/03/2014 major modification C ; 24/09/2013 consistency check -> ok C ; 08/08/2013 C ; 24/07/2013 C ; 26/05/2013 C ; 'rswap' reads a process whose number is in r1, C ; from disk into core. C ; C ; RETRO UNIX 8086 v1 modification -> C ; 'swap to disk' is replaced with 'change running segment' C ; according to 8086 cpu (x86 real mode) architecture. C ; pdp-11 was using 64KB uniform memory while IBM PC C ; compatibles was using 1MB segmented memory C ; in 8086/8088 times. C ; C ; INPUTS -> C ; r1 - process number of process to be read in C ; p.break - negative of word count of process C ; p.dska - disk address of the process C ; u.emt - determines handling of emt's C ; u.ilgins - determines handling of illegal instructions C ; OUTPUTS -> C ; 8 = (u.ilgins) C ; 24 = (u.emt) C ; swp - bit 10 is set to indicate read C ; (bit 15=0 when reading is done) C ; swp+2 - disk block address C ; swp+4 - negative word count C ; ((swp+6 - address of user structure)) C ; C ; RETRO UNIX 8086 v1 input/output: C ; C ; INPUTS -> C ; AL - new process number (to be swapped in) C ; OUTPUTS -> C ; none C ; C ; ((Modified registers: AX, CX, SI, DI)) C 0EA8 8A E0 C mov ah, al 0EAA FE CC C dec ah 0EAC 32 C0 C xor al, al C ;;shr ax, 1 ; 08/03/2014 (256 bytes per process) 0EAE 8B F0 C mov si, ax ; SI points copy of sstack in sdsegment C ; u.sp_ points sstack-12 (for 6 registers) 0EB0 B8 06C0 C mov ax, sdsegmnt ; 17/05/2013 0EB3 8E D8 C mov ds, ax ; sdsegment C ; 08/03/2014 0EB5 BF 38CC R C mov di, offset u 0EB8 B9 0020 C mov cx, 32 0EBB F3/ A5 C rep movsw 0EBD 26: 8B 3E 38CE R C mov di, word ptr ES:[u.usp] ; system stack pointer location 0EC2 B9 3A74 R C mov cx, sstack 0EC5 2B CF C sub cx, di ; Max. 256-64 bytes stack space 0EC7 F3/ A4 C rep movsb 0EC9 8C C8 C mov ax, cs 0ECB 8E D8 C mov ds, ax 0ECD C3 C retn C ; C ; 08/08/2013 14 -> 16, 7 ->8 C ; 24/07/2013 C ;mov di, sstack - 16 ; offset sstack-14 C ;mov cx, 8 C ;rep movsw C ;mov di, offset u C ;mov cl, 32 C ;rep movsw C ;mov ax, cs C ;mov ds, ax C ;retn C C ; Original UNIX v1 'rswap' and 'unpack' routines: C ;rswap: C ; asl r1 / process number x2 for index C ; mov p.break-2(r1), swp+4 / word count C ; mov p.dska-2(r1),swp+2 / disk address C ; bis $2000,swp / read C ; jsr r0,ppoke / read it in C ; 1: C ; tstb swp+1 / done C ; bne 1b / no, wait for bit 15 to clear (inhibit bit) C ; mov u.emt,*$30 / yes move these C ; mov u.ilgins,*$10 / back C ; rts r0 / return C C ;unpack: ; / move stack back to its normal place C ; mov u.break,r2 / r2 points to end of user program C ; cmp r2,$core / at beginning of user program yet? C ; blos 2f / yes, return C ; cmp r2,u.usp / is break_above the stack pointer C ; / before swapping C ; bhis 2f / yes, return C ; mov $ecore,r3 / r3 points to end of core C ; add r3,r2 C ; sub u.usp,r2 / end of users stack is in r2 C ; 1: C ; mov -(r2),-(r3) / move stack back to its normal place C ; cmp r2,u.break / in core C ; bne 1b C ; 2: C ; rts r0 C 0ECE C putlu: C ; 23/02/2014 C ; 14/02/2014 single level run queue C ; 08/08/2013 C ; 26/05/2013 (si -> di) C ; 15/04/2013 C ; C ; 'putlu' is called with a process number in r1 and a pointer C ; to lowest priority Q (runq+4) in r2. A link is created from C ; the last process on the queue to process in r1 by putting C ; the process number in r1 into the last process's link. C ; C ; INPUTS -> C ; r1 - user process number C ; r2 - points to lowest priority queue C ; p.dska - disk address of the process C ; u.emt - determines handling of emt's C ; u.ilgins - determines handling of illegal instructions C ; OUTPUTS -> C ; r3 - process number of last process on the queue upon C ; entering putlu C ; p.link-1 + r3 - process number in r1 C ; r2 - points to lowest priority queue C ; C ; ((Modified registers: DX, BX, DI)) C ; C C ; / r1 = user process no.; r2 points to lowest priority queue C C ; BX = r2 C ; AX = r1 (AL=r1b) C C ; 14/02/2014 0ECE BB 2C02 R C mov bx, offset runq C ; 23/02/2014 0ED1 8B 17 C mov dx, word ptr [BX] 0ED3 43 C inc bx 0ED4 23 D2 C and dx, dx C ; tstb (r2)+ / is queue empty? 0ED6 74 0C C jz short putlu_1 C ; beq 1f / yes, branch 0ED8 8A D6 C mov dl, dh 0EDA 32 F6 C xor dh, dh 0EDC 8B FA C mov di, dx C ; movb (r2),r3 / no, save the "last user" process number C ; / in r3 0EDE 88 85 2A0D R C mov byte ptr [DI]+p.link-1, al C ; movb r1,p.link-1(r3) / put pointer to user on C ; / "last users" link 0EE2 EB 03 C jmp short putlu_2 C ; br 2f / 0EE4 C putlu_1: ; 1: 0EE4 88 47 FF C mov byte ptr [BX]-1, al ; 08/08/2013 C ; movb r1,-1(r2) / user is only user; C ; / put process no. at beginning and at end 0EE7 C putlu_2: ; 2: 0EE7 88 07 C mov byte ptr [BX], al C ; movb r1,(r2) / user process in r1 is now the last entry C ; / on the queue C ; 23/02/2014 0EE9 8A D0 C mov dl, al 0EEB 8B FA C mov di, dx 0EED 88 B5 2A0D R C mov byte ptr [DI]+p.link-1, dh ; 0 C ; C ;14/02/2014 C ;dec bx C ; dec r2 / restore r2 0EF1 C3 C retn C ; rts r0 C C ;copyz: C ; mov r1,-(sp) / put r1 on stack C ; mov r2,-(sp) / put r2 on stack C ; mov (r0)+,r1 C ; mov (r0)+,r2 C ;1: C ; clr (r1)+ / clear all locations between r1 and r2 C ; cmp r1,r2 C ; blo 1b C ; mov (sp)+,r2 / restore r2 C ; mov (sp)+,r1 / restore r1 C ; rts r0 C 0EF2 C idle: C ; 23/10/2013 C ; 10/10/2013 C ; 29/07/2013 C ; 09/07/2013 C ; 10/04/2013 C ; (idle & wait loop) C ; Retro Unix 8086 v1 modification on original Unixv1 idle procedure! C ; input -> CX = wait count C C ;sti C ; 29/07/2013 0EF2 F4 C hlt 0EF3 90 C nop ; 10/10/2013 0EF4 90 C nop 0EF5 90 C nop C ; 23/10/2013 0EF6 90 C nop 0EF7 90 C nop 0EF8 90 C nop 0EF9 90 C nop 0EFA C3 C retn C C ;sti C ;;;push word ptr [clockp] C ;or cx, cx C ;jnz short @f C ;inc cx C ;@@: C ;;;mov word ptr [clockp], cx 0EFB C @@: C ;hlt ; wait for interrupt (timer interrupt or keyboard interrupt etc.) C ;;;dec word ptr [clockp] C ;dec cx ; 09/07/2013 ;;; C ;jnz short @b C ;;; pop word ptr [clockp] C ;retn C C ;mov *$ps,-(sp) / save ps on stack C ;clr *$ps / clear ps C ;mov clockp,-(sp) / save clockp on stack C ;mov (r0)+,clockp / arg to idle in clockp C ;1 / wait for interrupt C ;mov (sp)+,clockp / restore clockp, ps C ;mov (sp)+,*$ps C ;rts r0 C 0EFB C clear: C ; 03/08/2013 C ; 01/08/2013 C ; 23/07/2013 C ; 09/04/2013 C ; C ; 'clear' zero's out of a block (whose block number is in r1) C ; on the current device (cdev) C ; C ; INPUTS -> C ; r1 - block number of block to be zeroed C ; cdev - current device number C ; OUTPUTS -> C ; a zeroed I/O buffer onto the current device C ; r1 - points to last entry in the I/O buffer C ; C ; ((AX = R1)) input/output C ; (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C 0EFB E8 08F9 C call wslot C ; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first C ; / word of I/O queue r5 points to first data word in buffer 0EFE 8B FB C mov di, bx ; r5 0F00 8B D0 C mov dx, ax ; 01/08/2013 0F02 B9 0100 C mov cx, 256 C ; mov $256.,r3 0F05 33 C0 C xor ax, ax 0F07 F3/ AB C rep stosw ; 03/08/2013 0F09 8B C2 C mov ax, dx ; 01/08/2013 C C ; 1: C ; clr (r5)+ / zero data word in buffer C ; dec r3 C ; bgt 1b / branch until all data words in buffer are zero 0F0B E8 08FF C call dskwr C ; jsr r0,dskwr / write zeroed buffer area out onto physical C ; / block specified in r1 C ; AX (r1) = block number 0F0E C3 C retn C ; rts r0 C include u4.asm ; u4.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U4.ASM (include u4.asm) //// UNIX v1 -> u4.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 04/07/2014 ] !!! completed !!! C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 04/07/2014 (swakeup has been removed) C ; 11/06/2014 swakeup C ; 02/06/2014 swakeup C ; 30/05/2014 isintr C ; 20/03/2014 sleep C ; 18/03/2014 clock C ; 25/02/2014 sleep C ; 23/02/2014 wakeup, sleep C ; 17/02/2014 wakeup C ; 14/02/2014 clock C ; 14/02/2014 sleep, wakeup (sigle level runq) ((to prevent s/w locking)) C ; 05/02/2014 sleep, wakeup (SSLEEP/SRUN, p.waitc) C ; 26/01/2014 C ; 10/12/2013 C ; 07/12/2013 clock C ; 23/10/2013 wakeup, sleep C ; 20/10/2013 isintr, clock, wakeup, sleep C ; 05/10/2013 clock, wakeup, sleep C ; 24/09/2013 sleep, wakeup (consistency check) C ; 22/09/2013 sleep, wakeup (completed/modified) C ; 20/09/2013 clock, sleep C ; NOTE: 'sleep' and 'wakeup' need to be modified according to C ; original Unix v1 waiting channel feature. C ; Currently 'wakeup' is disabled and 'sleep' is not written C ; properly and clock, sleep, wakeup are not similar C ; to original unix v1 (musti tasking, time sharing feature). C ; 03/09/2013 clock, isintr C ; 30/08/2013 clock C ; 21/08/2013 C ; 29/07/2013 sleep C ; 09/07/2013 clock (INT 1Ch handler) C ; 16/05/2013 'isintr' modifications C ; 15/05/2013 C ; 09/05/2013 C ; 11/03/2013 C ;setisp: C ;mov r1,-(sp) C ;mov r2,-(sp) C ;mov r3,-(sp) C ;mov clockp,-(sp) C ;mov $s.syst+2,clockp C ;jmp (r0) C 0F0F C clock: ; / interrupt from 60 cycle clock C ; 10/04/2014 C ; 18/03/2014 C ; 14/02/2014 uquant --> u.quant C ; 10/12/2013 C ; 07/12/2013 C ;; Retro Unix 8086 v1 Modification: INT 1Ch interrupt handler ! C ;; 30/08/2013 C ;; 09/07/2013 C ;mov r0,-(sp) / save r0 C ;tst *$lks / restart clock? C ;mov $s.time+2,r0 / increment the time of day C ;inc (r0) C ;bne 1f C ;inc -(r0) C ;1: C ;mov clockp,r0 / increment appropriate time category C ;inc (r0) C ;bne 1f C ;inc -(r0) C ;1: C ;; 30/08/2013 C ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 09/07/2013 C C ; 20/10/2013 0F0F 1E C push ds 0F10 0E C push cs 0F11 1F C pop ds C ; C ;; 10/04/2014 C ;pushf C ;call dword ptr [int1Ch] ; Old INT 1Ch C ; ; (Turn off floppy motor) C 0F12 80 3E 38FA R 00 C cmp byte ptr [u.quant], 0 0F17 77 39 C ja short clk_1 C C ; 03/09/2013 0F19 80 3E 2C07 R FF C cmp byte ptr [sysflg], 0FFh ; user or system space ? 0F1E 75 36 C jne short clk_2 ; system space (sysflg <> 0FFh) C ;; 06/12/2013 0F20 80 3E 3907 R 01 C cmp byte ptr [u.uno], 1 ; /etc/init ? C ; 14/02/2014 0F25 76 2B C jna short clk_1 ; yes, do not swap out 0F27 83 3E 38FC R 00 C cmp word ptr [u.intr], 0 C ; 14/02/2014 0F2C 76 28 C jna short clk_2 0F2E C clk_0: C ; 30/08/2013 C ;cli C ;;push cs C ;;pop ds C ; 18/03/2014 0F2E FE 06 2C07 R C inc byte ptr [sysflg] ; Now, we are in system spacee C ; 0F32 A3 38D0 R C mov word ptr [u.r0], ax C ; 07/12/2013 0F35 58 C pop ax ; DS (user) C ; 0F36 89 26 38CE R C mov word ptr [u.usp], sp C ;; 07/12/2013 C ;;mov ax, ss ; mov ax, es C ;;mov word ptr [u.segmnt], ax 0F3A 8C C8 C mov ax, cs C ;mov es, ax ; 18/03/2014 0F3C BC 3A74 R C mov sp, sstack 0F3F 8E D0 C mov ss, ax C ; 0F41 FF 36 38CE R C push word ptr [u.usp] 0F45 52 C push dx 0F46 51 C push cx 0F47 53 C push bx 0F48 56 C push si 0F49 57 C push di 0F4A 55 C push bp C ; 0F4B 89 26 38CC R C mov word ptr [u.sp_], sp C ;sti C ; 07/12/2013 0F4F E9 F408 C jmp sysrelease ; 'sys release' by clock/timer 0F52 C clk_1: 0F52 FE 0E 38FA R C dec byte ptr [u.quant] 0F56 C clk_2: C ; 20/10/2013 0F56 1F C pop ds 0F57 CF C iret C C ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; C C ;mov $uquant,r0 / decrement user time quantum C ;decb (r0) C ;bge 1f / if less than 0 C ;clrb (r0) / make it 0 C ;1: / decrement time out counts return now if priority was not 0 C ;cmp 4(sp),$200 / ps greater than or equal to 200 C ;bge 2f / yes, check time outs C ;tstb (r0) / no, user timed out? C ;bne 1f / no C ;cmpb sysflg,$-1 / yes, are we outside the system? C ;bne 1f / no, 1f C ;mov (sp)+,r0 / yes, put users r0 in r0 C ;sys 0 / sysrele C ;rti C ;2: / priority is high so just decrement time out counts C ;mov $toutt,r0 / r0 points to beginning of time out table C ;2: C ;tstb (r0) / is the time out? C ;beq 3f / yes, 3f (get next entry) C ;decb (r0) / no, decrement the time C ;bne 3f / isit zero now? C ;incb (r0) / yes, increment the time C ;3: C ;inc r0 / next entry C ;cmp r0,$touts / end of toutt table? C ;blo 2b / no, check this entry C ;mov (sp)+,r0 / yes, restore r0 C ;rti / return from interrupt C ;1: / decrement time out counts; if 0 call subroutine C ;mov (sp)+,r0 / restore r0 C ;mov $240,*$ps / set processor priority to 5 C ;jsr r0,setisp / save registers C ;mov $touts-toutt-1,r0 / set up r0 as index to decrement thru C ; / the table C ;1: C ;tstb toutt(r0) / is the time out for this entry C ;beq 2f / yes C ;decb toutt(r0) / no, decrement the time C ;bne 2f / is the time 0, now C ;asl r0 / yes, 2 x r0 to get word index for tout entry C ;jsr r0,*touts(r0) / go to appropriate routine specified in this C ;asr r0 / touts entry; set r0 back to toutt index C ;2: C ;dec r0 / set up r0 for next entry C ;bge 1b / finished? , no, go back C ;br retisp / yes, restore registers and do a rti C C ;retisp: C ;mov (sp)+,clockp / pop values before interrupt off the stack C ;mov (sp)+,r3 C ;mov (sp)+,r2 C ;mov (sp)+,r1 C ;mov (sp)+,r0 C ;rti / return from interrupt C 0F58 C @@: ; 22/09/2013 0F58 C3 C retn C 0F59 C wakeup: ; / wakeup processes waiting for an event C ; / by linking them to the queue C ; C ; 02/06/2014 C ; 23/02/2014 C ; 17/02/2014 C ; 14/02/2014 single level runq (BX input is not needed) C ; 05/02/2014 SSLEEP/SRUN, p.waitc C ; 23/10/2013 (consistency check is OK) C ; 20/10/2013 C ; 10/10/2013 C ; 05/10/2013 C ; 24/09/2013 (consistency check is OK) C ; 22/09/2013 C ; 18/08/2013 -> tty lock and console tty setting (p.ttyc) C ; 15/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; (Process/task switching routine by using C ; Retro UNIX 8086 v1 keyboard interrupt output.)) C ; C ; In original UNIX v1, 'wakeup' is called to wake the process C ; sleeping in the specified wait channel by creating a link C ; to it from the last user process on the run queue. C ; If there is no process to wake up, nothing happens. C ; C ; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set C ; 'switching' status of the current process (owns current tty) C ; (via alt + function keys) to a process which has highest C ; priority (on run queue) on the requested tty (0 to 7, except C ; 8 and 9 which are tty identifiers of COM1, COM2 serial ports) C ; as it's console tty. (NOTE: 'p.ttyc' is used to set console C ; tty for tty switching by keyboard.) C ; C ; INPUT -> C ; AL = wait channel (r3) ('tty number' for now) C ; ;;BX = Run queue (r2) offset C ; C ; ((modified registers: AX, BX)) C ; C ; 20/10/2013 C ; 10/10/2013 C ;;cmp byte ptr [u.uno], 2 C ;;jb short wakeup_4 C ; 14/02/2014 0F59 32 FF C xor bh, bh 0F5B 8A D8 C mov bl, al 0F5D 81 C3 2CA2 R C add bx, offset wlist C ; 23/02/2014 0F61 8A 07 C mov al, byte ptr [BX] ; waiting list (waiting process number) C 0F63 22 C0 C and al, al 0F65 74 0F C jz short @f ; nothing to wakeup C ;cmp al, 1 C ;jb short @f ; nothing to wakeup C C ; 23/02/2014 C ; 0F67 32 E4 C xor ah, ah 0F69 88 26 38FA R C mov byte ptr [u.quant], ah ; 0 ; time quantum = 0 0F6D 88 27 C mov byte ptr [BX], ah ; 0 ; zero wait channel entry 0F6F 57 C push di 0F70 52 C push dx 0F71 E8 FF5A C call putlu 0F74 5A C pop dx 0F75 5F C pop di 0F76 C @@: 0F76 C3 C retn C C ;mov r1,-(sp) / put char on stack C ;mov (r0)+,r2 / r2 points to a queue C ;mov (r0)+,r3 / r3 = wait channel number C ;movb wlist(r3),r1 / r1 contains process number C ; / in that wait channel that was sleeping C ;beq 2f / if 0 return, nothing to wakeup C ;cmp r2,u.pri / is runq greater than or equal C ; / to users process priority C ;bhis 1f / yes, don't set time quantum to zero C ;clrb uquant / time quantum = 0 C ;1: C ;clrb wlist(r3) / zero wait channel entry C ;jsr r0,putlu / create a link from the last user C ; / on the Q to this process number that got woken C ;2: C ;mov (sp)+,r1 / restore r1 C ;rts r0 C 0F77 C sleep: C ; 20/03/2014 C ; 25/02/2014 C ; 23/02/2014 C ; 14/02/2014 single level runq C ; 05/02/2014 SSLEEP/SRUN, p.waitc C ; 26/01/2014 C ; 10/12/2013 C ; 23/10/2013 (consistency check is OK) C ; 20/10/2013 C ; 05/10/2013 (u.uno = 1 --> /etc/init ?) (r1 = ah) C ; 24/09/2013 consistency check -> OK C ; 22/09/2013 C ; 20/09/2013 C ; 29/07/2013 ;;; C ; 09/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; (Process/task switching and quit routine by using C ; Retro UNIX 8086 v1 keyboard interrupt output.)) C ; C ; In original UNIX v1, 'sleep' is called to wait for C ; tty and tape output or input becomes available C ; and process is put on waiting channel and swapped out, C ; then -when the tty or tape is ready to write or read- C ; 'wakeup' gets process back to active swapped-in status.) C ; C ; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and C ; Int 09h keyboard interrupt will set 'quit' or 'switching' C ; status of the current process also INT 1Ch will count down C ; 'uquant' value and INT 09h will redirect scancode of keystroke C ; to tty buffer of the current process and kernel will get C ; user input by using tty buffer of the current process C ; (instead of standard INT 16h interrupt). C ; TTY output will be redirected to related video page of text mode C ; (INT 10h will be called with different video page depending C ; on tty assignment of the active process: 0 to 7 for C ; pseudo screens.) C ; C ; In Retro UNIX 8086 v1, 'sleep' will be called to wait for C ; a keystroke from keyboard or wait for reading or writing C ; characters/data on serial port(s). C ; C ; Character/Terminal input/output through COM1 and COM2 will be C ; performed by related routines in addition to pseudo TTY routines. C ; C ; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013) C ; C ;; 05/10/2013 C ;10/12/2013 C ;cmp byte ptr [u.uno], 1 C ;ja short @f C ;retn C C ; 20/03/2014 C ;mov bx, word ptr [runq] C ;cmp bl, bh C ;jne short @f C ; 25/02/2014 C ;cmp word ptr [runq], 0 C ;ja short @f C ;retn 0F77 C @@: C ; 0F77 E8 0031 C call isintr 0F7A 74 03 E9 F39A C jnz sysret C ; / wait for event C ; jsr r0,isintr / check to see if interrupt C ; / or quit from user C ; br 2f / something happened C ; / yes, his interrupt so return C ; / to user C C ; 20/10/2013 0F7F 32 FF C xor bh, bh 0F81 8A DC C mov bl, ah C ; 22/09/2013 0F83 81 C3 2CA2 R C add bx, offset wlist C ; 23/02/2014 0F87 8A 07 C mov al, byte ptr [BX] 0F89 22 C0 C and al, al 0F8B 74 05 C jz short @f 0F8D 53 C push bx 0F8E E8 FF3D C call putlu 0F91 5B C pop bx 0F92 C @@: 0F92 A0 3907 R C mov al, byte ptr [u.uno] 0F95 88 07 C mov byte ptr [BX], al ; put the process number C ; in the wait channel C ; mov (r0)+,r1 / put number of wait channel in r1 C ; movb wlist(r1),-(sp) / put old process number in there, C ; / on the stack C ; movb u.uno,wlist(r1) / put process number of process C ; / to put to sleep in there 0F97 FF 36 2BD2 R C push word ptr [cdev] C ; mov cdev,-(sp) / nothing happened in isintr so 0F9B E8 FE9C C call swap C ; jsr r0,swap / swap out process that needs to sleep 0F9E 8F 06 2BD2 R C pop word ptr [cdev] C ; mov (sp)+,cdev / restore device 0FA2 E8 0006 C call isintr C ; 22/09/2013 0FA5 74 03 E9 F36F C jnz sysret C ; jsr r0,isintr / check for interrupt of new process C ; br 2f / yes, return to new user C ; movb (sp)+,r1 / no, r1 = old process number that was C ; / originally on the wait channel C ; beq 1f / if 0 branch C ; mov $runq+4,r2 / r2 points to lowest priority queue C ; mov $300,*$ps / processor priority = 6 C ; jsr r0,putlu / create link to old process number C ; clr *$ps / clear the status; process priority = 0 C ;1: 0FAA C3 C retn C ; rts r0 / return C ;2: C ;;jmp sysret C ; jmp sysret / return to user C 0FAB C isintr: C ; 30/05/2014 C ; 20/10/2013 C ; 22/09/2013 C ; 03/09/2013 C ; 16/05/2013 tty/video_page switching C ; 09/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; (Process/task switching and quit routine by using C ; Retro UNIX 8086 v1 keyboard interrupt output.)) C ; C ; Retro UNIX 8086 v1 modification: C ; 'isintr' checks if user interrupt request is enabled C ; and there is a 'quit' request by user; C ; otherwise, 'isintr' will return with zf=1 that means C ; "nothing to do". (20/10/2013) C ; C ; 20/10/2013 0FAB 83 3E 38EE R 00 C cmp word ptr [u.ttyp], 0 ; has process got a tty ? 0FB0 76 17 C jna short isintr2 ; retn C ; 03/09/2013 C ; (nothing to do) C ;retn C ; 22/09/2013 0FB2 83 3E 38FC R 00 C cmp word ptr [u.intr], 0 0FB7 76 10 C jna short isintr2 ; retn C ; 30/05/2014 0FB9 50 C push ax 0FBA A1 38FE R C mov ax, word ptr [u.quit] 0FBD 0B C0 C or ax, ax ; 0 ? 0FBF 74 07 C jz short isintr1 ; zf = 1 0FC1 83 F8 FE C cmp ax, 0FFFEh ; 'ctrl + brk' check 0FC4 77 02 C ja short isintr1 ; 0FFFFh, zf = 0 0FC6 33 C0 C xor ax, ax ; zf = 1 0FC8 C isintr1: 0FC8 58 C pop ax 0FC9 C isintr2: ; 22/09/2013 C ; zf=1 -> nothing to do 0FC9 C3 C retn C C ; UNIX v1 original 'isintr' routine... C ;mov r1,-(sp) / put number of wait channel on the stack C ;mov r2,-(sp) / save r2 C ;mov u.ttyp,r1 / r1 = pointer to buffer of process control C ; / typewriter C ;beq 1f / if 0, do nothing except skip return C ;movb 6(r1),r1 / put interrupt char in the tty buffer in r1 C ;beq 1f / if its 0 do nothing except skip return C ;cmp r1,$177 / is interrupt char = delete? C ;bne 3f / no, so it must be a quit (fs) C ;tst u.intr / yes, value of u.intr determines handling C ; / of interrupts C ;bne 2f / if not 0, 2f. If zero do nothing. C ;1: C ;tst (r0)+ / bump r0 past system return (skip) C ;4: C ;mov (sp)+,r2 / restore r1 and r2 C ;mov (sp)+,r1 C ;rts r0 C ;3: / interrupt char = quit (fs) C ;tst u.quit / value of u.quit determines handling of quits C ;beq 1b / u.quit = 0 means do nothing C ;2: / get here because either u.intr <> 0 or u.qult <> O C ;mov $tty+6,r1 / move pointer to tty block into r1 C ;1: / find process control tty entry in tty block C ;cmp (r1),u.ttyp / is this the process control tty buffer? C ;beq 1f / block found go to 1f C ;add $8,r1 / look at next tty block C ;cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks C ;blo 1b / no C ;br 4b / no process control tty found so go to 4b C ;1: C ;mov $240,*$ps / set processor priority to 5 C ;movb -3(r1),0f / load getc call argument; character llst C ; / identifier C ;inc 0f / increment C ;1: C ;jsr r0,getc; 0:.. / erase output char list for control C ; br 4b / process tty. This prevents a line of stuff C ; / being typed out after you hit the interrupt C ; / key C ;br 1b C include u5.asm ; u5.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U5.ASM (include u5.asm) //// UNIX v1 -> u5.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 07/08/2013 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 07/08/2013 iget C ; 01/08/2013 alloc, (free3, free), itrunc C ; 31/07/2013 u.rw -> rw, setimod, mget C ; 28/07/2013 iget, icalc (u.rw) C ; 21/07/2013 alloc, free, imap C ; 18/07/2013 iget C ; 17/07/2013 icalc (inode->i), iget C ; 09/07/2013 iget (cdev=1) C ; 29/04/2013 access modification C ; 26/04/2013 imap, iget (mntd->mdev) C ; 24/04/2013 access C ; 23/04/2013 itrunc C ; 07/04/2013 alloc, free, iget, icalc C ; 02/04/2013 alloc C ; 01/04/2013 alloc C ; 24/03/2013 mget C ; 22/03/2013 mget C ; 11/03/2013 C 0FCA C mget: C ; 31/07/2013 C ; 24/03/2013 C ; 22/03/2013 C ; Get existing or (allocate) a new disk block for file C ; C ; INPUTS -> C ; u.fofp (file offset pointer) C ; inode C ; u.off (file offset) C ; OUTPUTS -> C ; r1 (physical block number) C ; r2, r3, r5 (internal) C ; C ; ((AX = R1)) output C ; (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, BX, CX, SI, DI, BP)) C C ; mov *u.fofp,mq / file offset in mq C ; clr ac / later to be high sig C ; mov $-8,lsh / divide ac/mq by 256. C ; mov mq,r2 C ; bit $10000,i.flgs / lg/sm is this a large or small file C ; bne 4f / branch for large file 0FCA C mget_0: 0FCA 8B 36 38DE R C mov si, word ptr [u.fofp] ; 24/03/2013 0FCE 8A 5C 01 C mov bl, byte ptr [SI]+1 0FD1 32 FF C xor bh, bh C ; BX = r2 0FD3 F7 06 296E R 1000 C test word ptr [i.flgs], 4096 ; 1000h C ; is this a large or small file 0FD9 75 49 C jnz short mget_5 ; 4f ; large file C 0FDB F6 C3 F0 C test bl, 0F0h ; !0Fh C ; bit $!17,r2 0FDE 75 19 C jnz short mget_2 C ; bne 3f / branch if r2 greater than or equal to 16 0FE0 80 E3 0E C and bl, 0Eh C ; bic $!16,r2 / clear all bits but bits 1,2,3 0FE3 8B 87 2974 R C mov ax, word ptr i.dskp[BX] ; AX = R1, physical block number C ; mov i.dskp(r2),r1 / r1 has physical block number 0FE7 0B C0 C or ax, ax 0FE9 75 0D C jnz short mget_1 ; if physical block number is zero C ; bne 2f / if physical block num is zero then need a new block C ; / for file 0FEB E8 0070 C call alloc C ; jsr r0,alloc / allocate a new block C ; AX (r1) = Physical block number 0FEE 89 87 2974 R C mov word ptr i.dskp[BX], ax C ; mov r1,i.dskp(r2) / physical block number stored in i-node 0FF2 E8 01AB C call setimod C ; jsr r0,setimod / set inode modified byte (imod) 0FF5 E8 FF03 C call clear C ; jsr r0,clear / zero out disk/drum block just allocated 0FF8 C mget_1: ; 2: C ; AX (r1) = Physical block number 0FF8 C3 C retn C ; rts r0 0FF9 C mget_2: ; 3: / adding on block which changes small file to a large file 0FF9 E8 0062 C call alloc C ; jsr r0,alloc / allocate a new block for this file; C ; / block number in r1 C ; AX (r1) = Physical block number 0FFC E8 07F8 C call wslot C ; jsr r0,wslot / set up I/O buffer for write, r5 points to C ; / first data word in buffer C ; AX (r1) = Physical block number 0FFF B9 0008 C mov cx, 8 ; R3, transfer old physical block pointers C ; into new indirect block area for the new C ; large file 1002 8B FB C mov di, bx ; r5 1004 BE 2974 R C mov si, offset i.dskp C ; mov $8.,r3 / next 6 instructions transfer old physical C ; / block pointers C ; mov $i.dskp,r2 / into new indirect block for the new C ; / large file 1007 33 C0 C xor ax, ax ; mov ax, 0 1009 C mget_3: ;1: 1009 A5 C movsw C ; mov (r2),(r5)+ 100A 89 44 FE C mov word ptr [SI]-2, ax C ; clr (r2)+ 100D E2 FA C loop mget_3 ; 1b C ; dec r3 C ; bgt 1b C 100F B1 F8 C mov cl, 256-8 C ; mov $256.-8.,r3 / clear rest of data buffer 1011 C mget_4: ; 1 1011 F3/ AB C rep stosw C ; clr (r5)+ C ; dec r3 C ; bgt 1b C ; 24/03/2013 C ; AX (r1) = Physical block number 1013 E8 07F7 C call dskwr C ; jsr r0,dskwr / write new indirect block on disk C ; AX (r1) = Physical block number 1016 A3 2974 R C mov word ptr [i.dskp], ax C ; mov r1,i.dskp / put pointer to indirect block in i-node 1019 81 0E 296E R 1000 C or word ptr [i.flgs], 4096 ; 1000h C ; bis $10000,i.flgs / set large file bit C ; / in i.flgs word of i-node 101F E8 017E C call setimod C ; jsr r0,setimod / set i-node modified flag 1022 EB A6 C jmp short mget_0 C ; br mget C 1024 C mget_5: ; 4 ; large file C ; 05/03/2013 (UNIXCOPY.ASM) C ;mov ax, bx ; ax <= 255 for this file (UNIX v1, RUFS) system C ;mov cx, 256 ; 01/03/2013 no need a division here C ;xor dx, dx ; 01/03/2013 no need a division here C ;div cx ; 01/03/2013 no need a division here C ;and bx, 1FEh ; zero all bit but 1,2,3,4,5,6,7,8 C ; gives offset in indirect block C ;push bx ; R2 C ;mov bx, ax ; calculate offset in i-node for pointer C ; to proper indirect block C ;and bx, 0Eh C ;mov ax, word ptr i.dskp[BX] ; R1 C ; mov $-8,lsh / divide byte number by 256. C ; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset C ; / in indirect block C ; mov r2,-(sp) / save on stack (*) C ; mov mq,r2 / calculate offset in i-node for pointer to proper C ; / indirect block C ; bic $!16,r2 1024 80 E3 FE C and bl, 0FEh ; bh = 0 1027 53 C push bx ; i-node pointer offset in indirect block (*) C ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512) C ; for this file system (offset 128 to 255 not in use) C ; There is always 1 indirect block for this file system 1028 A1 2974 R C mov ax, word ptr [i.dskp] ; i.dskp[0] C ; mov i.dskp(r2),r1 102B 0B C0 C or ax, ax ; R1 102D 75 0C C jnz short mget_6 ; 2f C ; bne 2f / if no indirect block exists 102F E8 002C C call alloc C ; jsr r0,alloc / allocate a new block C ; mov word ptr i.dskp[BX], ax ; R1, block number 1032 A3 2974 R C mov word ptr [i.dskp], ax ; 03/03/2013 C ; mov r1,i.dskp(r2) / put block number of new block in i-node 1035 E8 0168 C call setimod C ; jsr r0,setimod / set i-node modified byte C ; AX = new block number 1038 E8 FEC0 C call clear C ; jsr r0,clear / clear new block 103B C mget_6: ;2 C ; 05/03/2013 C ; AX = r1, physical block number (of indirect block) 103B E8 077E C call dskrd ; read indirect block C ; jsr r0,dskrd / read in indirect block 103E 5A C pop dx ; R2, get offset (*) C ; mov (sp)+,r2 / get offset C ; AX = r1, physical block number (of indirect block) 103F 50 C push ax ; ** ; 24/03/2013 C ; mov r1,-(sp) / save block number of indirect block on stack C ; BX (r5) = pointer to buffer (indirect block) 1040 03 DA C add bx, dx ; / r5 points to first word in indirect block, r2 C ; add r5,r2 / r5 points to first word in indirect block, r2 C ; / points to location of inter 1042 8B 07 C mov ax, word ptr [BX] ; put physical block no of block C ; in file sought in R1 (AX) C ; mov (r2),r1 / put physical block no of block in file C ; / sought in r1 1044 0B C0 C or ax, ax 1046 75 14 C jnz short mget_7 ; 2f C ; bne 2f / if no block exists 1048 E8 0013 C call alloc C ; jsr r0,alloc / allocate a new block 104B 89 07 C mov word ptr [BX], ax ; R1 C ; mov r1,(r2) / put new block number into proper location in C ; / indirect block 104D 5A C pop dx ; ** ; 24/03/2013 C ; mov (sp)+,r1 / get block number of indirect block 104E 52 C push dx ; ** ; 31/07/2013 104F 50 C push ax ; * ; 24/03/2013, 31/07/2013 (new block number) 1050 8B C2 C mov ax, dx ; 24/03/2013 C ; mov (r2),-(sp) / save block number of new block C ; AX (r1) = physical block number (of indirect block) 1052 E8 07A2 C call wslot C ; jsr r0,wslot C ; AX (r1) = physical block number C ; BX (r5) = pointer to buffer (indirect block) 1055 E8 07B5 C call dskwr C ; AX = r1 = physical block number (of indirect block) C ; jsr r0,dskwr / write newly modified indirect block C ; / back out on disk 1058 58 C pop ax ; * ; 31/07/2013 C ; mov (sp),r1 / restore block number of new block C ; AX (r1) = physical block number of new block 1059 E8 FE9F C call clear C ; jsr r0,clear / clear new block 105C C mget_7: ; 2 105C 5A C pop dx ; ** C ; tst (sp)+ / bump stack pointer C ; AX (r1) = Block number of new block 105D C3 C retn C ; rts r0 C 105E C alloc: C ; 01/08/2013 C ; 21/07/2013 C ; 02/04/2013 C ; 01/04/2013 C ; C ; get a free block and C ; set the corresponding bit in the free storage map C ; C ; INPUTS -> C ; cdev (current device) C ; r2 C ; r3 C ; OUTPUTS -> C ; r1 (physical block number of block assigned) C ; smod, mmod, systm (super block), mount (mountable super block) C ; C ; ((AX = R1)) output C ; (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX)) C C ;mov r2,-(sp) / save r2, r3 on stack C ;mov r3,-(sp) C ;push cx 105E 53 C push bx ; R2 C ;push dx ; R3 C ;mov bx, offset systm ; SuperBlock 105F BB 256A R C mov bx, offset s ; 21/07/2013 C ; mov $systm,r2 / start of inode and free storage map for drum 1062 80 3E 2BD2 R 00 C cmp byte ptr [cdev], 0 C ; tst cdev 1067 76 03 C jna short alloc_1 C ; beq 1f / drum is device 1069 BB 276E R C mov bx, offset mount C ; mov $mount,r2 / disk or tape is device, start of inode and C ; / free storage map 106C C alloc_1: ; 1 106C 8B 07 C mov ax, word ptr [BX] C ; mov (r2)+,r1 / first word contains number of bytes in free C ; / storage map 106E D1 E0 C shl ax, 1 C ; asl r1 / multiply r1 by eight gives C ; number of blocks in device 1070 D1 E0 C shl ax, 1 C ; asl r1 1072 D1 E0 C shl ax, 1 C ; asl r1 1074 8B C8 C mov cx, ax C ;; push cx ;; 01/08/2013 C ; mov r1,-(sp) / save # of blocks in device on stack 1076 33 C0 C xor ax, ax ; 0 C ; clr r1 / r1 contains bit count of free storage map 1078 C alloc_2: ; 1 1078 43 C inc bx ; 18/8/2012 1079 43 C inc bx ; 107A 8B 17 C mov dx, word ptr [BX] C ; mov (r2)+,r3 / word of free storage map in r3 107C 0B D2 C or dx, dx 107E 75 0A C jnz short alloc_3 ; 1f C ; bne 1f / branch if any free blocks in this word 1080 83 C0 10 C add ax, 16 C ; add $16.,r1 1083 3B C1 C cmp ax, cx C ; cmp r1 ,(sp) / have we examined all free storage bytes 1085 72 F1 C jb short alloc_2 C ; blo 1b 1087 E9 F036 C jmp panic C ; jmp panic / found no free storage 108A C alloc_3: ; 1 108A D1 EA C shr dx, 1 C ; asr r3 / find a free block 108C 72 03 C jc short alloc_4 ; 1f C ; bcs 1f / branch when free block found; bit for block k C ; / is in byte k/8 / in bit k (mod 8) 108E 40 C inc ax C ; inc r1 / increment bit count in bit k (mod8) 108F EB F9 C jmp short alloc_3 C ; br 1b 1091 C alloc_4: ; 1: C ;; pop cx ;; 01/08/2013 C ; tst (sp)+ / bump sp C ; 02/04/2013 1091 E8 001E C call free3 C ; jsr r0,3f / have found a free block C ; 21/8/2012 1094 F7 D2 C not dx ; masking bit is '0' and others are '1' 1096 21 17 C and word ptr [BX], dx ;; 0 -> allocated C ; bic r3,(r2) / set bit for this block C ; / i.e. assign block C ; br 2f 1098 EB 06 C jmp short alloc_5 C 109A C free: C ; 01/08/2013 C ; 21/07/2013 C ; 07/04/2013 C ; C ; calculates byte address and bit position for given block number C ; then sets the corresponding bit in the free storage map C ; C ; INPUTS -> C ; r1 - block number for a block structured device C ; cdev - current device C ; OUTPUTS -> C ; free storage map is updated C ; smod is incremented if cdev is root device (fixed disk) C ; mmod is incremented if cdev is a removable disk C ; C ; (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX)) C C ;mov r2,-(sp) / save r2, r3 C ;mov r3,-(sp) C ;push cx 109A 53 C push bx ; R2 C ;push dx ; R3 C 109B E8 0014 C call free3 C ; jsr r0,3f / set up bit mask and word no. C ; / in free storage map for block 109E 09 17 C or word ptr [BX], dx C ; bis r3, (r2) / set free storage block bit; C ; / indicates free block C ; 0 -> allocated, 1 -> free C 10A0 C alloc_5: C ; 07/04/2013 10A0 C free_1: ; 2: C ; pop dx C ; mov (sp)+,r3 / restore r2, r3 10A0 5B C pop bx C ; mov (sp)+,r2 C ; pop cx 10A1 80 3E 2BD2 R 00 C cmp byte ptr [cdev], 0 C ; tst cdev / cdev = 0, block structured, drum; C ; / cdev = 1, mountable device 10A6 77 05 C ja short alloc_6 ; 1f C ; bne 1f C ;mov byte ptr [smod], 1 10A8 FE 06 2C05 R C inc byte ptr [smod] C ; incb smod / set super block modified for drum C ; AX (r1) = block number 10AC C3 C retn C ; rts r0 10AD C free_2: 10AD C alloc_6: ; 1: C ;mov byte ptr [mmod], 1 10AD FE 06 2C06 R C inc byte ptr [mmod] C ; incb mmod C ; / set super block modified for mountable device C ; AX (r1) = block number 10B1 C3 C retn C ; rts r0 10B2 C free3: C ; 01/08/2013 C ; 02/04/2013 C ; C ; free3 is called from 'alloc' and 'free' procedures C ; 10B2 C alloc_free_3: ; 3 10B2 BA 0001 C mov dx, 1 10B5 8B C8 C mov cx, ax C ; mov r1,r2 / block number, k, = 1 10B7 83 E1 0F C and cx, 0Fh ; 0Fh <-- (k) mod 16 C ; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8) 10BA 74 02 C jz short @f C ; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to C ; / (k) mod 8 10BC D3 E2 C shl dx, cl 10BE C @@: 10BE 8B D8 C mov bx, ax C ; mov r1,r2 / divide block number by 16 10C0 D1 EB C shr bx, 1 C ; asr r2 10C2 D1 EB C shr bx, 1 C ; asr r2 10C4 D1 EB C shr bx, 1 C ; asr r2 10C6 D1 EB C shr bx, 1 C ; asr r2 C ; bcc 1f / branch if bit 3 in r1 was 0 i.e., C ; / bit for block is in lower half of word C ; swab r3 / swap bytes in r3; bit in upper half of word in free C ; / storage map 10C8 C alloc_free_4: ; 1 10C8 D1 E3 C shl bx, 1 ; 21/8/2012 C ; asl r2 / multiply block number by 2; r2 = k/8 C ;add bx, offset systm+2 ; SuperBlock+2 10CA 81 C3 256C R C add bx, offset s + 2 ; 21/07/2013 C ; add $systm+2,r2 / address of word of free storage map for drum C ; / with block bit in it 10CE 80 3E 2BD2 R 00 C cmp byte ptr [cdev], 0 C ; tst cdev 10D3 76 04 C jna short alloc_free_5 C ; beq 1f / cdev = 0 indicates device is drum C ;add bx, offset mount - offset systm 10D5 81 C3 0204 C add bx, offset sb1 - offset sb0 ; 21/07/2013 C ; add $mount-systm,r2 / address of word of free storage map for C ; / mountable device with bit of block to be C ; / freed 10D9 C alloc_free_5: ; 1 10D9 C3 C retn C ; rts r0 / return to 'free' C ; 2 C ; .byte 1,2,4,10,20,40,100,200 / masks for bits 0,...,7 C 10DA C iget: C ; 07/08/2013 C ; 31/07/2013 C ; 28/07/2013 C ; 18/07/2013 C ; 17/07/2013 C ; 09/07/2013 (cdev,mdev) C ; 26/04/2013 (mdev) C ; 07/04/2013 C ; C ; get a new i-node whose i-number in r1 and whose device is in cdev C ; C ; ('iget' returns current i-number in r1, if input value of r1 is 0) C ; C ; INPUTS -> C ; ii - current i-number, rootdir C ; cdev - new i-node device C ; idev - current i-node device C ; imod - current i-node modified flag C ; mnti - cross device file i-number C ; r1 - i-numbe rof new i-node C ; mntd - mountable device number C ; C ; OUTPUTS -> C ; cdev, idev, imod, ii, r1 C ; C ; ((AX = R1)) input/output C ; C ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C 10DA 8A 16 2BD2 R C mov dl, byte ptr [cdev] ; 18/07/2013 10DE 8A 36 2BD0 R C mov dh, byte ptr [idev] ; 07/08/2013 C ; 10E2 3B 06 2BCE R C cmp ax, word ptr [ii] C ; cmp r1,ii / r1 = i-number of current file 10E6 75 04 C jne short iget_1 C ; bne 1f 10E8 38 F2 C cmp dl, dh C ; cmp idev,cdev C ; / is device number of i-node = current device 10EA 74 4E C je short @f C ; beq 2f 10EC C iget_1: ; 1: 10EC 32 DB C xor bl, bl 10EE 38 1E 2C04 R C cmp byte ptr [imod], bl ; 0 C ; tstb imod / has i-node of current file C ; / been modified i.e., imod set 10F2 76 1C C jna short iget_2 C ; beq 1f 10F4 88 1E 2C04 R C mov byte ptr [imod], bl ; 0 C ; clrb imod / if it has, C ; / we must write the new i-node out on disk 10F8 50 C push ax C ; mov r1,-(sp) C ;mov dl, byte ptr [cdev] 10F9 52 C push dx C ; mov cdev,-(sp) 10FA A1 2BCE R C mov ax, word ptr [ii] C ; mov ii,r1 C ;mov dh, byte ptr [idev] 10FD 88 36 2BD2 R C mov byte ptr [cdev], dh C ; mov idev,cdev 1101 FE C3 C inc bl ; 1 C ; 31/07/2013 1103 88 1E 2C08 R C mov byte ptr [rw], bl ; 1 == write C ;;28/07/2013 rw -> u.rw C ;;mov byte ptr [u.rw], bl ; 1 == write 1107 E8 0031 C call icalc C ; jsr r0,icalc; 1 110A 5A C pop dx 110B 88 16 2BD2 R C mov byte ptr [cdev], dl C ; mov (sp)+,cdev 110F 58 C pop ax C ; mov (sp)+,r1 1110 C iget_2: ; 1: 1110 23 C0 C and ax, ax C ; tst r1 / is new i-number non zero 1112 74 23 C jz short iget_4 ; 2f C ; beq 2f / branch if r1=0 C C ; mov dl, byte ptr [cdev] 1114 0A D2 C or dl, dl C ; tst cdev / is the current device number non zero C ; / (i.e., device =/ drum) 1116 75 0F C jnz short iget_3 ; 1f C ; bne 1f / branch 1f cdev =/ 0 ;; (cdev != 0) 1118 3B 06 2BFC R C cmp ax, word ptr [mnti] C ; cmp r1,mnti / mnti is the i-number of the cross device C ; / file (root directory of mounted device) 111C 75 09 C jne short iget_3 ; 1f C ; bne 1f C ;mov bl, byte ptr [mntd] 111E FE C2 C inc dl ; move dl, 1 ; 17/07/2013 1120 88 16 2BD2 R C mov byte ptr [cdev], dl ; 17/07/2013 - 09/07/2013 C ; mov mntd,cdev / make mounted device the current device 1124 A1 2C00 R C mov ax, word ptr [rootdir] C ; mov rootdir,r1 1127 C iget_3: ; 1: 1127 A3 2BCE R C mov word ptr [ii], ax C ; mov r1,ii 112A 88 16 2BD0 R C mov byte ptr [idev], dl ; cdev C ; mov cdev,idev 112E 32 DB C xor bl, bl C ; 31/07/2013 1130 88 1E 2C08 R C mov byte ptr [rw], bl ; 0 == read C ;;28/07/2013 rw -> u.rw C ;;mov byte ptr [u.rw], bl ; 0 = read 1134 E8 0004 C call icalc C ; jsr r0,icalc; 0 / read in i-node ii 1137 C iget_4: ; 2: 1137 A1 2BCE R C mov ax, word ptr [ii] C ; mov ii,r1 113A C @@: 113A C3 C retn C ; rts r0 C 113B C icalc: C ; 31/07/2013 C ; 28/07/2013 C ; 17/07/2013 C ; 07/04/2013 C ; C ; calculate physical block number from i-number then C ; read or write that block C ; C ; 'icalc' is called from 'iget' C ; C ; for original unix v1: C ; / i-node i is located in block (i+31.)/16. and begins 32.* C ; / (i+31)mod16 bytes from its start C ; C ; for retro unix 8086 v1: C ; i-node is located in block (i+47)/16 and C ; begins 32*(i+47) mod 16 bytes from its start C ; C ; INPUTS -> C ; r1 - i-number of i-node C ; C ; OUTPUTS -> C ; inode r/w C ; C ; ((AX = R1)) input C ; C ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) C ; ((Modified registers: AX, DX, CX, BX, SI, DI, BP)) C ; C 113B 83 C0 2F C add ax, 47 ; add 47 to inode number C ; add $31.,r1 / add 31. to i-number 113E 50 C push ax C ; mov r1,-(sp) / save i+31. on stack 113F D1 E8 C shr ax, 1 C ; asr r1 / divide by 16. 1141 D1 E8 C shr ax, 1 C ; asr r1 1143 D1 E8 C shr ax, 1 C ; asr r1 1145 D1 E8 C shr ax, 1 C ; asr r1 / r1 contains block number of block C ; / in which i-node exists 1147 E8 0672 C call dskrd C ; jsr r0,dskrd / read in block containing i-node i. C ; 31/07/2013 114A 80 3E 2C08 R 00 C cmp byte ptr [rw], 0 ; Retro Unix 8086 v1 feature ! C ;; 28/07/2013 rw -> u.rw C ;;cmp byte ptr [u.rw], 0 ; Retro Unix 8086 v1 feature ! C ; tst (r0) 114F 76 03 C jna short icalc_1 C ; beq 1f / branch to wslot when argument C ; / in icalc call = 1 C ; AX = r1 = block number 1151 E8 06A3 C call wslot C ; jsr r0,wslot / set up data buffer for write C ; / (will be same buffer as dskrd got) C ; BX = r5 points to first word in data area for this block 1154 C icalc_1: ; 1: 1154 5A C pop dx 1155 83 E2 0F C and dx, 0Fh ; (i+47) mod 16 C ; bic $!17,(sp) / zero all but last 4 bits; C ; / gives (i+31.) mod 16 1158 D1 E2 C shl dx, 1 115A D1 E2 C shl dx, 1 115C D1 E2 C shl dx, 1 115E D1 E2 C shl dx, 1 1160 D1 E2 C shl dx, 1 C ; DX = 32 * ((i+47) mod 16) 1162 8B F3 C mov si, bx ; bx points 1st word of the buffer 1164 03 F2 C add si, dx ; dx is inode offset in the buffer C ; SI (r5) points to first word in i-node i. C ; mov (sp)+,mq / calculate offset in data buffer; C ; / 32.*(i+31.)mod16 C ; mov $5,lsh / for i-node i. C ; add mq,r5 / r5 points to first word in i-node i. C ;mov di, offset inode 1166 BF 296E R C mov di, offset i ; 17/07/2013 C ; mov $inode,r1 / inode is address of first word C ; / of current i-node 1169 B9 0010 C mov cx, 16 ; CX = r3 C ; mov $16.,r3 C ; 31/07/2013 116C 38 2E 2C08 R C cmp byte ptr [rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! C ;;28/07/2013 rw -> u.rw C ;;cmp byte ptr [u.rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! C ; tst (r0)+ / branch to 2f when argument in icalc call = 0 1170 76 08 C jna short icalc_3 C ; beq 2f / r0 now contains proper return address C ; / for rts r0 1172 C icalc_2: ; 1: 1172 87 F7 C xchg si, di C ; over write old i-node (in buffer to be written) 1174 F3/ A5 C rep movsw C ; mov (r1)+,(r5)+ / over write old i-node C ; dec r3 C ; bgt 1b 1176 E8 0694 C call dskwr C ; jsr r0,dskwr / write inode out on device 1179 C3 C retn C ; rts r0 117A C icalc_3: ; 2: C ; copy new i-node into inode area of (core) memory 117A F3/ A5 C rep movsw C ; mov (r5)+,(r1)+ / read new i-node into C ; / "inode" area of core C ; dec r3 C ; bgt 2b 117C C3 C retn C ; rts r0 C 117D C access: C ; 29/04/2013 (AX register preserved) C ; 24/04/2013 C ; check whether user is owner of file or user has read or write C ; permission (based on i.flgs). C ; C ; INPUTS -> C ; r1 - i-number of file C ; u.uid C ; arg0 -> (owner flag mask) C ; Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) C ; OUTPUTS -> C ; inode (or jump to error) C ; C ; ((AX = R1)) input/output C ; C ; ((Modified registers: CX, BX, SI, DI, BP)) C ; 117D 52 C push dx ; flags 117E E8 FF59 C call iget C ; jsr r0,iget / read in i-node for current directory C ; / (i-number passed in r1) 1181 8B 0E 296E R C mov cx, word ptr [i.flgs] C ; mov i.flgs,r2 1185 5A C pop dx 1186 8A 36 3904 R C mov dh, byte ptr [u.uid_] ; 29/04/2013 al -> dh 118A 3A 36 2971 R C cmp dh, byte ptr [i.uid] ; 29/04/2013 C ; cmpb i.uid,u.uid / is user same as owner of file 118E 75 04 C jne short access_1 C ; bne 1f / no, then branch 1190 D0 E9 C shr cl, 1 C ; asrb r2 / shift owner read write bits into non owner C ; / read/write bits 1192 D0 E9 C shr cl, 1 C ; asrb r2 1194 C access_1: ; 1: 1194 22 CA C and cl, dl C ; bit r2,(r0)+ / test read-write flags against argument C ; / in access call 1196 75 07 C jnz short access_2 C ; bne 1f 1198 0A F6 C or dh, dh ; 29/04/2013 al -> dh C ; tstb u.uid 119A 74 03 E9 F15D C jnz error C ; beq 1f C ; jmp error 119F C access_2: ; 1: 119F C3 C retn C ; rts r0 C 11A0 C setimod: C ; 31/07/2013 C ; 09/04/2013 C ; C ; 'setimod' sets byte at location 'imod' to 1; thus indicating that C ; the inode has been modified. Also puts the time of modification C ; into the inode. C ; C ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX, BX)) C ; C C ; push dx 11A0 50 C push ax C 11A1 C6 06 2C04 R 01 C mov byte ptr [imod], 1 C ; movb $1,imod / set current i-node modified bytes C ; Erdogan Tan 14-7-2012 11A6 E8 11E4 C call epoch C ; mov s.time,i.mtim C ; / put present time into file modified time C ; mov s.time+2,i.mtim+2 C 11A9 A3 2988 R C mov word ptr [i.mtim], ax 11AC 89 16 298A R C mov word ptr [i.mtim]+2, dx C C ; Retro UNIX 8086 v1 modification ! 11B0 8B 0E 2984 R C mov cx, word ptr [i.ctim] 11B4 8B 1E 2986 R C mov bx, word ptr [i.ctim]+2 C 11B8 85 CB C test cx, bx 11BA 75 07 C jnz short @f C 11BC A3 2984 R C mov word ptr [i.ctim], ax 11BF 89 16 2986 R C mov word ptr [i.ctim]+2, dx 11C3 C @@: ; 31/07/2013 11C3 58 C pop ax C ;pop dx C 11C4 C3 C retn C ; rts r0 C 11C5 C itrunc: C ; 01/08/2013 C ; 23/04/2013 C ; C ; 'itrunc' truncates a file whose i-number is given in r1 C ; to zero length. C ; C ; INPUTS -> C ; r1 - i-number of i-node C ; i.dskp - pointer to contents or indirect block in an i-node C ; i.flgs - large file flag C ; i.size - size of file C ; C ; OUTPUTS -> C ; i.flgs - large file flag is cleared C ; i.size - set to 0 C ; i.dskp .. i.dskp+16 - entire list is cleared C ; setimod - set to indicate i-node has been modified C ; r1 - i-number of i-node C ; C ; ((AX = R1)) input/output C ; C ; (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C 11C5 E8 FF12 C call iget C ; jsr r0,iget 11C8 BE 2974 R C mov si, offset i.dskp C ; mov $i.dskp,r2 / address of block pointers in r2 11CB C itrunc_1: ; 1: 11CB AD C lodsw C ; mov (r2)+,r1 / move physical block number into r1 11CC 0B C0 C or ax, ax 11CE 74 29 C jz short itrunc_5 C ; beq 5f 11D0 56 C push si C ; mov r2,-(sp) 11D1 F7 06 296E R 1000 C test word ptr [i.flgs], 1000h C ; bit $10000,i.flgs / test large file bit? 11D7 74 1C C jz short itrunc_4 C ; beq 4f / if clear, branch 11D9 50 C push ax C ; mov r1,-(sp) / save block number of indirect block 11DA E8 05DF C call dskrd C ; jsr r0,dskrd / read in block, 1st data word C ; / pointed to by r5 C ; BX = r5 = Buffer data address (the 1st word) 11DD B9 0100 C mov cx, 256 C ; mov $256.,r3 / move word count into r3 11E0 8B F3 C mov si, bx 11E2 C itrunc_2: ; 2: 11E2 AD C lodsw C ; mov (r5)+,r1 / put 1st data word in r1; C ; / physical block number 11E3 23 C0 C and ax, ax 11E5 74 05 C jz short itrunc_3 C ; beq 3f / branch if zero 11E7 51 C push cx C ; mov r3,-(sp) / save r3, r5 on stack C ;push si C ; mov r5,-(sp) 11E8 E8 FEAF C call free C ; jsr r0,free / free block in free storage map C ;pop si C ; mov(sp)+,r5 11EB 59 C pop cx C ; mov (sp)+,r3 11EC C itrunc_3: ; 3: 11EC E2 F4 C loop itrunc_2 C ; dec r3 / decrement word count C ; bgt 2b / branch if positive 11EE 58 C pop ax C ; mov (sp)+,r1 / put physical block number of C ; / indirect block C ; 01/08/2013 11EF 81 26 296E R EFFF C and word ptr [i.flgs], 0EFFFh ; 1110111111111111b 11F5 C itrunc_4: ; 4: 11F5 E8 FEA2 C call free C ; jsr r0,free / free indirect block 11F8 5E C pop si C ; mov (sp)+,r2 11F9 C itrunc_5: ; 5: 11F9 81 FE 2984 R C cmp si, offset i.dskp+16 C ; cmp r2,$i.dskp+16. 11FD 72 CC C jb short itrunc_1 C ; bne 1b / branch until all i.dskp entries check C ; 01/08/2013 C ;and word ptr [i.flgs], 0EFFFh ; 1110111111111111b C ; bic $10000,i.flgs / clear large file bit 11FF BF 2974 R C mov di, offset i.dskp 1202 B9 0008 C mov cx, 8 1205 33 C0 C xor ax, ax 1207 A3 2972 R C mov word ptr [i.size_], ax ; 0 C ; clr i.size / zero file size 120A F3/ AB C rep stosw C ; jsr r0,copyz; i.dskp; i.dskp+16. C ; / zero block pointers 120C E8 FF91 C call setimod C ; jsr r0,setimod / set i-node modified flag 120F A1 2BCE R C mov ax, word ptr [ii] C ; mov ii,r1 1212 C3 C retn C ; rts r0 C 1213 C imap: C ; 26/04/2013 C ; 'imap' finds the byte in core (superblock) containing C ; allocation bit for an i-node whose number in r1. C ; C ; INPUTS -> C ; r1 - contains an i-number C ; fsp - start of table containing open files C ; C ; OUTPUTS -> C ; r2 - byte address of byte with the allocation bit C ; mq - a mask to locate the bit position. C ; (a 1 is in calculated bit posisiton) C ; C ; ((AX = R1)) input/output C ; ((DL/DX = MQ)) output C ; ((BX = R2)) output C ; C ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, CX, BX, SI)) C ; C ; / get the byte that has the allocation bit for C ; / the i-number contained in r1 C ;mov dx, 1 1213 B2 01 C mov dl, 1 C ; mov $1,mq / put 1 in the mq 1215 8B D8 C mov bx, ax C ; mov r1,r2 / r2 now has i-number whose byte C ; / in the map we must find 1217 83 EB 29 C sub bx, 41 C ; sub $41.,r2 / r2 has i-41 121A 8A CB C mov cl, bl C ; mov r2,r3 / r3 has i-41 121C 80 E1 07 C and cl, 7 C ; bic $!7,r3 / r3 has (i-41) mod 8 to get C ; / the bit position 121F 74 02 C jz short @f C ;shl dx, cl 1221 D2 E2 C shl dl, cl C ; mov r3,lsh / move the 1 over (i-41) mod 8 positions 1223 C @@: ; / to the left to mask the correct bit 1223 D1 EB C shr bx, 1 C ; asr r2 1225 D1 EB C shr bx, 1 C ; asr r2 1227 D1 EB C shr bx, 1 C ; asr r2 / r2 has (i-41) base 8 of the byte number C ; / from the start of the map C ; mov r2,-(sp) / put (i-41) base 8 on the stack C ;mov si, offset systm 1229 BE 256A R C mov si, offset s ; 21/07/2013 C ; mov $systm,r2 / r2 points to the in-core image of C ; / the super block for drum C ;cmp word ptr [cdev], 0 122C 80 3E 2BD2 R 00 C cmp byte ptr [cdev], 0 C ; tst cdev / is the device the disk 1231 76 04 C jna short @f C ; beq 1f / yes C ;add si, offset mount - offset systm 1233 81 C6 0204 C add si, offset mount - offset s ; 21/07/2013 C ; add $mount-systm,r2 / for mounted device, C ; / r2 points to 1st word of its super block 1237 C @@: ; 1: 1237 03 1C C add bx, word ptr [SI] ;; add free map size to si C ; add (r2)+,(sp) / get byte address of allocation bit 1239 03 DE C add bx, si C ; add (sp)+,r2 / ? 123B 83 C3 04 C add bx, 4 ;; inode map offset in superblock C ;; (2 + free map size + 2) C ; add $2,r2 / ? C ; DL/DX (MQ) has a 1 in the calculated bit position C ; BX (R2) has byte address of the byte with allocation bit 123E C3 C retn C ; rts r0 C include u6.asm ; u6.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U6.ASM (include u6.asm) //// UNIX v1 -> u6.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 16/07/2015 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 23/07/2014 rtty C ; 07/07/2014 wtty C ; 27/06/2014 wtty (putc) C ; 19/06/2014 rtty, wtty C ; 03/06/2014 (rtty/wtty check is ok) C ; 02/06/2014 wtty C ; 26/05/2014 wtty C ; 15/04/2014 rtty, wtty ('getc' and 'putc' error return modifications) C ; 14/04/2014 wtty C ; 23/02/2014 rtty C ; 01/02/2014 rtty C ; 13/01/2014 rtty, wtty C ; 06/12/2013 rtty, wtty (major modification: p.ttyc, u.ttyp) C ; 10/10/2013 rtty, wtty (tty read lock & tty write lock are removed) C ; 05/10/2013 rtty, wtty C ; 29/09/2013 rtty C ; 20/09/2013 rtty & passc (tty read lock) C ; wtty & cpass (tty write lock), dskw, rmem, wmem C ; 13/09/2013 rtty C ; 26/08/2013 wtty C ; 14/08/2013 rtty, rcvt, wtty, xmtt, cpass C ; 03/08/2013 dskr (namei_r), dskw (mkdir_w) C ; 01/08/2013 dskw (mkdir_w) C ; 31/07/2013 dskr (namei_r), writei C ; 29/07/2013 rtty, idle C ; 28/07/2013 rtty, rcvt, wtty, u.namei_r C ; 26/07/2013 readi C ; 16/07/2013 rtty, rcvt, chk_ttyp, rmem, wmem modifications C ; 27/05/2013 chk_ttyp C ; 21/05/2013 chk_ttyp, chk_com_o C ; 20/05/2013 chk_ttyp C ; 15/05/2013 rcvt, xmtt, COM1, COM2 C ; 26/04/2013 readi, writei modifications C ; 14/03/2013 -> writei C ; 12/03/2013 -> writei, u.segment C C ; 11/03/2013 C 123F C readi: C ; 31/07/2013 C ; 26/07/2013 (namei_r check in 'dskr') C ; 15/05/2013 COM1, COM2 (serial ports) modification C ; 26/04/2013 (modification depending on 'dsrkd' modification) C ; 12/03/2013 -> u.segment C ; 11/03/2013 C ; Reads from an inode whose number in R1 C ; C ; INPUTS -> C ; r1 - inode number C ; u.count - byte count user desires C ; u.base - points to user buffer C ; u.fofp - points to word with current file offset C ; OUTPUTS -> C ; u.count - cleared C ; u.nread - accumulates total bytes passed back C ; C ; ((AX = R1)) input/output C ; (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, BX, CX, SI, DI, BP)) C 123F 33 D2 C xor dx, dx ; 0 1241 89 16 38EA R C mov word ptr [u.nread], dx ; 0 C ; clr u.nread / accumulates number of bytes transmitted 1245 39 16 38E8 R C cmp word ptr [u.count], dx ; 0 C ; tst u.count / is number of bytes to be read greater than 0 1249 77 01 C ja short @f ; 1f C ; bgt 1f / yes, branch 124B C3 C retn C ; rts r0 / no, nothing to read; return to caller 124C C @@: ; 1: C ; mov r1,-(sp) / save i-number on stack 124C 83 F8 28 C cmp ax, 40 C ; cmp r1,$40. / want to read a special file C ; / (i-nodes 1,...,40 are for special files) 124F 76 03 E9 0081 C ja dskr C ; ble 1f / yes, branch C ; jmp dskr / no, jmp to dskr; C ; / read file with i-node number (r1) C ; / starting at byte ((u.fofp)), read in u.count bytes 1254 50 C push ax ; because subroutines will jump to 'ret_' 1255 C @@: ; 1: 1255 8B D8 C mov bx, ax 1257 D1 E3 C shl bx, 1 C ; asl r1 / multiply inode number by 2 1259 81 C3 125D R C add bx, offset @f - 2 125D FF 27 C jmp word ptr [BX] C ; jmp *1f-2(r1) 125F C @@: ; 1: 125F 1285 R C dw offset rtty ; tty, AX = 1 (runix) C ;rtty / tty; r1=2 C ;rppt / ppt; r1=4 1261 12C1 R C dw offset rmem ; mem, AX = 2 (runix) C ;rmem / mem; r1=6 C ;rrf0 / rf0 C ;rrk0 / rk0 C ;rtap / tap0 C ;rtap / tap1 C ;rtap / tap2 C ;rtap / tap3 C ;rtap / tap4 C ;rtap / tap5 C ;rtap / tap6 C ;rtap / tap7 1263 16DD R C dw offset rfd ; fd0, AX = 3 (runix only) 1265 16DD R C dw offset rfd ; fd1, AX = 4 (runix only) 1267 16E9 R C dw offset rhd ; hd0, AX = 5 (runix only) 1269 16E9 R C dw offset rhd ; hd1, AX = 6 (runix only) 126B 16E9 R C dw offset rhd ; hd2, AX = 7 (runix only) 126D 16E9 R C dw offset rhd ; hd3, AX = 8 (runix only) 126F 12D2 R C dw offset rlpr ; lpr, AX = 9 (invalid, write only device !?) 1271 12BD R C dw offset rcvt ; tty0, AX = 10 (runix) C ;rcvt / tty0 1273 12BD R C dw offset rcvt ; tty1, AX = 11 (runix) C ;rcvt / tty1 1275 12BD R C dw offset rcvt ; tty2, AX = 12 (runix) C ;rcvt / tty2 1277 12BD R C dw offset rcvt ; tty3, AX = 13 (runix) C ;rcvt / tty3 1279 12BD R C dw offset rcvt ; tty4, AX = 14 (runix) C ;rcvt / tty4 127B 12BD R C dw offset rcvt ; tty5, AX = 15 (runix) C ;rcvt / tty5 127D 12BD R C dw offset rcvt ; tty6, AX = 16 (runix) C ;rcvt / tty6 127F 12BD R C dw offset rcvt ; tty7, AX = 17 (runix) C ;rcvt / tty7 1281 12BD R C dw offset rcvt ; COM1, AX = 18 (runix only) C ;rcrd / crd 1283 12BD R C dw offset rcvt ; COM2, AX = 19 (runix only) C 1285 C rtty: ; / read from console tty C ; 16/07/2015 (Only 1 byte is read, by ignoring byte count!) C ; WHAT FOR: Every character from Keyboard input C ; must be written immediate on video page (screen) C ; when it is required. C ; 19/06/2014 C ; 15/04/2014 ('getc' error return modifications) C ; 23/02/2014 C ; 01/02/2014 C ; 13/01/2014 C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 10/10/2013 C ; 05/10/2013 C ; 29/09/2013 C ; 20/09/2013 (tty read lock) C ; 13/09/2013 C ; 14/08/2013 C ; 28/07/2013 u.ttyn C ; 16/07/2013 C ; 16/07/2013 'getc' modifications C ; 20/05/2013 C ; 15/05/2013 'getc' error return for serial ports C ; 14/05/2013 'getc' modifications instead of INT 16h C ; 11/03/2013 C ; Console tty buffer is PC keyboard buffer C ; and keyboard-keystroke handling is different than original C ; unix (PDP-11) here. TTY/Keyboard procedures here are changed C ; according to IBM PC compatible ROM BIOS keyboard functions. C ; C ; 06/12/2013 1285 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 1289 32 FF C xor bh, bh 128B 8A 87 29ED R C mov al, byte ptr [BX]+p.ttyc-1 ; current/console tty 128F C rttys: C ; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of C ; / of the control and status block C ; tst 2(r5) / for the console tty; this word points to the console C ; / tty buffer C ; 28/07/2013 128F A2 390A R C mov byte ptr [u.ttyn], al C ; 06/12/2013 C ;; 13/01/2014 C ;;cmp al, 7 C ;;ja short rtty_nc 1292 FE C0 C inc al 1294 A2 38EE R C mov byte ptr [u.ttyp], al ; tty number + 1 1297 C rtty_nc: ; 01/02/2014 C ; 29/09/2013 1297 B9 000A C mov cx, 10 129A C @@: ; 01/02/2014 129A 51 C push cx ; 29/09/2013 C ; byte ptr [u.ttyn] = tty number (0 to 9) 129B B0 01 C mov al, 1 129D E8 076B C call getc 12A0 59 C pop cx ; 29/09/2013 C ; 28/07/2013 C ; byte ptr [u.ttyn] = tty number C ;; 15/04/2014 C ;;jc error ; 15/05/2013 (COM1 or COM2 serial port error) C ;mov ah, 01h ; Test for available key, ZF=1 if none, ZF=0 and C ;int 16h ; AX contains next key code if key available. 12A1 75 10 C jnz short @f C ; bne 1f / 2nd word of console tty buffer contains number C ; / of chars. Is this number non-zero? C ;dec cx C ;jnz short rtty_idle 12A3 E2 09 C loop rtty_idle ; 01/02/2014 C ; 05/10/2013 12A5 8A 26 390A R C mov ah, byte ptr [u.ttyn] C ; 29/09/2013 12A9 E8 FCCB C call sleep C ; jsr r0,canon; ttych / if 0, call 'canon' to get a line C ; / (120 chars.) C ;byte ptr [u.ttyn] = tty number (0 to 9) 12AC EB E9 C jmp short rtty_nc ; 01/02/2014 C 12AE C rtty_idle: C ; 16/07/2013 C ;; mov cx, word ptr [s.idlet]+2 ;; 29/07/2013 12AE E8 FC41 C call idle C ; 29/09/2013 12B1 EB E7 C jmp short @b ; 01/02/2014 C ;1: C ;rtty_nc: C ;mov al, 1 C ;call getc C ;mov ah, 01h ; Test for available key, ZF=1 if none, ZF=0 and C ;int 16h ; AX contains next key code if key available. C ;jz short ret_ C ; tst 2(r5) / is the number of characters zero C ; beq ret1 / yes, return to caller via 'ret1' C ; movb *4(r5),r1 / no, put character in r1 C ; inc 4(r5) / 3rd word of console tty buffer points to byte which C ; / contains the next char. C ; dec 2(r5) / decrement the character count 12B3 C @@: 12B3 32 C0 C xor al, al 12B5 E8 0753 C call getc C ;; 23/07/0014 C ;;jc error ; 15/05/2013 (COM1 or COM2 serial port error) C ; AL = ascii code of the character C ;xor ah, ah C ;int 16h C ; 12B8 E8 0061 C call passc C ; jsr r0,passc / move the character to core (user) C ;; 16/07/2015 C ; 19/06/2014 C ;;jnz short rtty_nc C ; 23/07/2014 C ;jmp short ret_ 12BB 58 C pop ax 12BC C3 C retn C C ;ret1: C ; jmp ret / return to caller via 'ret' C 12BD C rcvt: ; < receive/read character from tty > C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 28/07/2013 al = tty number (ah -> al) C ; 16/07/2013 rttys C ; 21/05/2013 owner checking for COM/serial ports C ; 15/05/2013 C ; C ; Retro UNIX 8086 v1 modification ! C ; C ; In original UNIX v1, 'rcvt' routine C ; (exactly different than this one) C ; was in 'u9.s' file. C ; 12BD 2C 0A C sub al, 10 C ; AL = tty number (0 to 9), (COM1=8, COM2=9) C ; 16/07/2013 C ; 21/05/2013 12BF EB CE C jmp short rttys C C ;rppt: / read paper tape C ; jsr r0,pptic / gets next character in clist for ppt input and C ; / places C ; br ret / it in r1; if there 1s no problem with reader, it C ; / also enables read bit in prs C ; jsr r0,passc / place character in users buffer area C ; br rppt C 12C1 C rmem: ; / transfer characters from memory to a user area of core C ; 16/07/2015 12C1 8B 36 38DE R C mov si, word ptr [u.fofp] 12C5 C @@: 12C5 8B 1C C mov bx, word ptr [SI] C ; mov *u.fofp,r1 / save file offset which points to the char C ; / to be transferred to user 12C7 FF 04 C inc word ptr [SI] ; 16/07/2013 C ; inc *u.fofp / increment file offset to point to 'next' C ; / char in memory file 12C9 8A 07 C mov al, byte ptr [BX] C ; movb (r1),r1 / get character from memory file, C ; / put it in r1 12CB E8 004E C call passc ; jsr r0,passc / move this character to C ; / the next byte of the users core area C ; 20/09/2013 C ;jmp short @b C ; br rmem / continue 12CE 75 F5 C jnz short @b C ; 12D0 C ret_: 12D0 58 C pop ax 12D1 C3 C retn C 12D2 C rlpr: C ;1: C ;rcrd: 12D2 E9 F027 C jmp error C ;jmp error / see 'error' routine C 12D5 C dskr: C ; 03/08/2013 C ; 31/07/2013 C ; 26/07/2013 (namei_r check) 12D5 50 C push ax ; 26/04/2013 C ; mov (sp),r1 / i-number in r1 C ; AX = i-number 12D6 E8 FE01 C call iget C ; jsr r0,iget / get i-node (r1) into i-node section of core 12D9 8B 16 2972 R C mov dx, word ptr [i.size_] C ; mov i.size,r2 / file size in bytes in r2 12DD 8B 1E 38DE R C mov bx, word ptr [u.fofp] 12E1 2B 17 C sub dx, word ptr [BX] C ; sub *u.fofp,r2 / subtract file offset 12E3 76 EB C jna short ret_ C ; blos ret 12E5 3B 16 38E8 R C cmp dx, word ptr [u.count] C ; cmp r2,u.count / are enough bytes left in file C ; / to carry out read 12E9 73 04 C jnb short dskr_1 C ; bhis 1f 12EB 89 16 38E8 R C mov word ptr [u.count], dx C ; mov r2,u.count / no, just read to end of file 12EF C dskr_1: ; 1: C ; AX = i-number 12EF E8 FCD8 C call mget C ; jsr r0,mget / returns physical block number of block C ; / in file where offset points C ; AX = physical block number 12F2 E8 04C7 C call dskrd C ; jsr r0,dskrd / read in block, r5 points to C ; / 1st word of data in buffer C ; BX (r5) = system (I/O) buffer address 12F5 E8 0155 C call sioreg C ; jsr r0,sioreg 12F8 87 F7 C xchg si, di C ; DI = file (user data) offset C ; SI = sector (I/O) buffer offset C ; CX = byte count C ; 03/08/2013 12FA 80 3E 2C09 R 00 C cmp byte ptr [namei_r], 0 C ;;28/07/2013 namei_r -> u.namei_r C ; 26/07/2013 C ;;dec byte ptr [u.namei_r] ; the caller is 'namei' sign (=1) 12FF 76 04 C jna short dskr_2 ; zf=0 -> the caller is 'namei' 1301 F3/ A4 C rep movsb 1303 EB 0B C jmp short dskr_3 1305 C dskr_2: C ;;28/07/2013 C ; 26/07/2013 C ;;inc byte ptr [u.namei_r] ; (=0) 1305 A1 3908 R C mov ax, word ptr [u.segmnt] ; Retro Unix 8086 v1 feature only ! 1308 8E C0 C mov es, ax ; Retro Unix 8086 v1 feature: ES = user segment ! C ; 2: 130A F3/ A4 C rep movsb C ; movb (r2)+,(r1)+ / move data from buffer into working core C ; / starting at u.base C ; dec r3 C ; bne 2b / branch until proper number of bytes are transferred 130C 8C D8 C mov ax, ds 130E 8E C0 C mov es, ax 1310 C dskr_3: C ; 03/08/2013 1310 58 C pop ax 1311 39 0E 38E8 R C cmp word ptr [u.count], cx ; 0 C ; tst u.count / all bytes read off disk C ; bne dskr 1315 77 BE C ja short dskr 1317 88 0E 2C09 R C mov byte ptr [namei_r], cl ; 0 131B C3 C retn C ;jna short ret_ C ; br ret C ;pop ax ; 26/04/2013 (i-node number) C ;jmp short dskr C 131C C passc: 131C 8B 1E 3908 R C mov bx, word ptr [u.segmnt] ; Retro Unix 8086 v1 feature only ! 1320 8E C3 C mov es, bx ; Retro Unix 8086 v1 feature: ES = user segment ! C 1322 8B 1E 38E6 R C mov bx, word ptr [u.base] 1326 26: 88 07 C mov byte ptr ES:[BX], al C ; movb r1,*u.base / move a character to the next byte of the C ; / users buffer C 1329 8C DB C mov bx, ds ; Retro Unix 8086 v1 feature: DS = system segment ! 132B 8E C3 C mov es, bx ; Retro Unix 8086 v1 feature: ES = system segment ! C 132D FF 06 38E6 R C inc word ptr [u.base] C ; inc u.base / increment the pointer to point to C ; / the next byte in users buffer 1331 FF 06 38EA R C inc word ptr [u.nread] C ; inc u.nread / increment the number of bytes read 1335 FF 0E 38E8 R C dec word ptr [u.count] C ; dec u.count / decrement the number of bytes to be read C ; 20/09/2013 (;;) 1339 C3 C retn C ;;jnz short @f C ; bne 1f / any more bytes to read?; yes, branch C ;;pop ax C ;; ; mov (sp)+,r0 / no, do a non-local return to the caller of C ; / 'readi' by: C ;;ret_: ;/ (1) pop the return address off the stack into r0 C ;; pop ax C ; mov (sp)+,r1 / (2) pop the i-number off the stack into r1 C ;;@@: ;1: C ; clr *$ps / clear processor status C ;; retn C ; rts r0 / return to address currently on top of stack C 133A C writei: C ; 31/07/2013 C ; 15/05/2013 COM1, COM2 (serial ports) modification C ; 26/04/2013 C ; 14/03/2013 wslot, sioreg C ; 12/03/2013 C ; Write data to file with inode number in R1 C ; C ; INPUTS -> C ; r1 - inode number C ; u.count - byte count to be written C ; u.base - points to user buffer C ; u.fofp - points to word with current file offset C ; OUTPUTS -> C ; u.count - cleared C ; u.nread - accumulates total bytes passed back C ; ((AX = R1)) C ; (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM) C ; ((Modified registers: DX, BX, CX, SI, DI, BP)) C 133A 33 C9 C xor cx, cx 133C 89 0E 38EA R C mov word ptr [u.nread], cx ; 0 C ; clr u.nread / clear the number of bytes transmitted during C ; / read or write calls 1340 39 0E 38E8 R C cmp word ptr [u.count], cx C ; ; tst u.count / test the byte count specified by the user 1344 77 01 C ja short @f ; 1f C ; bgt 1f / any bytes to output; yes, branch 1346 C3 C retn C ; ; rts r0 / no, return - no writing to do 1347 C @@: ;1: C ; mov r1 ,-(sp) / save the i-node number on the stack 1347 83 F8 28 C cmp ax, 40 C ; cmp r1,$40. C ; / does the i-node number indicate a special file? 134A 77 7A C ja dskw C ; bgt dskw / no, branch to standard file output C ; 134C 50 C push ax ; because subroutines will jump to 'ret_' 134D 8B D8 C mov bx, ax 134F D1 E3 C shl bx, 1 C ; asl r1 / yes, calculate the index into the special file 1351 81 C3 1355 R C add bx, offset @f - 2 1355 FF 27 C jmp word ptr [BX] C ; jmp *1f-2(r1) C ; / jump table and jump to the appropriate routine 1357 C @@: ;1: 1357 137D R C dw offset wtty ; tty, AX = 1 (runix) C ;wtty / tty; r1=2 C ;wppt / ppt; r1=4 1359 13B5 R C dw offset wmem ; mem, AX = 2 (runix) C ;wmem / mem; r1=6 C ;wrf0 / rf0 C ;wrk0 / rk0 C ;wtap / tap0 C ;wtap / tap1 C ;wtap / tap2 C ;wtap / tap3 C ;wtap / tap4 C ;wtap / tap5 C ;wtap / tap6 C ;wtap / tap7 135B 16E3 R C dw offset wfd ; fd0, AX = 3 (runix only) 135D 16E3 R C dw offset wfd ; fd1, AX = 4 (runix only) 135F 16EF R C dw offset whd ; hd0, AX = 5 (runix only) 1361 16EF R C dw offset whd ; hd1, AX = 6 (runix only) 1363 16EF R C dw offset whd ; hd2, AX = 7 (runix only) 1365 16EF R C dw offset whd ; hd3, AX = 8 (runix only) 1367 13B2 R C dw offset wlpr ; lpr, AX = 9 (runix) 1369 13AC R C dw offset xmtt ; tty0, AX = 10 (runix) C ;xmtt / tty0 136B 13AC R C dw offset xmtt ; tty1, AX = 11 (runix) C ;xmtt / tty1 136D 13AC R C dw offset xmtt ; tty2, AX = 12 (runix) C ;xmtt / tty2 136F 13AC R C dw offset xmtt ; tty3, AX = 13 (runix) C ;xmtt / tty3 1371 13AC R C dw offset xmtt ; tty4, AX = 14 (runix) C ;xmtt / tty4 1373 13AC R C dw offset xmtt ; tty5, AX = 15 (runix) C ;xmtt / tty5 1375 13AC R C dw offset xmtt ; tty6, AX = 16 (runix) C ;xmtt / tty6 1377 13AC R C dw offset xmtt ; tty7, AX = 17 (runix) C ;xmtt / tty7 1379 13AC R C dw offset xmtt ; COM1, AX = 18 (runix only) C ; / wlpr / lpr 137B 13AC R C dw offset xmtt ; COM2, AX = 19 (runix only) C 137D C wtty: ; write to console tty (write to screen) C ; 07/07/2014 C ; 27/06/2014 C ; 19/06/2014 C ; 02/06/2014 C ; 26/05/2014 (putc_eot, putc_n, sleep bugfix) C ; 15/04/2014 ('putc' error return modification) C ; 14/04/2014 (serial port modification) C ; 13/01/2014 C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 10/10/2013 C ; 05/10/2013 C ; 20/09/2013 (tty write lock) C ; 13/09/2013 C ; 26/08/2013 C ; 14/08/2013 C ; 28/07/2013 u.ttyn C ; 21/05/2013 owner checking C ; 15/05/2013 'mov ah, byte ptr [ptty]', wtty_nc C ; 14/05/2013 'putc' modifications instead of INT 10h C ; 12/03/2013 C ; Console tty output is on on current video page C ; Console tty character output procedure is changed here C ; acconding to IBM PC compatible ROM BIOS video (text mode) functions. C ; C ; 06/12/2013 137D 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 1381 32 FF C xor bh, bh 1383 8A A7 29ED R C mov ah, byte ptr [BX]+p.ttyc-1 ; current/console tty 1387 8A C4 C mov al, ah ; 07/07/2014 1389 C wttys: ; C ; 10/10/2013 1389 88 26 390A R C mov byte ptr [u.ttyn], ah C ; 06/12/2013 C ;; 13/01/2014 C ;;cmp ah, 7 C ;;ja short @f C ;mov al, ah 138D FE C0 C inc al 138F A2 38EF R C mov byte ptr [u.ttyp]+1, al ; tty number + 1 C ;;@@: ; 26/08/2013 1392 C wtty_nc: ; 15/05/2013 C ; AH = [u.ttyn] = tty number ; 28/07/2013 1392 E8 0093 C call cpass C ; jsr r0,cpass / get next character from user buffer area; if C ; / none go to return address in syswrite C ; tst r1 / is character = null C ; beq wtty / yes, get next character C ; 10/10/2013 1395 74 13 C jz short wret C ;1 : C ;mov $240,*$ps / no, set processor priority to five C ;cmpb cc+1,$20. / is character count for console tty greater C ; / than 20 C ;bhis 2f / yes; branch to put process to sleep C ; 27/06/2014 1397 C @@: C ; AH = tty number C ; AL = ASCII code of the character C ; 15/04/2014 1397 50 C push ax 1398 E8 070B C call putc ; 14/05/2013 139B 73 0A C jnc short @f C ; 02/06/2014 139D 8A 26 390A R C mov ah, byte ptr [u.ttyn] 13A1 E8 FBD3 C call sleep 13A4 58 C pop ax 13A5 EB F0 C jmp short @b C ; jc error ; 15/05/2013 (COM1 or COM2 serial port error) C ; jsr r0,putc; 1 / find place in freelist to assign to C ; / console tty and C ; br 2f / place character in list; if none available C ; / branch to put process to sleep C ; jsr r0,startty / attempt to output character on tty 13A7 C @@: C ; 15/04/2014 13A7 58 C pop ax 13A8 EB E8 C jmp short wtty_nc C ; br wtty 13AA C wret: ; 10/10/2013 13AA 58 C pop ax 13AB C3 C retn C ;2: C ;mov r1,-(sp) / place character on stack C ;jsr r0,sleep; 1 / put process to sleep C ;mov (sp)+,r1 / remove character from stack C ;br 1b / try again to place character in clist and output C 13AC C xmtt: ; < send/write character to tty > C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 10/10/2013 C ; 14/08/2013 C ; 28/07/2013 C ; 21/05/2013 owner checking for COM/serial ports C ; 15/05/2013 C ; C ; Retro UNIX 8086 v1 modification ! C ; C ; In original UNIX v1, 'xmtt' routine C ; (exactly different than this one) C ; was in 'u9.s' file. C ; 13AC 2C 0A C sub al, 10 C ; AL = tty number (0 to 9), (COM1=8, COM2=9) C ; 10/10/2013 13AE 8A E0 C mov ah, al C ; 28/07/2013 13B0 EB D7 C jmp short wttys C C ;wppt: C ; jsr r0,cpass / get next character from user buffer area, C ; / if none return to writei's calling routine C ; jsr r0,pptoc / output character on ppt C ; br wppt 13B2 C wlpr: 13B2 E9 EF47 C jmp error ; ... Printing procedure will be located here ... C ;/ jsr r0,cpass C ;/ cmp r0,$'a C ;/ blo 1f C ;/ cmp r1,$'z C ;/ bhi 1f C ;/ sub $40,r1 C ;/1: C ;/ jsr r0,lptoc C ;/ br wlpr C ; br rmem / continue C 13B5 C wmem: ; / transfer characters from a user area of core to memory file 13B5 8B 36 38DE R C mov si, word ptr [u.fofp] 13B9 C @@: 13B9 E8 006C C call cpass C ; jsr r0,cpass / get next character from users area of C ; / core and put it in r1 C ; mov r1,-(sp) / put character on the stack C ; 20/09/2013 13BC 74 EC C jz short wret ; @f 13BE 8B 1C C mov bx, word ptr [SI] C ; mov *u.fofp,r1 / save file offset in r1 13C0 FF 04 C inc word ptr [SI] ; 16/07/2015 C ; inc *u.fofp / increment file offset to point to next C ; / available location in file 13C2 88 07 C mov byte ptr [BX], al C ; movb (sp)+,(r1) / pop char off stack, put in memory loc C ; / assigned to it 13C4 EB F3 C jmp short @b C ; br wmem / continue C ;1: C ;jmp error / ? C ;@@: C ; ; 20/09/2013 C ; pop ax C ; retn C C 13C6 C dskw: ; / write routine for non-special files C ; 20/09/2013 C ; 03/08/2013 C ; 01/08/2013 (mkdir_w check) 13C6 50 C push ax ; 26/04/2013 C ; mov (sp),r1 / get an i-node number from the stack into r1 C ; AX = inode number 13C7 E8 FD10 C call iget C ; jsr r0,iget / write i-node out (if modified), C ; / read i-node 'r1' into i-node area of core 13CA 8B 1E 38DE R C mov bx, word ptr [u.fofp] 13CE 8B 17 C mov dx, word ptr [BX] C ; mov *u.fofp,r2 / put the file offset [(u.off) or the offset C ; / in the fsp entry for this file] in r2 13D0 03 16 38E8 R C add dx, word ptr [u.count] C ; add u.count,r2 / no. of bytes to be written C ; / + file offset is put in r2 13D4 3B 16 2972 R C cmp dx, word ptr [i.size_] C ; cmp r2,i.size / is this greater than the present size of C ; / the file? 13D8 76 07 C jna short dskw_1 C ; blos 1f / no, branch 13DA 89 16 2972 R C mov word ptr [i.size_], dx C ; mov r2,i.size / yes, increase the f11e size to C ; / file offset + no. of data bytes 13DE E8 FDBF C call setimod C ; jsr r0,setimod / set imod=1 (i.e., core inode has been C ; / modified), stuff time of modification into C ; / core image of i-node 13E1 C dskw_1: ; 1: 13E1 E8 FBE6 C call mget C ; AX = Block number C ; jsr r0,mget / get the block no. in which to write C ; / the next data byte 13E4 8B 1E 38DE R C mov bx, word ptr [u.fofp] 13E8 8B 17 C mov dx, word ptr [BX] 13EA 81 E2 01FF C and dx, 1FFh C ; bit *u.fofp,$777 / test the lower 9 bits of the file offset 13EE 75 08 C jnz short dskw_2 C ; bne 2f / if its non-zero, branch; if zero, file offset = 0, C ; / 512, 1024,...(i.e., start of new block) 13F0 81 3E 38E8 R 0200 C cmp word ptr [u.count], 512 C ; cmp u.count,$512. / if zero, is there enough data to fill C ; / an entire block? (i.e., no. of 13F6 73 03 C jnb short dskw_3 C ; bhis 3f / bytes to be written greater than 512.? C ; / Yes, branch. Don't have to read block C 13F8 C dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be C ; / overwritten). 13F8 E8 03C1 C call dskrd C ; jsr r0,dskrd / no, must retain old info.. C ; / Hence, read block 'r1' into an I/O buffer 13FB C dskw_3: ; 3: C ; AX (r1) = block/sector number 13FB E8 03F9 C call wslot C ; jsr r0,wslot / set write and inhibit bits in I/O queue, C ; / proc. status=0, r5 points to 1st word of data C ; BX (r5) = system (I/O) buffer address 13FE E8 004C C call sioreg C ; jsr r0,sioreg / r3 = no. of bytes of data, C ; / r1 = address of data, r2 points to location C ; / in buffer in which to start writing data C ; SI = file (user data) offset C ; DI = sector (I/O) buffer offset C ; CX = byte count C ; C ; 03/08/2013 C ; 01/08/2013 1401 80 3E 2C0A R 00 C cmp byte ptr [mkdir_w], 0 1406 76 04 C jna short dskw_4 ; zf=0 -> the caller is 'mkdir' 1408 F3/ A4 C rep movsb 140A EB 0B C jmp short dskw_5 140C C dskw_4: 140C A1 3908 R C mov ax, word ptr [u.segmnt] ; Retro Unix 8086 v1 feature only ! 140F 8E D8 C mov ds, ax ; Retro Unix 8086 v1 feature: ES = user segment ! C ; 2: 1411 F3/ A4 C rep movsb C ; movb (r1 )+,(r2)+ C ; / transfer a byte of data to the I/O buffer C ; dec r3 / decrement no. of bytes to be written C ; bne 2b / have all bytes been transferred? No, branch C 1413 8C C8 C mov ax, cs ; Retro Unix 8086 v1 feature: CS = system segment ! 1415 8E D8 C mov ds, ax ; Retro Unix 8086 v1 feature: DS = system segment ! 1417 C dskw_5: 1417 E8 03F3 C call dskwr C ; jsr r0,dskwr / yes, write the block and the i-node 141A 83 3E 38E8 R 00 C cmp word ptr [u.count], 0 C ; tst u.count / any more data to write? 141F 77 C0 C ja short dskw_1 C ; bne 1b / yes, branch C ; 03/08/2013 1421 C6 06 2C0A R 00 C mov byte ptr [mkdir_w], 0 C ; 20/09/2013 (;;) 1426 58 C pop ax 1427 C3 C retn C ;;jmp short dskw_ret C ; jmp ret / no, return to the caller via 'ret' C 1428 C cpass: ; / get next character from user area of core and put it in r1 1428 83 3E 38E8 R 00 C cmp word ptr [u.count], 0 ; 14/08/2013 C ; tst u.count / have all the characters been transferred C ; / (i.e., u.count, # of chars. left 142D 76 1D C jna short @f C ; beq 1f / to be transferred = 0?) yes, branch 142F FF 0E 38E8 R C dec word ptr [u.count] C ; dec u.count / no, decrement u.count C ; 1433 8B 1E 3908 R C mov bx, word ptr [u.segmnt] ; Retro Unix 8086 v1 feature only ! 1437 8E C3 C mov es, bx ; Retro Unix 8086 v1 feature: ES = user segment ! C ; 1439 8B 1E 38E6 R C mov bx, word ptr [u.base] 143D 26: 8A 07 C mov al, byte ptr ES:[BX] ; Runix v1: get data from user segment! C ; movb *u.base,r1 / take the character pointed to C ; / by u.base and put it in r1 1440 8C DB C mov bx, ds ; Retro Unix 8086 v1 feature: DS = system segment ! 1442 8E C3 C mov es, bx ; Retro Unix 8086 v1 feature: ES = system segment ! C ; 1444 FF 06 38EA R C inc word ptr [u.nread] C ; inc u.nread / increment no. of bytes transferred 1448 FF 06 38E6 R C inc word ptr [u.base] C ; inc u.base / increment the buffer address to point to the 144C C @@: ; 20/09/2013 (;;) 144C C3 C retn C ; rts r0 / next byte C ;;@@: ; 1: C ;; pop ax C ; mov (sp)+,r0 C ; / put return address of calling routine into r0 C ;;dskw_ret: C ;; pop ax C ; mov (sp)+,r1 / i-number in r1 C ;; retn C ; rts r0 / non-local return C 144D C sioreg: C ; 22/07/2013 C ; 14/03/2013 bx -> si, ax input -> bx input C ; 12/03/2013 C ; INPUTS -> C ; BX = system buffer (data) address (r5) C ; OUTPUTS -> C ; SI = user data offset (r1) C ; DI = system (I/O) buffer offset (r2) C ; CX = byte count (r3) C ; ((Modified registers: AX)) ; 22/07/2013 C 144D 8B 36 38DE R C mov si, word ptr [u.fofp] 1451 8B 3C C mov di, word ptr [SI] C ; mov *u.fofp,r2 / file offset (in bytes) is moved to r2 1453 8B CF C mov cx, di C ; mov r2,r3 / and also to r3 1455 81 C9 FE00 C or cx, 0FE00h C ; bis $177000,r3 / set bits 9,...,15 of file offset in r3 1459 81 E7 01FF C and di, 1FFh C ; bic $!777,r2 / calculate file offset mod 512. 145D 03 FB C add di, bx ; BX = system buffer (data) address C ; add r5,r2 / r2 now points to 1st byte in system buffer C ; / where data is to be placed 145F A1 38E6 R C mov ax, word ptr [u.base] ; 22/07/2013 C ; mov u.base,r1 / address of data is in r1 1462 F7 D9 C neg cx C ; neg r3 / 512 - file offset (mod512.) in r3 C ; / (i.e., the no. of free bytes in the file block) 1464 3B 0E 38E8 R C cmp cx, word ptr [u.count] C ; cmp r3,u.count / compare this with the no. of data bytes C ; / to be written to the file 1468 76 04 C jna short @f C ; blos 2f / if less than branch. Use the no. of free bytes C ; / in the file block as the number to be written 146A 8B 0E 38E8 R C mov cx, word ptr [u.count] C ; mov u.count,r3 / if greater than, use the no. of data C ; / bytes as the number to be written 146E C @@: ; 2: 146E 01 0E 38EA R C add word ptr [u.nread], cx C ; add r3,u.nread / r3 + number of bytes xmitted C ; / during write is put into u.nread 1472 29 0E 38E8 R C sub word ptr [u.count], cx C ; sub r3,u.count / u.count = no. of bytes that still C ; / must be written or read 1476 01 0E 38E6 R C add word ptr [u.base], cx C ; add r3,u.base / u.base points to the 1st of the remaining C ; / data bytes 147A 01 0C C add word ptr [SI], cx C ; add r3,*u.fofp / new file offset = number of bytes done C ; / + old file offset 147C 8B F0 C mov si, ax ; 22/07/2013 147E C3 C retn C ; rts r0 C include u7.asm ; u7.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U7.ASM (include u7.asm) //// UNIX v1 -> u7.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 13/07/2014 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 13/07/2014 ottyp C ; 12/07/2014 ottyp C ; 15/04/2014 ottyp C ; 26/01/2014 otty, ottyp, ctty, cttyp C ; 17/01/0214 otty, ottyp, ottys, ctty, cttyp C ; 13/01/2014 otty, ocvt, ottys, ctty, ccvt, ottyp, cttyp C ; 12/01/2014 iclose C ; 06/12/2013 otty, ocvt, ctty, ccvt (major modification: p.ttyc, u.ttyp) C ; 04/12/2013 (getc, putc procedures have been moved to U9.ASM) C ; 03/12/2013 putc (write_tty, beep, waitf) C ; 30/11/2013 putc C ; 04/11/2013 putc, symount, sysumount C ; 30/10/2013 putc C ; 20/10/2013 getc C ; 10/10/2013 getc C ; 05/10/2013 getc C ; 24/09/2013 getc, otty, ocvt, ctty, ccvt, putc (consistency check) C ; 20/09/2013 putc, getc C ; 17/09/2013 otty (ottys), ctty, ccvt C ; 16/09/2013 ocvt, ctty C ; 13/09/2013 otty C ; 03/09/2013 otty, ocvt, ctty, ccvt C ; 27/08/2013 iopen, iclose, ocvt, ccvt C ; 26/08/2013 putc C ; 16/08/2013 iopen, iclose, otty, ctty C ; 13/08/2013 ctty (cttys) C ; 05/08/2013 ctty C ; 30/07/2013 iclose, ctty, ccvt C ; 29/07/2013 C ; 28/07/2013 C ; 16/07/2013 iopen, otty, ocvt, ctty, ccvt, getc, iclose modifications C ; 15/07/2013 C ; 09/07/2013 - sysmount, sysumount C C 147F C sysmount: ; / mount file system; args special; name C ; 04/11/2013 C ; 09/07/2013 C ; 'sysmount' anounces to the system that a removable C ; file system has been mounted on a special file. C ; The device number of the special file is obtained via C ; a call to 'getspl'. It is put in the I/O queue entry for C ; dismountable file system (sb1) and the I/O queue entry is C ; set up to read (bit 10 is set). 'ppoke' is then called to C ; to read file system into core, i.e. the first block on the C ; mountable f'le system is read in. This block is super block C ; for the file system. This call is super user restricted. C ; C ; Calling sequence: C ; sysmount; special; name C ; Arguments: C ; special - pointer to name of special file (device) C ; name - pointer to name of the root directory of the C ; newly mounted file system. 'name' should C ; always be a directory. C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysmount' system call has two arguments; so, C ; Retro UNIX 8086 v1 argument transfer method 2 is used C ; to get sysmount system call arguments from the user; C ; * 1st argument, special is pointed to by BX register C ; * 2nd argument, name is in CX register C ; C ; NOTE1: Retro UNIX 8086 v1 'arg2' routine gets these C ; arguments which were in these registers; C ; but, it returns by putting the 1st argument C ; in 'u.namep' and the 2nd argument C ; on top of stack. (1st argument is offset of the C ; file/path name in the user's program segment. C ; NOTE2: Device numbers, names and related procedures are C ; already modified for IBM PC compatibility and C ; Retro UNIX 8086 v1 device configuration. C C ;call arg2 C ; jsr r0,arg2 / get arguments special and name 147F 89 1E 38E2 R C mov word ptr [u.namep], bx 1483 51 C push cx 1484 83 3E 2BFC R 00 C cmp word ptr [mnti], 0 C ; tst mnti / is the i-number of the cross device file C ; / zero? 1489 76 03 E9 EE6E C ja error C ; bne errora / no, error 148E E8 0077 C call getspl C ; jsr r0,getspl / get special files device number in r1 C ; 04/11/2013 C ;pop cx ; file name pointer 1491 8B D8 C mov bx, ax ; ; Retro UNIX 8086 v1 device number (0 to 5) 1493 80 BF 2BD6 R 00 C cmp byte ptr [BX]+drv.err, 0 1498 76 03 E9 EE5F C ja error C ;mov word ptr [u.namep], cx 149D 8F 06 38E2 R C pop word ptr [u.namep] C ; mov (sp)+,u.namep / put the name of file to be placed C ; / on the device 14A1 50 C push ax ; push bx C ; mov r1,-(sp) / save the device number C ; 14A2 E8 F6F6 C call namei C ;or ax, ax ; Retro UNIX 8086 v1 modification ! C ; ax = 0 -> file not found C ;jz error 14A5 73 03 E9 EE52 C jc error C ; jsr r0,namei / get the i-number of the file C ; br errora 14AA A3 2BFC R C mov word ptr [mnti], ax C ; mov r1,mnti / put it in mnti C ; 04/11/2013 14AD BB 276A R C mov bx, offset sb1 ; super block buffer (of mounted disk) 14B0 C @@: ;1: 14B0 80 7F 01 00 C cmp byte ptr [BX]+1, 0 C ; tstb sb1+1 / is 15th bit of I/O queue entry for C ; / dismountable device set? 14B4 76 05 C jna short @f C ; bne 1b / (inhibit bit) yes, skip writing 14B6 E8 FA39 C call idle ; 04/11/2013 (wait for hardware interrupt) 14B9 EB F5 C jmp short @b 14BB C @@: 14BB 58 C pop ax ; Retro UNIX 8086 v1 device number/ID (0 to 5) 14BC A2 2BD5 R C mov byte ptr [mdev], al C ; mov (sp),mntd / no, put the device number in mntd C ; 04/11/2013 14BF 88 07 C mov byte ptr [BX], al C ; movb (sp),sb1 / put the device number in the lower byte C ; / of the I/O queue entry C ;mov byte ptr [cdev], 1 ; mounted device/drive C ; mov (sp)+,cdev / put device number in cdev 14C1 81 0F 0400 C or word ptr [BX], 400h ; Bit 10, 'read' flag/bit C ; bis $2000,sb1 / set the read bit 14C5 C6 47 02 01 C mov byte ptr [BX]+2, 1 ; physical block number = 1 14C9 E8 0429 C call diskio 14CC 73 0D C jnc short @f 14CE 33 C0 C xor ax, ax 14D0 A3 2BFC R C mov word ptr [mnti], ax ; 0 14D3 A2 2BD5 R C mov byte ptr [mdev], al ; 0 C ;mov byte ptr [cdev], al ; 0 14D6 89 07 C mov word ptr [BX], ax ; 0 14D8 E9 EE21 C jmp error 14DB C @@: 14DB C6 47 01 00 C mov byte ptr [BX]+1, 0 ; 18/07/2013 C ;;call ppoke C ; jsr r0,ppoke / read in entire file system C ;@@: ;1: C ;;cmp byte ptr [sb1]+1, 0 C ; tstb sb1+1 / done reading? C ;;jna sysret C ;,call idle ; 04/11/2013 (wait for hardware interrupt) C ;;jmp short @b C ;bne 1b / no, wait C ;br sysreta / yes 14DF E9 EE37 C jmp sysret C C 14E2 C sysumount: ; / special dismount file system C ; 04/11/2013 C ; 09/07/2013 C ; 'sysmount' anounces to the system that the special file, C ; indicated as an argument is no longer contain a removable C ; file system. 'getspl' gets the device number of the special C ; file. If no file system was mounted on that device an error C ; occurs. 'mntd' and 'mnti' are cleared and control is passed C ; to 'sysret'. C ; C ; Calling sequence: C ; sysmount; special C ; Arguments: C ; special - special file to dismount (device) C ; C ; Inputs: - C ; Outputs: - C ; ............................................................... C ; C ; Retro UNIX 8086 v1 modification: C ; 'sysumount' system call has one argument; so, C ; Retro UNIX 8086 v1 argument transfer method 1 is used C ; to get sysmount system call argument from the user; C ; * Single argument, special is pointed to by BX register C ; C C ;mov ax, 1 ; one/single argument, put argument in BX C ;call arg C ; jsr r0,arg; u.namep / point u.namep to special 14E2 89 1E 38E2 R C mov word ptr [u.namep], bx 14E6 E8 001F C call getspl C ; jsr r0,getspl / get the device number in r1 14E9 3A 06 2BD5 R C cmp al, byte ptr [mdev] C ; cmp r1,mntd / is it equal to the last device mounted? 14ED 74 03 E9 EE0A C jne error C ; bne errora / no error 14F2 32 C0 C xor al, al ; ah = 0 14F4 C @@: ;1: 14F4 38 06 276B R C cmp byte ptr [sb1]+1, al ; 0 C ; tstb sb1+1 / yes, is the device still doing I/O C ; / (inhibit bit set)? 14F8 76 05 C jna short @f C ; bne 1b / yes, wait 14FA E8 F9F5 C call idle ; 04/11/2013 (wait for hardware interrupt) 14FD EB F5 C jmp short @b 14FF C @@: 14FF A2 2BD5 R C mov byte ptr [mdev], al C ; clr mntd / no, clear these 1502 A3 2BFC R C mov word ptr [mnti], ax C ; clr mnti 1505 E9 EE11 C jmp sysret C ; br sysreta / return C 1508 C getspl: ; / get device number from a special file name C ; 09/07/2013 1508 E8 F690 C call namei C ;or ax, ax ; Retro UNIX 8086 v1 modification ! C ; ax = 0 -> file not found C ;jz error 150B 73 03 E9 EDEC C jc error C ; jsr r0,namei / get the i-number of the special file C ; br errora / no such file 1510 83 E8 03 C sub ax, 3 ; Retro UNIX 8086 v1 modification ! C ; i-number-3, 0 = fd0, 5 = hd3 C ; sub $4,r1 / i-number-4 rk=1,tap=2+n 1513 73 03 E9 EDE4 C jc error C ; ble errora / less than 0? yes, error 1518 83 F8 05 C cmp ax, 5 ; C ; cmp r1,$9. / greater than 9 tap 7 151B 76 03 E9 EDDC C ja error C ; bgt errora / yes, error C ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 1520 C @@: 1520 C3 C retn C ; rts r0 / return with device number in r1 C 1521 C iopen: C ;27/08/2013 C ;16/08/2013 C ;16/07/2013 C ;21/05/2013 C ; C ; open file whose i-number is in r1 C ; C ; INPUTS -> C ; r1 - inode number C ; OUTPUTS -> C ; file's inode in core C ; r1 - inode number (positive) C ; C ; ((AX = R1)) C ; ((Modified registers: DX, BX, CX, SI, DI, BP)) C ; C ; / open file whose i-number is in r1 1521 F6 C4 80 C test ah, 80h ; Bit 15 of AX C ;tst r1 / write or read access? 1524 75 3B C jnz short iopen_2 C ;blt 2f / write, go to 2f 1526 B2 02 C mov dl, 2 ; read access 1528 E8 FC52 C call access C ; jsr r0,access; 2 C ; / get inode into core with read access C ; DL=2 152B C iopen_0: 152B 83 F8 28 C cmp ax, 40 C ; cmp r1,$40. / is it a special file C ;ja short @f C ;bgt 3f / no. 3f 152E 77 F0 C ja short @b ; 16/08/2013 1530 50 C push ax C ; mov r1,-(sp) / yes, figure out 1531 8B D8 C mov bx, ax 1533 D1 E3 C shl bx, 1 C ; asl r1 1535 81 C3 1539 R C add bx, offset iopen_1 - 2 1539 FF 27 C jmp word ptr [BX] C ; jmp *1f-2(r1) / which one and transfer to it 153B C iopen_1: ; 1: 153B 1575 R C dw offset otty ; tty, AX = 1 (runix) C ;otty / tty ; r1=2 C ;oppt / ppt ; r1=4 153D 1655 R C dw offset sret ; mem, AX = 2 (runix) C ;sret / mem ; r1=6 C ;sret / rf0 C ;sret / rk0 C ;sret / tap0 C ;sret / tap1 C ;sret / tap2 C ;sret / tap3 C ;sret / tap4 C ;sret / tap5 C ;sret / tap6 C ;sret / tap7 153F 1655 R C dw offset sret ; fd0, AX = 3 (runix only) 1541 1655 R C dw offset sret ; fd1, AX = 4 (runix only) 1543 1655 R C dw offset sret ; hd0, AX = 5 (runix only) 1545 1655 R C dw offset sret ; hd1, AX = 6 (runix only) 1547 1655 R C dw offset sret ; hd2, AX = 7 (runix only) 1549 1655 R C dw offset sret ; hd3, AX = 8 (runix only) C ;dw offset error ; lpr, AX = 9 (error !) 154B 1655 R C dw offset sret ; lpr, AX = 9 (runix) 154D 1581 R C dw offset ocvt ; tty0, AX = 10 (runix) C ;ocvt / tty0 154F 1581 R C dw offset ocvt ; tty1, AX = 11 (runix) C ;ocvt / tty1 1551 1581 R C dw offset ocvt ; tty2, AX = 12 (runix) C ;ocvt / tty2 1553 1581 R C dw offset ocvt ; tty3, AX = 13 (runix) C ;ocvt / tty3 1555 1581 R C dw offset ocvt ; tty4, AX = 14 (runix) C ;ocvt / tty4 1557 1581 R C dw offset ocvt ; tty5, AX = 15 (runix) C ;ocvt / tty5 1559 1581 R C dw offset ocvt ; tty6, AX = 16 (runix) C ;ocvt / tty6 155B 1581 R C dw offset ocvt ; tty7, AX = 17 (runix) C ;ocvt / tty7 155D 1581 R C dw offset ocvt ; COM1, AX = 18 (runix only) C ;error / crd 155F 1581 R C dw offset ocvt ; COM2, AX = 19 (runix only) C ;@@: C ;retn C 1561 C iopen_2: ; 2: / check open write access 1561 F7 D8 C neg ax C ;neg r1 / make inode number positive 1563 B2 01 C mov dl, 1 ; write access 1565 E8 FC15 C call access C ;jsr r0,access; 1 / get inode in core C ; DL=1 1568 F7 06 296E R 4000 C test word ptr [i.flgs], 4000h ; Bit 14 : Directory flag C ;bit $40000,i.flgs / is it a directory? 156E 74 03 E9 ED89 C jnz error C ; bne 2f / yes, transfer (error) 1573 EB B6 C jmp short iopen_0 C ;cmp ax, 40 C ; cmp r1,$40. / no, is it a special file? C ;ja short @b C ;bgt 3f / no, return C ;push ax C ;mov r1,-(sp) / yes C ;mov bx, ax C ;shl bx, 1 C ; asl r1 C ;add bx, offset ipen_3 - 2 C ;jmp word ptr [BX] C ; jmp *1f-2(r1) / figure out C ; / which special file it is and transfer C ;iopen_3: ; 1: C ; dw offset otty ; tty, AX = 1 (runix) C ;otty / tty ; r1=2 C ;leadr / ppt ; r1=4 C ; dw offset sret ; mem, AX = 2 (runix) C ;sret / mem ; r1=6 C ;sret / rf0 C ;sret / rk0 C ;sret / tap0 C ;sret / tap1 C ;sret / tap2 C ;sret / tap3 C ;sret / tap4 C ;sret / tap5 C ;sret / tap6 C ;sret / tap7 C ; dw offset sret ; fd0, AX = 3 (runix only) C ; dw offset sret ; fd1, AX = 4 (runix only) C ; dw offset sret ; hd0, AX = 5 (runix only) C ; dw offset sret ; hd1, AX = 6 (runix only) C ; dw offset sret ; hd2, AX = 7 (runix only) C ; dw offset sret ; hd3, AX = 8 (runix only) C ; dw offset sret ; lpr, AX = 9 (runix) C ;dw offset ejec ; lpr, AX = 9 (runix) C ; dw offset sret ; tty0, AX = 10 (runix) C ;ocvt / tty0 C ; dw offset sret ; tty1, AX = 11 (runix) C ;ocvt / tty1 C ; dw offset sret ; tty2, AX = 12 (runix) C ;ocvt / tty2 C ; dw offset sret ; tty3, AX = 13 (runix) C ;ocvt / tty3 C ; dw offset sret ; tty4, AX = 14 (runix) C ;ocvt / tty4 C ; dw offset sret ; tty5, AX = 15 (runix) C ;ocvt / tty5 C ; dw offset sret ; tty6, AX = 16 (runix) C ;ocvt / tty6 C ; dw offset sret ; tty7, AX = 17 (runix) C ;ocvt / tty7 C ; dw offset ocvt ; COM1, AX = 18 (runix only) C ;/ ejec / lpr C ; dw offset ocvt ; COM2, AX = 19 (runix only) C C 1575 C otty: ;/ open console tty for reading or writing C ; 13/07/2014 C ; 12/07/2014 C ; 15/04/2014 (modification for serial ports) C ; 26/01/2014 C ; 17/01/2014 C ; 13/01/2014 C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 24/09/2013 consistency check -> ok C ; 17/09/2013 C ; 16/09/2013 C ; 13/09/2013 C ; 03/09/2013 C ; 16/08/2013 C ; 16/07/2013 C ; 15/07/2013 C ; 27/05/2013 C ; 21/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; C ; 16/07/2013 C ; Retro UNIX 8086 v1 modification: C ; If a tty is open for read or write by C ; a process (u.uno), only same process can open C ; same tty to write or read (R->R&W or W->W&R). C ; C ; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty) C ; ah = 0 C ; 06/12/2013 1575 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 1579 32 FF C xor bh, bh 157B 8A 87 29ED R C mov al, byte ptr [BX]+p.ttyc-1 ; current/console tty C ; 13/01/2014 157F EB 02 C jmp short ottyp 1581 C ocvt: 1581 2C 0A C sub al, 10 1583 C ottyp: C ; 13/07/2014 C ; 12/07/2014 C ; 15/04/2014 (modification for serial ports) C ; 26/01/2014 C ; 13/01/2014 C ; 06/12/2013 1583 8A F0 C mov dh, al ; tty number C ; 16/08/2013 1585 8B D8 C mov bx, ax ; AL = tty number (0 to 9), AH = 0 1587 D0 E3 C shl bl, 1 ; aligned to word C ;26/01/2014 1589 81 C3 2C8E R C add bx, offset ttyl 158D 8B 0F C mov cx, word ptr [BX] C ; CL = lock value (0 or process number) C ; CH = open count 158F 22 C9 C and cl, cl C ; 13/01/2014 1591 74 25 C jz short otty_ret C ; 1593 3A 0E 3907 R C cmp cl, byte ptr [u.uno] 1597 74 1F C je short otty_ret C ; 1599 8A D9 C mov bl, cl ; the process which has locked the tty 159B D0 E3 C shl bl, 1 159D 32 FF C xor bh, bh 159F 8B 87 298C R C mov ax, word ptr [BX]+p.pid-2 15A3 8A 1E 3907 R C mov bl, byte ptr [u.uno] 15A7 D0 E3 C shl bl, 1 15A9 3B 87 29AC R C cmp ax, word ptr [BX]+p.ppid-2 15AD 74 09 C je short otty_ret C ;;jne short otty_err C ; the tty is locked by another process C ; except the parent process (p.ppid) C ;;otty_err: ; 13/01/2014 15AF 0A D2 C or dl, dl ; DL = 0 -> called by sysstty 15B1 74 03 E9 ED46 C jnz error 15B6 F9 C stc 15B7 C3 C retn C 15B8 C otty_ret: C ; 13/01/2014 15B8 80 FE 07 C cmp dh, 7 15BB 76 7F C jna short ottys_ret 15BD C ottys: C ; 17/01/2013 15BD 52 C push dx ; * 15BE 8A E2 C mov ah, dl ; open mode 15C0 8A D6 C mov dl, dh 15C2 32 F6 C xor dh, dh 15C4 80 EA 08 C sub dl, 8 C ; 15C7 22 E4 C and ah, ah ; sysstty system call check 15C9 74 19 C jz short com_port_init C ; 15CB 23 C9 C and cx, cx 15CD 74 13 C jz short @f ; unlocked/free tty (serial port) C ; C ; 13/01/2014 C ; DX = port number (COM1=0, COM2=1) 15CF B4 03 C mov ah, 3 15D1 CD 14 C int 14h ; Get serial port status C ; 13/07/2014 15D3 5A C pop dx ; * 15D4 F6 C4 80 C test ah, 80h 15D7 74 6B C jz short ottys_rtn C ;;otty_err: ; 13/01/2014 15D9 0A D2 C or dl, dl ; DL = 0 -> called by sysstty 15DB 74 03 E9 ED1C C jnz error 15E0 F9 C stc 15E1 C3 C retn 15E2 C @@: 15E2 32 E4 C xor ah, ah ; 0 15E4 C com_port_init: 15E4 BE 2CAE R C mov si, offset com1p 15E7 0A D2 C or dl, dl ; COM1 ? 15E9 74 01 C jz short @f ; yes, it is COM1 15EB 46 C inc si ; no, it is COM2 15EC C @@: 15EC 8A 04 C mov al, byte ptr [SI] ; comm. parameters C ; C ; Initializing serial port parameters C ;xor ah, ah ; 0 C ; AL = Communication parameters C ; DX = Serial port number (COM1 = 0, COM2 = 1) 15EE CD 14 C int 14h ; Initialize serial port parameters C ; C ; (Note: Serial port interrupts C ; will be disabled here...) C ; (INT 14h initialization code C ; disables interrupts.) C ; 13/07/2014 15F0 22 D2 C and dl, dl 15F2 74 19 C jz short com1p_eirq C ; C ;; COM2 - enabling IRQ 3 15F4 BA 02FC C mov dx, 2FCh ;modem control register 15F7 EC C in al, dx ;read register 15F8 0C 08 C or al, 8 ;enable bit 3 (OUT2) 15FA EE C out dx, al ;write back to register 15FB BA 02F9 C mov dx, 2F9h ;interrupt enable register 15FE EC C in al, dx ;read register 15FF 0C 01 C or al, 1 ;receiver data interrupt enable 1601 EE C out dx, al ;write back to register 1602 E4 21 C in al, 21h ;read interrupt mask register 1604 24 F7 C and al, 0F7h ;enable IRQ 3 (COM2) 1606 E6 21 C out 21h, al ;write back to register 1608 BA 0001 C mov dx, 1 160B EB 16 C jmp short comp_get_stat 160D C com1p_eirq: C ;; COM1 - enabling IRQ 4 160D BA 03FC C mov dx, 3FCh ;modem control register 1610 EC C in al, dx ;read register 1611 0C 08 C or al, 8 ;enable bit 3 (OUT2) 1613 EE C out dx, al ;write back to register 1614 BA 03F9 C mov dx, 3F9h ;interrupt enable register 1617 EC C in al, dx ;read register 1618 0C 01 C or al, 1 ;receiver data interrupt enable 161A EE C out dx, al ;write back to register 161B E4 21 C in al, 21h ;read interrupt mask register 161D 24 EF C and al, 0EFh ;enable IRQ 4 (COM1) 161F E6 21 C out 21h, al ;write back to register 1621 33 D2 C xor dx, dx 1623 C comp_get_stat: 1623 B4 03 C mov ah, 3 1625 CD 14 C int 14h ; Get serial port status C ; 1627 F6 C4 80 C test ah, 80h 162A 74 0F C jz short comp_init_ok ; successfully initialized C ; Initialization ERROR ! C ; 11100011b ; E3h C ; (111) Baud rate: 9600, (00) parity: none, C ; (0) stop bits: 1, (11) word length: 8 bits C ; 15/04/2014 162C 80 3C E3 C cmp byte ptr [SI], 0E3h 162F 74 07 C je short @f C ; 1631 C6 04 E3 C mov byte ptr [SI], 0E3h ; Reset comm. parameters 1634 32 E4 C xor ah, ah 1636 EB B4 C jmp short @b 1638 C @@: C ; 12/07/2014 1638 5A C pop dx ; * 1639 F9 C stc 163A C3 C retn C 163B C comp_init_ok: C ; 12/07/2014 163B 5A C pop dx ; * 163C C ottys_ret: 163C 0A C9 C or cl, cl ; cl = lock/owner, ch = open count 163E 75 04 C jnz short @f 1640 8A 0E 3907 R C mov cl, byte ptr [u.uno] 1644 C ottys_rtn: 1644 C @@: 1644 FE C5 C inc ch 1646 89 0F C mov word ptr [BX], cx ; set tty lock again C ; 06/12/2013 1648 FE C6 C inc dh ; tty number + 1 164A BB 38EE R C mov bx, offset u.ttyp C ; 13/01/2014 164D F6 C2 02 C test dl, 2 ; open for read sign 1650 75 01 C jnz short @f 1652 43 C inc bx 1653 C @@: C ; Set 'u.ttyp' ('the recent TTY') value 1653 88 37 C mov byte ptr [BX], dh ; tty number + 1 1655 C sret: 1655 0A D2 C or dl, dl ; sysstty system call check (DL=0) 1657 74 01 C jz short @f 1659 58 C pop ax 165A C @@: 165A C3 C retn C C ; C ; Original UNIX v1 'otty' routine: C ; C ;mov $100,*$tks / set interrupt enable bit (zero others) in C ; / reader status reg C ;mov $100,*$tps / set interrupt enable bit (zero others) in C ; / punch status reg C ;mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the C ; / console tty buffer C ;incb (r5) / increment the count of processes that opened the C ; / console tty C ;tst u.ttyp / is there a process control tty (i.e., has a tty C ; / buffer header C ;bne sret / address been loaded into u.ttyp yet)? yes, branch C ;mov r5,u.ttyp / no, make the console tty the process control C ; / tty C ;br sret / ? C ;sret: C ;clr *$ps / set processor priority to zero C ; pop ax C ;mov (sp)+,r1 / pop stack to r1 C ;3: C ; retn C ;rts r0 C C ;ocvt: ; < open tty > C ; 13/01/2014 C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 24/09/2013 consistency check -> ok C ; 16/09/2013 C ; 03/09/2013 C ; 27/08/2013 C ; 16/08/2013 C ; 16/07/2013 C ; 27/05/2013 C ; 21/05/2013 C ; C ; Retro UNIX 8086 v1 modification ! C ; C ; In original UNIX v1, 'ocvt' routine C ; (exactly different than this one) C ; was in 'u9.s' file. C ; C ; 16/07/2013 C ; Retro UNIX 8086 v1 modification: C ; If a tty is open for read or write by C ; a process (u.uno), only same process can open C ; same tty to write or read (R->R&W or W->W&R). C ; C ; INPUT: DL=2 for Read DL=1 for Write C C ; 16/09/2013 C ; sub al, 10 C C ; 06/12/2013 C ;cmp al, 7 C ;jna short ottyp C ; 13/01/2014 C ;jmp short ottyp C C C ;oppt: / open paper tape for reading or writing C ; mov $100,*$prs / set reader interrupt enable bit C ; tstb pptiflg / is file already open C ; bne 2f / yes, branch C ;1: C ; mov $240,*$ps / no, set processor priority to 5 C ; jsr r0,getc; 2 / remove all entries in clist C ; br .+4 / for paper tape input and place in free list C ; br 1b C ; movb $2,pptiflg / set pptiflg to indicate file just open C ; movb $10.,toutt+1 / place 10 in paper tape input tout entry C ; br sret C ;2: C ; jmp error / file already open C 165B C iclose: C ;13/01/2014 C ;12/01/2014 C ;27/08/2013 C ;16/08/2013 C ;30/07/2013 C ;16/07/2013 C ;21/05/2013 C ; C ; close file whose i-number is in r1 C ; C ; INPUTS -> C ; r1 - inode number C ; OUTPUTS -> C ; file's inode in core C ; r1 - inode number (positive) C ; C ; ((AX = R1)) C ; ((Modified registers: -BX-, DX)) C ; C ;/ close file whose i-number is in r1 165B B2 02 C mov dl, 2 ; 12/01/2014 165D F6 C4 80 C test ah, 80h ; Bit 15 of AX C ;tst r1 / test i-number C ;jnz short iclose_2 C ;blt 2f / if neg., branch 1660 74 04 C jz short iclose_0 ; 30/07/2013 C ; 16/07/2013 1662 F7 D8 C neg ax ; make it positive C ; 12/01/2014 1664 FE CA C dec dl ; dl = 1 (open for write) 1666 C iclose_0: 1666 83 F8 28 C cmp ax, 40 C ;cmp r1,$40. / is it a special file 1669 77 EF C ja short @b ; 13/01/2014 C ;bgt 3b / no, return C ; 12/01/2014 C ; DL=2 -> special file was opened for reading C ; DL=1 -> special file was opened for writing 166B 50 C push ax C ;mov r1,-(sp) / yes, save r1 on stack 166C 8B D8 C mov bx, ax 166E D1 E3 C shl bx, 1 C ; asl r1 1670 81 C3 1674 R C add bx, offset iclose_1 - 2 1674 FF 27 C jmp word ptr [BX] C ; jmp *1f-2(r1) / compute jump address and transfer 1676 C iclose_1 : 1676 169C R C dw offset ctty ; tty, AX = 1 (runix) 1678 16D7 R C dw offset cret ; mem, AX = 2 (runix) 167A 16D7 R C dw offset cret ; fd0, AX = 3 (runix only) 167C 16D7 R C dw offset cret ; fd1, AX = 4 (runix only) 167E 16D7 R C dw offset cret ; hd0, AX = 5 (runix only) 1680 16D7 R C dw offset cret ; hd1, AX = 6 (runix only) 1682 16D7 R C dw offset cret ; hd2, AX = 7 (runix only) 1684 16D7 R C dw offset cret ; hd3, AX = 8 (runix only) 1686 16D7 R C dw offset cret ; lpr, AX = 9 (runix) C ;dw offset error; lpr, AX = 9 (error !) C ;;dw offset ejec ;;lpr, AX = 9 1688 16A8 R C dw offset ccvt ; tty0, AX = 10 (runix) 168A 16A8 R C dw offset ccvt ; tty1, AX = 11 (runix) 168C 16A8 R C dw offset ccvt ; tty2, AX = 12 (runix) 168E 16A8 R C dw offset ccvt ; tty3, AX = 13 (runix) 1690 16A8 R C dw offset ccvt ; tty4, AX = 14 (runix) 1692 16A8 R C dw offset ccvt ; tty5, AX = 15 (runix) 1694 16A8 R C dw offset ccvt ; tty6, AX = 16 (runix) 1696 16A8 R C dw offset ccvt ; tty7, AX = 17 (runix) 1698 16A8 R C dw offset ccvt ; COM1, AX = 18 (runix only) 169A 16A8 R C dw offset ccvt ; COM2, AX = 19 (runix only) C C ; 1: C ; ctty / tty C ; cppt / ppt C ; sret / mem C ; sret / rf0 C ; sret / rk0 C ; sret / tap0 C ; sret / tap1 C ; sret / tap2 C ; sret / tap3 C ; sret / tap4 C ; sret / tap5 C ; sret / tap6 C ; sret / tap7 C ; ccvt / tty0 C ; ccvt / tty1 C ; ccvt / tty2 C ; ccvt / tty3 C ; ccvt / tty4 C ; ccvt / tty5 C ; ccvt / tty6 C ; ccvt / tty7 C ; error / crd C C ;iclose_2: ; 2: / negative i-number C ;neg ax C ;neg r1 / make it positive C ;cmp ax, 40 C ;cmp r1,$40. / is it a special file? C ;ja short @b C ;bgt 3b / no. return C ;push ax C ;mov r1,-(sp) C ;mov bx, ax C ;shl bx, 1 C ;asl r1 / yes. compute jump address and transfer C ;add bx, offset iclose_3 - 2 C ;jmp word ptr [BX] C ;jmp *1f-2(r1) / figure out C ;iclose_3: C ;dw offset ctty ; tty, AX = 1 (runix) C ;dw offset sret ; mem, AX = 2 (runix) C ;dw offset sret ; fd0, AX = 3 (runix only) C ;dw offset sret ; fd1, AX = 4 (runix only) C ;dw offset sret ; hd0, AX = 5 (runix only) C ;dw offset sret ; hd1, AX = 6 (runix only) C ;dw offset sret ; hd2, AX = 7 (runix only) C ;dw offset sret ; hd3, AX = 8 (runix only) C ;dw offset sret ; lpr, AX = 9 C ;dw offset ejec ; lpr, AX = 9 (runix) C ;dw offset ccvt ; tty0, AX = 10 (runix) C ;dw offset ccvt ; tty1, AX = 11 (runix) C ;dw offset ccvt ; tty2, AX = 12 (runix) C ;dw offset ccvt ; tty3, AX = 13 (runix) C ;dw offset ccvt ; tty4, AX = 14 (runix) C ;dw offset ccvt ; tty5, AX = 15 (runix) C ;dw offset ccvt ; tty6, AX = 16 (runix) C ;dw offset ccvt ; tty7, AX = 17 (runix) C ;dw offset ccvt ; COM1, AX = 18 (runix only) C ;dw offset ccvt ; COM2, AX = 19 (runix only) C C ;1: C ; ctty / tty C ; leadr / ppt C ; sret / mem C ; sret / rf0 C ; sret / rk0 C ; sret / tap0 C ; sret / tap1 C ; sret / tap2 C ; sret / tap3 C ; sret / tap4 C ; sret / tap5 C ; sret / tap6 C ; sret / tap7 C ; ccvt / tty0 C ; ccvt / tty1 C ; ccvt / tty2 C ; ccvt / tty3 C ; ccvt / tty4 C ; ccvt / tty5 C ; ccvt / tty6 C ; ccvt / tty7 C ;/ ejec / lpr C 169C C ctty: ; / close console tty C ; 26/01/2014 C ; 17/01/2014 C ; 13/01/2014 C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 24/09/2013 consistency check -> OK C ; 17/09/2013 C ; 16/09/2013 C ; 03/09/2013 C ; 16/08/2013 C ; 13/08/2013 C ; 05/08/2013 C ; 30/07/2013 C ; 16/07/2013 C ; 27/05/2013 C ; 21/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; C ; (DL = 2 -> it is open for reading) C ; (DL = 1 -> it is open for writing) C ; (DL = 0 -> it is open for sysstty system call) C ; C ; 06/12/2013 169C 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 16A0 32 FF C xor bh, bh 16A2 8A 87 29ED R C mov al, byte ptr [BX]+p.ttyc-1 C ; 13/01/2014 16A6 EB 02 C jmp short cttyp 16A8 C ccvt: 16A8 2C 0A C sub al, 10 16AA C cttyp: C ; 26/01/2014 C ; 13/01/2014 C ; 24/09/2013 consistency check -> ok C ; 16/08/2013 C ; AH = 0 16AA 8B D8 C mov bx, ax ; tty number (0 to 9) 16AC D0 E3 C shl bl, 1 ; aligned to word C ; 26/01/2014 16AE 81 C3 2C8E R C add bx, offset ttyl 16B2 8A F0 C mov dh, al ; tty number 16B4 8B 07 C mov ax, word ptr [BX] C ; AL = lock value (0 or process number) C ; AH = open count 16B6 22 E4 C and ah, ah C ;jz short ctty_err ; open count = 0, it is not open ! 16B8 75 03 E9 EC3F C jz error C ; 26/01/2014 16BD C ctty_ret: 16BD FE CC C dec ah ; decrease open count 16BF 75 02 C jnz short @f 16C1 32 C0 C xor al, al ; unlock/free tty 16C3 C @@: 16C3 89 07 C mov word ptr [BX], ax ; close tty instance C ; 16C5 BB 38EE R C mov bx, offset u.ttyp 16C8 F6 C2 01 C test dl, 1 ; open for write sign 16CB 74 01 C jz short @f 16CD 43 C inc bx 16CE C @@: 16CE FE C6 C inc dh ; tty number + 1 16D0 3A 37 C cmp dh, byte ptr [BX] 16D2 75 03 C jne short cret C ; Reset/Clear 'u.ttyp' ('the recent TTY') value 16D4 C6 07 00 C mov byte ptr [BX], 0 16D7 C cret: 16D7 0A D2 C or dl, dl ; sysstty system call check (DL=0) 16D9 74 01 C jz short @f 16DB 58 C pop ax 16DC C @@: 16DC C3 C retn C C ;ctty_err: ; 13/01/2014 C ; or dl, dl ; DL = 0 -> called by sysstty C ; jnz error C ; stc C ; retn C C C ; Original UNIX v1 'ctty' routine: C ; C ;mov tty+[ntty*8]-8+6,r5 C ; ;/ point r5 to the console tty buffer C ;decb (r5) / dec number of processes using console tty C ;br sret / return via sret C C ;ccvt: ; < close tty > C ; 13/01/2014 C ; 06/12/2013 (major modification: p.ttyc, u.ttyp) C ; 24/09/2013 consistency check -> ok C ; 17/09/2013 C ; 03/09/2013 C ; 27/08/2013 C ; 16/08/2013 C ; 30/07/2013 C ; 16/07/2013 C ; 27/05/2013 C ; 21/05/2013 C ; C ; Retro UNIX 8086 v1 modification ! C ; C ; In original UNIX v1, 'ccvt' routine C ; (exactly different than this one) C ; was in 'u9.s' file. C ; C ; DL = 2 -> it is open for reading C ; DL = 1 -> it is open for writing C ; C ; 17/09/2013 C ;sub al, 10 C ;cmp al, 7 C ;jna short cttyp C ; 13/01/2014 C ;jmp short cttyp C C C ;cppt: / close paper tape C ; clrb pptiflg / set pptiflg to indicate file not open C ;1: C ; mov $240,*$ps /set process or priority to 5 C ; jsr r0,getc; 2 / remove all ppt input entries from clist C ; / and assign to free list C ; br sret C ; br 1b C C ;ejec: C ; jmp error C ;/ejec: C ;/ mov $100,*$lps / set line printer interrupt enable bit C ;/ mov $14,r1 / 'form feed' character in r1 (new page). C ;/ jsr r0,lptoc / space the printer to a new page C ;/ br sret / return to caller via 'sret' C include u8.asm ; u8.s C ; **************************************************************************** C ; C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U8.ASM (include u8.asm) //// UNIX v1 -> u8.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (13/03/2013) C ; C ; [ Last Modification: 14/07/2015 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 18/01/2014 C ; 03/08/2013 dskwr C ; 31/07/2013 C ; 29/07/2013 C ; 26/07/2013 bread, bwrite (bug) note C ; 23/07/2013 poke C ; 20/07/2013 poke, bufaloc, bread, bwrite, dskrd, dskwr, wslot C ; 17/07/2013 poke C ; 09/07/2013 bufaloc, poke C ; 26/04/2013 device number modifications (cdev/0/1 -> 0/rdev, 1/mdev -> drv) C ; 18/04/2013 C ; 24/03/2013 poke C ; 15/03/2013 poke, diskio (runix) C ; 14/03/2013 C ; 13/03/2013 C C ;; I/O Buffer ((8+512 bytes in original Unix v1)) C ;; ((4+512 bytes in Retro UNIX 8086 v1)) C ;; C ;; I/O Queue Entry (of original UNIX operating system v1) C ;; Word 1, Byte 0 = device id C ;; Word 1, Byte 1 = (bits 8 to 15) C ;; bit 9 = write bit C ;; bit 10 = read bit C ;; bit 12 = waiting to write bit C ;; bit 13 = waiting to read bit C ;; bit 15 = inhibit bit C ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) C ;; C ;; Original UNIX v1 -> C ;; Word 3 = number of words in buffer (=256) C ;; Original UNIX v1 -> C ;; Word 4 = bus address (addr of first word of data buffer) C ;; C ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! C ;; C ;; Device IDs (of Retro Unix 8086 v1) C ;; 0 = fd0 C ;; 1 = fd1 C ;; 2 = hd0 C ;; 3 = hd1 C ;; 4 = hd2 C ;; 5 = hd3 C 16DD C rfd: ; 26/04/2013 C ; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) C ;sub ax, 3 ; zero based device number (Floppy disk) 16DD B9 0B40 C mov cx, 2880 ; size of floppy disks (1.44 MB) 16E0 E8 0012 C call bread ; **** returns to routine that called readi ('jmp ret') 16E3 C wfd: ; 26/04/2013 C ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) C ;sub ax, 3 ; zero based device number (Hard disk) 16E3 B9 0B40 C mov cx, 2880 ; size of floppy disks (1.44 MB) 16E6 E8 0066 C call bwrite ; **** returns to routine that called writei ('jmp ret') 16E9 C rhd: ; 26/04/2013 C ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) C ;sub ax, 3 ; zero based device number (Hard disk) 16E9 B9 FFFF C mov cx, 0FFFFh ; size of fixed disks (32 MB, first 65535 sectors) 16EC E8 0006 C call bread ; **** returns to routine that called readi ('jmp ret') 16EF C whd: C ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) C ;sub ax, 3 ; zero based device number (Hard disk) 16EF B9 FFFF C mov cx, 0FFFFh ; size of fixed disks (32 MB, first 65535 sectors) 16F2 E8 005A C call bwrite ; **** returns to routine that called writei ('jmp ret') C 16F5 C bread: C ; 14/07/2015 C ; 11/06/2015 C ; 29/07/2013 C ; 20/07/2013 C ; 26/04/2013 Retro Unix 8086 v1 feature (device number) modifications C ; 14/03/2013 C ; 13/03/2013 Retro UNIX 8086 v1 modification on original unix code C ;; / read a block from a block structured device C ; C ; INPUTS -> C ; [u.fopf] points to the block number C ; CX = maximum block number allowed on device C ; ; that was an arg to bread, in original Unix v1, but C ; ; CX register is used instead of arg in Retro Unix 8086 v1 C ; [u.count] number of bytes to read in C ; OUTPUTS -> C ; [u.base] starting address of data block or blocks in user area C ; [u.fopf] points to next consecutive block to be read C ; C ; ((Modified registers: AX, DX, CX, BX, SI, DI, BP)) C ; C ; NOTE: Original UNIX v1 has/had a defect/bug here, even if read C ; byte count is less than 512, block number in *u.fofp (u.off) C ; is increased by 1. For example: If user/program request C ; to read 16 bytes in current block, 'sys read' increaces C ; the next block number just as 512 byte reading is done. C ; This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, C ; for user (u) structure compatibility (because 16 bit is not C ; enough to keep byte position/offset of the disk), this C ; defect will not be corrected, user/program must request C ; 512 byte read per every 'sys read' call to block devices C ; for achieving correct result. In future version(s), C ; this defect will be corrected by using different C ; user (u) structure. 26/07/2013 - Erdogan Tan C C ; jsr r0,tstdeve / error on special file I/O C ; / (only works on tape) C ; mov *u.fofp,r1 / move block number to r1 C ; mov $2.-cold,-(sp) / "2-cold" to stack C ; 1: C ; cmp r1,(r0) / is this block # greater than or equal to C ; / maximum block # allowed on device C ; jnb short @f C ; bhis 1f / yes, 1f (error) C ; mov r1,-(sp) / no, put block # on stack C ; jsr r0,preread / read in the block into an I/O buffer C ; mov (sp)+,r1 / return block # to r1 C ; inc r1 / bump block # to next consecutive block C ; dec (sp) / "2-1-cold" on stack C ; bgt 1b / 2-1-cold = 0? No, go back and read in next block C ;1: C ; tst (sp)+ / yes, pop stack to clear off cold calculation C ;push cx ; ** C ;26/04/2013 C ;sub ax, 3 ; 3 to 8 -> 0 to 5 16F5 2C 03 C sub al, 3 C ; AL = Retro Unix 8086 v1 disk (block device) number 16F7 BF 2BFB R C mov di, offset brwdev ; block device number for direct I/O 16FA 88 05 C mov byte ptr [DI], al 16FC C bread0: ; 11/06/2015 16FC 51 C push cx ; ** C ; 14/07/2015 (Retro UNIX 8086 v1 modification!) C ; [u.fopf] points to byte position in disk, not sector/block ! 16FD 8B 1E 38DE R C mov bx, word ptr [u.fofp] 1701 8A 47 01 C mov al, byte ptr [BX+1] 1704 98 C cbw 1705 D0 E8 C shr al, 1 ; convert byte position to block/sector number C ; mov *u.fofp,r1 / restore r1 to initial value of the C ; / block # 1707 3B C1 C cmp ax, cx C ; cmp r1,(r0)+ / block # greater than or equal to maximum C ; / block number allowed 1709 72 03 E9 EBEE C jnb error ; 18/04/2013 C ; bhis error10 / yes, error C ;inc word ptr [BX] C ; inc *u.fofp / no, *u.fofp has next block number C ; AX = Block number (zero based) C ;;jsr r0,preread / read in the block whose number is in r1 170E C preread: ;; call preread 170E E8 017F C call bufaloc_0 ; 26/04/2013 C ;; jc error C ; BX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) C ; AX = Block/Sector number (r1) C ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number) C ; 14/03/2013 1711 74 07 C jz short @f ; Retro UNIX 8086 v1 modification C ; br 1f / branch if block already in a I/O buffer 1713 81 0F 0400 C or word ptr [BX], 400h ; set read bit (10) in I/O Buffer C ; bis $2000,(r5) / set read bit (bit 10 in I/O buffer) 1717 E8 00FB C call poke C ; jsr r0,poke / perform the read C ;;jc error ;2 0/07/2013 C ; 1: C ; clr *$ps / ps = 0 C ; rts r0 C ;; return from preread 171A C @@: 171A 81 0F 4000 C or word ptr [BX], 4000h C ; bis $40000,(r5) C ; / set bit 14 of the 1st word of the I/O buffer 171E C @@: ; 1: 171E F7 07 2400 C test word ptr [BX], 2400h C ; bit $22000,(r5) / are 10th and 13th bits set (read bits) 1722 74 05 C jz short @f C ; beq 1f / no C ; cmp cdev,$1 / disk or drum? C ; ble 2f / yes C ; tstb uquant / is the time quantum = 0? C ; bne 2f / no, 2f C ; mov r5,-(sp) / yes, save r5 (buffer address) C ; jsr r0,sleep; 31. C ; / put process to sleep in channel 31 (tape) C ; mov (sp)+,r5 / restore r5 C ; br 1b / go back C ;@@: ; 2: / drum or disk C ;; mov cx, word ptr [s.wait_]+2 ;; 29/07/2013 1724 E8 F7CB C call idle C ; jsr r0,idle; s.wait+2 / wait 1727 EB F5 C jmp short @b C ; br 1b 1729 C @@: ; 1: / 10th and 13th bits not set 1729 81 27 BFFF C and word ptr [BX], 0BFFFh ; 1011111111111111b C ; bic $40000,(r5) / clear bit 14 C ; jsr r0,tstdeve / test device for error (tape) C ;add bx, 8 C ; 26/04/2013 172D 83 C3 04 C add bx, 4 ; Retro Unix 8086 v1 modification ! C ; add $8,r5 / r5 points to data in I/O buffer C ; BX = system (I/O) buffer address 1730 E8 005C C call dioreg C ; jsr r0,dioreg / do bookkeeping on u.count etc. C ; 14/07/2015 C ; SI = start address of the transfer (in the buffer) C ; DI = [u.base] value before it gets updated C ; CX = transfer count (in bytes) C ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning C ; / of users data 1733 A1 3908 R C mov ax, word ptr [u.segmnt] C ; Retro Unix 8086 v1 feature only 1736 8E C0 C mov es, ax 1738 F3/ A4 C rep movsb 173A 8C D8 C mov ax, ds 173C 8E C0 C mov es, ax C ; movb (r5)+,(r2)+ / move data from the I/O buffer C ; dec r3 / to the user's area in core starting at u.base C ; bne 1b 173E 59 C pop cx ; ** 173F 83 3E 38E8 R 00 C cmp word ptr [u.count], 0 C ; tst u.count / done 1744 76 05 C jna short @f C ; beq 1f / yes, return C ; tst -(r0) / no, point r0 to the argument again 1746 BF 2BFB R C mov di, offset brwdev ; 11/06/2015 1749 EB B1 C jmp short bread0 C ; br bread / read some more 174B C @@: ; 1: 174B 58 C pop ax ; **** C ; mov (sp)+,r0 174C E9 FB81 C jmp ret_ C ;jmp ret / jump to routine that called readi C 174F C bwrite: C ; 14/07/2015 C ; 11/06/2015 C ; 20/07/2013 C ; 26/04/2013 Retro Unix 8086 v1 feature (device number) modifications C ; 14/03/2013 C ;; / write on block structured device C ; INPUTS -> C ; [u.fopf] points to the block number C ; CX = maximum block number allowed on device C ; ; that was an arg to bwrite, in original Unix v1, but C ; ; CX register is used instead of arg in Retro Unix 8086 v1 C ; [u.count] number of bytes to user desires to write C ; OUTPUTS -> C ; [u.fopf] points to next consecutive block to be written into C ; C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C ; C ; NOTE: Original UNIX v1 has/had a defect/bug here, even if write C ; byte count is less than 512, block number in *u.fofp (u.off) C ; is increased by 1. For example: If user/program request C ; to write 16 bytes in current block, 'sys write' increaces C ; the next block number just as 512 byte writing is done. C ; This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, C ; for user (u) structure compatibility (because 16 bit is not C ; enough to keep byte position/offset of the disk), this C ; defect will not be corrected, user/program must request C ; 512 byte write per every 'sys write' call to block devices C ; for achieving correct result. In future version(s), C ; this defect will be corrected by using different C ; user (u) structure. 26/07/2013 - Erdogan Tan C C ; jsr r0,tstdeve / test the device for an error C ;push cx ; ** C ;26/04/2013 C ;sub ax, 3 ; 3 to 8 -> 0 to 5 174F 2C 03 C sub al, 3 C ; AL = Retro Unix 8086 v1 disk (block device) number 1751 BF 2BFB R C mov di, offset brwdev ; block device number for direct I/O 1754 88 05 C mov byte ptr [DI], al 1756 C bwrite0: ; 11/06/2015 1756 51 C push cx ; ** C ; 14/07/2015 (Retro UNIX 8086 v1 modification!) C ; [u.fopf] points to byte position in disk, not sector/block ! 1757 8B 1E 38DE R C mov bx, word ptr [u.fofp] 175B 8A 47 01 C mov al, byte ptr [BX+1] 175E 98 C cbw 175F D0 E8 C shr al, 1 ; convert byte position to block/sector number C ; mov *u.fofp,r1 / put the block number in r1 1761 3B C1 C cmp ax, cx C ; cmp r1,(r0)+ / does block number exceed maximum allowable # C ; / block number allowed 1763 72 03 E9 EB94 C jnb error ; 18/04/2013 C ; bhis error10 / yes, error C ;inc word ptr [BX] C ; inc *u.fofp / no, increment block number 1768 E8 006C C call bwslot ; 26/04/2013 (wslot -> bwslot) C ; jsr r0,wslot / get an I/O buffer to write into 176B E8 0021 C call dioreg C ; jsr r0,dioreg / do the necessary bookkeeping C ; 14/07/2015 C ; SI = destination address (in the buffer) C ; DI = [u.base] value before it gets updated C ; CX = byte count to transfer C ; 1: / r2 points to the users data; r5 points to the I/O buffers data area 176E 87 F7 C xchg si, di ; 14/07/2015 1770 A1 3908 R C mov ax, word ptr [u.segmnt] C ; Retro Unix 8086 v1 feature only 1773 8E D8 C mov ds, ax 1775 F3/ A4 C rep movsb 1777 8C C8 C mov ax, cs 1779 8E D8 C mov ds, ax C ; movb (r2)+,(r5)+ / ; r3, has the byte count C ; dec r3 / area to the I/O buffer C ; bne 1b 177B E8 008F C call dskwr C ; jsr r0,dskwr / write it out on the device 177E 59 C pop cx ; ** 177F 83 3E 38E8 R 00 C cmp word ptr [u.count], 0 C ; tst u.count / done 1784 76 05 C jna short @f C ; beq 1f / yes, 1f C ; tst -(r0) / no, point r0 to the argument of the call 1786 BF 2BFB R C mov di, offset brwdev ; 11/06/2015 1789 EB CB C jmp short bwrite0 C ; br bwrite / go back and write next block 178B C @@: ; 1: 178B 58 C pop ax ; **** C ; mov (sp)+,r0 178C E9 FB41 C jmp ret_ C ; jmp ret / return to routine that called writei C C ;error10: C ; jmp error ; / see 'error' routine C 178F C dioreg: C ; 14/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block) C ; 14/03/2013 C ; bookkeeping on block transfers of data C ; C ; * returns value of u.base before it gets updated, in DI (r2) C ; * returns byte count (to transfer) in CX (<=512) C ; * returns byte offset from beginning of current sector buffer C ; (beginning of data) in SI C 178F 8B 0E 38E8 R C mov cx, word ptr [u.count] C ; mov u.count,r3 / move char count to r3 1793 81 F9 0200 C cmp cx, 512 C ; cmp r3,$512. / more than 512. char? 1797 76 03 C jna short @f C ; blos 1f / no, branch 1799 B9 0200 C mov cx, 512 C ; mov $512.,r3 / yes, just take 512. 179C C @@: ; 1: 179C 8B 3E 38E6 R C mov di, word ptr [u.base] C ; mov u.base,r2 / put users base in r2 17A0 01 0E 38EA R C add word ptr [u.nread], cx C ; add r3,u.nread / add the number to be read to u.nread 17A4 29 0E 38E8 R C sub word ptr [u.count], cx C ; sub r3,u.count / update count 17A8 01 0E 38E6 R C add word ptr [u.base], cx C ; add r3,u.base / update base C ; 14/07/2015 C ; Retro UNIX 8086 v1 - modification ! C ; (File pointer points to byte position, not block/sector no.) C ; (It will point to next byte position instead of next block no.) 17AC 8B 36 38DE R C mov si, word ptr [u.fofp] ; u.fopf points to byte position pointer 17B0 8B 04 C mov ax, word ptr [si] ; si points to current byte pos. on the disk 17B2 01 0C C add word ptr [si], cx ; cx is added to set the next byte position 17B4 25 01FF C and ax, 1FFh ; get offset from beginning of current block 17B7 8B F3 C mov si, bx ; beginning of data in sector/block buffer 17B9 03 F0 C add si, ax ; esi contains start address of the transfer 17BB C3 C retn C ; rts r0 / return 17BC C dskrd: C ; 14/07/2015 C ; 29/07/2013 C ; 20/07/2013 C ; 26/04/2013 C ; 14/03/2013 C ; C ; 'dskrd' acquires an I/O buffer, puts in the proper C ; I/O queue entries (via bufaloc) then reads a block C ; (number specified in r1) in the acquired buffer.) C ; If the device is busy at the time dskrd is called, C ; dskrd calls idle. C ; C ; INPUTS -> C ; r1 - block number C ; cdev - current device number C ; OUTPUTS -> C ; r5 - points to first data word in I/O buffer C ; C ; ((AX = R1)) input/output C ; ((BX = R5)) output C ; C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C ; 17BC E8 00C6 C call bufaloc C ; jsr r0,bufaloc / shuffle off to bufaloc; C ; / get a free I/O buffer C ;;jc error ; 20/07/2013 17BF 74 07 C jz short @f ; Retro UNIX 8086 v1 modification C ; br 1f / branch if block already in a I/O buffer 17C1 C dskrd_0: 17C1 81 0F 0400 C or word ptr [BX], 400h ; set read bit (10) in I/O Buffer C ; bis $2000,(r5) / set bit 10 of word 1 of C ; / I/O queue entry for buffer 17C5 E8 004D C call poke C ; jsr r0,poke / just assigned in bufaloc, C ; / bit 10=1 says read C ;;jc error ; 20/07/2013 17C8 C @@: ; 1: C ;clr *$ps 17C8 F7 07 2400 C test word ptr [BX], 2400h C ; bit $22000,(r5) / if either bits 10, or 13 are 1; C ; jump to idle 17CC 74 05 C jz short @f C ; beq 1f C ;; mov cx, word ptr [s.wait_]+2 ;; 29/07/2013 17CE E8 F721 C call idle C ; jsr r0,idle; s.wait+2 17D1 EB F5 C jmp short @b C ; br 1b 17D3 C @@: ; 1: C ;add bx, 8 C ; 26/04/2013 17D3 83 C3 04 C add bx, 4 ; Retro Unix 8086 v1 modification ! C ; add $8,r5 / r5 points to first word of data in block C ; / just read in 17D6 C3 C retn C ; rts r0 C 17D7 C bwslot: C ; 14/07/2015 C ; If the block/sector is not placed in a buffer C ; before 'wslot', it must be read before C ; it is written! (Otherwise transfer counts less C ; than 512 bytes will be able to destroy existing C ; data on disk.) C ; C ; 26/04/2013 C ; Retro UNIX 8086 v1 modification ! C ; ('bwslot' will be called from 'bwrite' only!) C ; INPUT -> DI - points to device id (in brwdev) C ; -> AX = block number C ; 17D7 E8 00B6 C call bufaloc_0 17DA 74 1E C jz short @f ; wslot_0 ; sector already is in the buffer 17DC C bwslot_0: C ; 14/07/2015 17DC 8B 36 38DE R C mov si, word ptr [u.fofp] 17E0 8B 04 C mov ax, word ptr [si] 17E2 25 01FF C and ax, 1FFh ; offset from beginning of the sector/block 17E5 75 08 C jnz short bwslot_1 ; it is not a full sector write C ; recent disk data must be placed in the buffer 17E7 81 3E 38E8 R 0200 C cmp word ptr [u.count], 512 17ED 73 0B C jnb short @f ;wslot_0 17EF C bwslot_1: 17EF E8 FFCF C call dskrd_0 17F2 83 EB 04 C sub bx, 4 ; set bx to the buffer header address again 17F5 EB 03 C jmp short @f ; wslot_0 C 17F7 C wslot: C ; 29/07/2013 C ; 20/07/2013 C ; 26/04/2013 C ; 14/03/2013 C ; C ; 'wslot' calls 'bufaloc' and obtains as a result, a pointer C ; to the I/O queue of an I/O buffer for a block structured C ; device. It then checks the first word of I/O queue entry. C ; If bits 10 and/or 13 (read bit, waiting to read bit) are set, C ; wslot calls 'idle'. When 'idle' returns, or if bits 10 C ; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first C ; word of the I/O queue entry (write bit, inhibit bit). C ; C ; INPUTS -> C ; r1 - block number C ; cdev - current (block/disk) device number C ; C ; OUTPUTS -> C ; bufp - bits 9 and 15 are set, C ; the remainder of the word left unchanged C ; r5 - points to first data word in I/O buffer C ; C ; ((AX = R1)) input/output C ; ((BX = R5)) output C ; C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C 17F7 E8 008B C call bufaloc C ; jsr r0,bufaloc / get a free I/O buffer; pointer to first C ;;jc error ; 20/07/2013 C ; BX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) C ; AX = Block/Sector number (r1) C ; jz short @f C ; br 1f / word in buffer in r5 C ;wslot_0: 17FA C @@: ;1: 17FA F7 07 2400 C test word ptr [BX], 2400h C ; bit $22000,(r5) / check bits 10, 13 (read, waiting to read) C ; / of I/O queue entry 17FE 74 05 C jz short @f C ; beq 1f / branch if 10, 13 zero (i.e., not reading, C ; / or not waiting to read) C C ;; mov cx, word ptr [s.wait_]+2 ; 29/07/2013 1800 E8 F6EF C call idle C ; jsr r0,idle; / if buffer is reading or writing to read, C ; / idle 1803 EB F5 C jmp short @b C ; br 1b / till finished 1805 C @@: ;1: 1805 81 0F 8200 C or word ptr [BX], 8200h C ; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue C ; / (write, inhibit bits) C ; clr *$ps / clear processor status C ;add bx, 8 C ; 26/04/2013 1809 83 C3 04 C add bx, 4 ; Retro Unix 8086 v1 modification ! C ; add $8,r5 / r5 points to first word in data area C ; / for this block 180C C3 C retn C ; rts r0 180D C dskwr: C ; 03/08/2013 C ; 31/07/2013 C ; 20/07/2013 C ; 26/04/2013 C ; 14/03/2013 C ; C ; 'dskwr' writes a block out on disk, via ppoke. The only C ; thing dskwr does is clear bit 15 in the first word of I/O queue C ; entry pointed by 'bufp'. 'wslot' which must have been called C ; previously has supplied all the information required in the C ; I/O queue entry. C ; C ; (Modified registers: CX, DX, BX, SI, DI) C ; C ; C ; 03/08/2013 (si -> bx) 180D 8B 1E 2BBE R C mov bx, word ptr [bufp] 1811 81 27 7FFF C and word ptr [bx], 7FFFh ; 0111111111111111b C ; bic $100000,*bufp / clear bit 15 of I/O queue entry at C ; / bottom of queue 1815 C ppoke: C ; mov $340,*$ps C ; jsr r0,poke C ; clr *$ps C ; rts r0 1815 C poke: C ; 11/06/2015 C ; 18/01/2014 C ; 31/07/2013 C ; 23/07/2013 C ; 20/07/2013 C ; 17/07/2013 C ; 09/07/2013 C ; 26/04/2013 C ; 24/03/2013 AX (r1) -> push/pop (to save physical block number) C ; 15/03/2013 C ; (NOTE: There are some disk I/O code modifications & extensions C ; & exclusions on original 'poke' & other device I/O procedures of C ; UNIX v1 OS for performing disk I/O functions by using IBM PC C ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) C ; C ; Basic I/O functions for all block structured devices C ; (Modified registers: CX, DX, SI, DI) C C ; 20/07/2013 modifications C ; (Retro UNIX 8086 v1 features only !) C ; INPUTS -> C ; (BX = buffer header address) C ; OUTPUTS -> C ; cf=0 -> successed r/w (at least, for the caller's buffer) C ; cf=1 -> error, word ptr [BX] = 0FFFFh C ; (drive not readi or r/w error!) C ; (word ptr [BX]+2 <> 0FFFFh indicates r/w success) C ; (word ptr [BX]+2 = FFFFh mean RW/IO error) C ; (also it indicates invalid buffer data) C C ; 17/07/2013 1815 53 C push bx C ; 24/03/2013 C ; mov r1,-(sp) C ; mov r2,-(sp) C ; mov r3,-(sp) 1816 50 C push ax ; Physical Block Number (r1) (mget) C ;mov si, offset bufp + nbuf + nbuf + 6 C ; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority C ; / I/O queue pointer 1817 BE 2BCE R C mov si, offset bufp + (2*nbuf) + (2*2) ; 09/07/2013 181A C poke_1: ; 1: 181A 4E C dec si 181B 4E C dec si 181C 8B 1C C mov bx, word ptr [SI] C ; mov -(r2),r1 / r1 points to an I/O queue entry 181E 8B 07 C mov ax, word ptr [BX] ; 17/07/2013 1820 F6 C4 06 C test ah, 06h C ;test word ptr [BX], 600h ; 0000011000000000b C ; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O C ; / queue entry 1823 74 4E C jz short poke_2 C ; beq 2f / branch to 2f if both are clear C ; 31/07/2013 C ;test ah, 0B0h ; (*) C ;;test word ptr [BX], 0B000h ; 1011000000000000b C ; bit $130000,(r1) / test bits 12, 13, and 15 C ;jnz short poke_2 ; 31/07/2013 (*) C ; bne 2f / branch if any are set 1825 8A 0F C mov cl, byte ptr [BX] ; 26/04/2013 ; Device Id C ; movb (r1),r3 / get device id 1827 32 ED C xor ch, ch ; mov ch, 0 ; 26/04/2013 1829 8B F9 C mov di, cx ; 11/06/2015 182B 33 C0 C xor ax, ax ; 0 C ;cmp byte ptr [DI]+drv.err, al ; 0 ; 26/04/2013 C ; tstb deverr(r3) / test for errors on this device C ;jna short poke_3 C ; beq 3f / branch if no errors C ; 20/07/2013 C ;dec ax C ;mov word ptr [BX]+2, ax ; FFFFh ; -1 C ; mov $-1,2(r1) / destroy associativity C ;inc ah ; 0 C ;mov word ptr [BX], ax ; 00FFh, reset C ; clrb 1(r1) / do not do I/O C ;jmp short poke_2 C ; ; br 2f C ; rts r0 182D C poke_3: ; 3: C ; 26/04/2013 Modification 182D FE C0 C inc al ; mov ax, 1 182F 0A C9 C or cl, cl ; Retro UNIX 8086 v1 device id. 1831 74 02 C jz short @f ; cl = 0 1833 D2 E0 C shl al, cl ; shl ax, cl 1835 C @@:: C ;test word ptr [active], ax 1835 84 06 2BFA R C test byte ptr [active], al C ; bit $2,active / test disk busy bit 1839 75 38 C jnz short poke_2 C ; bne 2f / branch if bit is set C ;or word ptr [active], ax 183B 08 06 2BFA R C or byte ptr [active], al C ; bis $2,active / set disk busy bit 183F 50 C push ax ; 17/07/2013 1840 E8 00B2 C call diskio ; Retro UNIX 8086 v1 Only ! 1843 88 A5 2BD6 R C mov byte ptr [DI]+drv.err, ah 1847 58 C pop ax 1848 73 0B C jnc short @f ; 20/07/2013 C ; tstb deverr(r3) / test for errors on this device C ; beq 3f / branch if no errors C ; 20/07/2013 184A C7 47 02 FFFF C mov word ptr [BX]+2, 0FFFFh ; -1 C ; mov $-1,2(r1) / destroy associativity 184F C6 47 01 00 C mov byte ptr [BX]+1, 0 C ; clrb 1(r1) / do not do I/O 1853 EB 1E C jmp short poke_2 1855 C @@: ; 20/07/2013 C ; 17/07/2013 1855 F6 D0 C not al 1857 20 06 2BFA R C and byte ptr [active], al ; reset, not busy C ; BX = system I/O buffer header (queue entry) address 185B C seta: ; / I/O queue bookkeeping; set read/write waiting bits. 185B 8B 07 C mov ax, word ptr [BX] C ; mov (r1),r3 / move word 1 of I/O queue entry into r3 185D 25 0600 C and ax, 600h C ; bic $!3000,r3 / clear all bits except 9 and 10 1860 81 27 F9FF C and word ptr [BX], 0F9FFh C ; bic $3000,(r1) / clear only bits 9 and 10 C ;shl ax, 1 C ;shl ax, 1 C ;shl ax, 1 C ; rol r3 C ; rol r3 C ; rol r3 C ; 23/07/2013 1864 D0 E4 C shl ah, 1 1866 D0 E4 C shl ah, 1 1868 D0 E4 C shl ah, 1 186A 09 07 C or word ptr [BX], ax C ; bis r3,(r1) / or old value of bits 9 and 10 with C ; bits 12 and 13 186C E8 F683 C call idle ; 18/01/2014 C ;; sti C ;hlt ; wait for a hardware interrupt C ;; cli C ; NOTE: In fact, disk controller's 'disk I/O completed' C ; interrupt would be used to reset busy bits, but INT 13h C ; returns when disk I/O is completed. So, here, as temporary C ; method, this procedure will wait for a time according to C ; multi tasking and time sharing concept. 186F F7 D0 C not ax 1871 21 07 C and word ptr [BX], ax ; clear bits 12 and 13 1873 C poke_2: ;2: 1873 81 FE 2BBE R C cmp si, offset bufp C ; cmp r2,$bufp / test to see if entire I/O queue C ; / has been scanned 1877 77 A1 C ja short poke_1 C ; bhi 1b C ; 24/03/2013 C ; mov (sp)+,r3 C ; mov (sp)+,r2 C ; mov (sp)+,r1 1879 58 C pop ax ; Physical Block Number (r1) (mget) C ; 17/07/2013 187A 5B C pop bx C ; 20/07/2013 187B 83 7F 02 FF C cmp word ptr [BX]+2, 0FFFFh 187F 75 03 E9 EA78 C je error C ; 'poke' returns with cf=0 if the requested buffer is read C ; or written succesfully; even if an error occurs while C ; reading to or writing from other buffers. 20/07/2013 C ; C ;cmc 1884 C3 C retn C ; rts r0 C 1885 C bufaloc: C ; 29/07/2013 C ; 20/07/2013 C ; 09/07/2013 C ; 26/04/2013 (device number/id modifications) C ; 13/03/2013 C ; bufaloc - Block device I/O buffer allocation C ; C ; INPUTS -> C ; r1 - block number C ; cdev - current (block/disk) device number C ; bufp+(2*n)-2 --- n = 1 ... nbuff C ; OUTPUTS -> C ; r5 - pointer to buffer allocated C ; bufp ... bufp+12 --- (bufp), (bufp)+2 C ; C ; ((AX = R1)) input/output C ; ((BX = R5)) output C ; ((Modified registers: DX, CX, BX, SI, DI, BP)) C ; zf=1 -> block already in a I/O buffer C ; zf=0 -> a new I/O buffer has been allocated C ; ((DL = Device ID)) C ; (((DH = 0 or 1))) C ; (((CX = previous value of word ptr [bufp]))) C ; ((CX and DH will not be used after return))) C C ;;push si ; *** C ; mov r2,-(sp) / save r2 on stack C ; mov $340,*$ps / set processor priority to 7 C ; 20/07/2013 C ; 26/04/2013 1885 32 FF C xor bh, bh 1887 8A 1E 2BD2 R C mov bl, byte ptr [cdev] ; 0 or 1 188B BF 2BD4 R C mov di, offset rdev ; offset mdev = offset rdev + 1 188E 03 FB C add di, bx 1890 C bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !! C ;; DI points to device id. C ; 20/07/2013 1890 8A 1D C mov bl, byte ptr [DI] ; DI -> rdev/mdev or brwdev 1892 32 FF C xor bh, bh 1894 80 BF 2BDC R FF C cmp byte ptr [BX]+drv.pdn, 0FFh ; Drive not ready ! 1899 75 03 E9 EA5E C je error ; 20/07/2013 189E C @@: 189E 8B D3 C mov dx, bx ; dh = 0, dl = device number (0 to 5) 18A0 33 ED C xor bp, bp ; 0 18A2 55 C push bp ; 0 18A3 8B EC C mov bp, sp C ; 18A5 C bufaloc_1: ;1: C ; clr -(sp) / vacant buffer 18A5 BE 2BBE R C mov si, offset bufp C ; mov $bufp,r2 / bufp contains pointers to I/O queue C ; / entrys in buffer area 18A8 C bufaloc_2: ;2: 18A8 8B 1C C mov bx, word ptr [SI] 18AA 46 C inc si 18AB 46 C inc si C ; mov (r2)+,r5 / move pointer to word 1 of an I/O C ; queue entry into r5 18AC F7 07 F600 C test word ptr [BX], 0F600h C ; bit $173000,(r5) / lock+keep+active+outstanding 18B0 75 03 C jnz short bufaloc_3 C ; bne 3f / branch when C ; / any of bits 9,10,12,13,14,15 are set C ; / (i.e., buffer busy) 18B2 89 76 00 C mov word ptr [BP], si ; pointer to word 2 of I/0 queue C ; entry C ; mov r2,(sp) ;/ save pointer to last non-busy buffer C ; / found points to word 2 of I/O queue entry) 18B5 C bufaloc_3: ;3: C ;mov dl, byte ptr [DI] ; 26/04/2013 C ; 18B5 38 17 C cmp byte ptr [BX], dl C ; cmpb (r5),cdev / is device in I/O queue entry same C ; / as current device 18B7 75 0A C jne short bufaloc_4 C ; bne 3f 18B9 39 47 02 C cmp word ptr [BX]+2, ax C ; cmp 2(r5),r1 / is block number in I/O queue entry, C ; / same as current block number 18BC 75 05 C jne short bufaloc_4 C ; bne 3f C ;add sp, 2 18BE 59 C pop cx C ; tst (sp)+ / bump stack pointer 18BF 4E C dec si ; 09/07/2013 18C0 4E C dec si ; 09/07/2013 18C1 EB 1E C jmp short bufaloc_7 ; Retro Unix 8086 v1 modification C ; jump to bufaloc_6 in original Unix v1 C ; br 1f / use this buffer 18C3 C bufaloc_4: ;3: 18C3 81 FE 2BCA R C cmp si, offset bufp + nbuf + nbuf C ; cmp r2,$bufp+nbuf+nbuf 18C7 72 DF C jb short bufaloc_2 C ; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all C ; / buffers not checked) 18C9 5E C pop si C ; mov (sp)+,r2 / once all bufs are examined move pointer C ; / to last free block 18CA 0B F6 C or si, si 18CC 75 08 C jnz short bufaloc_5 C ; bne 2f / if (sp) is non zero, i.e., C ; / if a free buffer is found branch to 2f C ;; mov cx, word ptr [s.wait_]+2 ;; 29/07/2013 18CE E8 F621 C call idle C ; jsr r0,idle; s.wait+2 / idle if no free buffers C ; 26/04/2013 C ;xor dx, dx 18D1 32 D2 C xor dl, dl 18D3 52 C push dx ; 0 C ; 18D4 EB CF C jmp short bufaloc_1 C ; br 1b 18D6 C bufaloc_5: ;2: C ; tst (r0)+ / skip if warmed over buffer 18D6 FE C6 C inc dh ; Retro UNIX 8086 v1 modification 18D8 C bufaloc_6: ;1: 18D8 4E C dec si 18D9 4E C dec si 18DA 8B 1C C mov bx, word ptr [SI] C ; mov -(r2),r5 / put pointer to word 1 of I/O queue C ; / entry in r5 C ;; 26/04/2013 C ;mov dl, byte ptr [DI] ; byte ptr [rdev] or byte ptr [mdev] 18DC 88 17 C mov byte ptr [BX], dl C ; movb cdev,(r5) / put current device number C ; / in I/O queue entry 18DE 89 47 02 C mov word ptr [BX]+2, ax C ; mov r1,2(r5) / move block number into word 2 C ; / of I/O queue entry 18E1 C bufaloc_7: ;1: 18E1 81 FE 2BBE R C cmp si, offset bufp C ; cmp r2,$bufp / bump all entrys in bufp C ; / and put latest assigned 18E5 76 09 C jna short bufaloc_8 C ; blos 1f / buffer on the top C ; / (this makes if the lowest priority) 18E7 4E C dec si 18E8 4E C dec si 18E9 8B 0C C mov cx, word ptr [SI] 18EB 89 4C 02 C mov word ptr [SI]+2, cx C ; mov -(r2),2(r2) / job for a particular device 18EE EB F1 C jmp short bufaloc_7 C ; br 1b 18F0 C bufaloc_8: ;1: 18F0 89 1C C mov word ptr [SI], bx C ; mov r5,(r2) C ;;pop si ; *** C ; mov (sp)+,r2 / restore r2 18F2 0A F6 C or dh, dh ; 0 or 1 ? C ; Retro UNIX 8086 v1 modification C ; zf=1 --> block already in a I/O buffer C ; zf=0 --> a new I/O buffer has been allocated C 18F4 C3 C retn C ; rts r0 C 18F5 C diskio: C ; 26/04/2013 Device ID modifications C ; 15/03/2013 C ; Retro UNIX 8086 v1 feature only ! C ; C ; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011) C ; 04/07/2009 - 20/07/2011 C ; C ; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes) C ; C ; INPUTS -> C ; BX = System I/O Buffer header address C ; OUTPUTS -> cf=0 --> done C ; cf=1 ---> error code in AH C ; C ; (Modified registers: CX,DX,AX) C C ;; I/O Queue Entry (of original UNIX operating system v1) C ;; Word 1, Byte 0 = device id C ;; Word 1, Byte 1 = (bits 8 to 15) C ;; bit 9 = write bit C ;; bit 10 = read bit C ;; bit 12 = waiting to write bit C ;; bit 13 = waiting to read bit C ;; bit 15 = inhibit bit C ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) C ;; C ;; Original UNIX v1 -> ; 26/04/2013 C ;; Word 3 = number of words in buffer (=256) C ;; Original UNIX v1 -> ; 26/04/2013 C ;; Word 4 = bus address (addr of first word of data buffer) C ;; C ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! C ;; C ;; Device IDs (of Retro Unix 8086 v1) ; 26/04/2013 C ;; 0 = fd0 C ;; 1 = fd1 C ;; 2 = hd0 C ;; 3 = hd1 C ;; 4 = hd2 C ;; 5 = hd3 C 18F5 BA 0201 C mov dx, 0201h ; Read 1 sector/block 18F8 8B 07 C mov ax, word ptr [BX] C ; 26/04/2013 18FA 56 C push si ; **** 18FB 8A C8 C mov cl, al 18FD 32 ED C xor ch, ch 18FF 8B F1 C mov si, cx C ; 1901 F6 C4 02 C test ah, 2 C ;test ax, 200h ; Bit 9 of word 0 (status word) C ; write bit 1904 74 02 C jz short @f C ;test ah, 4 C ;;test ax, 400h ; Bit 10 of word 0 (status word) C ; ; read bit C ;jz short diskio_ret 1906 FE C6 C inc dh ; 03h = write 1908 C @@: C ;mov cx, 4 ; Retry Count 1908 B1 04 C mov cl, 4 C C ; push ds C ; pop es 190A C @@: 190A 52 C push dx ; *** 190B 53 C push bx ; *** 190C 51 C push cx ; *** 190D 52 C push dx ; ** ; I/O type (Int 13h function, r/w) 190E 43 C inc bx ; +1 190F 43 C inc bx ; +2 1910 8B 07 C mov ax, word ptr [BX] ; Block/Sector number 1912 33 D2 C xor dx, dx 1914 D1 E6 C shl si, 1 ; 2 * device number ; 26/04/2013 1916 8B 8C 2BE2 R C mov cx, word ptr [SI]+drv.spt C ; Sectors per track 191A F7 F1 C div cx 191C 8B CA C mov cx, dx ; remainder, sector (zero based) 191E 41 C inc cx ; sector (1 based) 191F 51 C push cx ; * 1920 8B 8C 2BEE R C mov cx, word ptr [SI]+drv.hds ; Heads 1924 33 D2 C xor dx, dx C ; ax = track number 1926 F7 F1 C div cx 1928 8A F2 C mov dh, dl ; head number (<=255) 192A D1 EE C shr si, 1 ; device number ; 26/04/2013 192C 8A 94 2BDC R C mov dl, byte ptr [SI]+drv.pdn ; 26/04/2013 C ; Physical device number 1930 59 C pop cx ; * ; cx = sector of track (1 to spt) 1931 43 C inc bx ; +2 1932 43 C inc bx ; +3 ; I/O Buffer (Data) 1933 8A E8 C mov ch, al ; low 8 bytes of cylinder number 1935 D0 CC C ror ah, 1 1937 D0 CC C ror ah, 1 1939 0A CC C or cl, ah 193B 58 C pop ax ; ** ; AH=2-read, AH=3-write 193C CD 13 C int 13h ; AL-count CH-track CL-sect C ; DH-head DL-drive ES:BX-buffer C ; CF-flag AH-stat AL-sec read 193E 59 C pop cx ; *** 193F 5B C pop bx ; *** 1940 73 0D C jnc short @f 1942 80 F9 01 C cmp cl, 1 1945 72 08 C jb short @f 1947 32 E4 C xor ah, ah ; Disk Reset 1949 CD 13 C int 13h 194B 49 C dec cx 194C 5A C pop dx ; *** 194D EB BB C jmp short @b 194F C @@: 194F 5A C pop dx ; *** 1950 5E C pop si ; **** C 1951 C3 C retn C include u9.asm ; u9.s C ; **************************************************************************** C ; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks) C ; ---------------------------------------------------------------------------- C ; U9.ASM (include u9.asm) //// UNIX v1 -> u9.s C C ; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix) C ; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) C ; 1.44 MB Floppy Disk C ; (11/03/2013) C ; C ; [ Last Modification: 30/06/2015 ] ;;; completed ;;; C ; C ; Derivation from UNIX Operating System (v1.0 for PDP-11) C ; (Original) Source Code by Ken Thompson (1971-1972) C ; C ; C ; C ; **************************************************************************** C C ; 01/09/2014 C ; 28/08/2014 C ; 28/07/2014 C ; 27/07/2014 C ; 23/07/2014 C ; 20/07/2014 C ; 12/07/2014 C ; 04/07/2014 C ; 30/06/2014 C ; 27/06/2014 C ; 25/06/2014 C ; 11/06/2014 C ; 03/06/2014 C ; 02/06/2014 C ; 05/05/2014 C ; 30/04/2014 C ; 17/04/2014 C ; 15/04/2014 C ; 04/04/2014 scroll_up C ; 07/03/2014 C ; 04/03/2014 act_disp_page --> tty_sw C ; 03/03/2014 int_09h, int_16h C ; 28/02/2014 int_16h C ; 17/02/2014 C ; 14/02/2014 C ; 01/02/2014 write_tty C ; 18/01/2014 C ; 17/01/2014 C ; 13/01/2014 getc, putc C ; 12/12/2013 C ; 10/12/2013 C ; 07/12/2013 C ; 04/12/2013 getc, putc, write_tty C ; 04/11/2013 drv_init C ; 24/07/2013 bf_init C ; 20/07/2013 bf_init C ; 19/07/2013 drv_init C ; 18/07/2013 drv_init C ; 17/07/2013 bf_init C ; 14/07/2013 C ; 13/07/2013 drv_init, dparam (Retro UNIX 8086 v1 features only!) C ; 21/05/2013 'ocvt' & 'ccvt' routines (in U7.ASM) C ; 15/05/2013 'rcvt' & 'xmtt' routines (in U6.ASM) C ; 11/03/2013 C C ;;rcvt: C ;; 'rcvt' routine is in U6.ASM (Retro UNIX 8086 v1 modification!) C C ;;xmtt: C ;; 'xmtt' routine is in U6.ASM (Retro UNIX 8086 v1 modification!) C C ;;ocvt: C ;; 'ocvt' routine is in U7.ASM (Retro UNIX 8086 v1 modification!) C C ;;ccvt: C ;; 'ccvt' routine is in U7.ASM (Retro UNIX 8086 v1 modification!) C 1952 C drv_init: C ; 04/11/2013 C ; 19/07/2013 C ; 18/07/2013 C ; 14/07/2013 C ; 13/07/2013 C ; Retro UNIX 8086 v1 feature only ! C ; C ; Derived from DRVINIT.ASM (DRVINIT4) file of TR-DOS project C ; by Erdogan Tan, (26/09/2009 --> 07/08/2011) C ; C ; Modified/Simplified for Retro UNIX 8086 v1 C ; C ; (LBA disks excluded, hard disk file systems excluded) C ; C ; ((RUFS and/or TRFS/SINGLIX partitions will be validated C ; in future RUNIX/TR-UNIX versions if they will be available.) C ; C ; Input: none C ; Output: C ; cf = 0 -> disk drive initialization is ok. C ; cf = 1 -> error (error code in ah) C ; ((Modified registers: AX, BX, CX, DX, SI, DI)) 1952 C fd_init: 1952 33 D2 C xor dx, dx ; fd0 1954 33 F6 C xor si, si ; 0 1956 E8 0064 C call dparam 1959 46 C inc si ; 1 195A 3C 02 C cmp al, 2 ; 04/11/2013 195C 72 05 C jb short hd_init 195E FE C2 C inc dl ; fd1 1960 E8 005A C call dparam 1963 C hd_init: 1963 46 C inc si ; 2 1964 B2 80 C mov dl, 80h ; hd0 1966 E8 0054 C call dparam 1969 72 15 C jc short drv_init_lbs C ; al = number of hard disk drives 196B 3C 02 C cmp al, 2 ; 04/11/2013 196D 72 11 C jb short drv_init_lbs 196F A2 2BFB R C mov byte ptr [brwdev], al ; 19/07/2013 1972 C @@: 1972 FE 0E 2BFB R C dec byte ptr [brwdev] ; 19/07/2013 1976 74 08 C jz short drv_init_lbs 1978 46 C inc si 1979 FE C2 C inc dl 197B E8 003F C call dparam 197E EB F2 C jmp short @b C 1980 C drv_init_lbs: 1980 0E C push cs ; 14/07/2013 1981 07 C pop es ; 14/07/2013 1982 33 DB C xor bx, bx 1984 8A 16 2564 R C mov dl, byte ptr [unixbootdrive] 1988 C @@: 1988 3A 97 2BDC R C cmp dl, byte ptr [BX]+drv.pdn 198C 74 0E C je short @f 198E 3B DE C cmp bx, si ; 19/07/2013 1990 73 04 C jnb short drv_init_err 1992 FE C3 C inc bl 1994 EB F2 C jmp short @b 1996 C drv_init_err: 1996 8A A7 2BD6 R C mov ah, byte ptr [BX]+drv.err 199A F9 C stc 199B C3 C retn 199C C @@: 199C 80 BF 2BD6 R 00 C cmp byte ptr [BX]+drv.err, 0 19A1 77 F3 C ja short drv_init_err 19A3 BE 2566 R C mov si, offset sb0 ; super block buffer 19A6 88 1C C mov byte ptr [SI], bl ; Device Id 19A8 C6 44 01 04 C mov byte ptr [SI]+1, 4 ; Bit 10, C ; read bit 19AC 88 1E 2BD4 R C mov byte ptr [rdev], bl ; 19/07/2013 19B0 8B DE C mov bx, si 19B2 FE 47 02 C inc byte ptr [BX]+2 ; physical block number = 1 19B5 E8 FF3D C call diskio 19B8 C6 47 01 00 C mov byte ptr [BX]+1, 0 ; 18/07/2013 19BC C3 C retn C 19BD C dparam: C ; 13/07/2013 C ; Retro UNIX 8086 v1 feature only ! C ; 19BD 52 C push dx 19BE B4 08 C mov ah, 08h 19C0 CD 13 C int 13h 19C2 88 A4 2BD6 R C mov byte ptr [SI]+drv.err, ah 19C6 73 02 C jnc short @f 19C8 C dparam_error: 19C8 5A C pop dx 19C9 C3 C retn 19CA C @@: 19CA 8A C2 C mov al, dl ; Number of disk drives C ;cmp al, 1 C ;jb short dparam_err C ; dh = last head number 19CC FE C6 C inc dh 19CE 8A D6 C mov dl, dh 19D0 32 F6 C xor dh, dh 19D2 D1 E6 C shl si, 1 ; align to word ptr drv.hds 19D4 89 94 2BEE R C mov word ptr [SI]+drv.hds, dx C ; number of heads 19D8 83 E1 3F C and cx, 3Fh C ; SI is already aligned for word ptr drv.spt 19DB 89 8C 2BE2 R C mov word ptr [SI]+drv.spt, cx 19DF D1 EE C shr si, 1 ; align to byte ptr drv.pdn 19E1 5A C pop dx 19E2 88 94 2BDC R C mov byte ptr [SI]+drv.pdn, dl C ; Physical drive number 19E6 C3 C retn C 19E7 C bf_init: C ; 24/07/2013 (from last to first) C ; 20/07/2013 Device id reset (0FFh) C ; 17/07/2013 C ; Buffer (pointer) initialization ! C ; C ; Retro UNIX 8086 v1 feature only ! C ; 19E7 B1 06 C mov cl, nbuf 19E9 BF 2BBE R C mov di, offset bufp C ; 24/07/2013 19EC B8 38CC R C mov ax, offset Buffer + (nbuf*516) 19EF BA FFFF C mov dx, 0FFFFh 19F2 C @@: C ; 24/07/2013 19F2 2D 0204 C sub ax, 516 ; 4 header + 512 data 19F5 AB C stosw 19F6 8B F0 C mov si, ax ; 24/07/2013 C ; mov word ptr [SI], dx ; 0FF00h 19F8 88 14 C mov byte ptr [SI], dl ; 0FFh C ; Not a valid device sign C ;mov word ptr [SI]+2, dx ; 0FFFFh C ; Not a valid block number sign 19FA FE C9 C dec cl 19FC 75 F4 C jnz short @b 19FE B8 2566 R C mov ax, offset sb0 1A01 AB C stosw 1A02 B8 276A R C mov ax, offset sb1 1A05 AB C stosw C ; 20/07/2013 1A06 8B F0 C mov si, ax ; offset sb1 1A08 88 14 C mov byte ptr [SI], dl ; 0FFh C ;mov word ptr [SI]+2, dx ; 0FFFFh C ; 1A0A C3 C retn C 1A0B C getc: C ;04/07/2014 (rcvc has been removed) C ; (serial port interrupts) C ;27/06/2014 (rcvc, EOT) C ;03/06/2014 (rcvc) C ;02/06/2014 (rcvc has been moved here again) C ;05/05/2014 (rcvc has been moved from here) C ;17/04/2014 C ;15/04/2014 (rcvc) C ;17/02/2014 C ;14/02/2014 C ;17/01/2014 C ;13/01/2014 C ;10/12/2013 C ;20/10/2013 C ;10/10/2013 C ;05/10/2013 C ;24/09/2013 C ;20/09/2013 C ;29/07/2013 (getc_s, sleep -> idle) C ;28/07/2013 (byte ptr [u.ttyn] = tty number) C ;16/07/2013 C ;20/05/2013 C ;14/05/2013 (AH input instead of 'mov ax, byte ptr [ptty]') C ;13/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; C ; 'getc' gets (next) character C ; from requested TTY (keyboard) buffer C ; INPUTS -> C ; [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2) C ; AL=0 -> Get (next) character from requested TTY buffer C ; (Keyboard buffer will point to C ; next character at next call) C ; AL=1 -> Test a key is available in requested TTY buffer C ; (Keyboard buffer will point to C ; current character at next call) C ; OUTPUTS -> C ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) C ; ZF=0 -> AX has (current) character C ; AL = ascii code C ; AH = scan code (AH = line status for COM1 or COM2) C ; (cf=1 -> error code/flags in AH) C ; Original UNIX V1 'getc': C ; get a character off character list C ; C ; ((Modified registers: AX, BX, -CX-, -DX-, -SI-, -DI-)) C ; C C ; 16/07/2013 C ; mov byte ptr [getctty], ah C ; C 1A0B 8A 26 390A R C mov ah, byte ptr [u.ttyn] ; 28/07/2013 1A0F C getc_n: C ; 10/10/2013 1A0F BB 2C7A R C mov bx, offset ttychr 1A12 22 E4 C and ah, ah 1A14 74 07 C jz short @f 1A16 D0 E4 C shl ah, 1 C ; 17/02/2014 1A18 02 DC C add bl, ah 1A1A 80 D7 00 C adc bh, 0 C ; 24/09/2013 C ;mov bl, ah C ;xor bh, bh C ;shl bl, 1 C ;add bx, offset ttychr 1A1D C @@: 1A1D 8B 0F C mov cx, word ptr [BX] ; ascii & scan code C ; (by kb_int) 1A1F 0B C9 C or cx, cx 1A21 75 07 C jnz short @f 1A23 22 C0 C and al, al 1A25 74 11 C jz short getc_s 1A27 33 C0 C xor ax, ax 1A29 C3 C retn 1A2A C @@: 1A2A 22 C0 C and al, al 1A2C 8B C1 C mov ax, cx 1A2E B9 0000 C mov cx, 0 1A31 75 04 C jnz short @f 1A33 C getc_sn: 1A33 89 0F C mov word ptr [BX], cx ; 0, reset 1A35 3B C1 C cmp ax, cx ; zf = 0 1A37 C @@: 1A37 C3 C retn 1A38 C getc_s: C ; 14/02/2014 uquant -> u.quant C ; 10/12/2013 C ; 20/10/2013 C ; 05/10/2013 C ; 24/09/2013 C ; 20/09/2013 C ; 29/07/2013 C ; 28/07/2013 C ; 16/07/2013 C ; tty of the current process is not C ; current tty (ptty); so, current process only C ; can use keyboard input when its tty becomes C ; current tty (ptty). C ; 'sleep' is for preventing an endless lock C ; during this tty input request. C ; (Because, the user is not looking at the video page C ; of the process to undersand there is a keyboard C ; input request.) C ;; 29/07/2013 C ; 20/09/2013 C ;((Modified registers: AX, BX, CX, DX, SI, DI)) C ; C ; 05/10/2013 C ; ah = byte ptr [u.ttyn] ; (tty number) C ; C ; 10/10/2013 1A38 C gcw0: 1A38 B1 0A C mov cl, 10 ; ch = 0 1A3A C gcw1: 1A3A E8 F4B5 C call idle 1A3D 8B 07 C mov ax, word ptr [BX] ; ascii & scan code C ; (by kb_int) 1A3F 0B C0 C or ax, ax 1A41 75 1E C jnz short gcw3 1A43 E2 F5 C loop gcw1 C ; 1A45 8A 26 390A R C mov ah, byte ptr [u.ttyn] ; 20/10/2013 C ; 10/12/2013 1A49 3A 26 2C4A R C cmp ah, byte ptr [ptty] 1A4D 75 07 C jne short gcw2 C ; 14/02/2014 1A4F 80 3E 3907 R 01 C cmp byte ptr [u.uno], 1 1A54 76 E2 C jna short gcw0 1A56 C gcw2: 1A56 E8 F51E C call sleep C C ; 20/09/2013 1A59 8A 26 390A R C mov ah, byte ptr [u.ttyn] 1A5D 32 C0 C xor al, al 1A5F EB AE C jmp short getc_n 1A61 C gcw3: C ; 10/10/2013 1A61 32 C9 C xor cl, cl 1A63 EB CE C jmp short getc_sn C C 1A65 C sndc: ; C ; C ; 28/07/2014 C ; 27/07/2014 C ; 23/07/2014 C ; 20/07/2014 C ; 12/07/2014 C ; 04/07/2014 C ; 27/06/2014 C ; 25/06/2014 C ; 15/04/2014 C ; 13/01/2014 C ; 16/07/2013 bx C ; 14/05/2013 C ; C ; Retro UNIX 8086 v1 feature only ! C ; C ; 12/07/2014 1A65 32 F6 C xor dh, dh 1A67 8A D4 C mov dl, ah C ; 27/07/2014 1A69 80 EA 08 C sub dl, 8 C ; 25/06/2014 1A6C 50 C push ax 1A6D C sndcs: C ; 28/07/2014 C ; ; 27/07/2014 C ; mov cx, 10 C ;@@: 1A6D B4 03 C mov ah, 3 ; Get serial port status 1A6F CD 14 C int 14h 1A71 F6 C4 20 C test ah, 20h ; Transmitter holding register empty ? 1A74 75 15 C jnz short @f C ; call idle C ; loop @b C ; 1A76 52 C push dx 1A77 53 C push bx C ; 27/07/2014 1A78 8B DA C mov bx, dx 1A7A 81 C3 2CAC R C add bx, offset tsleep C ; 1A7E 8A 26 390A R C mov ah, byte ptr [u.ttyn] C ; 1A82 88 27 C mov byte ptr [BX], ah ; 27/07/2014 C ; 1A84 E8 F4F0 C call sleep 1A87 5B C pop bx 1A88 5A C pop dx 1A89 EB E2 C jmp short sndcs 1A8B C @@: 1A8B 58 C pop ax 1A8C C @@: C ;mov ah, 1 ; Send character C ;int 14h C ; 13/07/2014 1A8C 52 C push dx 1A8D 0A D2 C or dl, dl 1A8F BA 02F8 C mov dx, 2F8h ;data port (COM2) 1A92 75 04 C jnz short @f 1A94 81 C2 0100 C add dx, 100h ;3F8h, data port (COM1) 1A98 C @@: 1A98 EE C out dx, al ;send on serial port 1A99 5A C pop dx C ; 27/07/2014 1A9A E8 F455 C call idle C ; 1A9D B4 03 C mov ah, 3 ; Get serial port status 1A9F CD 14 C int 14h 1AA1 80 FC 80 C cmp ah, 80h ; time out error 1AA4 F5 C cmc ; cf = 0 (OK), cf = 1 (error!) 1AA5 C @@: 1AA5 C3 C retn C 1AA6 C putc: C ;27/07/2014 C ;23/07/2014 C ;20/07/2014 C ;27/06/2014 (sndc, EOT) C ;25/06/2014 C ;05/05/2014 C ;15/04/2014 C ;13/01/2014 C ;04/12/2013 write_tty C ;03/12/2013 write_tty, beep, waitf C ; (for video page switch bug-fixing) C ;30/11/2013 C ;04/11/2013 C ;30/10/2013 C ;24/09/2013 consistency check -> ok C ;20/09/2013 (cx = repeat count) C ; (int 10h, function 0Eh -> function 09h) C ; (video page can be selected in function 09h only!) C ;26/08/2013 C ;14/05/2013 C ; Retro UNIX 8086 v1 modification ! C ; C ; 'putc' puts a character C ; onto requested (tty) video page or C ; serial port C ; INPUTS -> C ; AL = ascii code of the character C ; AH = video page (tty) number (0 to 7) C ; (8 is COM1, 9 is COM2) C ; OUTPUTS -> C ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) C ; ZF=0 -> AX has (current) character C ; cf=0 and AH = 0 -> no error C ; cf=1 and AH > 0 -> error (only for COM1 and COM2) C ; C ; Original UNIX V1 'putc': C ; put a character at the end of character list C ; C ; ((Modified registers: AX, BX, CX, DX, SI, DI)) C ; 1AA6 80 FC 07 C cmp ah, 7 1AA9 77 BA C ja short sndc ; send character C 1AAB C write_tty: C ; 01/02/2014 C ; 18/01/2014 C ; 12/12/2013 C ; 04/12/2013 C ; 03/12/2013 C ; (Modified registers: AX, BX, CX, DX, SI, DI) C = 0008 C RVRT equ 00001000b ; VIDEO VERTICAL RETRACE BIT = 0001 C RHRZ equ 00000001b ; VIDEO HORIZONTAL RETRACE BIT C C ; mov bl, 07h C C ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code C ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO C ; C ; 06/10/85 VIDEO DISPLAY BIOS C ; C ;--- WRITE_TTY ------------------------------------------------------------------ C ; : C ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE : C ; VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT : C ; CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. : C ; IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN : C ; IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW : C ; ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, : C ; FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. : C ; WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE : C ; NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : C ; LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE, : C ; THE 0 COLOR IS USED. : C ; ENTRY -- : C ; (AH) = CURRENT CRT MODE : C ; (AL) = CHARACTER TO BE WRITTEN : C ; NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE : C ; HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS : C ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE : C ; EXIT -- : C ; ALL REGISTERS SAVED : C ;-------------------------------------------------------------------------------- C C ;;push ax ; save character and video page number C ;;mov bh, ah ; get page setting C ;;mov ah, 03h ; (read cursor position) C ;;int 10h C ;;pop ax ; recover character and video page C 1AAB FA C cli C C ; READ CURSOR (04/12/2013) 1AAC 32 FF C xor bh, bh 1AAE 8A DC C mov bl, ah 1AB0 D0 E3 C shl bl, 1 1AB2 81 C3 2C3A R C add bx, offset cursor_posn 1AB6 8B 17 C mov dx, word ptr [BX] C ;mov cx, word ptr [cursor_mode] C ; C C ;mov bl, 07h ; C ;mov bh, ah ; 1AB8 8A DC C mov bl, ah ; video page number C ;xor bh, bh C C ; dx now has the current cursor position C 1ABA 3C 0D C cmp al, 0Dh ; is it carriage return or control character 1ABC 76 3F C jbe short u8 C C ; write the char to the screen C 1ABE C u0: C ;mov ah, 0Ah ; write character only command C ;mov cx, 1 ; only one character C ;int 10h ; write the character C 1ABE B4 07 C mov ah, 07h ; attribute/color C ; al = character C ; bl = video page number (0 to 7) C ; 1AC0 E8 019F C call write_c_current C C ; position the cursor for next char C 1AC3 FE C2 C inc dl 1AC5 80 FA 50 C cmp dl, 80 ; test for column overflow C ;jne short u7 1AC8 74 03 E9 00C8 C jne set_cpos 1ACD B2 00 C mov dl, 0 1ACF 80 FE 18 C cmp dh, 25-1 ; check for last row 1AD2 75 24 C jne short u6 C C ; scroll required 1AD4 C u1: C ;;mov ah, 02h C ;;int 10h ; set the cursor C ; SET CURSOR POSITION (04/12/2013) 1AD4 E8 00BE C call set_cpos C C ; determine value to fill with during scroll 1AD7 C u2: C ;;mov ah, 08h ; get read cursor command C ;;int 10h ; read char/attr at current cursor C C ; READ_AC_CURRENT : C ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER C ; AT THE CURRENT CURSOR POSITION C ; C ; INPUT C ; (AH) = CURRENT CRT MODE C ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) C ; (DS) = DATA SEGMENT C ; (ES) = REGEN SEGMENT C ; OUTPUT C ; (AL) = CHARACTER READ C ; (AH) = ATTRIBUTE READ C C ; mov ah, byte ptr [crt_mode] ; move current mode into ah C ; C ; bl = video page number C ; 1AD7 E8 0106 C call find_position ; get regen location and port address C ; dx = status port C ;mov si, di ; establish addressing in si C ; si = cursor location/address C ;push es ; get regen segment for quick access C ;pop ds 1ADA C p11: 1ADA FB C sti ; enable interrupts 1ADB 90 C nop ; allow for small interupts window 1ADC FA C cli ; blocks interrupts for single loop 1ADD EC C in al, dx ; get status from adapter 1ADE A8 01 C test al, RHRZ ; is horizontal retrace low 1AE0 75 F8 C jnz short p11 ; wait until it is C ; 1AE2 C p12: ; now wait for either retrace high 1AE2 EC C in al, dx ; get status 1AE3 A8 09 C test al, RVRT+RHRZ ; is horizontal or vertical retrace high 1AE5 74 FB C jz short p12 ; wait until either is active 1AE7 C p13: C ;lodsw ; get the character and attribute C ; 1AE7 1E C push ds 1AE8 B8 B800 C mov ax, 0B800h 1AEB 8E D8 C mov ds, ax 1AED 8B 04 C mov ax, word ptr [SI] 1AEF 1F C pop ds C ; C ; al = character, ah = attribute C ; 1AF0 FB C sti 1AF1 8A FC C mov bh, ah ; store in bh C ; bl = video page number 1AF3 C u3: C ;;mov ax, 0601h ; scroll one line C ;;sub cx, cx ; upper left corner C ;;mov dh, 25-1 ; lower right row C ;mov dl, 80 ; lower right column C ;dec dl C ;;mov dl, 79 C C ;call scroll_up ; 04/12/2013 1AF3 B0 01 C mov al, 1 1AF5 E9 010B C jmp scroll_up C ;u4: C ;;int 10h ; video-call return C ; scroll up the screen C ; tty return C ;u5: C ;retn ; return to the caller C 1AF8 C u6: ; set-cursor-inc 1AF8 FE C6 C inc dh ; next row C ; set cursor C ;u7: C ;;mov ah, 02h C ;;jmp short u4 ; establish the new cursor C ;call set_cpos C ;jmp short u5 1AFA E9 0098 C jmp set_cpos C C ; check for control characters 1AFD C u8: 1AFD 74 2C C je short u9 1AFF 3C 0A C cmp al, 0Ah ; is it a line feed (0Ah) 1B01 74 2C C je short u10 1B03 3C 07 C cmp al, 07h ; is it a bell 1B05 74 2F C je short u11 1B07 3C 08 C cmp al, 08h ; is it a backspace C ;jne short u0 1B09 74 19 C je short bs ; 12/12/2013 C ; 12/12/2013 (tab stop) 1B0B 3C 09 C cmp al, 09h ; is it a tab stop 1B0D 75 AF C jne short u0 1B0F 8A C2 C mov al, dl 1B11 98 C cbw 1B12 B1 08 C mov cl, 8 1B14 F6 F1 C div cl 1B16 2A CC C sub cl, ah 1B18 C ts: 1B18 51 C push cx 1B19 B0 20 C mov al, 20h 1B1B E8 FF8D C call write_tty 1B1E 59 C pop cx 1B1F FE C9 C dec cl 1B21 75 F5 C jnz short ts 1B23 C3 C retn 1B24 C bs: C ; back space found C 1B24 0A D2 C or dl, dl ; is it already at start of line C ;je short u7 ; set_cursor 1B26 74 6D C jz short set_cpos 1B28 4A C dec dx ; no -- just move it back C ;jmp short u7 1B29 EB 6A C jmp short set_cpos C C ; carriage return found 1B2B C u9: 1B2B B2 00 C mov dl, 0 ; move to first column C ;jmp short u7 1B2D EB 66 C jmp short set_cpos C C ; line feed found 1B2F C u10: 1B2F 80 FE 18 C cmp dh, 25-1 ; bottom of screen 1B32 75 C4 C jne short u6 ; no, just set the cursor 1B34 EB 9E C jmp short u1 ; yes, scroll the screen C 1B36 C beeper: ; 18/01/2014 (sti) C ; 17/01/2014 (call from 'kb_int') C ;sti C C ; bell found 1B36 C u11: 1B36 FB C sti ; 01/02/2014 C ; 12/12/2013 1B37 3A 1E 2C4A R C cmp bl, byte ptr [active_page] 1B3B 75 48 C jne short @f ; Do not sound the beep C ; if it is not written on the active page 1B3D B9 0533 C mov cx, 1331 ; divisor for 896 hz tone 1B40 B3 1F C mov bl, 31 ; set count for 31/64 second for beep C ;call beep ; sound the pod bell C ;jmp short u5 ; tty_return C ;retn C = 0040 C TIMER equ 040h ; 8254 TIMER - BASE ADDRESS = 0061 C PORT_B equ 061h ; PORT B READ/WRITE DIAGNOSTIC REGISTER = 0001 C GATE2 equ 00000001b ; TIMER 2 INPUT CATE CLOCK BIT = 0002 C SPK2 equ 00000010b ; SPEAKER OUTPUT DATA ENABLE BIT C 1B42 C beep: C ; 18/01/2014 C ; 10/12/2013 C ; 07/12/2013 (sti) C ; 03/12/2013 C ; C ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES C ; C ; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE C ; C ; ENTRY: C ; (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND ) C ; (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ) C ; EXIT: : C ; (AX),(BL),(CX) MODIFIED. C 1B42 9C C pushf ; 18/01/2014 ; save interrupt status 1B43 FA C cli ; block interrupts during update 1B44 B0 B6 C mov al, 10110110b ; select timer 2, lsb, msb binary 1B46 E6 43 C out TIMER+3, al ; write timer mode register 1B48 EB 00 C jmp $+2 ; I/O delay 1B4A 8A C1 C mov al, cl ; divisor for hz (low) 1B4C E6 42 C out TIMER+2,AL ; write timer 2 count - lsb 1B4E EB 00 C jmp $+2 ; I/O delay 1B50 8A C5 C mov al, ch ; divisor for hz (high) 1B52 E6 42 C out TIMER+2, al ; write timer 2 count - msb 1B54 E4 61 C in al, PORT_B ; get current setting of port 1B56 8A E0 C mov ah, al ; save that setting 1B58 0C 03 C or al, GATE2+SPK2 ; gate timer 2 and turn speaker on 1B5A E6 61 C out PORT_B, al ; and restore interrupt status C ;popf ; 18/01/2014 1B5C FB C sti 1B5D C g7: ; 1/64 second per count (bl) 1B5D B9 040B C mov cx, 1035 ; delay count for 1/64 of a second 1B60 E8 0023 C call waitf ; go to beep delay 1/64 count 1B63 FE CB C dec bl ; (bl) length count expired? 1B65 75 F6 C jnz short g7 ; no - continue beeping speaker C ; C ;pushf ; save interrupt status 1B67 FA C cli ; 18/01/2014 ; block interrupts during update 1B68 E4 61 C in al, PORT_B ; get current port value 1B6A 0C FC C or al, not (GATE2+SPK2) ; isolate current speaker bits in case 1B6C 22 E0 C and ah, al ; someone turned them off during beep 1B6E 8A C4 C mov al, ah ; recover value of port 1B70 0C FC C or al, not (GATE2+SPK2) ; force speaker data off 1B72 E6 61 C out PORT_B, al ; and stop speaker timer C ;popf ; restore interrupt flag state 1B74 FB C sti 1B75 B9 040B C mov cx, 1035 ; force 1/64 second delay (short) 1B78 E8 000B C call waitf ; minimum delay between all beeps C ;pushf ; save interrupt status 1B7B FA C cli ; block interrupts during update 1B7C E4 61 C in al, PORT_B ; get current port value in case 1B7E 24 03 C and al, GATE2+SPK2 ; someone turned them on 1B80 0A C4 C or al, ah ; recover value of port_b 1B82 E6 61 C out PORT_B, al ; restore speaker status 1B84 9D C popf ; restore interrupt flag state 1B85 C @@: 1B85 C3 C retn C = 0010 C REFRESH_BIT equ 00010000b ; REFRESH TEST BIT C 1B86 C waitf: C ; 03/12/2013 C ; C ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES C ; C ; WAITF - FIXED TIME WAIT ROUTINE HARDWARE CONTROLLED - NOT PROCESSOR C ; C ; ENTRY: C ; (CX) = COUNT OF 15.,085737 MICROSECOND INTERVALS TO WAIT C ; MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE C ; EXIT: C ; AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS) C ; (CX) = 0 C C ; delay for (cx)*15.085737 us 1B86 50 C push ax ; save work register (ah) 1B87 C waitf1: C ; use timer 1 output bits 1B87 E4 61 C in al, PORT_B ; read current counter output status 1B89 24 10 C and al, REFRESH_BIT ; mask for refresh determine bit 1B8B 38 E0 C cmp al, ah ; did it just change 1B8D 74 F8 C je short waitf1 ; wait for a change in output line C ; 1B8F 8A E0 C mov ah, al ; save new lflag state 1B91 E2 F4 C loop waitf1 ; decrement half cycles till count end C ; 1B93 58 C pop ax ; restore (ah) 1B94 C3 C retn ; return (cx)=0 C 1B95 C set_cpos: C ; 01/09/2014 C ; 12/12/2013 C ; 10/12/2013 C ; 04/12/2013 C ; C ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS C ; C ; SET_CPOS C ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE C ; NEW X-Y VALUES PASSED C ; INPUT C ; DX - ROW,COLUMN OF NEW CURSOR C ; BH - DISPLAY PAGE OF CURSOR C ; OUTPUT C ; CURSOR ID SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY C C ;mov al, bh ; move page number to work register 1B95 8A C3 C mov al, bl ; page number 1B97 98 C cbw ; convert page to word value 1B98 8B F0 C mov si, ax ; ah = 0, al = video page number 1B9A D1 E6 C shl si, 1 ; word offset 1B9C 89 94 2C3A R C mov word ptr [SI + offset cursor_posn], dx ; save the pointer C ; 01/09/2014 1BA0 38 1E 2C4A R C cmp byte ptr [active_page], bl ; al 1BA4 75 28 C jne short m17 C ; 1BA6 8B C2 C mov ax, dx ; get row/column to ax C ;call m18 ; CURSOR SET C ;m17: ; SET_CPOS_RETURN C ; 01/09/2014 C ; retn 1BA8 C m18: 1BA8 E8 0024 C call position ; determine location in regen buffer 1BAB 8B C8 C mov cx, ax C ; 01/09/2014 1BAD 03 0E 2C38 R C add cx, word ptr [crt_start] C ; add in the start address for this page C ;sar cx, 1 1BB1 D1 E9 C shr cx, 1 ; divide by 2 for char only count 1BB3 B4 0E C mov ah, 14 ; register number for cursor C ;call m16 ; output value to the 6845 C ;retn C C ;----- THIS ROUTINE OUTPUTS THE CX REGISTER C ; TO THE 6845 REGISTERS NAMED IN (AH) 1BB5 C m16: 1BB5 FA C cli C ;mov dx, word ptr [addr_6845] ; address register 1BB6 BA 03D4 C mov dx, 03D4h ; I/O address of color card 1BB9 8A C4 C mov al, ah ; get value 1BBB EE C out dx, al ; register set 1BBC 42 C inc dx ; data register 1BBD EB 00 C jmp $+2 ; i/o delay 1BBF 8A C5 C mov al, ch ; data 1BC1 EE C out dx, al 1BC2 4A C dec dx 1BC3 8A C4 C mov al, ah 1BC5 FE C0 C inc al ; point to other data register 1BC7 EE C out dx, al ; set for second register 1BC8 42 C inc dx 1BC9 EB 00 C jmp $+2 ; i/o delay 1BCB 8A C1 C mov al, cl ; second data value 1BCD EE C out dx, al 1BCE C m17: C ; 01/09/2014 1BCE C3 C retn C 1BCF C position: C ; 04/12/2013 C ; C ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS C ; C ; POSITION C ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS C ; OF A CHARACTER IN THE ALPHA MODE C ; INPUT C ; AX = ROW, COLUMN POSITION C ; OUTPUT C ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER C 1BCF 53 C push bx ; save register 1BD0 8A D8 C mov bl, al 1BD2 8A C4 C mov al, ah ; rows to al C ;mul byte ptr [crt_cols] ; determine bytes to row 1BD4 B7 50 C mov bh, 80 1BD6 F6 E7 C mul bh 1BD8 32 FF C xor bh, bh 1BDA 03 C3 C add ax, bx ; add in column value C ;sal ax, 1 1BDC D1 E0 C shl ax, 1 ; * 2 for attribute bytes 1BDE 5B C pop bx 1BDF C3 C retn C 1BE0 C find_position: C ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 1BE0 8A CB C mov cl, bl ; video page number 1BE2 32 ED C xor ch, ch 1BE4 8B F1 C mov si, cx ; ch = 0, cl = video page number 1BE6 D1 E6 C shl si, 1 1BE8 8B 84 2C3A R C mov ax, word ptr [SI + Offset cursor_posn] 1BEC 74 08 C jz short p21 C ; 1BEE 33 F6 C xor si, si ; else set buffer address to zero C ; 1BF0 C p20: C ;add si, word ptr [crt_len] ; add length of buffer for one page 1BF0 81 C6 0FA0 C add si, 80*25*2 1BF4 E2 FA C loop p20 1BF6 C p21: 1BF6 23 C0 C and ax, ax 1BF8 74 05 C jz short @f 1BFA E8 FFD2 C call position ; determine location in regen in page 1BFD 03 F0 C add si, ax ; add location to start of regen page 1BFF C @@: C ;mov dx, word ptr [addr_6845] ; get base address of active display C ;mov dx, 03D4h ; I/O address of color card C ;add dx, 6 ; point at status port 1BFF BA 03DA C mov dx, 03DAh C ; cx = 0 1C02 C3 C retn C 1C03 C scroll_up: C ; 04/04/2014 (BugFix) C ; 12/12/2013 C ; 04/12/2013 C ; C ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS C ; C ; SCROLL UP C ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP C ; ON THE SCREEN C ; INPUT C ; (AH) = CURRENT CRT MODE C ; (AL) = NUMBER OF ROWS TO SCROLL C ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER C ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER C ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE C ; (DS) = DATA SEGMENT C ; (ES) = REGEN BUFFER SEGMENT C ; OUTPUT C ; NONE -- THE REGEN BUFFER IS MODIFIED C ; C ; ((ah = 3)) C ; dl = 79 C ; dh = 24 C ; C ; al = line count (0 or 1) ((0 == clear video page)) C ; ((al = 1 for write_tty (putc) procedure)) C ; bl = video page number (0 to 7) C ; bh = attribute to be used on blanked line C C ;cli 1C03 50 C push ax 1C04 3A 1E 2C4A R C cmp bl, byte ptr [active_page] 1C08 74 12 C je short n0 1C0A 33 F6 C xor si, si 1C0C 22 DB C and bl, bl 1C0E 74 1D C jz short n9 1C10 8A CB C mov cl, bl 1C12 C @@: 1C12 81 C6 0FA0 C add si, 25*80*2 ; 04/04/2014 1C16 FE C9 C dec cl 1C18 75 F8 C jnz short @b 1C1A EB 11 C jmp short n9 1C1C C n0: 1C1C 8B 36 2C38 R C mov si, word ptr [crt_start] 1C20 C n1: ; 04/04/2014 C ;mov di, si C ; C ;inc dh C ;inc dl ; increment for origin C ; dl = 80 C ; dh = 25 C ;cmp bl, byte ptr [active_page] C ;jne short n9 C ; 1C20 BA 03DA C mov dx, 3DAh ; guaranteed to be color card here 1C23 C n8: ; wait_display_enable 1C23 EC C in al, dx ; get port 1C24 A8 08 C test al, RVRT ; wait for vertical retrace 1C26 74 FB C jz short n8 ; wait_display_enable 1C28 B0 25 C mov al, 25h 1C2A B2 D8 C mov dl, 0D8h ; address control port 1C2C EE C out dx, al ; turn off video during vertical retrace 1C2D C n9: 1C2D 59 C pop cx ; al = line count C ; 1C2E 8B FE C mov di, si ; 04/04/2014 C ; 1C30 06 C push es 1C31 1E C push ds 1C32 B8 B800 C mov ax, 0B800h 1C35 8E C0 C mov es, ax 1C37 8E D8 C mov ds, ax C ; 1C39 22 C9 C and cl, cl 1C3B 75 05 C jnz short @f C ; clear video page 1C3D B9 07D0 C mov cx, 25 * 80 1C40 EB 0B C jmp short n3 1C42 C @@: C ;mov ax, 160 C ; mov al, 160 ; 2 * (80 columns) C ; mul cl C ;add si, ax 1C42 81 C6 00A0 C add si, 160 C ; ;mov cx, 24 C ;n2: ; row loop C ; ;call n10 ; move one row C ; ;add si, ax C ; ;add di, ax C ; ;loop n2 C ; mov al, cl C ; mov cl, 25 C ; sub cl, al C ; xor ch, ch C ; ; cx = line count to move C ;@@: C ; push cx 1C46 C n10: C ;mov cx, 80 1C46 B9 0780 C mov cx, 24*80 ; 24 rows/lines 1C49 F3/ A5 C rep movsw ; move one line (up) C ;loop n2 C ; pop cx C ; loop @b C ; mov cl, al 1C4B B1 50 C mov cl, 80 1C4D C n3: ; clear entry 1C4D 8A E7 C mov ah, bh ; attribute in ah 1C4F B0 20 C mov al, 20h ; fill with blanks C ; cx = word count to clear (80 or 25*80) C ;@@: C ; push cx 1C51 C n11: C ; mov cl, 80 ; get # of columns to clear 1C51 F3/ AB C rep stosw ; store the fill character C ; pop cx C ; loop @b 1C53 C n5: ; SCROLL_END 1C53 1F C pop ds 1C54 3A 1E 2C4A R C cmp bl, byte ptr [active_page] 1C58 75 06 C jne short @f C ;mov al, byte ptr [crt_mode_set] ; get the value of mode set 1C5A B0 29 C mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 1C5C BA 03D8 C mov dx, 03D8h ; always set color card port 1C5F EE C out dx, al 1C60 C @@: 1C60 07 C pop es C ;sti 1C61 C3 C retn C 1C62 C write_c_current: C ; 18/01/2014 C ; 04/12/2013 C ; C ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS C ; C ; WRITE_C_CURRENT C ; THIS ROUTINE WRITES THE CHARACTER AT C ; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED C ; INPUT C ; (AH) = CURRENT CRT MODE C ; (BH) = DISPLAY PAGE C ; (CX) = COUNT OF CHARACTERS TO WRITE C ; (AL) = CHAR TO WRITE C ; (DS) = DATA SEGMENT C ; (ES) = REGEN SEGMENT C ; OUTPUT C ; DISPLAY REGEN BUFFER UPDATED C 1C62 FA C cli C C ; bl = video page C ; al = character C ; ah = color/attribute 1C63 52 C push dx 1C64 50 C push ax ; save character & attribute/color 1C65 E8 FF78 C call find_position ; get regen location and port address C ; si = regen location C ; dx = status port C ; C ; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE C ; 1C68 C p41: ; wait for horizontal retrace is low or vertical 1C68 FB C sti ; enable interrupts first 1C69 3A 1E 2C4A R C cmp bl, byte ptr [active_page] 1C6D 75 10 C jne short p44 ; 18/01/2014 1C6F FA C cli ; block interrupts for single loop 1C70 EC C in al, dx ; get status from the adapter 1C71 A8 08 C test al, RVRT ; check for vertical retrace first 1C73 75 09 C jnz short p43 ; Do fast write now if vertical retrace 1C75 A8 01 C test al, RHRZ ; is horizontal retrace low 1C77 75 EF C jnz short p41 ; wait until it is 1C79 C p42: ; wait for either retrace high 1C79 EC C in al, dx ; get status again 1C7A A8 09 C test al, RVRT+RHRZ ; is horizontal or vertical retrace high 1C7C 74 FB C jz short p42 ; wait until either retrace active 1C7E C p43: ; 18/01/2014 1C7E FB C sti 1C7F C p44: 1C7F 58 C pop ax ; restore the character (al) & attribute (ah) 1C80 1E C push ds 1C81 B9 B800 C mov cx, 0B800h 1C84 8E D9 C mov ds, cx 1C86 89 04 C mov word ptr [SI], ax 1C88 1F C pop ds 1C89 5A C pop dx 1C8A C3 C retn C 1C8B C tty_sw: 1C8B C6 06 38FA R 00 C mov byte ptr [u.quant], 0 ; 04/03/2014 C ; C ;act_disp_page: C ; 30/06/2015 C ; 04/03/2014 (act_disp_page --> tty_sw) C ; 10/12/2013 C ; 04/12/2013 C ; C ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS C ; C ; ACT_DISP_PAGE C ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING C ; THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT C ; INPUT C ; AL HAS THE NEW ACTIVE DISPLAY PAGE C ; OUTPUT C ; THE 6845 IS RESET TO DISPLAY THAT PAGE C C ;cli C C ;push bx 1C90 51 C push cx 1C91 52 C push dx C ; 1C92 A2 2C4A R C mov byte ptr [active_page], al ; save active page value ; [ptty] C ;mov cx, word ptr [crt_len] ; get saved length of regen buffer 1C95 B9 0FA0 C mov cx, 25*80*2 1C98 98 C cbw ; convert AL to word 1C99 50 C push ax ; save page value 1C9A F7 E1 C mul cx ; display page times regen length C ; 10/12/2013 1C9C A3 2C38 R C mov word ptr [crt_start], ax ; save start address for later 1C9F 8B C8 C mov cx, ax ; start address to cx C ;sar cx, 1 1CA1 D1 E9 C shr cx, 1 ; divide by 2 for 6845 handling 1CA3 B4 0C C mov ah, 12 ; 6845 register for start address 1CA5 E8 FF0D C call m16 1CA8 5B C pop bx ; recover page value C ;sal bx, 1 1CA9 D1 E3 C shl bx, 1 ; *2 for word offset 1CAB 8B 87 2C3A R C mov ax, word ptr [BX + offset cursor_posn] ; get cursor for this page 1CAF E8 FEF6 C call m18 C ; 1CB2 5A C pop dx 1CB3 59 C pop cx C ;pop bx C ; C ;sti C ; 1CB4 C3 C retn C 1CB5 C get_cpos: C ; 04/12/2013 (sysgtty) C ; C ; INPUT -> bl = video page number C ; RETURN -> dx = cursor position C 1CB5 53 C push bx 1CB6 32 FF C xor bh, bh 1CB8 D0 E3 C shl bl, 1 1CBA 81 C3 2C3A R C add bx, offset cursor_posn 1CBE 8B 17 C mov dx, word ptr [BX] 1CC0 5B C pop bx 1CC1 C3 C retn C 1CC2 C read_ac_current: C ; 04/12/2013 (sysgtty) C ; C ; INPUT -> bl = video page number C ; RETURN -> ax = character (al) and attribute (ah) C 1CC2 E8 FF1B C call find_position 1CC5 1E C push ds 1CC6 B8 B800 C mov ax, 0B800h 1CC9 8E D8 C mov ds, ax 1CCB 8B 04 C mov ax, word ptr [SI] 1CCD 1F C pop ds 1CCE C3 C retn C C C ; 11/06/2014 C ; Retro UNIX 8086 v1 feature only C ; (INPUT -> none) 1CCF C syssleep: 1CCF 8A 1E 3907 R C mov bl, byte ptr [u.uno] ; process number 1CD3 32 FF C xor bh, bh 1CD5 8A A7 29ED R C mov ah, byte ptr [BX]+p.ttyc-1 ; current/console tty 1CD9 E8 F29B C call sleep 1CDC E9 E63A C jmp sysret C C C ; COMMENT Þ C C C ; 28/02/2014 C ; Keyboard function variables (for INT 16h) C ; DS = 40h C ;;DDSDATA equ 40h C ; C ;;KB_FLAG equ 17h ; byte C ;;;KB_FLAGS equ 17h ; word ; initial value = 0 C ;;BUFF_HEAD equ 1Ah ; word ; initial value = offset KB_BUFF C ;;BUFF_TAIL equ 1Ch ; word ; initial value = offset KB_BUFF C ;;BUFF_START equ 80h ; word ; initial value = offset KB_BUFF C ;;BUFF_END equ 82h ; word ; initial value = offset KB_BUFF + 32 C ;;;KB_BUFF equ 1Eh ; 32 bytes ; Keyboard buffer (circular queue buffer) C C ; 03/03/2014 = 0040 C BIOS_DSEGM equ 40h = 0072 C RESET_FLAG equ 72h ; WORD=1234H IF KEYBOARD RESET UNDERWAY C ; (40h:72h) C ;---------------------------------------- C ; VIDEO DISPLAY DATA AREA ; C ;---------------------------------------- = 0049 C CRT_MODE equ 49h ; CURRENT DISPLAY MODE (TYPE) = 0065 C CRT_MODE_SET equ 65h ; CURRENT SETTING OF THE 3X8 REGISTER C C ;--------- 8042 COMMANDS ------------------------------------------------------- = 00AE C ENA_KBD equ 0AEh ; ENABLE KEYBOARD COMMAND = 00AD C DIS_KBD equ 0ADh ; DISABLE KEYBOARD COMMAND C ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ = 0064 C STATUS_PORT equ 064h ; 8042 STATUS PORT = 0002 C INPT_BUF_FULL equ 00000010b ; 1 = +INPUT BUFFER FULL = 0060 C PORT_A equ 060h ; 8042 KEYBOARD SCAN CODE/CONTROL PORT C ;---------- 8042 KEYBOARD RESPONSE --------------------------------------------- = 00FA C KB_ACK equ 0FAh ; ACKNOWLEDGE PROM TRANSMISSION = 00FE C KB_RESEND equ 0FEh ; RESEND REQUEST = 00FF C KB_OVER_RUN equ 0FFh ; OVER RUN SCAN CODE C ;---------- KEYBOARD/LED COMMANDS ---------------------------------------------- = 00F4 C KB_ENABLE equ 0F4h ; KEYBOARD ENABLE = 00ED C LED_CMD EQU 0EDH ; LED WRITE COMMAND C C ;---------- KEYBOARD SCAN CODES ------------------------------------------------ = 00AB C ID_1 equ 0ABh ; 1ST ID CHARACTER FOR KBX = 0041 C ID_2 equ 041h ; 2ND ID CHARACTER FOR KBX = 0038 C ALT_KEY equ 56 ; SCAN CODE FOR ALTERNATE SHIFT KEY = 001D C CTL_KEY equ 29 ; SCAN CODE FOR CONTROL KEY = 003A C CAPS_KEY equ 58 ; SCAN CODE FOR SHIFT LOCK KEY = 0053 C DEL_KEY equ 83 ; SCAN CODE FOR DELETE KEY = 0052 C INS_KEY equ 82 ; SCAN CODE FOR INSERT KEY = 002A C LEFT_KEY equ 42 ; SCAN CODE FOR LEFT SHIFT = 0045 C NUM_KEY equ 69 ; SCAN CODE FOR NUMBER LOCK KEY = 0036 C RIGHT_KEY equ 54 ; SCAN CODE FOR RIGHT SHIFT = 0046 C SCROLL_KEY equ 70 ; SCAN CODE FOR SCROLL LOCK KEY = 0054 C SYS_KEY equ 84 ; SCAN CODE FOR SYSTEM KEY C ;---------- FLAG EQUATES WITHIN @KB_FLAG---------------------------------------- = 0001 C RIGHT_SHIFT equ 00000001b ; RIGHT SHIFT KEY DEPRESSED = 0002 C LEFT_SHIFT equ 00000010b ; LEFT SHIFT KEY DEPRESSED = 0004 C CTL_SHIFT equ 00000100b ; CONTROL SHIFT KEY DEPRESSED = 0008 C ALT_SHIFT equ 00001000b ; ALTERNATE SHIFT KEY DEPRESSED = 0010 C SCROLL_STATE equ 00010000b ; SCROLL LOCK STATE HAS BEEN TOGGLED = 0020 C NUM_STATE equ 00100000b ; NUM LOCK STATE HAS BEEN TOGGLED = 0040 C CAPS_STATE equ 01000000b ; CAPS LOCK STATE HAS BEEN TOGGLED = 0080 C INS_STATE equ 10000000b ; INSERT STATE IS ACTIVE C C ;---------- FLAG EQUATES WITHIN @KB_FLAG_1 ------------------------------------- = 0004 C SYS_SHIFT equ 00000100b ; SYSTEM KEY DEPRESSED AND HELD = 0008 C HOLD_STATE equ 00001000b ; SUSPEND KEY HAS BEEN TOGGLED = 0010 C SCROLL_SHIFT equ 00010000b ; SCROLL LOCK KEY IS DEPRESSED = 0020 C NUM_SHIFT equ 00100000b ; NUM LOCK KEY IS DEPRESSED = 0040 C CAPS_SHIFT equ 01000000b ; CAPS LOCK KEY IS DEPRE55ED = 0080 C INS_SHIFT equ 10000000b ; INSERT KEY IS DEPRESSED C C ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 ----------------------------------- = 0007 C KB_LEDS equ 00000111b ; KEYBOARD LED STATE BITS C ; equ 00001000b ; RESERVED (MUST BE ZERO) = 0010 C KB_FA equ 00010000b ; ACKNOWLEDGMENT RECEIVED = 0020 C KB_FE equ 00100000b ; RESEND RECEIVED FLAG = 0040 C KB_PR_LED equ 01000000b ; MODE INDICATOR UPDATE = 0080 C KB_ERR equ 10000000b ; REYBOARD TRANSMIT ERROR FLAG C C ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 ----------------------------------- = 0001 C KBX equ 00000001b ; KBX INSTALLED = 0002 C LC_HC equ 00000010b ; LAST SCAN CODED WAS A HIDDEN CODE = 0004 C GRAPH_ON equ 00000100b ; ALL GRAPHICS KEY DOWN (W.T. ONLY) C ; equ 00011000b ; RESERVED (MUST BE ZERO) = 0020 C SET_NUM_LK equ 00100000b ; FORCE NUM LOCK IF READ ID AND KBX = 0040 C LC_AB equ 01000000b ; LAST CHARACTER WAS FIRST ID CHARACTER = 0080 C RD_ID equ 10000000b ; DOING A READ ID (MUST BE BIT0) C ; C ;----- THIS CODE CONTAINS THE KBX SUPPORT FOR INT 09H C ; EQUATES = 00D9 C F11_M equ 217 ; FUNC 11 MAKE = 00D7 C F11_B equ 215 ; FUNC 11 BREAK = 00DA C F12_M equ 218 ; FUNC 12 MAKE = 00D8 C F12_B equ 216 ; FUNC 12 BREAK = 0056 C K102_M equ 86 ; KEY 102 MAKE = 00D6 C K102_B equ 214 ; KEY 102 BREAK C ; = 0052 C INS_M equ 82 ; INSERT KEY MAKE = 0053 C DEL_M equ 83 ; DELETE KEY MAKE = 004B C LEFT_M equ 75 ; CURSOR LEFT MAKE = 004D C RIGHT_M equ 77 ; CURSOR RIGHT MARE = 0048 C UP_M equ 72 ; CURSOR UP MAKE = 0050 C DN_M equ 80 ; CURSOR DOWN MAKE = 0049 C PGUP_M equ 73 ; PG UP MAKE = 0051 C PGDN_M equ 81 ; PG DN MAKE = 0047 C HOME_M equ 71 ; HOME MAKE = 004F C END_M equ 79 ; END MAKE C ; = 0085 C FUNC11 equ 133 ; FUNCTION 11 KEY = 00E0 C HC equ 224 ; HIDDEN CODE C ;----------- INTERRUPT EQUATES ------------------------------------------------- = 0020 C EOI equ 020h ; END OF INTERRUPT COMMAND TO 8259 = 0020 C INTA00 equ 020h ; 8259 PORT C C 1CDF C int_16h: C ; 28/08/2014 C ; 30/06/2014 C ; 03/03/2014 C ; 28/02/2014 C ; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-at" C ; rombios source code (06/10/1985) C ; 'keybd.asm', INT 16H, KEYBOARD_IO C ; C ; 06/10/85 KEYBOARD BIOS C ; C ;--- INT 16 H -------------------------------------------------------------------- C ; KEYBOARD I/O : C ; THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT : C ; INPUT : C ; (AH)= 00H READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD, : C ; RETURN THE RESULT IN (AL), SCAN CODE IN (AH). : C ; : C ; (AH)= 01H SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS : C ; AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER. : C ; (ZF)= 1 -- NO CODE AVAILABLE : C ; (ZF)= 0 -- CODE IS AVAILABLE (AX)= CHARACTER : C ; IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS : C ; IN (AX), AND THE ENTRY REMAINS IN THE BUFFER. : C ; (AH)= 02H RETURN THE CURRENT SHIFT STATUS IN (AL) REGISTER : C ; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE : C ; EQUATES FOR @KB_FLAG : C ; OUTPUT : C ; AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED : C ; ALL REGISTERS RETAINED : C ;--------------------------------------------------------------------------------- C 1CDF FB C sti 1CE0 1E C push ds ; SAVE CURRENT DS 1CE1 53 C push bx ; SAVE BX TEMPORARILY 1CE2 8C CB C mov bx, cs 1CE4 8E DB C mov ds, bx ; PUT SEGMENT VALUE OF DATA AREA INTO DS 1CE6 0A E4 C or ah, ah ; CHECK FOR (AH)= 00H 1CE8 74 0B C jz short k1b ; ASCII_READ C ; 1CEA FE CC C dec ah 1CEC 74 40 C jz short k2 ; CHECK FOR (AH)= 01H C ; ASCII_STATUS 1CEE FE CC C dec ah ; CHECK FOR (AH)= 02H 1CF0 74 62 C jz short k3 ; SHIFT STATUS 1CF2 5B C pop bx ; RECOVER REGISTER 1CF3 1F C pop ds ; RECOVER SEGMENT 1CF4 CF C iret ; INVALID COMMAND EXIT C C ;----- READ THE KEY TO FIGURE OUT WHAT TO DO 1CF5 C k1b: 1CF5 8B 1E 2C56 R C mov bx, word ptr [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 1CF9 3B 1E 2C58 R C cmp bx, word ptr [BUFFER_TAIL] ; TEST END OF BUFFER C ;; 28/08/2014 C ;;jne short k1c ; IF ANYTHING IN BUFFER SKIP INTERRUPT 1CFD 75 0B C jne short k1d C ;;mov ax, 09002h ; MOVE IN WAIT CODE A TYPE C ;;int 15h ; PERFORM OTHER FUNCTION 1CFF C k1: ; ASCII READ 1CFF FB C sti ; INTERRUPTS BACK ON DURING LOOP 1D00 90 C nop ; ALLOW AN INTERRUPT TO OCCUR 1D01 FA C k1c: cli ; INTERRUPTS BACK OFF 1D02 8B 1E 2C56 R C mov bx, word ptr [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 1D06 3B 1E 2C58 R C cmp bx, word ptr [BUFFER_TAIL] ; TEST END OF BUFFER 1D0A C k1d: C ; 30/06/2014 (original code again) 1D0A 53 C push bx ; SAVE ADDRESS 1D0B 9C C pushf ; SAVE FLAGS 1D0C E8 052F C call make_led ; GO GET MODE INDICATOR DATA BYTE 1D0F 8A 1E 2C4F R C mov bl, byte ptr [KB_FLAG_2] ; GET PREVIOUS BITS 1D13 32 D8 C xor bl, al ; SEE IF ANY DIFFERENT 1D15 80 E3 07 C and bl, KB_LEDS ; ISOLATE INDICATOR BITS 1D18 74 04 C jz short k1a ; IF NO CHANGE BYPASS UPDATE 1D1A E8 04E3 C call snd_led1 1D1D FA C cli 1D1E C k1a: 1D1E 9D C popf ; RESTORE FLAGS 1D1F 5B C pop bx ; RESTORE ADDRESS 1D20 74 DD C jz short k1 ; LOOP UNTIL SOMETHING IN BUFFER C ; 1D22 8B 07 C mov ax, word ptr [BX] ; GET SCAN CODE AND ASCII CODE 1D24 E8 0033 C call k4 ; MOVE POINTER TO NEXT POSITION C ; 03/03/2014 1D27 89 1E 2C56 R C mov word ptr [BUFFER_HEAD], bx ; STORE VALUE IN VARIABLE 1D2B 5B C pop bx ; RECOVER REGISTER 1D2C 1F C pop ds ; RECOVER SEGMENT 1D2D CF C iret ; RETURN TO CALLER C C ;----- ASCII STATUS 1D2E C k2: 1D2E FA C cli ; INTERRUPTS OFF 1D2F 8B 1E 2C56 R C mov bx, word ptr [BUFFER_HEAD] ; GET HEAD POINTER 1D33 3B 1E 2C58 R C cmp bx, word ptr [BUFFER_TAIL] ; IF EQUAL (Z=1) THEN NOTHING THERE 1D37 8B 07 C mov ax, word ptr [BX] C ; 30/06/2014 (original code again) 1D39 9C C pushf ; SAVE FLAGS 1D3A 50 C push ax ; SAVE CODE 1D3B E8 0500 C call make_led ; GO GET MODE INDICATOR DATA BYTE 1D3E 8A 1E 2C4F R C mov bl, byte ptr [KB_FLAG_2] ; GET PREVIOUS BITS 1D42 32 D8 C xor bl, al ; SEE IF ANY DIFFERENT 1D44 80 E3 07 C and bl, KB_LEDS ; ISOLATE INDICATOR BITS 1D47 74 03 C jz short sk2 ; IF NO CHANGE BYPASS UPDATE C ; 1D49 E8 04B4 C call snd_led1 1D4C C sk2: 1D4C 58 C pop ax ; RESTORE CODE 1D4D 9D C popf ; RESTORE FLAGS 1D4E FB C sti ; INTERRUPTS BACK ON 1D4F 5B C pop bx ; RECOVER REGISTER 1D50 1F C pop ds ; RECOVER SEGMENT 1D51 CA 0002 C retf 2 ; THROW AWAY FLAGS C C ;----- SHIFT STATUS 1D54 C k3: 1D54 A0 2C4D R C mov al, byte ptr [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 1D57 5B C pop bx ; RECOVER REGISTERS 1D58 1F C pop ds 1D59 CF C iret ; RETURN TO CALLER C C ; 03/03/2014 C ;----- INCREMENT A BUFFER POINTER 1D5A 43 C k4: inc bx 1D5B 43 C inc bx ; MOVE TO NEXT WORD IN LIST 1D5C 3B 1E 2C54 R C cmp bx, word ptr [BUFFER_END] ; AT END OF BUFFER? C ;jne short k5 ; NO, CONTINUE 1D60 72 04 C jb short k5 1D62 8B 1E 2C52 R C mov bx, word ptr [BUFFER_START] ; YES, RESET TO BUFFER BEGINNING 1D66 C k5: 1D66 C3 C retn C 1D67 C int_09h: C ; 07/03/2014 C ; 03/03/2014 C ; Derived from "KEYBOARD_INT_1" procedure of IBM "pc-at" C ; rombios source code (06/10/1985) C ; 'keybd.asm', INT 16H, KEYBOARD_IO C ; C ; 06/10/85 KEYBOARD BIOS C ; C ;--- HARDWARE INT 09 H - ( IRQ LEVEL 1 )------------------------------------------ C ; C ; KEYBOARD INTERRUPT ROUTINE C ; C ;--------------------------------------------------------------------------------- C 1D67 FB C sti ; ENABLE INTERRUPTS 1D68 55 C push bp 1D69 50 C push ax 1D6A 53 C push bx 1D6B 51 C push cx 1D6C 52 C push dx 1D6D 56 C push si 1D6E 57 C push di 1D6F 1E C push ds 1D70 06 C push es 1D71 FC C cld ; FORWARD DIRECTION C ;call dds ; SET UP ADDRESSING C ;mov ax, offset DDSData ; 1D72 8C C8 C mov ax, cs 1D74 8E D8 C mov ds, ax 1D76 8E C0 C mov es, ax C ; C ;----- WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED 1D78 B0 AD C mov al, DIS_KBD ; DISABLE THE KEYBOARD COMMAND 1D7A E8 04CF C call ship_it ; EXECUTE DISABLE 1D7D FA C cli ; DISABLE INTERRUPTS C ;sub cx, cx ; SET MAXIMUM TIMEOUT 1D7E 33 C9 C xor cx, cx 1D80 C kb_int_01: 1D80 E4 64 C in al, STATUS_PORT ; READ ADAPTER STATUS 1D82 A8 02 C test al, INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT 1D84 E0 FA C loopnz kb_int_01 ; WAIT FOR COMMAND TO BE ACCEPTED C ; C ;----- READ CHARACTER FROM KEYBOARD INTERFACE 1D86 E4 60 C in al, PORT_A ; READ IN THE CHARACTER C ; C ;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INTERRUPT LEVEL 9HI C ;mov ah, 04Fh ; SYSTEM INTERCEPT - KEY CODE FUNCTION C ;stc ; SET CY= 1 (IN CASE OF IRET) C ;int 15h ; CASSETTE CALL (AL)= KEY SCAN CODE C ; RETURNS CY= 1 FOR INVALID FUNCTION C ;jc short kb_int_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) C ; C ;jmp short k26 ; EXIT IF SYSTEM HANDLED SCAN CODE C ; EXIT HANDLES HARDWARE EOI AND ENABLE C ;jnc k26 C C ; C ;----- CHECK FOR A RESEND COMMAND TO KEYBOARD 1D88 C kb_int_02: ; (AL)= SCAN CODE 1D88 FB C sti ; ENABLE INTERRUPTS AGAIN 1D89 3C FE C cmp al, KB_RESEND ; IS THE INPUT A RESEND 1D8B 74 0D C je short kb_int_03 ; GO IF RESEND C ; C ;----- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD 1D8D 3C FA C cmp al, KB_ACK ; IS THE INPUT AN ACKNOWLEDGE 1D8F 75 12 C jne short kb_int_04 ; GO IF NOT C ; C ;----- A COMMAND TO THE KEYBOARD WAS ISSUED 1D91 FA C cli ; DISABLE INTERRUPTS 1D92 80 0E 2C4F R 10 C or byte ptr [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED 1D97 E9 022D C jmp k26 ; RETURN IF NOT (ACK RETURNED FOR DATA) C ; C ;----- RESEND THE LAST BYTE 1D9A C kb_int_03: 1D9A FA C cli ; DISABLE INTERRUPTS 1D9B 80 0E 2C4F R 20 C or byte ptr [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED 1DA0 E9 0224 C jmp k26 ; RETURN IF NOT ACK RETURNED FOR DATA) C ; 1DA3 C kb_int_04: C ;----- UPDATE MODE INDICATORS IF CHANGE IN STATE 1DA3 50 C push ax ; SAVE DATA IN 1DA4 E8 0497 C call make_led ; GO GET MODE INDICATOR DATA BYTE 1DA7 8A 1E 2C4F R C mov bl, byte ptr [KB_FLAG_2] ; GET PREVIOUS BITS 1DAB 32 D8 C xor bl, al ; SEE IF ANY DIFFERENT 1DAD 80 E3 07 C and bl, KB_LEDS ; ISOLATE INDICATOR BITS 1DB0 74 03 C jz short up0 ; IF NO CHANGE BYPASS UPDATE 1DB2 E8 0438 C call snd_led ; GO TURN ON MODE INDICATORS 1DB5 58 C up0: pop ax ; RESTORE DATA IN 1DB6 8A E0 C mov ah, al ; SAVE SCAN CODE IN AH ALSO C ; C ;----- TEST FOR OVERRUN SCAN CODE FROM KEYBOARD 1DB8 3C FF C cmp al, KB_OVER_RUN ; IS THIS AN OVERRUN CHAR C ;jne short k16 ; NO, TEST FOR SHIFT KEY C ;jmp short k62 ; BUFFER_FULL_BEEP 1DBA 75 03 E9 03E4 C je k62 C ; 1DBF C k16: 1DBF 24 7F C and al, 07Fh ; REMOVE BREAK BIT C ;push cs C ;pop es ; ESTABLISH ADDRESS OF TABLES C ; 1DC1 F6 06 2C50 R C0 C test byte ptr [KB_FLAG_3], RD_ID+LC_AB ; ARE WE DOING A READ ID? 1DC6 74 3B C jz short not_id ; CONTINUE IF NOT 1DC8 79 12 C jns short tst_id_2 ; IS THE RD_ID FLAG ON? 1DCA 80 FC AB C cmp ah, ID_1 ; IS THIS THE 1ST ID CHARACTER? 1DCD 75 05 C jne short rst_rd_id 1DCF 80 0E 2C50 R 40 C or byte ptr [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK 1DD4 C rst_rd_id: 1DD4 80 26 2C50 R 7F C and byte ptr [KB_FLAG_3], NOT RD_ID ; RESET THE READ ID FLAG C ;jmp short do_ext 1DD9 E9 01EB C jmp k26 C ; 1DDC C tst_id_2: 1DDC 80 26 2C50 R BF C and byte ptr [KB_FLAG_3], NOT LC_AB ; RESET FLAG 1DE1 80 FC 41 C cmp ah, ID_2 ; IS THIS THE 2ND ID CHARACTER? C ;jne short do_ext ; LEAVE IF NOT 1DE4 74 03 E9 01DE C jne k26 C ; C ;----- A READ ID SAID THAT IT WAS KBX 1DE9 80 0E 2C50 R 01 C or byte ptr [KB_FLAG_3], KBX ; INDICATE KBX WAS FOUND 1DEE F6 06 2C50 R 20 C test byte ptr [KB_FLAG_3], SET_NUM_LK ; SHOULD WE SET NUM LOCK? C ;jz short do_ext ; EXIT IF NOT 1DF3 75 03 E9 01CF C jz k26 1DF8 80 0E 2C4D R 20 C or byte ptr [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON 1DFD E8 03ED C call snd_led ; GO SET THE NUM LOCK INDICATOR C ;jmp short exit 1E00 E9 01C4 C jmp k26 C ; 1E03 C not_id: 1E03 F6 06 2C50 R 02 C test byte ptr [KB_FLAG_3], LC_HC ; WAS THE LAST CHARACTER A HIDDEN CODE 1E08 74 6C C jz short not_lc_hc ; JUMP IF NOT C ; C ;----- THE LAST CHARACTER WAS A HIDDEN CODE 1E0A 80 26 2C50 R FD C and byte ptr [KB_FLAG_3], NOT LC_HC ; RESET LAST CHAR HIDDEN CODE FLAG 1E0F 3C 52 C cmp al, INS_M ; WAS IT THE INSERT KEY? 1E11 74 08 C je short not_i 1E13 F6 C4 80 C test ah, 80h ; IS THIS A BREAK CODE C ;jnz short exit ; IGNORE BREAK ON REST OF THESE KEYS 1E16 74 03 E9 01AC C jnz k26 1E1B C not_i: 1E1B BF 235F R C mov di, offset K_TAB1 ; TEST FOR ONE OF THE KEYPAD CURSOR FUNC 1E1E B9 000A C mov cx, L_TAB1 1E21 F2/ AE C repne scasb ; SCAN FOR THE KEY 1E23 75 5E C jne short not_cur ; GO ON IF NOT FOUND 1E25 F6 06 2C4E R 08 C test byte ptr [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE? 1E2A 74 08 C jz short n_hld 1E2C 80 26 2C4E R F7 C and byte ptr [KB_FLAG_1], NOT HOLD_STATE ; EXIT HOLD STATE C ;do_ext: C ; jmp short exit ; IGNORE THIS KEY 1E31 E9 0193 C jmp k26 1E34 C n_hld: 1E34 F6 06 2C4D R 08 C test byte ptr [KB_FLAG], ALT_SHIFT ; IS ALT DOWN? 1E39 74 14 C jz short not_alt 1E3B F6 06 2C4D R 04 C test byte ptr [KB_FLAG], CTL_SHIFT ; HOW ABOUT CTRL? C ;jz short exit ; IGNORE ALL IF ONLY ALT DOWN 1E40 75 03 E9 0182 C jz k26 1E45 3C 53 C cmp al, DEL_M ; WAS IT THE DELETE KEY' C ;jne short exit ; IGNORE IF NOT 1E47 74 03 E9 017B C jne k26 1E4C E9 0194 C jmp k29 ; GO DO THE CTL, ALT, DEL RESET C ; 1E4F C not_alt: 1E4F F6 06 2C4D R 04 C test byte ptr [KB_FLAG], CTL_SHIFT ; IS CTL DOWN? 1E54 75 15 C jnz short ctl_on ; SPECIAL CASE IF SO 1E56 3C 52 C cmp al, INS_M ; IS THIS THE INSERT KEY? C ;jne short n_ins 1E58 74 03 E9 02B3 C jne k49 C ; C ;----- SPECIAL HANDLING FOR INSERT KEY 1E5D 8A C4 C mov al, ah ; RECOVER SCAN CODE 1E5F B4 80 C mov ah, INS_SHIFT ; AH = MASK FOR INSERT 1E61 A8 80 C test al, 80h ; WAS THIS A BREAK CODE? C ;jnz short b_c 1E63 74 03 E9 0143 C jnz k24 1E68 E9 00FD C jmp k22 ; GO HANDLE INSERT SHIFT C ;b_c: C ; jmp short k24 ; HANDLE BREAK C ;n_ins: C ; jmp short k49 ; HANDLE & IGNORE NUMLOCK 1E6B C ctl_on: 1E6B 80 F9 05 C cmp cl, 5 ; WAS IT INS, DEL, UP OR DOWN? C ;ja short exit ; IGNORE IF DO 1E6E 76 03 E9 0154 C ja k26 1E73 E9 024C C jmp k42 ; GO HANDLE CTRL CASE C ; 1E76 C not_lc_hc: ; LAST CHARACTER WAS NOT A HIDDEN CODE 1E76 80 FC E0 C cmp ah, HC ; IS THIS CHARACTER A HIDDEN CODE? 1E79 75 08 C jne short not_cur 1E7B 80 0E 2C50 R 03 C or byte ptr [KB_FLAG_3], LC_HC+KBX ; SET LAST CHAR WAS A HIDDEN CODE & KOX C ;exit: 1E80 E9 0144 C jmp k26 ; THROW AWAY THIS CODE C ; 1E83 C not_cur: 1E83 80 FC D9 C cmp ah, F11_M ; WAS IT F11? 1E86 75 14 C jne short t_f12 ; HANDLE IF SO 1E88 B1 85 C mov cl, FUNC11 ; SET BASE FUNCTION 11 1E8A 80 FC D7 C cmp ah, F11_B ; IS THIS A BREAK CODE C ;je short exit ; IGNORE SPEAK CODES 1E8D 75 03 E9 0135 C je k26 1E92 80 FC D8 C cmp ah, F12_B ; IS THIS A BREAK CODE C ;je short exit ; IGNORE BREAK CODES 1E95 75 03 E9 012D C je k26 1E9A EB 07 C jmp short do_fn 1E9C C t_f12: 1E9C 80 FC DA C cmp ah, F12_M ; WAS IT F12? 1E9F 75 3C C jne short t_sys_key ; GO TEST FOR SYSTEM KEY 1EA1 B1 86 C mov cl, FUNC11+1 ; SET BASE FUNCTION 12 1EA3 C do_fn: 1EA3 F6 06 2C4E R 08 C test byte ptr [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE? 1EA8 74 0A C jz short n_hld1 1EAA 80 26 2C4E R F7 C and byte ptr [KB_FLAG_1], NOT HOLD_STATE ; EXIT HOLD STATE C ;jmp short exit ; IGNORE THIS KEY 1EAF 75 03 E9 0113 C je k26 1EB4 C n_hld1: 1EB4 8A E1 C mov ah, cl C ; 1EB6 F6 06 2C4D R 08 C test byte ptr [KB_FLAG], ALT_SHIFT ; ARE WE IN ALT 1EBB 74 05 C jz short t_ctl 1EBD 80 C4 06 C add ah, 6 ; CNVT TO ALT FN 11-12 1EC0 EB 16 C jmp short set_fn 1EC2 C t_ctl: 1EC2 F6 06 2C4D R 04 C test byte ptr [KB_FLAG], CTL_SHIFT ; ARE WE IN CTRL 1EC7 74 05 C jz short t_shf 1EC9 80 C4 04 C add ah, 4 ; CNVT TO CTRL FN 11-12 1ECC EB 0A C jmp short set_fn 1ECE C t_shf: 1ECE F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT ; IS EITHER SHIFT ON? 1ED3 74 03 C jz short set_fn 1ED5 80 C4 02 C add ah, 2 ; CNVT TO SHIFT FN 11-12 1ED8 C set_fn: 1ED8 2A C0 C sub al, al ; FORCE PSEUDO SCAN CODE 1EDA E9 029B C jmp k61 ; PUT IT INTO BUFFER C ; C ;----- TEST FOR SYSTEM KEY 1EDD C t_sys_key: 1EDD 3C 54 C cmp al, SYS_KEY ; IS IT THE SYSTEM KEY? 1EDF 75 31 C jnz short k16a ; CONTINUE IF NOT C ; 1EE1 F6 C4 80 C test ah, 80h ; CHECK IF THIS A BREAK CODE 1EE4 75 1B C jnz short k16c ; DO NOT TOUCH SYSTEM INDICATOR IF TRUE C ; 1EE6 F6 06 2C4E R 04 C test byte ptr [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN C ;jnz short k16b ; IF YES, DO NOT PROCESS SYSTEM INDICATOR 1EEB 74 03 E9 00D7 C jnz k26 C ; 1EF0 80 0E 2C4E R 04 C or byte ptr [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED 1EF5 B0 20 C mov al, EOI ; END OF INTERRUPT COMMAND 1EF7 E6 20 C out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT C ; INTERRUPT-RETURN-NO-EOI 1EF9 B0 AE C mov al, ENA_KBD ; INSURE KEYBOARD 15 ENABLED 1EFB E8 034E C call ship_it ; EXECUTE ENABLE C ;mov ax, 8500h ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY C ;sti ; MAKE SURE INTERRUPTS ENABLED C ;int 15h ; USER INTERRUPT 1EFE E9 00D0 C jmp k27a ; END PROCESSING C ;k16b: C ; jmp short k26 ; IGNORE SYSTEM KEY C 1F01 C k16c: 1F01 80 26 2C4E R FB C and byte ptr [KB_FLAG_1], NOT SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN 1F06 B0 20 C mov al, EOI ; END OF INTERRUPT COMMAND 1F08 E6 20 C out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT C ; INTERRUPT-RETURN-NO-EOI 1F0A B0 AE C mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 1F0C E8 033D C call ship_it ; EXECUTE ENABLE C ;mov ax, 08501h ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY C ;sti ; MAKE SURE INTERRUPTS ENABLED C ;int 15h ; USER INTERRUPT 1F0F E9 00BF C jmp k27a ; IGNORE SYSTEM KEY 1F12 C k16a: 1F12 BF 225B R C mov di, offset K6 ; SHIFT KEY TABLE 1F15 B9 0008 C mov cx, K6L ; LENGTH 1F18 F2/ AE C repne scasb ; LOOK THROUGH THE TABLE FOR A MATCH 1F1A 8A C4 C mov al, ah ; RECOVER SCAN CODE C ;je short k17 ; JUMP IF MATCH FOUND C ;jmp short k25 ; IF NO MATCH, THEN SHIFT NOT FOUND 1F1C 74 03 E9 0092 C jne k25 C ; C ;------ SHIFT KEY FOUND 1F21 C k17: 1F21 81 EF 225C R C sub di, offset K6+1 ; ADJUST PTR TO SCAN CODE MATCH 1F25 81 C7 2263 R C add di, offset K7 1F29 8A 25 C mov ah, byte ptr [DI] ; GET MASK INTO AH 1F2B A8 80 C test al, 80h ; TEST FOR BREAK KEY C ;jz short k17c ; BREAK_SHIFT_FOUND C ;jmp short k23 ; CONTINUE 1F2D 75 5D C jnz short k23 C ; C ;----- DETERMINE SET OR TOGGLE 1F2F C k17c: 1F2F 80 FC 10 C cmp ah, SCROLL_SHIFT 1F32 73 07 C jae short k18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY C ; C ;----- PLAIN SHIFT KEY, SET SHIFT ON 1F34 08 26 2C4D R C or byte ptr [KB_FLAG], ah ; TURN ON SHIFT BIT 1F38 E9 008C C jmp k26 ; INTERRUPT_RETURN C ; C ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT 1F3B C k18: ; SHIFT-TOGGLE 1F3B F6 06 2C4D R 04 C test byte ptr [KB_FLAG], CTL_SHIFT ; CHECK CTL SHIFT STATE 1F40 75 71 C jnz short k25 ; JUMP IF CTL STATE C ; 1F42 3C 52 C cmp al, INS_KEY ; CHECK FOR INSERT KEY 1F44 75 22 C jnz short k22 ; JUMP IF NOT INSERT KEY 1F46 F6 06 2C4D R 08 C test byte ptr [KB_FLAG], ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT 1F4B 75 66 C jnz short k25 ; JUMP IF ALTERNATE SHIFT C ; 1F4D F6 06 2C4D R 20 C test byte ptr [KB_FLAG], NUM_STATE ; CHECK FOR BASE STATE 1F52 75 0D C jnz short k21 ; JUMP IF NUM LOCK IS ON 1F54 F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT 1F59 74 0D C jz short k22 ; JUMP IF BASE STATE C ; 1F5B C k20: ; NUMERIC ZERO, NOT INSERT KEY 1F5B B8 5230 C mov ax, 5230h ; PUT OUT AN ASCII ZERO 1F5E E9 01E4 C jmp k57 ; BUFFER FILL 1F61 C k21: ; MIGHT BE NUMERIC 1F61 F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT 1F66 74 F3 C jz short k20 ; JUMP NUMERIC, NOT INSERT C ; 1F68 C k22: ; SHIFT TOGGLE KEY HIT; PROCESS IT 1F68 84 26 2C4E R C test ah, byte ptr [KB_FLAG_1] ; IS KEY ALREADY DEPRESSED 1F6C 74 02 C jz short k22a0 ; GO IF NOT 1F6E EB 57 C jmp short k26 ; JUMP IF KEY ALREADY DEPRESSED 1F70 C k22a0: 1F70 08 26 2C4E R C or byte ptr [KB_FLAG_1], ah ; INDICATE THAT THE KEY IS DEPRESSED 1F74 30 26 2C4D R C xor byte ptr [KB_FLAG], ah ; TOGGLE THE SHIFT STATE C ; C ;----- TOGGLE LED IF CAPS OR NUM KEY DEPRESSED 1F78 F6 C4 70 C test ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? 1F7B 74 05 C jz short k22b ; GO IF NOT C ; 1F7D 50 C push ax ; SAVE SCAN CODE AND SHIFT MASK 1F7E E8 026C C call snd_led ; GO TURN MODE INDICATORS ON 1F81 58 C pop ax ; RESTORE SCAN CODE 1F82 C k22b: 1F82 3C 52 C cmp al, INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY 1F84 75 41 C jne short k26 ; JUMP IF NOT INSERT KEY 1F86 B8 5200 C mov ax, INS_KEY*100h ; SET SCAN CODE INTO AH, 0 INTO AL 1F89 E9 01B9 C jmp k57 ; PUT INTO OUTPUT BUFFER C ; C ;----- BREAK SHIFT FOUND 1F8C C k23: ; BREAK-SHIFT-FOUND 1F8C 80 FC 10 C cmp ah, SCROLL_SHIFT ; IS THIS A TOGGLE KEY 1F8F 73 1A C jae short k24 ; YES, HANDLE BREAK TOGGLE 1F91 F6 D4 C not ah ; INVERT MASK 1F93 20 26 2C4D R C and byte ptr [KB_FLAG], ah ; TURN OFF SHIFT BIT 1F97 3C B8 C cmp al, ALT_KEY+80h ; IS THIS ALTERNATE SHIFT RELEASE 1F99 75 2C C jne short k26 ; INTERRUPT_RETURN C ; C ;----- ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER 1F9B A0 2C51 R C mov al, byte ptr [ALT_INPUT] 1F9E B4 00 C mov ah, 0 ; SCAN CODE OF 0 1FA0 88 26 2C51 R C mov byte ptr [ALT_INPUT], ah ; ZERO OUT THE FIELD 1FA4 3C 00 C cmp al, 0 ; WAS THE INPUT=0 1FA6 74 1F C je short k26 ; INTERRUPT_RETURN 1FA8 E9 01A9 C jmp k58 ; IT WASN'T, SO PUT IN BUFFER C ; 1FAB C k24: ; BREAK-TOGGLE 1FAB F6 D4 C not ah ; INVERT MASK 1FAD 20 26 2C4E R C and byte ptr [KB_FLAG_1], ah ; INDICATE NO LONGER DEPRESSED 1FB1 EB 14 C jmp short k26 ; INTERRUPT_RETURN C ; C ;----- TEST FOR HOLD STATE 1FB3 C k25: ; NO-SHIFT-FOUND 1FB3 3C 80 C cmp al, 80h ; TEST FOR BREAK KEY 1FB5 73 10 C jae short k26 ; NOTHING FOR BREAK CHARS FROM HERE ON 1FB7 F6 06 2C4E R 08 C test byte ptr [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE 1FBC 74 1E C jz short k28 ; BRANCH AROUND TEST IF NOT 1FBE 3C 45 C cmp al, NUM_KEY 1FC0 74 05 C je short k26 ; CAN'T END HOLD ON NUM_LOCK 1FC2 80 26 2C4E R F7 C and byte ptr [KB_FLAG_1], NOT HOLD_STATE ; TURN OFF THE HOLD STATE BIT C ; 1FC7 C k26: ; INTERRUPT-RETURN 1FC7 FA C cli ; TURN OFF INTERRUPTS 1FC8 B0 20 C mov al, EOI ; END OF INTERRUPT COMMAND 1FCA E6 20 C out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 1FCC C k27: ; INTERRUPT-RETURN-NO-EOI 1FCC B0 AE C mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 1FCE E8 027B C call ship_it ; EXECUTE ENABLE 1FD1 C k27a: 1FD1 FA C cli ; DISABLE INTERRUPTS 1FD2 07 C pop es ; RESTORE REGISTERS 1FD3 1F C pop ds 1FD4 5F C pop di 1FD5 5E C pop si 1FD6 5A C pop dx 1FD7 59 C pop cx 1FD8 5B C pop bx 1FD9 58 C pop ax 1FDA 5D C pop bp 1FDB CF C iret ; RETURN, INTERRUPTS ON WITH FLAG CHANGE C C ;----- NOT IN HOLD STATE 1FDC C k28: ; NO-HOLD-STATE 1FDC F6 06 2C4D R 08 C test byte ptr [KB_FLAG], ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT C ;jnz short k29 ; JUMP IF ALTERNATE SHIFT C ;jmp short k38 ; JUMP IF NOT ALTERNATE 1FE1 74 7C C jz short k38 C ; C ;----- TEST FOR CONTROL KEY AND RESET KEY SEQUENCE (CTL ALT DEL) 1FE3 C k29: ; TEST-RESET 1FE3 F6 06 2C4D R 04 C test byte ptr [KB_FLAG], CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO 1FE8 74 1B C jz short k31 ; NO RESET 1FEA 3C 45 C cmp al, NUM_KEY ; CHECK FOR INVALID NUM LOCK KEY 1FEC 74 D9 C je short k26 ; THROW AWAY IF (ALT-CTL)+NUM-LOCK 1FEE 3C 46 C cmp al, SCROLL_KEY ; CHECK FOR INVALID SCROLL-LOCK KEY 1FF0 74 D5 C je short k26 ; THROW AWAY IF (ALT-CTL)+SCROLL_LOCK 1FF2 3C 53 C cmp al, DEL_KEY ; CTL-ALT STATE, TEST FOR DELETE KEY 1FF4 75 0F C jne short k31 ; NO-RESET C ; C ;----- CTL-ALT-DEL HAS BEEN FOUND C ;;mov byte ptr [RESET_FLAG], 1234h ; SET FLAG FOR RESET FUNCTION C ;;jmp short START_1 ; JUMP TO POWER ON DIAGNOSTICS 1FF6 BB 0040 C mov bx, BIOS_DSEGM 1FF9 8E DB C mov ds, bx 1FFB BB 0072 C mov bx, RESET_FLAG 1FFE C7 07 1234 C mov word ptr [BX], 1234h ; warm reset C ; 07/03/2014 2002 E9 E0CF C jmp cpu_reset C C ;cpu_reset: C ; 07/03/2014 C ; CPU reset (power on) address C ;db 0EAh ; far jump (jmp 0FFFFh:0000h) C ;dw 0 C ;dw 0FFFFh ; F000:0FFF0h C C ;khere: hlt C ; jmp short khere C C ; C ;----- IN ALTERNATE SHIFT, RESET NOT FOUND 2005 C k31: ; NO-RESET 2005 3C 39 C cmp al, 57 ; TEST FOR SPACE KEY 2007 75 05 C jne short k32 ; NOT THERE 2009 B0 20 C mov al, ' ' ; SET SPACE CHAR 200B E9 0137 C jmp k57 ; BUFFER_FILL C ; C ;----- LOOK FOR KEY PAD ENTRY 200E C k32: ; ALT-KEY-PAD 200E BF 2369 R C mov di, offset K30 ; ALT-INPUT-TABLE 2011 B9 000A C mov cx, 10 ; LOOK FOR ENTRY USING KEYPAD 2014 F2/ AE C repne scasb ; LOOK FOR MATCH 2016 75 12 C jne short k33 ; NO_ALT_KEYPAD 2018 81 EF 236A R C sub di, offset K30+1 ; DI-NOW-HAS ENTRY VALUE 201C A0 2C51 R C mov al, byte ptr [ALT_INPUT] ; GET THE CURRENT BYTE 201F B4 0A C mov ah, 10 ; MULTIPLY BY 10 2021 F6 E4 C mul ah 2023 03 C7 C add ax, di ; ADD IN THE LATEST ENTRY 2025 A2 2C51 R C mov byte ptr [ALT_INPUT], al ; STORE IT AWAY 2028 EB 9D C jmp short k26 ; THROW AWAY THAT KEYSTROKE C ; C ;----- LOOK FOR SUPERSHIFT ENTRY 202A C k33: ; NO-ALT-KEYPAD 202A C6 06 2C51 R 00 C mov byte ptr [ALT_INPUT], 0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT 202F B9 001A C mov cx, 26 ; (DI),(ES) ALREADY POINTING 2032 F2/ AE C repne scasb ; LOOK FOR MATCH IN ALPHABET 2034 75 05 C jne short k34 ; NOT FOUND, FUNCTION KEY OR OTHER 2036 B0 00 C mov al, 0 ; ASCII CODE OF ZERO 2038 E9 010A C jmp k57 ; PUT IT IN THE BUFFER C ; C ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT 203B C k34: ; ALT-TOP-ROW 203B 3C 02 C cmp al, 2 ; KEY WITH '1' ON IT 203D 74 0C C je short k35 ; NOT ONE OF INTERESTING KEYS 203F 3C 0E C cmp al, 14 ; IS IT IN THE REGION 2041 73 08 C jae short k35 ; ALT-FUNCTION 2043 80 C4 76 C add ah, 118 ; CONVERT PSEUDO SCAN CODE TO RANGE 2046 B0 00 C mov al, 0 ; INDICATE AS SUCH 2048 E9 00FA C jmp k57 ; BUFFER_FILL C ; C ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES 204B C k35: ; ALT-FUNCTION C ; 59 = scan code of F1 key 204B 3C 3B C cmp al, 59 ; TEST FOR IN TABLE C ;jae short k37 ; ALT-CONTINUE 204D 73 03 E9 FF75 C jb k26 C ;k36: ; CLOSE-RETURN C ; jmp short k26 ; IGNORE THE KEY 2052 C k37: ; ALT-CONTINUE 2052 3C 47 C cmp al, 71 ; IN KEYPAD REGION C ;jae short k36 ; IF SO, IGNORE 2054 72 03 E9 FF6E C jae k26 C 2059 BB 233B R C mov bx, offset K13 ; ALT SHIFT PSEUDO SCAN TABLE 205C E9 013B C jmp k63 ; TRANSLATE THAT C ; C ;----- NOT IN ALTERNATE SHIFT 205F C k38: ; NOT-ALT-SHIFT 205F F6 06 2C4D R 04 C test byte ptr [KB_FLAG], CTL_SHIFT ; ARE WE IN CONTROL SHIFT 2064 74 69 C jz short k44 ; NOT-CTL-SHIFT C ; C ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS C ;----- TEST FOR BREAK AND PAUSE KEYS 2066 3C 46 C cmp al, SCROLL_KEY ; TEST FOR BREAK 2068 75 1D C jne short k39 ; NO-BREAK 206A 8B 1E 2C52 R C mov bx , word ptr [BUFFER_START] ; RESET BUFFER TO EMPTY 206E 89 1E 2C56 R C mov word ptr [BUFFER_HEAD], bx 2072 89 1E 2C58 R C mov word ptr [BUFFER_TAIL], bx 2076 C6 06 2C4C R 80 C mov byte ptr [BIOS_BREAK], 80h ; TURN ON @BIOS_BREAK BIT C ; C ;----- ENABLE KEYBOARD 207B B0 AE C mov al, ENA_KBD ; ENABLE KEYBOARD 207D E8 01CC C call ship_it ; EXECUTE ENABLE 2080 CD 1B C int 1Bh ; BREAK INTERRUPT VECTOR 2082 2B C0 C sub ax, ax ; PUT OUT DUMMY CHARACTER 2084 E9 00BE C jmp k57 ; BUFFER_FILL 2087 C k39: ; NO_BREAK 2087 3C 45 C cmp al, NUM_KEY ; LOOK FOR PAUSE KEY 2089 75 2D C jne short k41 ; NO-PAUSE 208B 80 0E 2C4E R 08 C or byte ptr [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG C ; C ;----- ENABLE KEYBOARD 2090 B0 AE C mov al, ENA_KBD ; ENABLE KEYBOARD 2092 E8 01B7 C call ship_it ; EXECUTE ENABLE 2095 B0 20 C mov al, EOI ; END OF INTERRUPT TO CONTROL PORT 2097 E6 20 C out INTA00, al ; ALLOW FURTHER KEYSTROKE INTERRUPTS C ; C ;----- DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON 2099 1E C push ds 209A BB 0040 C mov bx, BIOS_DSEGM 209D 8E DB C mov ds, bx 209F BB 0049 C mov bx, offset CRT_MODE 20A2 80 3F 07 C cmp byte ptr [BX], 7 ; IS THIS THE MONOCHROME CARD 20A5 74 06 C je short k40p ; YES, NOTHING TO DO 20A7 BA 03D8 C mov dx, 03D8h ; PORT FOR COLOR CARD 20AA B0 65 C mov al, byte ptr [CRT_MODE_SET] ; GET THE VALUE OF THE CURRENT MODE 20AC EE C out dx, al ; SET THE CRT MODE, SO THAT CRT 15 ON C ; C ;----- SUSPEND SYSTEM OPERATION (LOOP) TILL NEXT KEY CLEARS HOLD STATE FLAG 20AD C k40p: 20AD 1F C pop ds 20AE C k40: ; PAUSE-LOOP 20AE F6 06 2C4E R 08 C test byte ptr [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG 20B3 75 F9 C jnz short k40 ; LOOP UNTIL FLAG TURNED OFF C ; 20B5 E9 FF19 C jmp k27a ; INTERRUPT_RETURN_NO_EOI C ; C ;----- TEST SPECIAL CASE KEY 55 20B8 C k41: ; NO-PAUSE 20B8 3C 37 C cmp al, 55 20BA 75 06 C jne short k42 ; NOT-KEY-55 20BC B8 7200 C mov ax, 114*100h ; START/STOP PRINTING SWITCH 20BF E9 0083 C jmp k57 ; BUFFER_FILL C ; C ;----- SET UP TO TRANSLATE CONTROL SHIFT 20C2 C k42: ; NOT-KEY-55 20C2 BB 226B R C mov bx, offset K8 ; SET UP TO TRANSLATE C7L 20C5 3C 3B C cmp al, 59 ; IS IT IN TABLE 20C7 78 79 C js short k56 ; YES, GO TRANSLATE CHAR C ; CTL-TABLE-TRANSLATE 20C9 BB 22A5 R C mov bx, offset K9 ; CTL TABLE SCAN 20CC E9 00CB C jmp k63 ; TRANSLATE_SCAN C ; C ;----- NOT IN CONTROL SHIFT 20CF C k44: ; NOT-CTL-SHIFT 20CF 3C 47 C cmp al, 71 ; TEST FOR KEYPAD REGION 20D1 73 2F C jae short k48 ; HANDLE KEYPAD REGION 20D3 F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT 20D8 74 5D C jz short k54 ; TEST FOR SHIFT STATE C ; C ;----- UPPER CASE, HANDLE SPECIAL CASES 20DA 3C 0F C cmp al, 15 ; BACK TAB KEY 20DC 75 05 C jne short k45 ; NOT-BACK-TAB 20DE B8 0F00 C mov ax, 15*100h ; SET PSEUDO SCAN CODE 20E1 EB 62 C jmp short k57 ; BUFFER_FILL C ; 20E3 C k45: ; NOT-BACK-TAB 20E3 3C 37 C cmp al, 55 ; PRINT SCREEN KEY 20E5 75 0C C jne short k46 ; NOT-PRINT-SCREEN C ; C ;----- ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION 20E7 B0 AE C mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 20E9 E8 0160 C call ship_it ; EXECUTE ENABLE 20EC B0 20 C mov al, EOI ; END OF CURRENT INTERRUPT 20EE E6 20 C out INTA00, al ; SO FURTHER THINGS CAN HAPPEN C ;push bp ; SAVE POINTER C ;int 05h ; ISSUE PRINT SCREEN INTERRUPT C ;pop bp ; RESTORE POINTER 20F0 E9 FED9 C jmp k27 ; GO BACK WITHOUT EOI OCCURRING C ; 20F3 C k46: ; NOT-PRINT-SCREEN 20F3 3C 3B C cmp al, 59 ; FUNCTION KEYS 20F5 78 06 C js short k47 ; NOT-UPPER-FUNCTION 20F7 BB 2331 R C mov bx, offset K12 ; UPPER CASE PSEUDO SCAN CODES 20FA E9 009D C jmp k63 ; TRANSLATE_SCAN C ; 20FD C k47: ; NOT-UPPER-FUNCTION 20FD BB 22F7 R C mov bx, offset K11 ; POINT TO UPPER CASE TABLE 2100 EB 40 C jmp short k56 ; OK, TRANSLATE THE CHAR C ; C ;----- KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION 2102 C k48: ; KEYPAD-REGION 2102 F6 06 2C4D R 20 C test byte ptr [KB_FLAG], NUM_STATE ; ARE WE IN NUM LOCK 2107 75 20 C jnz short k52 ; TEST FOR SURE 2109 F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE 210E 75 20 C jnz short k53 ; IF SHIFTED, REALLY NUM STATE C ; C ;----- BASE CASE FOR KEYPAD 2110 C k49: ; BASE-CASE 2110 3C 4A C cmp al, 74 ; SPECIAL CASE FOR A COUPLE OF KEYS 2112 74 0B C je short k50 ; MINUS 2114 3C 4E C cmp al, 78 2116 74 0C C je short k51 2118 2C 47 C sub al, 71 ; CONVERT ORIGIN 211A BB 2352 R C mov bx, offset K15 ; BASE CASE TABLE 211D EB 7D C jmp k64 ; CONVERT TO PSEUDO SCAN 211F C k50: 211F B8 4A2D C mov ax, (74*100h)+'-' ; MINUS 2122 EB 21 C jmp short k57 ; BUFFER_FILL 2124 C k51: 2124 B8 4E2B C mov ax, (78*100h)+'+' ; PLUS 2127 EB 1C C jmp short k57 ; BUFFER_FILL C ; C ;----- MIGHT BE NUM LOCK, TEST SHIFT STATUS 2129 C k52: ; ALMOST-NUM-STATE 2129 F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT 212E 75 E0 C jnz short k49 ; SHIFTED TEMP OUT OF NUM STATE C ; 2130 C k53: ; REALLY NUM STATE 2130 2C 46 C sub al, 70 ; CONVERT ORIGIN 2132 BB 2345 R C mov bx, offset K14 ; NUM STATE TABLE 2135 EB 0B C jmp short k56 ; TRANSLATE_CHAR C ; C ;----- PLAIN OLD LOWER CASE 2137 C k54: ; NOT-SHIFT 2137 3C 3B C cmp al, 59 ; TEST FOR FUNCTION KEYS 2139 72 04 C jb short k55 ; NOT-LOWER-FUNCTION 213B B0 00 C mov al, 0 ; SCAN CODE IN AH ALREADY 213D EB 06 C jmp short k57 ; BUFFER_FILL C ; 213F C k55: ; NOT-LOWER-FUNCTION 213F BB 22BE R C mov bx, offset K10 ; LC TABLE C ; C ;----- TRANSLATE THE CHARACTER 2142 C k56: ; TRANSLATE-CHAR 2142 FE C8 C dec al ; CONVERT ORIGIN 2144 D7 C xlat ; CONVERT THE SCAN CODE TO ASCII C ; C ;----- PUT CHARACTER INTO BUFFER 2145 C k57: ; BUFFER_FILL 2145 3C FF C cmp al, -1 ; IS THIS AN IGNORE CHAR C ;je short k59 ; YES, DO NOTHING WITH IT 2147 75 03 E9 FE7B C je k26 214C 80 FC FF C cmp ah, -1 ; LOOK FOR -1 PSEUDO SCAN C ;je short k59 ; NEAR_INTERRUPT_RETURN 214F 75 03 E9 FE73 C je k26 C ; C ; ; 07/03/2014 C ;; DELETE key handling (ASCII = 127) C ;; (This code part was not in original INT 09h handler) C ;; AX = 53E0h => AX = 007Fh <= AX = 5300h C ; cmp ah, DEL_KEY C ; jne short k58 C ; cmp al, 0E0h C ; je short @f C ; and al, al C ; jnz short k58 C ;@@: C ; mov ax, 127 C ; jmp short k61 C ; C ; C ;----- HANDLE THE CAPS LOCK PROBLEM 2154 C k58: ; BUFFER_FILL-NOTEST 2154 F6 06 2C4D R 40 C test byte ptr [KB_FLAG], CAPS_STATE ; ARE WE IN CAPS LOCK STATE 2159 74 1D C jz short k61 ; SKIP IF NOT C ; C ;----- IN CAPS LOCK STATE 215B F6 06 2C4D R 03 C test byte ptr [KB_FLAG], LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE 2160 74 0C C jz short k60 ; IF NOT SHIFT, CONVERT LOWER TO UPPER C ; C ;----- CONVERT ANY UPPER CASE TO LOWER CASE 2162 3C 41 C cmp al, 'A' ; FIND OUT IF ALPHABETIC 2164 72 12 C jb short k61 ; NOT-CAPS-STATE 2166 3C 5A C cmp al, 'Z' 2168 77 0E C ja short k61 ; NOT_CAPS STATE 216A 04 20 C add al, 'a'-'A' ; CONVERT TO LOWER CASE 216C EB 0A C jmp short k61 ; NOT_CAPS_STATE C ; C ;k59: ; NEAR-INTERRUPT-RETURN C ; jmp short k26 ; INTERRUPT_RETURN C ; C ;----- CONVERT ANY LOWER CASE TO UPPER CASE 216E C k60: ; LOWER-TO-UPPER 216E 3C 61 C cmp al, 'a' ; FIND OUT IF ALPHABETIC 2170 72 06 C jb short k61 ; NOT_CAPS_STATE 2172 3C 7A C cmp al, 'z' 2174 77 02 C ja short k61 ; NOT CAPS STATE 2176 2C 20 C sub al, 'a'-'A' ; CONVERT TO UPPER CASE C ; 2178 C k61: ; NOT-CAPS-STATE 2178 8B 1E 2C58 R C mov bx, word ptr [BUFFER_TAIL] ; GET THE END POINTER TO THE BUFFER 217C 8B F3 C mov si, bx ; SAVE THE VALUE 217E E8 FBD9 C call k4 ; ADVANCE THE TAIL 2181 3B 1E 2C56 R C cmp bx, word ptr [BUFFER_HEAD] ; HAS THE BUFFER WRAPPED AROUND 2185 74 1C C je short k62 ; BUFFER_FULL_BEEP 2187 89 04 C mov word ptr [SI], ax ; STORE THE VALUE 2189 89 1E 2C58 R C mov word ptr [BUFFER_TAIL], bx ; MOVE THE POINTER UP 218D FA C cli ; TURN OFF INTERRUPTS 218E B0 20 C mov al, EOI ; END OF INTERRUPT COMMAND 2190 E6 20 C out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2192 B0 AE C mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2194 E8 00B5 C call ship_it ; EXECUTE ENABLE C ;mov ax, 09102h ; MOVE IN POST CODE & TYPE C ;int 15h ; PERFORM OTHER FUNCTION 2197 E9 FE37 C jmp k27a ; INTERRUPT_RETURN C ; C ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES 219A C k63: ; TRANSLATE-SCAN 219A 2C 3B C sub al, 59 ; CONVERT ORIGIN TO FUNCTION KEYS 219C C k64: ; TRANSLATE-SCAN-ORGD 219C D7 C xlat ; CTL TABLE SCAN 219D 8A E0 C mov ah, al ; PUT VALUE INTO AH 219F B0 00 C mov al, 0 ; ZERO ASCII CODE 21A1 EB A2 C jmp short k57 ; PUT IT INTO THE BUFFER 21A3 C k62: 21A3 B0 20 C mov al, EOI ; ENABLE INTERRUPT CONTROLLER CHIP 21A5 E6 20 C out INTA00, al 21A7 B9 02A6 C mov cx, 678 ; DIVISOR FOR 1760 HZ 21AA B3 04 C mov bl, 4 ; SHORT BEEP COUNT (1/16 1/64 DELAY) 21AC E8 F993 C call beep ; GO TO COMMON BEEP HANDLER 21AF E9 FE1A C jmp k27 ; EXIT C 21B2 C snd_data: C ; --------------------------------------------------------------------------------- C ; SND_DATA C ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES C ; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO C ; HANDLES ANY RETRIES IF REQUIRED C ; --------------------------------------------------------------------------------- C ; 21B2 50 C push ax ; SAVE REGISTERS 21B3 53 C push bx 21B4 51 C push cx 21B5 8A F8 C mov bh, al ; SAVE TRANSMITTED BYTE FOR RETRIES 21B7 B3 03 C mov bl, 3 ; LOAD RETRY COUNT SOOT 21B9 FA C cli ; DISABLE INTERRUPTS 21BA 80 26 2C4F R CF C and byte ptr [KB_FLAG_2], not (KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS C ; C ;----- WAIT FOR ANY PENDING COMMAND TO BE ACCEPTED 21BF 2B C9 C sub cx, cx ; MAXIMUM WAIT COUNT 21C1 C sd1: 21C1 E4 64 C in al, STATUS_PORT ; READ KEYBOARD PROCESSOR STATUS PORT 21C3 A8 02 C test al, INPT_BUF_FULL ; CHECK FOR ANY PENDING COMMAND 21C5 E0 FA C loopnz sd1 ; WAIT FOR COMMAND TO BE ACCEPTED C ; 21C7 8A C7 C mov al, bh ; REESTABLISH BYTE TO TRANSMIT 21C9 E6 60 C out PORT_A, al ; SEND BYTE 21CB FB C sti ; ENABLE INTERRUPTS C ;mov cx, 01A00h ; LOAD COUNT FOR 10 ms+ 21CC 33 C9 C xor cx, cx 21CE C sd3: 21CE F6 06 2C4F R 30 C test byte ptr [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET 21D3 75 0D C jnz short sd7 ; IF SET, SOMETHING RECEIVED GO PROCESS C ; 21D5 E2 F7 C loop sd3 ; OTHERWISE WAIT 21D7 C sd5: 21D7 FE CB C dec bl ; DECREMENT RETRY COUNT 21D9 75 E6 C jnz short sd1 ; RETRY TRANSMISSION C ; 21DB 80 0E 2C4F R 80 C or byte ptr [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG 21E0 EB 07 C jmp short sd9 ; RETRIES EXHAUSTED FORGET TRANSMISSION 21E2 C sd7: 21E2 F6 06 2C4F R 10 C test byte ptr [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE 21E7 74 EE C jz short sd5 ; IF NOT, GO RESEND 21E9 C sd9: 21E9 59 C pop cx ; RESTORE REGISTERS 21EA 5B C pop bx 21EB 58 C pop ax 21EC C3 C retn ; RETURN, GOOD TRANSMISSION C 21ED C snd_led: C ; --------------------------------------------------------------------------------- C ; SND_LED C ; SND_LED1 C ; C ; THIS ROUTINES TURNS ON THE MODE INDICATORS. C ; C ;---------------------------------------------------------------------------------- C ; 21ED FA C cli ; TURN OFF INTERRUPTS 21EE F6 06 2C4F R 40 C test byte ptr [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 21F3 75 47 C jnz short sl9 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY C ; 21F5 80 0E 2C4F R 40 C or byte ptr [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 21FA B0 20 C mov al, EOI ; END OF INTERRUPT COMMAND 21FC E6 20 C out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 21FE EB 0D C jmp short sl3 ; GO SEND MODE INDICATOR COMMAND C 2200 C snd_led1: 2200 FA C cli ; TURN OFF INTERRUPTS 2201 F6 06 2C4F R 40 C test byte ptr [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 2206 75 34 C jnz short sl9 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY C ; 2208 80 0E 2C4F R 40 C or byte ptr [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 220D C sl3: 220D B0 ED C mov al, LED_CMD ; LED CMD BYTE 220F E8 FFA0 C call snd_data ; SEND DATA TO KEYBOARD 2212 FA C cli 2213 E8 0028 C call make_led ; GO FORM INDICATOR DATA BYTE 2216 80 26 2C4F R F8 C and byte ptr [KB_FLAG_2], not KB_LEDS ; CLEAR MODE INDICATOR BITS 221B 08 06 2C4F R C or byte ptr [KB_FLAG_2], al ; SAVE INDICATORS STATES FOR NEXT TIME 221F F6 06 2C4F R 80 C test byte ptr [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 2224 75 0B C jnz short sl5 ; IF SO, BYPASS SECOND BYTE TRANSMISSION C ; 2226 E8 FF89 C call snd_data ; SEND DATA TO KEYBOARD 2229 FA C cli ; TURN OFF INTERRUPTS 222A F6 06 2C4F R 80 C test byte ptr [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 222F 74 06 C jz short sl7 ; IF NOT, DON'T SEND AN ENABLE COMMAND 2231 C sl5: 2231 B0 F4 C mov al, KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND 2233 E8 FF7C C call snd_data ; SEND DATA TO KEYBOARD 2236 FA C cli ; TURN OFF INTERRUPTS 2237 C sl7: 2237 80 26 2C4F R 3F C and byte ptr [KB_FLAG_2], not (KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR 223C C sl9: ; UPDATE AND TRANSMIT ERROR FLAG 223C FB C sti ; ENABLE INTERRUPTS 223D C3 C retn ; RETURN TO CALLER C 223E C make_led: C ;--------------------------------------------------------------------------------- C ; MAKE_LED C ; C ; THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF C ; THE MODE INDICATORS. C ; C ;--------------------------------------------------------------------------------- C ; 223E 51 C push cx ; SAVE CX 223F A0 2C4D R C mov al, byte ptr [KB_FLAG] ; GET CAPS & NUM LOCK INDICATORS 2242 24 70 C and al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS 2244 B1 04 C mov cl, 4 ; SHIFT COUNT 2246 D2 C0 C rol al, cl ; SHIFT BITS OVER TO TURN ON INDICATORS 2248 24 07 C and al, 07h ; MAKE SURE ONLY MODE BITS ON 224A 59 C pop cx 224B C3 C retn ; RETURN TO CALLER C 224C C ship_it: C ;--------------------------------------------------------------------------------- C ; SHIP_IT C ; C ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES C ; TO THE KEYBOARD CONTROLLER. C ; C ;--------------------------------------------------------------------------------- C ; 224C 50 C push ax ; SAVE DATA TO SEND C C ;----- WAIT FOR COMMAND TO ACCEPTED 224D FA C cli ; DISABLE INTERRUPTS TILL DATA SENT 224E 2B C9 C sub cx, cx ; CLEAR TIMEOUT COUNTER 2250 C s10: 2250 E4 64 C in al, STATUS_PORT ; READ KEYBOARD CONTROLLER STATUS 2252 A8 02 C test al, INPT_BUF_FULL ; CHECK FOR ITS INPUT BUFFER BUSY 2254 E0 FA C loopnz s10 ; WAIT FOR COMMAND TO BE ACCEPTED C 2256 58 C pop ax ; GET DATA TO SEND 2257 E6 64 C out STATUS_PORT, al ; SEND TO KEYBOARD CONTROLLER 2259 FB C sti ; ENABLE INTERRUPTS AGAIN 225A C3 C retn ; RETURN TO CALLER C C C ;----- TABLE OF SHIFT KEYS AND MASK VALUES (EARLY PC) 225B 52 C K6: db INS_KEY ; INSERT KEY 225C 3A 45 46 38 1D C db CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY 2261 2A 36 C db LEFT_KEY,RIGHT_KEY 2263 = 0008 C K6L equ $-K6 C C ;----- SHIFT_MASK_TABLE 2263 80 C K7: db INS_SHIFT ; INSERT MODE SHIFT 2264 40 20 10 08 04 C db CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT 2269 02 01 C db LEFT_SHIFT,RIGHT_SHIFT C C ;----- SCAN CODE TABLES 226B 1B FF 00 FF FF FF C K8: db 27,-1,0,-1,-1,-1,30,-1,-1,-1,-1,31 1E FF FF FF FF 1F 2277 FF 7F FF 11 17 05 C db -1,127,-1,17,23,5,18,20,25,21,9,15 12 14 19 15 09 0F 2283 10 1B 1D 0A FF 01 C db 16,27,29,10,-1,1,19,4,6,7,8,10 13 04 06 07 08 0A 228F 0B 0C FF FF FF FF C db 11,12,-1,-1,-1,-1,28,26,24,3,22,2 1C 1A 18 03 16 02 229B 0E 0D FF FF FF FF C db 14,13,-1,-1,-1,-1,-1,-1,' ',-1 FF FF 20 FF C C ;----- CTL TABLE SCAN 22A5 5E 5F 60 61 62 63 C K9: db 94,95,96,97,98,99,100,101,102,103,-1,-1 64 65 66 67 FF FF 22B1 77 FF 84 FF 73 FF C db 119,-1,132,-1,115,-1,116,-1,117,-1,118,-1 74 FF 75 FF 76 FF 22BD FF C db -1 C C ;----- LC TABLE 22BE 1B 31 32 33 34 35 C K10: db 01Bh,'1234567890-=',08h,09h 36 37 38 39 30 2D 3D 08 09 22CD 71 77 65 72 74 79 C db 'qwertyuiop[]',0Dh,-1,'asdfghjkl;',027h 75 69 6F 70 5B 5D 0D FF 61 73 64 66 67 68 6A 6B 6C 3B 27 22E6 60 FF 5C 7A 78 63 C db 60h,-1,5Ch,'zxcvbnm,./',-1,'*',-1,' ' 76 62 6E 6D 2C 2E 2F FF 2A FF 20 C C ;----- UC TABLE 22F7 1B 21 40 23 24 25 C K11: db 27,'!@#$',37,05Eh,'&*()_+',08h,0 5E 26 2A 28 29 5F 2B 08 00 2306 51 57 45 52 54 59 C db 'QWERTYUIOP{}',0Dh,-1,'ASDFGHJKL:"' 55 49 4F 50 7B 7D 0D FF 41 53 44 46 47 48 4A 4B 4C 3A 22 231F 7E FF 7C 5A 58 43 C db 07Eh,-1,'|ZXCVBNM<>?',-1,0,-1,' ',-1 56 42 4E 4D 3C 3E 3F FF 00 FF 20 FF C C ;----- UC TABLE SCAN 2331 54 55 56 57 58 59 C K12: db 84,85,86,87,88,89 2337 5A 5B 5C 5D C db 90,91,92,93 C C ;----- ALT TABLE SCAN 233B 68 69 6A 6B 6C C K13: db 104,105,106,107,108 2340 6D 6E 6F 70 71 C db 109,110,111,112,113 C C ;----- NUM STATE TABLE 2345 37 38 39 2D 34 35 C K14: db '789-456+1230.' 36 2B 31 32 33 30 2E C C ;----- BASE CASE TABLE 2352 47 48 49 FF 4B FF C K15: db 71,72,73,-1,75,-1 2358 4D FF 4F 50 51 52 C db 77,-1,79,80,81,82,83 53 C C ;----- TABLE OF KEYPAD CURSOR ; CONTROL KEYS 235F C K_TAB1: 235F 48 50 52 53 4B 4D C db UP_M, DN_M, INS_M, DEL_M, LEFT_M, RIGHT_M 2365 49 51 47 4F C db PGUP_M, PGDN_M, HOME_M, END_M 2369 = 000A C L_TAB1 equ $-K_TAB1 C C ;----- ALT-INPUT-TABLE 2369 52 4F 50 51 4B 4C C K30: db 82,79,80,81,75,76 236F 4D 47 48 49 C db 77,71,72,73 ; 10 NUMBERS ON KEYPAD C ; C ;----- SUPER-SHIFT-TABLE 2373 10 11 12 13 14 15 C db 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS 2379 16 17 18 19 1E 1F C db 22,23,24,25,30,31 237F 20 21 22 23 24 25 C db 32,33,34,35,36,37 2385 26 2C 2D 2E 2F 30 C db 38,44,45,46,47,48 238B 31 32 C db 49,50 C C ; Þ C ; RETRO UNIX 8086 v1 special/private procedures ; ; 238D epoch: ; 09/04/2013 ; Retro UNIX 8086 v1 feature/procedure only! ; 'epoch' procedure prototype: ; UNIXCOPY.ASM, 10/03/2013 ; 14/11/2012 ; unixboot.asm (boot file configuration) ; version of "epoch" procedure in "unixproc.asm" ; 21/7/2012 ; 15/7/2012 ; 14/7/2012 ; Erdogan Tan - RETRO UNIX v0.1 ; compute current date and time as UNIX Epoch/Time ; UNIX Epoch: seconds since 1/1/1970 00:00:00 ; ; ((Modified registers: AX, DX, CX, BX)) ; ; 21/7/2012 ;push bx ;push cx 238D B4 02 mov ah, 02h ; Return Current Time 238F CD 1A int 1Ah 2391 86 E9 xchg ch,cl 2393 89 0E 2C12 R mov word ptr [hour], cx 2397 86 F2 xchg dh,dl 2399 89 16 2C16 R mov word ptr [second], dx 239D B4 04 mov ah, 04h ; Return Current Date 239F CD 1A int 1Ah 23A1 86 E9 xchg ch,cl 23A3 89 0E 2C0C R mov word ptr [year], cx 23A7 86 F2 xchg dh,dl 23A9 89 16 2C0E R mov word ptr [month], dx 23AD B9 3030 mov cx, 3030h 23B0 A0 2C12 R mov al, byte ptr [hour] ; Hour ; AL <= BCD number) 23B3 D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23B5 D5 0A aad ; AX= AH*10+AL 23B7 A2 2C12 R mov byte ptr [hour], al 23BA A0 2C13 R mov al, byte ptr [hour]+1 ; Minute ; AL <= BCD number) 23BD D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23BF D5 0A aad ; AX= AH*10+AL 23C1 A2 2C14 R mov byte ptr [minute], al 23C4 A0 2C16 R mov al, byte ptr [second] ; Second ; AL <= BCD number) 23C7 D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23C9 D5 0A aad ; AX= AH*10+AL 23CB A2 2C16 R mov byte ptr [second], al 23CE A1 2C0C R mov ax, word ptr [year] ; Year (century) 23D1 50 push ax ; AL <= BCD number) 23D2 D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23D4 D5 0A aad ; AX= AH*10+AL 23D6 B4 64 mov ah, 100 23D8 F6 E4 mul ah 23DA A3 2C0C R mov word ptr [year], ax 23DD 58 pop ax 23DE 8A C4 mov al, ah ; AL <= BCD number) 23E0 D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23E2 D5 0A aad ; AX= AH*10+AL 23E4 01 06 2C0C R add word ptr [year], ax 23E8 A0 2C0E R mov al, byte ptr [month] ; Month ; AL <= BCD number) 23EB D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23ED D5 0A aad ; AX= AH*10+AL 23EF A2 2C0E R mov byte ptr [month], al 23F2 A0 2C0F R mov al, byte ptr [month]+1 ; Day ; AL <= BCD number) 23F5 D4 10 db 0D4h,10h ; Undocumented inst. AAM ; AH = AL / 10h ; AL = AL MOD 10h 23F7 D5 0A aad ; AX= AH*10+AL 23F9 A2 2C10 R mov byte ptr [Day], al 23FC convert_to_epoch: ; Derived from DALLAS Semiconductor ; Application Note 31 (DS1602/DS1603) ; 6 May 1998 23FC 8B 16 2C0C R mov dx, word ptr [year] 2400 81 EA 07B2 sub dx, 1970 2404 B8 016D mov ax, 365 2407 F7 E2 mul dx 2409 32 FF xor bh, bh 240B 8A 1E 2C0E R mov bl, byte ptr [month] 240F FE CB dec bl 2411 D0 E3 shl bl, 1 2413 8B 8F 2C18 R mov cx, word ptr DMonth[BX] 2417 8A 1E 2C10 R mov bl, byte ptr [Day] 241B FE CB dec bl 241D 03 C1 add ax, cx 241F 83 D2 00 adc dx, 0 2422 03 C3 add ax, bx 2424 83 D2 00 adc dx, 0 ; DX:AX = days since 1/1/1970 2427 8B 0E 2C0C R mov cx, word ptr [year] 242B 81 E9 07B1 sub cx, 1969 242F D1 E9 shr cx, 1 2431 D1 E9 shr cx, 1 ; (year-1969)/4 2433 03 C1 add ax, cx 2435 83 D2 00 adc dx, 0 ; + leap days since 1/1/1970 2438 80 3E 2C0E R 02 cmp byte ptr [month], 2 ; if past february 243D 76 0F jna short @f 243F 8B 0E 2C0C R mov cx, word ptr [year] 2443 83 E1 03 and cx, 3 ; year mod 4 2446 75 06 jnz short @f ; and if leap year 2448 83 C0 01 add ax, 1 ; add this year's leap day (february 29) 244B 83 D2 00 adc dx, 0 244E @@: ; compute seconds since 1/1/1970 244E BB 0018 mov bx, 24 2451 E8 0028 call mul32 2454 8A 1E 2C12 R mov bl, byte ptr [hour] 2458 03 C3 add ax, bx 245A 83 D2 00 adc dx, 0 245D BB 003C mov bx, 60 2460 E8 0019 call mul32 2463 8A 1E 2C14 R mov bl, byte ptr [minute] 2467 03 C3 add ax, bx 2469 83 D2 00 adc dx, 0 246C BB 003C mov bx, 60 246F E8 000A call mul32 2472 8A 1E 2C16 R mov bl, byte ptr [second] 2476 03 C3 add ax, bx 2478 83 D2 00 adc dx, 0 ; DX:AX -> seconds since 1/1/1970 00:00:00 ; 21/7/2012 ;pop cx ;pop bx 247B C3 retn 247C mul32: ; push cx 247C 8B CB mov cx, bx 247E 8B DA mov bx, dx 2480 F7 E1 mul cx 2482 93 xchg ax, bx 2483 52 push dx 2484 F7 E1 mul cx 2486 59 pop cx 2487 03 C1 add ax, cx 2489 83 D2 00 adc dx, 0 248C 93 xchg bx, ax 248D 87 D3 xchg dx, bx ; pop cx 248F C3 retn 2490 set_date_time: ; 20/06/2013 2490 convert_from_epoch: ; 20/06/2013 ; Retro UNIX 8086 v1 feature/procedure only! ; 'convert_from_epoch' procedure prototype: ; UNIXCOPY.ASM, 10/03/2013 ; 30/11/2012 ; Derived from DALLAS Semiconductor ; Application Note 31 (DS1602/DS1603) ; 6 May 1998 ; ; INPUT: ; DX:AX = Unix (Epoch) Time ; ; ((Modified registers: AX, DX, CX, BX)) ; 2490 B9 003C mov cx, 60 2493 E8 00C1 call div32 ;mov word ptr [imin], ax ; whole minutes ;mov word ptr [imin]+2, dx ; since 1/1/1970 2496 89 1E 2C16 R mov word ptr [second], bx ; leftover seconds ; mov cx, 60 249A E8 00BA call div32 ;mov word ptr [ihrs], ax ; whole hours ;mov word ptr [ihrs]+2, dx ; since 1/1/1970 249D 89 1E 2C14 R mov word ptr [minute], bx ; leftover minutes ; mov cx, 24 24A1 B1 18 mov cl, 24 24A3 E8 00B1 call div32 ;mov word ptr [iday], ax ; whole days ; since 1/1/1970 ; mov word ptr [iday]+2, dx ; DX = 0 24A6 89 1E 2C12 R mov word ptr [hour], bx ; leftover hours 24AA 05 02DB add ax, 365+366 ; whole day since ; 1/1/1968 ; adc dx, 0 ; DX = 0 ; mov word ptr [iday], ax 24AD 50 push ax 24AE B9 05B5 mov cx, (4*365)+1 ; 4 years = 1461 days 24B1 E8 00A3 call div32 24B4 59 pop cx ;mov word ptr [lday], ax ; count of quadyrs (4 years) 24B5 53 push bx ;mov word ptr [qday], bx ; days since quadyr began 24B6 83 FB 3C cmp bx, 31 + 29 ; if past feb 29 then 24B9 F5 cmc ; add this quadyr's leap day 24BA 83 D0 00 adc ax, 0 ; to # of qadyrs (leap days) ;mov word ptr [lday], ax ; since 1968 ;mov cx, word ptr [iday] 24BD 91 xchg cx, ax ; CX = lday, AX = iday 24BE 2B C1 sub ax, cx ; iday - lday 24C0 B9 016D mov cx, 365 ;xor dx, dx ; DX = 0 ; AX = iday-lday, DX = 0 24C3 E8 0091 call div32 ;mov word ptr [iyrs], ax ; whole years since 1968 ; jday = iday - (iyrs*365) - lday ;mov word ptr [jday], bx ; days since 1/1 of current year 24C6 05 07B0 add ax, 1968 ; compute year 24C9 A3 2C0C R mov word ptr [year], ax 24CC 8B D0 mov dx, ax ;mov ax, word ptr [qday] 24CE 58 pop ax 24CF 3D 016D cmp ax, 365 ; if qday <= 365 and qday >= 60 24D2 77 07 ja short @f ; jday = jday +1 24D4 83 F8 3C cmp ax, 60 ; if past 2/29 and leap year then 24D7 F5 cmc ; add a leap day to the # of whole 24D8 83 D3 00 adc bx, 0 ; days since 1/1 of current year 24DB @@: ;mov word ptr [jday], bx 24DB B9 000C mov cx, 12 ; estimate month 24DE 87 CB xchg cx, bx ; CX = jday, BX = month 24E0 B8 016E mov ax, 366 ; mday, max. days since 1/1 is 365 24E3 83 E2 03 and dx, 11b ; year mod 4 (and dx, 3) 24E6 @@: ; Month calculation ; 0 to 11 (11 to 0) 24E6 3B C8 cmp cx, ax ; mday = # of days passed from 1/1 24E8 73 15 jnb short @f 24EA 4B dec bx ; month = month - 1 24EB D1 E3 shl bx, 1 24ED 8B 87 2C18 R mov ax, word ptr DMonth[BX] ; # elapsed days at 1st of month 24F1 D1 EB shr bx, 1 ; bx = month - 1 (0 to 11) 24F3 83 FB 01 cmp bx, 1 ; if month > 2 and year mod 4 = 0 24F6 76 EE jna short @b ; then mday = mday + 1 24F8 0A D2 or dl, dl ; if past 2/29 and leap year then 24FA 75 EA jnz short @b ; add leap day (to mday) 24FC 40 inc ax ; mday = mday + 1 24FD EB E7 jmp short @b 24FF @@: 24FF 43 inc bx ; -> bx = month, 1 to 12 2500 89 1E 2C0E R mov word ptr [month], bx 2504 2B C8 sub cx, ax ; day = jday - mday + 1 2506 41 inc cx 2507 89 0E 2C10 R mov word ptr [day], cx ; ax, bx, cx, dx is changed at return ; output -> ; [year], [month], [day], [hour], [minute], [second] ; 20/06/2013 250B set_date: 250B A0 2C0D R mov al, byte ptr [Year]+1 250E D4 0A aam ; ah = al / 10, al = al mod 10 2510 D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 2512 8A E8 mov ch, al ; century (BCD) 2514 A0 2C0C R mov al, byte ptr [Year] 2517 D4 0A aam ; ah = al / 10, al = al mod 10 2519 D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 251B 8A C8 mov cl, al ; year (BCD) 251D A0 2C0E R mov al, byte ptr [Month] 2520 D4 0A aam ; ah = al / 10, al = al mod 10 2522 D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 2524 8A F0 mov dh, al ; month (BCD) 2526 A0 2C10 R mov al, byte ptr [Day] 2529 D4 0A aam ; ah = al / 10, al = al mod 10 252B D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 252D 8A F0 mov dh, al ; day (BCD) ; Set real-time clock date 252F B4 05 mov ah, 05h 2531 CD 1A int 1Ah ; retn 2533 set_time: ; Read real-time clock time 2533 B4 02 mov ah, 02h 2535 CD 1A int 1Ah ; DL = 1 or 0 (day light saving time) 2537 A0 2C12 R mov al, byte ptr [Hour] 253A D4 0A aam ; ah = al / 10, al = al mod 10 253C D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 253E 8A E8 mov ch, al ; hour (BCD) 2540 A0 2C14 R mov al, byte ptr [Minute] 2543 D4 0A aam ; ah = al / 10, al = al mod 10 2545 D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 2547 8A C8 mov cl, al ; minute (BCD) 2549 A0 2C16 R mov al, byte ptr [Second] 254C D4 0A aam ; ah = al / 10, al = al mod 10 254E D5 10 db 0D5h,10h ; Undocumented inst. AAD ; AL = AH * 10h + AL 2550 8A F0 mov dh, al ; second (BCD) ; Set real-time clock time 2552 B4 03 mov ah, 03h 2554 CD 1A int 1Ah 2556 C3 retn 2557 div32: ; Input -> DX:AX = 32 bit dividend ; CX = 16 bit divisor ; output -> DX:AX = 32 bit quotient ; BX = 16 bit remainder 2557 8B DA mov bx, dx 2559 93 xchg ax, bx 255A 33 D2 xor dx, dx 255C F7 F1 div cx ; at first, divide DX 255E 93 xchg ax, bx ; remainder is in DX ; now, BX has quotient ; save remainder 255F F7 F1 div cx ; so, DX_AX divided and ; AX has quotient ; DX has remainder 2561 87 D3 xchg dx, bx ; finally, BX has remainder 2563 C3 retn ;; 13/07/2013 2564 00 unixbootdrive: db 0 ;; ; Following (data) section is derived from UNIX v1 'ux.s' file ; 11/03/2013 ; align 2 ; 13/07/2013 2566 0004 [ sb0: db 4 dup(0) ; Retro UNIX 8086 v1 modification ! 00 ] ;systm: ;s: db 218 dup(?) 256A 0200 [ s: db 512 dup(0) ; Retro UNIX 8086 v1 modification ! 00 ] ;;inode: ;i: db 32 dup(0) 276A 0004 [ sb1: db 4 dup(0) ; Retro UNIX 8086 v1 modification ! 00 ] 276E 0200 [ mount: db 512 dup(0) ; Retro UNIX 8086 v1 modification ! 00 ] ;mount: db 1024 dup(0) ;inode: 296E 0020 [ i: db 32 dup(0) 00 ] ; ;proc: ;p: db 9*nproc dup(0) ; 03/09/2013 298E 00A0 [ p: db 10*nproc dup(0) 00 ] ;tty: db ntty*8 dup(0) 2A2E 0190 [ fsp: db nfiles*8 dup(0) 00 ] 2BBE 0010 [ bufp: db ((nbuf*2)+4) dup(0) ; will be initialized (09/07/2013) 00 ] ;;bufp: db ((nbuf*2)+6) dup(0) ;;sb0: db 8 dup(0) ;sb0: db 4 dup(0) ; Retro UNIX 8086 v1 modification ! ;;sb1: db 8 dup(0) ;sb1: db 4 dup(0) ; Retro UNIX 8086 v1 modification ! ;swp: db 8 dup(0) ;;swp: db 4 dup(0) ; Retro UNIX 8086 v1 modification ! 2BCE 0000 ii: dw 0 2BD0 0000 idev: dw 0 ; device number is 1 byte in Retro UNIX 8086 v1 ! 2BD2 0000 cdev: dw 0 ; device number is 1 byte in Retro UNIX 8086 v1 ! ;;deverr: db 12 dup(0) ; ; 26/04/2013 device/drive parameters ; Retro UNIX 8086 v1 feature only! ; there are 8 available Retro UNIX devices ; ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv') ; 0 -> root device (which has Retro UNIX 8086 v1 file system) ; 1 -> mounted device (which has Retro UNIX 8086 v1 file system) ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures) ; 0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0 ; 1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1 ; 2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h ; 3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h ; 4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h ; 5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h 2BD4 00 rdev: db 0 ; root device number ; Retro UNIX 8086 v1 feature only! ; as above, for physical drives numbers in following table 2BD5 00 mdev: db 0 ; mounted device number ; Retro UNIX 8086 v1 feature only! ; as above, for physical drives numbers in following table ; NOTE: the value of 'cdev' and 'u.drv' and 'idev' will be 0 or 1. ; 0 is for rdev, 1 is for mdev 2BD6 drv: ; Retro UNIX 8086 v1 feature only! 2BD6 drverr: 2BD6 0006 [ db 6 dup(0FFh) ; error status (>0 means error) FF ] 2BDC drvpdn: 2BDC 0006 [ db 6 dup(0FFh) ; physical drive number (FFh = invalid drive) FF ] 2BE2 drvspt: 2BE2 0006 [ dw 6 dup(0) ; sectors per track 0000 ] 2BEE drvhds: 2BEE 0006 [ dw 6 dup(0) ; number of heads 0000 ] ;active: dw 0 2BFA 00 active: db 0 ; 15/03/2013 2BFB 00 brwdev: db 0 ; 26/04/2013 Retro UNIX 8086 v1 feature only ! ;rfap: dw 0 ;rkap: dw 0 ;tcap: dw 0 ;tcstate:dw 0 ;tcerrc:dw 0 2BFC 0000 mnti: dw 0 ;mntd: dw 0 ; device number is 1 byte in Retro UNIX 8086 v1 ! 2BFE 0000 mpid: dw 0 ;clockp: dw 0 2C00 0000 rootdir:dw 0 ;toutt: db 16 dup(0) ;touts: db 32 dup(0) ;runq: db 6 dup (0) ; 14/02/2014 ; Major Modification: Retro UNIX 8086 v1 feature only! ; Single level run queue ; (in order to solve sleep/wakeup lock) 2C02 0000 runq: dw 0 ;wlist: db 40 dup(0) ;cc: db 30 dup(0) ;cf: db 31 dup(0) ;cl_: db 31 dup(0) ; cl ;clist: db 510 dup(0) 2C04 00 imod: db 0 2C05 00 smod: db 0 2C06 00 mmod: db 0 ;uquant: db 0 ; 14/02/2014 --> u.quant 2C07 00 sysflg: db 0 ;pptiflg:db 0 ;ttyoch: db 0 align 2 ; Retro Unix 8086 v1 features only ! ; 31/07/2013 ; 07/04/2013 2C08 00 rw: db 0 ;; Read/Write sign ;; 07/08/2013 (reset in error routine) ;; mov word ptr [namei_r], 0 -> namei_r = 0, mkdir_w = 0 ; 26/07/2013 2C09 00 namei_r: db 0 ; the caller is 'namei' sign for 'dskr' (ES=CS) ; 01/08/2013 2C0A 00 mkdir_w: db 0 ; the caller is 'mkdir' sign for 'dskw' (ES=CS) ; align 2 ; 09/04/2013 epoch variables ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013 ; 2C0C 07B2 year: dw 1970 2C0E 0001 month: dw 1 2C10 0001 day: dw 1 2C12 0000 hour: dw 0 2C14 0000 minute: dw 0 2C16 0000 second: dw 0 2C18 DMonth: 2C18 0000 dw 0 2C1A 001F dw 31 2C1C 003B dw 59 2C1E 005A dw 90 2C20 0078 dw 120 2C22 0097 dw 151 2C24 00B5 dw 181 2C26 00D4 dw 212 2C28 00F3 dw 243 2C2A 0111 dw 273 2C2C 0130 dw 304 2C2E 014E dw 334 ; 10/05/2013 ; Retro UNIX 8086 v1 feature only ! 2C30 int09h: ; BIOS INT 09h handler (original) 2C30 0000 dw 0 ; offset 2C32 0000 dw 0 ; segment ; 03/06/2013 2C34 00000000 p_time: dd 0 ; present time (for systime & sysmdate) ; 04/12/2013 ('putc', 'write_tty' in U9.ASM) 2C38 0000 crt_start: dw 0 ; starting address in regen buffer ; NOTE: active page only 2C3A 0008 [ cursor_posn: dw 8 dup(0) ; cursor positions for video pages 0000 ] ; 04/12/2013 2C4A active_page: ; = ptty ('putc', 'write_tty' in U9.ASM) ; 10/05/2013 ; Retro UNIX 8086 v1 feature only ! 2C4A 00 ptty: db 0 ; current tty ;nxtty: db 0 ; next tty (will be switched to) ; 16/07/2013 ;getctty: db 0 ; for using in 'getc' routine ; 12/08/2013 ;AltKeyDown: db 0 ; INT 09h align 2 ; 03/03/2014 ; Derived from IBM "pc-at" ; rombios source code (06/10/1985) ; 'dseg.inc' ;---------------------------------------; ; SYSTEM DATA AREA ; ;---------------------------------------- 2C4C 00 BIOS_BREAK db 0 ; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED ;---------------------------------------- ; KEYBOARD DATA AREAS ; ;---------------------------------------- 2C4D 00 KB_FLAG db 0 ; KEYBOARD SHIFT STATE AND STATUS FLAGS 2C4E 00 KB_FLAG_1 db 0 ; SECOND BYTE OF KEYBOARD STATUS 2C4F 00 KB_FLAG_2 db 0 ; KEYBOARD LED FLAGS 2C50 00 KB_FLAG_3 db 0 ; KEYBOARD MODE STATE AND TYPE FLAGS 2C51 00 ALT_INPUT db 0 ; STORAGE FOR ALTERNATE KEY PAD ENTRY 2C52 2C5A R BUFFER_START dW offset KB_BUFFER ; OFFSET OF KEYBOARD BUFFER START 2C54 2C7A R BUFFER_END dW offset KB_BUFFER + 32 ; OFFSET OF END OF BUFFER 2C56 2C5A R BUFFER_HEAD dw offset KB_BUFFER ; POINTER TO HEAD OF KEYBOARD BUFFER 2C58 2C5A R BUFFER_TAIL dw offset KB_BUFFER ; POINTER TO TAIL OF KEYBOARD BUFFER ; ------ HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY 2C5A 0010 [ KB_BUFFER dw 16 DUP (0) ; ROOM FOR 15 SCAN CODE ENTRIES 0000 ] ; ;align 2 ; 26/01/2014 'ttyl' lock table instead of 'ttyr' and 'ttyw' ; ; 16/08/2013 'ttypt' owner table -> 'ttyr', 'ttyw' lock table ; byte ptr [BX]+ttyl = owner/lock for read/write ; (process number = locked, 0 = unlocked/free) ; byte ptr [BX]+ttyr+1 = count of open for read&write ; (0 = free, >0 = in use) ; ;; Retro UNIX 8086 v1 feature only! ;; ;; (26/01/2014) ;; (13/01/2014) ;; 06/12/2013 ;; <<>> ;; ; Console TTY for process : ; 'sys fork' system call sets/copies parent process's ; console TTY number as child process's console TTY number. ; It is a zero based number (0 to 9) which is hold in 'p.ttyc'. ; Console TTY setting can be changed by 'sys stty' system call. ; Recent TTY for process: ; Recent TTY number during the last TTY read/write routine ; by process. 'u.ttyp' (word pointer) is used for that purpose. ; TTY num. of the last TTY Read is stored in low byte of 'u.ttyp'. ; TTY num. of the last TTY write is stored in high byte of 'u.ttyp. ; ; TTY 'Open' conditions: (06/12/2013 <--- 16/08/2013) ; 1) A process can open a free/unlocked tty or a tty ; which is locked by it or it's parent process. (13/01/2014) ; (Open count is increased by 1 while a new instance of ; tty is being open.) ; 2) The caller/process locks a tty if it is unlocked/free. ; 3) TTY open procedure sets 'u.ttyp' to related tty number + 1. ; Open for read procedure sets the low byte and open for ; write procedure sets the high byte. ; NOTE: TTY read and write procedures change these recent tty ; (u.ttyp) values. (06/12/2013) ; ; TTY 'close' conditions: (16/08/2013) ; 1) A tty is unlocked if it's open count becomes zero while ; closing it. (26/01/2014) ; (Open count is decreased by 1 when the instance of ; tty is closed.) ; 2) TTY close procedure resets low byte or high byte of ; 'u.ttyp' if it was set to related tty number + 1. ; Open for read procedure resets the low byte and open ; for write procedure resets the high byte. (06/12/2013) ; ; NOTE: 'tty' functionality of 'Retro UNIX 8086 v1' is almost ; different than original UNIX v1 (also v1 to recent ; unix sys v versions). Above logic/methods is/are ; developed by Erdogan Tan, for keeping 'multi screen', ; 'multi tasking' ability of 'Retro UNIX 8086 v1' (tty and ; process switching by 'ALT + Function keys' and ; for ensuring proper/stable process separation between ; pseudo TTYs and serial ports). ; ; 09/07/2014 (tty8, tty9) ; 24/09/2013 (tty0 to tty7) 2C7A ttychr: ; (0 to 9) 2C7A 000A [ dw ntty+2 dup(0) ; ascii (lb) & scan code (hb) of keys 0000 ] ; per every pseudo tty (video page) ; 26/01/2014 'ttyl' lock table instead of 'ttyr' and 'ttyw' ; 13/01/2014 (COM1 & COM2 have been added to pseudo TTYs) ; (ntty -> ntty + 2) ; 16/08/2013 (open mode locks for pseudo TTYs) ; [ major tty locks (return error in any conflicts) ] 2C8E ttyl: ; Retro UNIX 8086 v1 feature only ! 2C8E 000A [ dw ntty+2 dup(0) ; opening locks for TTYs. 0000 ] ; 22/09/2013 2CA2 000A [ wlist: db ntty+2 dup(0) ; wait channel list (0 to 9 for TTYs) 00 ] ; 27/07/2014 2CAC 0000 tsleep: dw 0 ; Transmit sleep sign for port processes ; which use serial ports (COM1, COM2) as tty. ;; 16/07/2013 ;; tty (keyboard) process/owner table (ttypt) ;ttypt: db ntty*2 dup(0) ;; 12/07/2014 -> communication status data is not needed here ; ; 16/07/2013 ; 21/05/2013 ;;com_stat: ; 13/01/2014 ;;com1_stat: ;; db 0 ; COM1 line status ;; db 0 ; COM1 modem status ;;com2_stat: ;; db 0 ; COM2 line status ;; db 0 ; COM2 modem status ; 16/08/2013 ; Communication parameters for serial ports ; Retro UNIX 8086 v1 default: ;; 11100011b ; E3h ;; (111) Baud rate: 9600, (00) parity: none, ;; (0) stop bits: 1, (11) word length: 8 bits ; ; NOTE: Default value (E3h) will be set again ; after an initalization error, even if 'sys stty' ; system call changes the value before ; an initialization error in tty 'open' routine. ; (Serial port initialization is performed ; when a tty 'open' routine runs for ; COM1 or COM2 while the tty is free/closed.) ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h ;; 0 means serial port is not available ;;comprm: ; 25/06/2014 2CAE 00 com1p: db 0 ;;0E3h 2CAF 00 com2p: db 0 ;;0E3h ;Buffer: ;db ntty*140 dup(0) ;db nbuf*520 dup(0) align 8 2CB0 00000000 dd 0 2CB4 Buffer: ; Retro UNIX 8086 v1 modification ! 2CB4 0C18 [ db nbuf*516 dup(0) 00 ] ;user: 38CC 0040 [ u: db 64 dup (0) ; (Original Unix v1 'user' structure has 62 bytes) 00 ] ; 14/07/2013 390C kernel_init_err_msg: 390C 0D 0A db 0Dh, 0Ah 390E 07 db 07h 390F 4B 65 72 6E 65 6C db 'Kernel initialization ERROR !' 20 69 6E 69 74 69 61 6C 69 7A 61 74 69 6F 6E 20 45 52 52 4F 52 20 21 392C 0D 0A 00 db 0Dh, 0Ah, 0 392F kernel_init_ok_msg: 392F 07 db 07h 3930 57 65 6C 63 6F 6D db 'Welcome to Retro UNIX 8086 v1 Operating System !' 65 20 74 6F 20 52 65 74 72 6F 20 55 4E 49 58 20 38 30 38 36 20 76 31 20 4F 70 65 72 61 74 69 6E 67 20 53 79 73 74 65 6D 20 21 3960 0D 0A db 0Dh, 0Ah 3962 62 79 20 45 72 64 db 'by Erdogan Tan - 16/07/2015' 6F 67 61 6E 20 54 61 6E 20 2D 20 31 36 2F 30 37 2F 32 30 31 35 397D 0D 0A 00 db 0Dh, 0Ah, 0 3980 panic_msg: 3980 0D 0A 07 db 0Dh, 0Ah, 07h 3983 45 52 52 4F 52 3A db 'ERROR: Kernel Panic !' 20 4B 65 72 6E 65 6C 20 50 61 6E 69 63 20 21 3998 0D 0A 00 db 0Dh, 0Ah, 0 399B etc_init_err_msg: 399B 0D 0A db 0Dh, 0Ah 399D 07 db 07h 399E 45 52 52 4F 52 3A db 'ERROR: /etc/init !?' 20 2F 65 74 63 2F 69 6E 69 74 20 21 3F 39B1 0D 0A 00 db 0Dh, 0Ah, 0 align 2 ; sstack: ; db 256 dup(0) ; 10/12/2013 ; 'Enable Multi Tasking' system call (sys emt) ; (time-out enabling/disabling functionality) ; has been added to Retro UNIX 8086 v1 Kernel (in U1.ASM) 39B4 = 39B4 SizeOfFile equ $ ; 08/03/2014 (system systack size = 256 - 64) = 3A74 sstack equ SizeOfFile + 256 - 64 ;sstack equ SizeOfFile + 256 ; 24/07/2013 39B4 UNIX ends end START Microsoft (R) Macro Assembler Version 6.14.8444 07/16/15 23:17:30 unix.asm Symbols 2 - 1 Macros: N a m e Type sys . . . . . . . . . . . . . . Proc Structures and Unions: N a m e Size Offset Type inode . . . . . . . . . . . . . 0020 flgs . . . . . . . . . . . . . 0000 Word nlks . . . . . . . . . . . . . 0002 Byte uid . . . . . . . . . . . . . 0003 Byte size_ . . . . . . . . . . . . 0004 Word dskp . . . . . . . . . . . . . 0006 Word ctim . . . . . . . . . . . . . 0016 DWord mtim . . . . . . . . . . . . . 001A DWord rsvd . . . . . . . . . . . . . 001E Word phydrv . . . . . . . . . . . . . 0024 err . . . . . . . . . . . . . 0000 Byte pdn . . . . . . . . . . . . . 0006 Byte spt . . . . . . . . . . . . . 000C Word hds . . . . . . . . . . . . . 0018 Word process . . . . . . . . . . . . 00A0 pid . . . . . . . . . . . . . 0000 Word ppid . . . . . . . . . . . . . 0020 Word break . . . . . . . . . . . . 0040 Word ttyc . . . . . . . . . . . . . 0060 Byte waitc . . . . . . . . . . . . 0070 Byte link . . . . . . . . . . . . . 0080 Byte stat . . . . . . . . . . . . . 0090 Byte systm . . . . . . . . . . . . . 00DA time . . . . . . . . . . . . . 00C4 DWord syst . . . . . . . . . . . . . 00C8 DWord wait_ . . . . . . . . . . . . 00CC DWord idlet . . . . . . . . . . . . 00D0 DWord chrgt . . . . . . . . . . . . 00D4 DWord drerr . . . . . . . . . . . . 00D8 Word user . . . . . . . . . . . . . . 0040 sp_ . . . . . . . . . . . . . 0000 Word usp . . . . . . . . . . . . . 0002 Word r0 . . . . . . . . . . . . . . 0004 Word cdir . . . . . . . . . . . . . 0006 Word fp . . . . . . . . . . . . . . 0008 Byte fofp . . . . . . . . . . . . . 0012 Word dirp . . . . . . . . . . . . . 0014 Word namep . . . . . . . . . . . . 0016 Word off . . . . . . . . . . . . . 0018 Word base . . . . . . . . . . . . . 001A Word count . . . . . . . . . . . . 001C Word nread . . . . . . . . . . . . 001E Word break_ . . . . . . . . . . . . 0020 Word ttyp . . . . . . . . . . . . . 0022 Word dirbuf . . . . . . . . . . . . 0024 Byte quant . . . . . . . . . . . . 002E Byte pri . . . . . . . . . . . . . 002F Byte intr . . . . . . . . . . . . . 0030 Word quit . . . . . . . . . . . . . 0032 Word ilgins . . . . . . . . . . . . 0034 Word cdrv . . . . . . . . . . . . . 0036 Word uid_ . . . . . . . . . . . . . 0038 Byte ruid . . . . . . . . . . . . . 0039 Byte bsys . . . . . . . . . . . . . 003A Byte uno . . . . . . . . . . . . . 003B Byte segmnt . . . . . . . . . . . . 003C Word ttyn . . . . . . . . . . . . . 003E Byte errn . . . . . . . . . . . . . 003F Byte Segments and Groups: N a m e Size Length Align Combine Class UNIX . . . . . . . . . . . . . . 16 Bit 39B4 Para Public 'CODE' Symbols: N a m e Type Value Attr ALT_INPUT . . . . . . . . . . . Byte 2C51 UNIX ALT_KEY . . . . . . . . . . . . Number 0038h ALT_SHIFT . . . . . . . . . . . Number 0008h BIOS_BREAK . . . . . . . . . . . Byte 2C4C UNIX BIOS_DSEGM . . . . . . . . . . . Number 0040h BUFFER_END . . . . . . . . . . . Word 2C54 UNIX BUFFER_HEAD . . . . . . . . . . Word 2C56 UNIX BUFFER_START . . . . . . . . . . Word 2C52 UNIX BUFFER_TAIL . . . . . . . . . . Word 2C58 UNIX Buffer . . . . . . . . . . . . . L Near 2CB4 UNIX CAPS_KEY . . . . . . . . . . . . Number 003Ah CAPS_SHIFT . . . . . . . . . . . Number 0040h CAPS_STATE . . . . . . . . . . . Number 0040h CRT_MODE_SET . . . . . . . . . . Number 0065h CRT_MODE . . . . . . . . . . . . Number 0049h CTL_KEY . . . . . . . . . . . . Number 001Dh CTL_SHIFT . . . . . . . . . . . Number 0004h DEL_KEY . . . . . . . . . . . . Number 0053h DEL_M . . . . . . . . . . . . . Number 0053h DIS_KBD . . . . . . . . . . . . Number 00ADh DMonth . . . . . . . . . . . . . L Near 2C18 UNIX DN_M . . . . . . . . . . . . . . Number 0050h ENA_KBD . . . . . . . . . . . . Number 00AEh END_M . . . . . . . . . . . . . Number 004Fh EOI . . . . . . . . . . . . . . Number 0020h F11_B . . . . . . . . . . . . . Number 00D7h F11_M . . . . . . . . . . . . . Number 00D9h F12_B . . . . . . . . . . . . . Number 00D8h F12_M . . . . . . . . . . . . . Number 00DAh FUNC11 . . . . . . . . . . . . . Number 0085h GATE2 . . . . . . . . . . . . . Number 0001h GRAPH_ON . . . . . . . . . . . . Number 0004h HC . . . . . . . . . . . . . . . Number 00E0h HOLD_STATE . . . . . . . . . . . Number 0008h HOME_M . . . . . . . . . . . . . Number 0047h ID_1 . . . . . . . . . . . . . . Number 00ABh ID_2 . . . . . . . . . . . . . . Number 0041h INPT_BUF_FULL . . . . . . . . . Number 0002h INS_KEY . . . . . . . . . . . . Number 0052h INS_M . . . . . . . . . . . . . Number 0052h INS_SHIFT . . . . . . . . . . . Number 0080h INS_STATE . . . . . . . . . . . Number 0080h INTA00 . . . . . . . . . . . . . Number 0020h K102_B . . . . . . . . . . . . . Number 00D6h K102_M . . . . . . . . . . . . . Number 0056h K10 . . . . . . . . . . . . . . L Near 22BE UNIX K11 . . . . . . . . . . . . . . L Near 22F7 UNIX K12 . . . . . . . . . . . . . . L Near 2331 UNIX K13 . . . . . . . . . . . . . . L Near 233B UNIX K14 . . . . . . . . . . . . . . L Near 2345 UNIX K15 . . . . . . . . . . . . . . L Near 2352 UNIX K30 . . . . . . . . . . . . . . L Near 2369 UNIX K6L . . . . . . . . . . . . . . Number 0008h K6 . . . . . . . . . . . . . . . L Near 225B UNIX K7 . . . . . . . . . . . . . . . L Near 2263 UNIX K8 . . . . . . . . . . . . . . . L Near 226B UNIX K9 . . . . . . . . . . . . . . . L Near 22A5 UNIX KBX . . . . . . . . . . . . . . Number 0001h KB_ACK . . . . . . . . . . . . . Number 00FAh KB_BUFFER . . . . . . . . . . . Word 2C5A UNIX KB_ENABLE . . . . . . . . . . . Number 00F4h KB_ERR . . . . . . . . . . . . . Number 0080h KB_FA . . . . . . . . . . . . . Number 0010h KB_FE . . . . . . . . . . . . . Number 0020h KB_FLAG_1 . . . . . . . . . . . Byte 2C4E UNIX KB_FLAG_2 . . . . . . . . . . . Byte 2C4F UNIX KB_FLAG_3 . . . . . . . . . . . Byte 2C50 UNIX KB_FLAG . . . . . . . . . . . . Byte 2C4D UNIX KB_LEDS . . . . . . . . . . . . Number 0007h KB_OVER_RUN . . . . . . . . . . Number 00FFh KB_PR_LED . . . . . . . . . . . Number 0040h KB_RESEND . . . . . . . . . . . Number 00FEh K_TAB1 . . . . . . . . . . . . . L Near 235F UNIX LC_AB . . . . . . . . . . . . . Number 0040h LC_HC . . . . . . . . . . . . . Number 0002h LED_CMD . . . . . . . . . . . . Number 00EDh LEFT_KEY . . . . . . . . . . . . Number 002Ah LEFT_M . . . . . . . . . . . . . Number 004Bh LEFT_SHIFT . . . . . . . . . . . Number 0002h L_TAB1 . . . . . . . . . . . . . Number 000Ah NUM_KEY . . . . . . . . . . . . Number 0045h NUM_SHIFT . . . . . . . . . . . Number 0020h NUM_STATE . . . . . . . . . . . Number 0020h PGDN_M . . . . . . . . . . . . . Number 0051h PGUP_M . . . . . . . . . . . . . Number 0049h PORT_A . . . . . . . . . . . . . Number 0060h PORT_B . . . . . . . . . . . . . Number 0061h RD_ID . . . . . . . . . . . . . Number 0080h REFRESH_BIT . . . . . . . . . . Number 0010h RESET_FLAG . . . . . . . . . . . Number 0072h RHRZ . . . . . . . . . . . . . . Number 0001h RIGHT_KEY . . . . . . . . . . . Number 0036h RIGHT_M . . . . . . . . . . . . Number 004Dh RIGHT_SHIFT . . . . . . . . . . Number 0001h RVRT . . . . . . . . . . . . . . Number 0008h SCROLL_KEY . . . . . . . . . . . Number 0046h SCROLL_SHIFT . . . . . . . . . . Number 0010h SCROLL_STATE . . . . . . . . . . Number 0010h SET_NUM_LK . . . . . . . . . . . Number 0020h SPK2 . . . . . . . . . . . . . . Number 0002h START . . . . . . . . . . . . . L Near 0000 UNIX STATUS_PORT . . . . . . . . . . Number 0064h SYS_KEY . . . . . . . . . . . . Number 0054h SYS_SHIFT . . . . . . . . . . . Number 0004h SizeOfFile . . . . . . . . . . . Number 39B4h TIMER . . . . . . . . . . . . . Number 0040h UP_M . . . . . . . . . . . . . . Number 0048h _break . . . . . . . . . . . . . Number 0011h _chdir . . . . . . . . . . . . . Number 000Ch _chmod . . . . . . . . . . . . . Number 000Fh _chown . . . . . . . . . . . . . Number 0010h _close . . . . . . . . . . . . . Number 0006h _creat . . . . . . . . . . . . . Number 0008h _emt . . . . . . . . . . . . . . Number 001Dh _exec . . . . . . . . . . . . . Number 000Bh _exit . . . . . . . . . . . . . Number 0001h _fork . . . . . . . . . . . . . Number 0002h _fstat . . . . . . . . . . . . . Number 001Ch _getuid . . . . . . . . . . . . Number 0018h _gtty . . . . . . . . . . . . . Number 0020h _ilgins . . . . . . . . . . . . Number 0021h _intr . . . . . . . . . . . . . Number 001Bh _link . . . . . . . . . . . . . Number 0009h _mdate . . . . . . . . . . . . . Number 001Eh _mkdir . . . . . . . . . . . . . Number 000Eh _mount . . . . . . . . . . . . . Number 0015h _open . . . . . . . . . . . . . Number 0005h _quit . . . . . . . . . . . . . Number 001Ah _read . . . . . . . . . . . . . Number 0003h _rele . . . . . . . . . . . . . Number 0000h _seek . . . . . . . . . . . . . Number 0013h _setuid . . . . . . . . . . . . Number 0017h _sleep . . . . . . . . . . . . . Number 0022h _stat . . . . . . . . . . . . . Number 0012h _stime . . . . . . . . . . . . . Number 0019h _stty . . . . . . . . . . . . . Number 001Fh _tell . . . . . . . . . . . . . Number 0014h _time . . . . . . . . . . . . . Number 000Dh _umount . . . . . . . . . . . . Number 0016h _unlink . . . . . . . . . . . . Number 000Ah _wait . . . . . . . . . . . . . Number 0007h _write . . . . . . . . . . . . . Number 0004h access_1 . . . . . . . . . . . . L Near 1194 UNIX access_2 . . . . . . . . . . . . L Near 119F UNIX access . . . . . . . . . . . . . L Near 117D UNIX active_page . . . . . . . . . . L Near 2C4A UNIX active . . . . . . . . . . . . . L Near 2BFA UNIX alloc_1 . . . . . . . . . . . . L Near 106C UNIX alloc_2 . . . . . . . . . . . . L Near 1078 UNIX alloc_3 . . . . . . . . . . . . L Near 108A UNIX alloc_4 . . . . . . . . . . . . L Near 1091 UNIX alloc_5 . . . . . . . . . . . . L Near 10A0 UNIX alloc_6 . . . . . . . . . . . . L Near 10AD UNIX alloc_free_3 . . . . . . . . . . L Near 10B2 UNIX alloc_free_4 . . . . . . . . . . L Near 10C8 UNIX alloc_free_5 . . . . . . . . . . L Near 10D9 UNIX alloc . . . . . . . . . . . . . L Near 105E UNIX anyi_1 . . . . . . . . . . . . . L Near 0E05 UNIX anyi_2 . . . . . . . . . . . . . L Near 0E30 UNIX anyi . . . . . . . . . . . . . . L Near 0E02 UNIX badsys_1 . . . . . . . . . . . . L Near 0398 UNIX badsys_2 . . . . . . . . . . . . L Near 03A1 UNIX badsys_3 . . . . . . . . . . . . L Near 03D6 UNIX badsys . . . . . . . . . . . . . L Near 037F UNIX beeper . . . . . . . . . . . . . L Near 1B36 UNIX beep . . . . . . . . . . . . . . L Near 1B42 UNIX bf_init . . . . . . . . . . . . L Near 19E7 UNIX bread0 . . . . . . . . . . . . . L Near 16FC UNIX bread . . . . . . . . . . . . . L Near 16F5 UNIX brwdev . . . . . . . . . . . . . L Near 2BFB UNIX bs . . . . . . . . . . . . . . . L Near 1B24 UNIX bufaloc_0 . . . . . . . . . . . L Near 1890 UNIX bufaloc_1 . . . . . . . . . . . L Near 18A5 UNIX bufaloc_2 . . . . . . . . . . . L Near 18A8 UNIX bufaloc_3 . . . . . . . . . . . L Near 18B5 UNIX bufaloc_4 . . . . . . . . . . . L Near 18C3 UNIX bufaloc_5 . . . . . . . . . . . L Near 18D6 UNIX bufaloc_6 . . . . . . . . . . . L Near 18D8 UNIX bufaloc_7 . . . . . . . . . . . L Near 18E1 UNIX bufaloc_8 . . . . . . . . . . . L Near 18F0 UNIX bufaloc . . . . . . . . . . . . L Near 1885 UNIX bufp . . . . . . . . . . . . . . L Near 2BBE UNIX bwrite0 . . . . . . . . . . . . L Near 1756 UNIX bwrite . . . . . . . . . . . . . L Near 174F UNIX bwslot_0 . . . . . . . . . . . . L Near 17DC UNIX bwslot_1 . . . . . . . . . . . . L Near 17EF UNIX bwslot . . . . . . . . . . . . . L Near 17D7 UNIX cbrk1 . . . . . . . . . . . . . L Near 011E UNIX cbrk2 . . . . . . . . . . . . . L Near 0133 UNIX cbrk3 . . . . . . . . . . . . . L Near 0142 UNIX ccvt . . . . . . . . . . . . . . L Near 16A8 UNIX cdev . . . . . . . . . . . . . . L Near 2BD2 UNIX clear . . . . . . . . . . . . . L Near 0EFB UNIX clk_0 . . . . . . . . . . . . . L Near 0F2E UNIX clk_1 . . . . . . . . . . . . . L Near 0F52 UNIX clk_2 . . . . . . . . . . . . . L Near 0F56 UNIX clock . . . . . . . . . . . . . L Near 0F0F UNIX com1_int . . . . . . . . . . . . L Near 01B5 UNIX com1p_eirq . . . . . . . . . . . L Near 160D UNIX com1p . . . . . . . . . . . . . L Near 2CAE UNIX com2_int . . . . . . . . . . . . L Near 01AB UNIX com2p . . . . . . . . . . . . . L Near 2CAF UNIX com_eoi . . . . . . . . . . . . L Near 01F4 UNIX com_iret . . . . . . . . . . . . L Near 01FC UNIX com_port_init . . . . . . . . . L Near 15E4 UNIX com_rdei . . . . . . . . . . . . L Near 01DE UNIX comp_get_stat . . . . . . . . . L Near 1623 UNIX comp_init_ok . . . . . . . . . . L Near 163B UNIX convert_from_epoch . . . . . . . L Near 2490 UNIX convert_to_epoch . . . . . . . . L Near 23FC UNIX core . . . . . . . . . . . . . . Number 0000h cpass . . . . . . . . . . . . . L Near 1428 UNIX cpu_reset . . . . . . . . . . . L Near 00D4 UNIX cret . . . . . . . . . . . . . . L Near 16D7 UNIX crt_start . . . . . . . . . . . L Near 2C38 UNIX csgmnt . . . . . . . . . . . . . Number 2000h ctl_on . . . . . . . . . . . . . L Near 1E6B UNIX ctrlbrk . . . . . . . . . . . . L Near 0115 UNIX ctty_ret . . . . . . . . . . . . L Near 16BD UNIX cttyp . . . . . . . . . . . . . L Near 16AA UNIX ctty . . . . . . . . . . . . . . L Near 169C UNIX cursor_posn . . . . . . . . . . L Near 2C3A UNIX day . . . . . . . . . . . . . . L Near 2C10 UNIX dioreg . . . . . . . . . . . . . L Near 178F UNIX diskio . . . . . . . . . . . . . L Near 18F5 UNIX div32 . . . . . . . . . . . . . L Near 2557 UNIX do_fn . . . . . . . . . . . . . L Near 1EA3 UNIX dparam_error . . . . . . . . . . L Near 19C8 UNIX dparam . . . . . . . . . . . . . L Near 19BD UNIX drv_init_err . . . . . . . . . . L Near 1996 UNIX drv_init_lbs . . . . . . . . . . L Near 1980 UNIX drv_init . . . . . . . . . . . . L Near 1952 UNIX drverr . . . . . . . . . . . . . L Near 2BD6 UNIX drvhds . . . . . . . . . . . . . L Near 2BEE UNIX drvpdn . . . . . . . . . . . . . L Near 2BDC UNIX drvspt . . . . . . . . . . . . . L Near 2BE2 UNIX drv . . . . . . . . . . . . . . L Near 2BD6 UNIX dskr_1 . . . . . . . . . . . . . L Near 12EF UNIX dskr_2 . . . . . . . . . . . . . L Near 1305 UNIX dskr_3 . . . . . . . . . . . . . L Near 1310 UNIX dskrd_0 . . . . . . . . . . . . L Near 17C1 UNIX dskrd . . . . . . . . . . . . . L Near 17BC UNIX dskr . . . . . . . . . . . . . . L Near 12D5 UNIX dskw_1 . . . . . . . . . . . . . L Near 13E1 UNIX dskw_2 . . . . . . . . . . . . . L Near 13F8 UNIX dskw_3 . . . . . . . . . . . . . L Near 13FB UNIX dskw_4 . . . . . . . . . . . . . L Near 140C UNIX dskw_5 . . . . . . . . . . . . . L Near 1417 UNIX dskwr . . . . . . . . . . . . . L Near 180D UNIX dskw . . . . . . . . . . . . . . L Near 13C6 UNIX ecore . . . . . . . . . . . . . Number 7FC0h emt_1 . . . . . . . . . . . . . L Near 06A4 UNIX emt_2 . . . . . . . . . . . . . L Near 06AD UNIX emt_iret . . . . . . . . . . . . L Near 06B2 UNIX epoch . . . . . . . . . . . . . L Near 238D UNIX error . . . . . . . . . . . . . L Near 02FC UNIX etc_init_err_msg . . . . . . . . L Near 399B UNIX fclose_1 . . . . . . . . . . . . L Near 0B66 UNIX fclose_2 . . . . . . . . . . . . L Near 0B6A UNIX fclose . . . . . . . . . . . . . L Near 0B37 UNIX fd_init . . . . . . . . . . . . L Near 1952 UNIX find_position . . . . . . . . . L Near 1BE0 UNIX free3 . . . . . . . . . . . . . L Near 10B2 UNIX free_1 . . . . . . . . . . . . . L Near 10A0 UNIX free_2 . . . . . . . . . . . . . L Near 10AD UNIX free . . . . . . . . . . . . . . L Near 109A UNIX fsp . . . . . . . . . . . . . . L Near 2A2E UNIX g7 . . . . . . . . . . . . . . . L Near 1B5D UNIX gcw0 . . . . . . . . . . . . . . L Near 1A38 UNIX gcw1 . . . . . . . . . . . . . . L Near 1A3A UNIX gcw2 . . . . . . . . . . . . . . L Near 1A56 UNIX gcw3 . . . . . . . . . . . . . . L Near 1A61 UNIX get_cpos . . . . . . . . . . . . L Near 1CB5 UNIX getc_n . . . . . . . . . . . . . L Near 1A0F UNIX getc_sn . . . . . . . . . . . . L Near 1A33 UNIX getc_s . . . . . . . . . . . . . L Near 1A38 UNIX getc . . . . . . . . . . . . . . L Near 1A0B UNIX getf1 . . . . . . . . . . . . . L Near 0B6E UNIX getf . . . . . . . . . . . . . . L Near 0B6C UNIX getspl . . . . . . . . . . . . . L Near 1508 UNIX gtty . . . . . . . . . . . . . . L Near 07ED UNIX hd_init . . . . . . . . . . . . L Near 1963 UNIX hlt_sys . . . . . . . . . . . . L Near 046A UNIX hour . . . . . . . . . . . . . . L Near 2C12 UNIX icalc_1 . . . . . . . . . . . . L Near 1154 UNIX icalc_2 . . . . . . . . . . . . L Near 1172 UNIX icalc_3 . . . . . . . . . . . . L Near 117A UNIX icalc . . . . . . . . . . . . . L Near 113B UNIX iclose_0 . . . . . . . . . . . . L Near 1666 UNIX iclose_1 . . . . . . . . . . . . L Near 1676 UNIX iclose . . . . . . . . . . . . . L Near 165B UNIX idev . . . . . . . . . . . . . . L Near 2BD0 UNIX idle . . . . . . . . . . . . . . L Near 0EF2 UNIX iget_1 . . . . . . . . . . . . . L Near 10EC UNIX iget_2 . . . . . . . . . . . . . L Near 1110 UNIX iget_3 . . . . . . . . . . . . . L Near 1127 UNIX iget_4 . . . . . . . . . . . . . L Near 1137 UNIX iget . . . . . . . . . . . . . . L Near 10DA UNIX ii . . . . . . . . . . . . . . . L Near 2BCE UNIX imap . . . . . . . . . . . . . . L Near 1213 UNIX imod . . . . . . . . . . . . . . L Near 2C04 UNIX init_argp . . . . . . . . . . . L Near 00B2 UNIX init_file . . . . . . . . . . . L Near 00B6 UNIX int09h . . . . . . . . . . . . . L Near 2C30 UNIX int_09h . . . . . . . . . . . . L Near 1D67 UNIX int_16h . . . . . . . . . . . . L Near 1CDF UNIX intract . . . . . . . . . . . . L Near 03DD UNIX iopen_0 . . . . . . . . . . . . L Near 152B UNIX iopen_1 . . . . . . . . . . . . L Near 153B UNIX iopen_2 . . . . . . . . . . . . L Near 1561 UNIX iopen . . . . . . . . . . . . . L Near 1521 UNIX isdir . . . . . . . . . . . . . L Near 08F7 UNIX isintr1 . . . . . . . . . . . . L Near 0FC8 UNIX isintr2 . . . . . . . . . . . . L Near 0FC9 UNIX isintr . . . . . . . . . . . . . L Near 0FAB UNIX isown . . . . . . . . . . . . . L Near 0C9D UNIX itrunc_1 . . . . . . . . . . . . L Near 11CB UNIX itrunc_2 . . . . . . . . . . . . L Near 11E2 UNIX itrunc_3 . . . . . . . . . . . . L Near 11EC UNIX itrunc_4 . . . . . . . . . . . . L Near 11F5 UNIX itrunc_5 . . . . . . . . . . . . L Near 11F9 UNIX itrunc . . . . . . . . . . . . . L Near 11C5 UNIX i . . . . . . . . . . . . . . . L Near 296E UNIX k16a . . . . . . . . . . . . . . L Near 1F12 UNIX k16c . . . . . . . . . . . . . . L Near 1F01 UNIX k16 . . . . . . . . . . . . . . L Near 1DBF UNIX k17c . . . . . . . . . . . . . . L Near 1F2F UNIX k17 . . . . . . . . . . . . . . L Near 1F21 UNIX k18 . . . . . . . . . . . . . . L Near 1F3B UNIX k1a . . . . . . . . . . . . . . L Near 1D1E UNIX k1b . . . . . . . . . . . . . . L Near 1CF5 UNIX k1c . . . . . . . . . . . . . . L Near 1D01 UNIX k1d . . . . . . . . . . . . . . L Near 1D0A UNIX k1 . . . . . . . . . . . . . . . L Near 1CFF UNIX k20 . . . . . . . . . . . . . . L Near 1F5B UNIX k21 . . . . . . . . . . . . . . L Near 1F61 UNIX k22a0 . . . . . . . . . . . . . L Near 1F70 UNIX k22b . . . . . . . . . . . . . . L Near 1F82 UNIX k22 . . . . . . . . . . . . . . L Near 1F68 UNIX k23 . . . . . . . . . . . . . . L Near 1F8C UNIX k24 . . . . . . . . . . . . . . L Near 1FAB UNIX k25 . . . . . . . . . . . . . . L Near 1FB3 UNIX k26 . . . . . . . . . . . . . . L Near 1FC7 UNIX k27a . . . . . . . . . . . . . . L Near 1FD1 UNIX k27 . . . . . . . . . . . . . . L Near 1FCC UNIX k28 . . . . . . . . . . . . . . L Near 1FDC UNIX k29 . . . . . . . . . . . . . . L Near 1FE3 UNIX k2 . . . . . . . . . . . . . . . L Near 1D2E UNIX k31 . . . . . . . . . . . . . . L Near 2005 UNIX k32 . . . . . . . . . . . . . . L Near 200E UNIX k33 . . . . . . . . . . . . . . L Near 202A UNIX k34 . . . . . . . . . . . . . . L Near 203B UNIX k35 . . . . . . . . . . . . . . L Near 204B UNIX k37 . . . . . . . . . . . . . . L Near 2052 UNIX k38 . . . . . . . . . . . . . . L Near 205F UNIX k39 . . . . . . . . . . . . . . L Near 2087 UNIX k3 . . . . . . . . . . . . . . . L Near 1D54 UNIX k40p . . . . . . . . . . . . . . L Near 20AD UNIX k40 . . . . . . . . . . . . . . L Near 20AE UNIX k41 . . . . . . . . . . . . . . L Near 20B8 UNIX k42 . . . . . . . . . . . . . . L Near 20C2 UNIX k44 . . . . . . . . . . . . . . L Near 20CF UNIX k45 . . . . . . . . . . . . . . L Near 20E3 UNIX k46 . . . . . . . . . . . . . . L Near 20F3 UNIX k47 . . . . . . . . . . . . . . L Near 20FD UNIX k48 . . . . . . . . . . . . . . L Near 2102 UNIX k49 . . . . . . . . . . . . . . L Near 2110 UNIX k4 . . . . . . . . . . . . . . . L Near 1D5A UNIX k50 . . . . . . . . . . . . . . L Near 211F UNIX k51 . . . . . . . . . . . . . . L Near 2124 UNIX k52 . . . . . . . . . . . . . . L Near 2129 UNIX k53 . . . . . . . . . . . . . . L Near 2130 UNIX k54 . . . . . . . . . . . . . . L Near 2137 UNIX k55 . . . . . . . . . . . . . . L Near 213F UNIX k56 . . . . . . . . . . . . . . L Near 2142 UNIX k57 . . . . . . . . . . . . . . L Near 2145 UNIX k58 . . . . . . . . . . . . . . L Near 2154 UNIX k5 . . . . . . . . . . . . . . . L Near 1D66 UNIX k60 . . . . . . . . . . . . . . L Near 216E UNIX k61 . . . . . . . . . . . . . . L Near 2178 UNIX k62 . . . . . . . . . . . . . . L Near 21A3 UNIX k63 . . . . . . . . . . . . . . L Near 219A UNIX k64 . . . . . . . . . . . . . . L Near 219C UNIX kb_init . . . . . . . . . . . . L Near 00E9 UNIX kb_int_01 . . . . . . . . . . . L Near 1D80 UNIX kb_int_02 . . . . . . . . . . . L Near 1D88 UNIX kb_int_03 . . . . . . . . . . . L Near 1D9A UNIX kb_int_04 . . . . . . . . . . . L Near 1DA3 UNIX kb_int_1 . . . . . . . . . . . . L Near 0182 UNIX kb_int_2 . . . . . . . . . . . . L Near 0193 UNIX kb_int_3 . . . . . . . . . . . . L Near 0195 UNIX kb_int_4 . . . . . . . . . . . . L Near 019B UNIX kb_int . . . . . . . . . . . . . L Near 0144 UNIX kernel_init_err_msg . . . . . . L Near 390C UNIX kernel_init_err . . . . . . . . L Near 00AA UNIX kernel_init_ok_msg . . . . . . . L Near 392F UNIX kernel_init . . . . . . . . . . L Near 0000 UNIX key_to_reboot . . . . . . . . . L Near 00C6 UNIX m16 . . . . . . . . . . . . . . L Near 1BB5 UNIX m17 . . . . . . . . . . . . . . L Near 1BCE UNIX m18 . . . . . . . . . . . . . . L Near 1BA8 UNIX make_led . . . . . . . . . . . . L Near 223E UNIX maknod . . . . . . . . . . . . . L Near 0D2F UNIX mdev . . . . . . . . . . . . . . L Near 2BD5 UNIX mget_0 . . . . . . . . . . . . . L Near 0FCA UNIX mget_1 . . . . . . . . . . . . . L Near 0FF8 UNIX mget_2 . . . . . . . . . . . . . L Near 0FF9 UNIX mget_3 . . . . . . . . . . . . . L Near 1009 UNIX mget_4 . . . . . . . . . . . . . L Near 1011 UNIX mget_5 . . . . . . . . . . . . . L Near 1024 UNIX mget_6 . . . . . . . . . . . . . L Near 103B UNIX mget_7 . . . . . . . . . . . . . L Near 105C UNIX mget . . . . . . . . . . . . . . L Near 0FCA UNIX minute . . . . . . . . . . . . . L Near 2C14 UNIX mkdir_1 . . . . . . . . . . . . L Near 095A UNIX mkdir_2 . . . . . . . . . . . . L Near 0976 UNIX mkdir_w . . . . . . . . . . . . L Near 2C0A UNIX mkdir . . . . . . . . . . . . . L Near 0948 UNIX mmod . . . . . . . . . . . . . . L Near 2C06 UNIX mnti . . . . . . . . . . . . . . L Near 2BFC UNIX month . . . . . . . . . . . . . L Near 2C0E UNIX mount . . . . . . . . . . . . . L Near 276E UNIX mpid . . . . . . . . . . . . . . L Near 2BFE UNIX mul32 . . . . . . . . . . . . . L Near 247C UNIX n0 . . . . . . . . . . . . . . . L Near 1C1C UNIX n10 . . . . . . . . . . . . . . L Near 1C46 UNIX n11 . . . . . . . . . . . . . . L Near 1C51 UNIX n1 . . . . . . . . . . . . . . . L Near 1C20 UNIX n3 . . . . . . . . . . . . . . . L Near 1C4D UNIX n5 . . . . . . . . . . . . . . . L Near 1C53 UNIX n8 . . . . . . . . . . . . . . . L Near 1C23 UNIX n9 . . . . . . . . . . . . . . . L Near 1C2D UNIX n_hld1 . . . . . . . . . . . . . L Near 1EB4 UNIX n_hld . . . . . . . . . . . . . L Near 1E34 UNIX namei_1 . . . . . . . . . . . . L Near 0BC3 UNIX namei_2 . . . . . . . . . . . . L Near 0BCE UNIX namei_3 . . . . . . . . . . . . L Near 0BEF UNIX namei_4 . . . . . . . . . . . . L Near 0C24 UNIX namei_5 . . . . . . . . . . . . L Near 0C33 UNIX namei_6 . . . . . . . . . . . . L Near 0C49 UNIX namei_7 . . . . . . . . . . . . L Near 0C57 UNIX namei_r . . . . . . . . . . . . L Near 2C09 UNIX namei . . . . . . . . . . . . . L Near 0B9B UNIX nbuf . . . . . . . . . . . . . . Number 0006h nfiles . . . . . . . . . . . . . Number 0032h nib . . . . . . . . . . . . . . L Near 0C20 UNIX nig . . . . . . . . . . . . . . L Near 0C23 UNIX not_alt . . . . . . . . . . . . L Near 1E4F UNIX not_cur . . . . . . . . . . . . L Near 1E83 UNIX not_id . . . . . . . . . . . . . L Near 1E03 UNIX not_i . . . . . . . . . . . . . L Near 1E1B UNIX not_lc_hc . . . . . . . . . . . L Near 1E76 UNIX nproc . . . . . . . . . . . . . Number 0010h ntty . . . . . . . . . . . . . . Number 0008h ocvt . . . . . . . . . . . . . . L Near 1581 UNIX op0 . . . . . . . . . . . . . . L Near 05E8 UNIX otty_ret . . . . . . . . . . . . L Near 15B8 UNIX ottyp . . . . . . . . . . . . . L Near 1583 UNIX ottys_ret . . . . . . . . . . . L Near 163C UNIX ottys_rtn . . . . . . . . . . . L Near 1644 UNIX ottys . . . . . . . . . . . . . L Near 15BD UNIX otty . . . . . . . . . . . . . . L Near 1575 UNIX p11 . . . . . . . . . . . . . . L Near 1ADA UNIX p12 . . . . . . . . . . . . . . L Near 1AE2 UNIX p13 . . . . . . . . . . . . . . L Near 1AE7 UNIX p20 . . . . . . . . . . . . . . L Near 1BF0 UNIX p21 . . . . . . . . . . . . . . L Near 1BF6 UNIX p41 . . . . . . . . . . . . . . L Near 1C68 UNIX p42 . . . . . . . . . . . . . . L Near 1C79 UNIX p43 . . . . . . . . . . . . . . L Near 1C7E UNIX p44 . . . . . . . . . . . . . . L Near 1C7F UNIX p_time . . . . . . . . . . . . . L Near 2C34 UNIX panic_msg . . . . . . . . . . . L Near 3980 UNIX panic . . . . . . . . . . . . . L Near 00C0 UNIX passc . . . . . . . . . . . . . L Near 131C UNIX poke_1 . . . . . . . . . . . . . L Near 181A UNIX poke_2 . . . . . . . . . . . . . L Near 1873 UNIX poke_3 . . . . . . . . . . . . . L Near 182D UNIX poke . . . . . . . . . . . . . . L Near 1815 UNIX position . . . . . . . . . . . . L Near 1BCF UNIX ppoke . . . . . . . . . . . . . L Near 1815 UNIX preread . . . . . . . . . . . . L Near 170E UNIX print_msg . . . . . . . . . . . L Near 00D9 UNIX ptty . . . . . . . . . . . . . . L Near 2C4A UNIX putc . . . . . . . . . . . . . . L Near 1AA6 UNIX putlu_1 . . . . . . . . . . . . L Near 0EE4 UNIX putlu_2 . . . . . . . . . . . . L Near 0EE7 UNIX putlu . . . . . . . . . . . . . L Near 0ECE UNIX p . . . . . . . . . . . . . . . L Near 298E UNIX rcvt . . . . . . . . . . . . . . L Near 12BD UNIX rdev . . . . . . . . . . . . . . L Near 2BD4 UNIX read_ac_current . . . . . . . . L Near 1CC2 UNIX readi . . . . . . . . . . . . . L Near 123F UNIX ret_ . . . . . . . . . . . . . . L Near 12D0 UNIX rfd . . . . . . . . . . . . . . L Near 16DD UNIX rhd . . . . . . . . . . . . . . L Near 16E9 UNIX rlpr . . . . . . . . . . . . . . L Near 12D2 UNIX rmem . . . . . . . . . . . . . . L Near 12C1 UNIX rootdir . . . . . . . . . . . . L Near 2C00 UNIX rst_rd_id . . . . . . . . . . . L Near 1DD4 UNIX rswap . . . . . . . . . . . . . L Near 0EA8 UNIX rtty_idle . . . . . . . . . . . L Near 12AE UNIX rtty_nc . . . . . . . . . . . . L Near 1297 UNIX rttys . . . . . . . . . . . . . L Near 128F UNIX rtty . . . . . . . . . . . . . . L Near 1285 UNIX runq . . . . . . . . . . . . . . L Near 2C02 UNIX rw1 . . . . . . . . . . . . . . L Near 05BF UNIX rw . . . . . . . . . . . . . . . L Near 2C08 UNIX s10 . . . . . . . . . . . . . . L Near 2250 UNIX sb0 . . . . . . . . . . . . . . L Near 2566 UNIX sb1 . . . . . . . . . . . . . . L Near 276A UNIX scroll_up . . . . . . . . . . . L Near 1C03 UNIX sd1 . . . . . . . . . . . . . . L Near 21C1 UNIX sd3 . . . . . . . . . . . . . . L Near 21CE UNIX sd5 . . . . . . . . . . . . . . L Near 21D7 UNIX sd7 . . . . . . . . . . . . . . L Near 21E2 UNIX sd9 . . . . . . . . . . . . . . L Near 21E9 UNIX sdsegmnt . . . . . . . . . . . . Number 06C0h second . . . . . . . . . . . . . L Near 2C16 UNIX seektell0 . . . . . . . . . . . L Near 0DA1 UNIX seektell_1 . . . . . . . . . . . L Near 0DCD UNIX seektell . . . . . . . . . . . . L Near 0D9D UNIX segm_sw . . . . . . . . . . . . L Near 0584 UNIX set_cpos . . . . . . . . . . . . L Near 1B95 UNIX set_date_time . . . . . . . . . L Near 2490 UNIX set_date . . . . . . . . . . . . L Near 250B UNIX set_fn . . . . . . . . . . . . . L Near 1ED8 UNIX set_time . . . . . . . . . . . . L Near 2533 UNIX seta . . . . . . . . . . . . . . L Near 185B UNIX setimod . . . . . . . . . . . . L Near 11A0 UNIX ship_it . . . . . . . . . . . . L Near 224C UNIX sioreg . . . . . . . . . . . . . L Near 144D UNIX sk2 . . . . . . . . . . . . . . L Near 1D4C UNIX sl3 . . . . . . . . . . . . . . L Near 220D UNIX sl5 . . . . . . . . . . . . . . L Near 2231 UNIX sl7 . . . . . . . . . . . . . . L Near 2237 UNIX sl9 . . . . . . . . . . . . . . L Near 223C UNIX sleep . . . . . . . . . . . . . L Near 0F77 UNIX smod . . . . . . . . . . . . . . L Near 2C05 UNIX snd_data . . . . . . . . . . . . L Near 21B2 UNIX snd_led1 . . . . . . . . . . . . L Near 2200 UNIX snd_led . . . . . . . . . . . . L Near 21ED UNIX sndcs . . . . . . . . . . . . . L Near 1A6D UNIX sndc . . . . . . . . . . . . . . L Near 1A65 UNIX sp_init . . . . . . . . . . . . L Near 0201 UNIX sret . . . . . . . . . . . . . . L Near 1655 UNIX sstack . . . . . . . . . . . . . Number 3A74h swap_0 . . . . . . . . . . . . . L Near 0E3A UNIX swap_1 . . . . . . . . . . . . . L Near 0E3D UNIX swap_2 . . . . . . . . . . . . . L Near 0E48 UNIX swap_3 . . . . . . . . . . . . . L Near 0E58 UNIX swap_4 . . . . . . . . . . . . . L Near 0E5C UNIX swap_5 . . . . . . . . . . . . . L Near 0E6F UNIX swap_6 . . . . . . . . . . . . . L Near 0E7B UNIX swap . . . . . . . . . . . . . . L Near 0E3A UNIX sysbreak_0 . . . . . . . . . . . L Near 0D1B UNIX sysbreak_1 . . . . . . . . . . . L Near 0D21 UNIX sysbreak_2 . . . . . . . . . . . L Near 0D24 UNIX sysbreak_3 . . . . . . . . . . . L Near 0D28 UNIX sysbreak . . . . . . . . . . . . L Near 0D03 UNIX syscalls . . . . . . . . . . . . L Near 02B6 UNIX syschdir . . . . . . . . . . . . L Near 0C65 UNIX syschmod . . . . . . . . . . . . L Near 0C8B UNIX syschown . . . . . . . . . . . . L Near 0CC2 UNIX sysclose . . . . . . . . . . . . L Near 067D UNIX syscreat . . . . . . . . . . . . L Near 0639 UNIX sysemt . . . . . . . . . . . . . L Near 068A UNIX sysent . . . . . . . . . . . . . L Near 0263 UNIX sysexec_10 . . . . . . . . . . . L Near 0ADF UNIX sysexec_1 . . . . . . . . . . . L Near 09CE UNIX sysexec_2 . . . . . . . . . . . L Near 09E8 UNIX sysexec_3 . . . . . . . . . . . L Near 09F2 UNIX sysexec_4 . . . . . . . . . . . L Near 09FA UNIX sysexec_5 . . . . . . . . . . . L Near 0A03 UNIX sysexec_6 . . . . . . . . . . . L Near 0A18 UNIX sysexec_7 . . . . . . . . . . . L Near 0A23 UNIX sysexec_8 . . . . . . . . . . . L Near 0A33 UNIX sysexec_9 . . . . . . . . . . . L Near 0ADC UNIX sysexec . . . . . . . . . . . . L Near 0999 UNIX sysexit_1 . . . . . . . . . . . L Near 03F3 UNIX sysexit_2 . . . . . . . . . . . L Near 0414 UNIX sysexit_3 . . . . . . . . . . . L Near 042A UNIX sysexit_4 . . . . . . . . . . . L Near 042C UNIX sysexit_5 . . . . . . . . . . . L Near 0434 UNIX sysexit_6 . . . . . . . . . . . L Near 0462 UNIX sysexit . . . . . . . . . . . . L Near 03EF UNIX sysflg . . . . . . . . . . . . . L Near 2C07 UNIX sysfork_1 . . . . . . . . . . . L Near 04C2 UNIX sysfork_2 . . . . . . . . . . . L Near 04D2 UNIX sysfork_3 . . . . . . . . . . . L Near 04FB UNIX sysfork_4 . . . . . . . . . . . L Near 0569 UNIX sysfork_5 . . . . . . . . . . . L Near 057D UNIX sysfork . . . . . . . . . . . . L Near 04C0 UNIX sysfstat . . . . . . . . . . . . L Near 0AFA UNIX sysgetuid . . . . . . . . . . . L Near 0DF9 UNIX sysgtty_0 . . . . . . . . . . . L Near 07ED UNIX sysgtty_1 . . . . . . . . . . . L Near 0821 UNIX sysgtty_2 . . . . . . . . . . . L Near 082D UNIX sysgtty_3 . . . . . . . . . . . L Near 0837 UNIX sysgtty_4 . . . . . . . . . . . L Near 0839 UNIX sysgtty_5 . . . . . . . . . . . L Near 084C UNIX sysgtty_6 . . . . . . . . . . . L Near 0876 UNIX sysgtty_7 . . . . . . . . . . . L Near 088D UNIX sysgtty_8 . . . . . . . . . . . L Near 0891 UNIX sysgtty_9 . . . . . . . . . . . L Near 08A0 UNIX sysgtty . . . . . . . . . . . . L Near 07ED UNIX sysilgins . . . . . . . . . . . L Near 06B3 UNIX sysintr . . . . . . . . . . . . L Near 0DD0 UNIX syslink . . . . . . . . . . . . L Near 08B3 UNIX sysmdate . . . . . . . . . . . . L Near 06B6 UNIX sysmkdir . . . . . . . . . . . . L Near 0659 UNIX sysmount . . . . . . . . . . . . L Near 147F UNIX sysopen . . . . . . . . . . . . L Near 05CB UNIX sysquit . . . . . . . . . . . . L Near 0DD7 UNIX sysread . . . . . . . . . . . . L Near 0596 UNIX sysrelease . . . . . . . . . . . L Near 035A UNIX sysrele . . . . . . . . . . . . L Near 0353 UNIX sysret . . . . . . . . . . . . . L Near 0319 UNIX sysseek . . . . . . . . . . . . L Near 0D83 UNIX syssetuid . . . . . . . . . . . L Near 0DDE UNIX syssleep . . . . . . . . . . . . L Near 1CCF UNIX sysstat . . . . . . . . . . . . L Near 0B0E UNIX sysstime . . . . . . . . . . . . L Near 0CEF UNIX sysstty_0 . . . . . . . . . . . L Near 070D UNIX sysstty_10 . . . . . . . . . . . L Near 07D3 UNIX sysstty_11 . . . . . . . . . . . L Near 07E2 UNIX sysstty_12 . . . . . . . . . . . L Near 074A UNIX sysstty_1 . . . . . . . . . . . L Near 0720 UNIX sysstty_2 . . . . . . . . . . . L Near 0722 UNIX sysstty_3 . . . . . . . . . . . L Near 0743 UNIX sysstty_4 . . . . . . . . . . . L Near 0759 UNIX sysstty_5 . . . . . . . . . . . L Near 0763 UNIX sysstty_6 . . . . . . . . . . . L Near 077A UNIX sysstty_7 . . . . . . . . . . . L Near 079A UNIX sysstty_8 . . . . . . . . . . . L Near 07AB UNIX sysstty_9 . . . . . . . . . . . L Near 07C5 UNIX sysstty . . . . . . . . . . . . L Near 06E4 UNIX systell . . . . . . . . . . . . L Near 0D8F UNIX systime . . . . . . . . . . . . L Near 0CDC UNIX sysumount . . . . . . . . . . . L Near 14E2 UNIX sysunlink . . . . . . . . . . . L Near 0915 UNIX syswait_0 . . . . . . . . . . . L Near 046D UNIX syswait_1 . . . . . . . . . . . L Near 047D UNIX syswait_2 . . . . . . . . . . . L Near 04A1 UNIX syswait_3 . . . . . . . . . . . L Near 04A3 UNIX syswait . . . . . . . . . . . . L Near 046D UNIX syswrite . . . . . . . . . . . . L Near 05A6 UNIX s . . . . . . . . . . . . . . . L Near 256A UNIX t_ctl . . . . . . . . . . . . . L Near 1EC2 UNIX t_f12 . . . . . . . . . . . . . L Near 1E9C UNIX t_shf . . . . . . . . . . . . . L Near 1ECE UNIX t_sys_key . . . . . . . . . . . L Near 1EDD UNIX time_count . . . . . . . . . . . Number 0004h tsleep . . . . . . . . . . . . . L Near 2CAC UNIX tst_id_2 . . . . . . . . . . . . L Near 1DDC UNIX tswap . . . . . . . . . . . . . L Near 0E34 UNIX ts . . . . . . . . . . . . . . . L Near 1B18 UNIX tty_sw . . . . . . . . . . . . . L Near 1C8B UNIX ttychr . . . . . . . . . . . . . L Near 2C7A UNIX ttyl . . . . . . . . . . . . . . L Near 2C8E UNIX u0 . . . . . . . . . . . . . . . L Near 1ABE UNIX u10 . . . . . . . . . . . . . . L Near 1B2F UNIX u11 . . . . . . . . . . . . . . L Near 1B36 UNIX u1 . . . . . . . . . . . . . . . L Near 1AD4 UNIX u2 . . . . . . . . . . . . . . . L Near 1AD7 UNIX u3 . . . . . . . . . . . . . . . L Near 1AF3 UNIX u6 . . . . . . . . . . . . . . . L Near 1AF8 UNIX u8 . . . . . . . . . . . . . . . L Near 1AFD UNIX u9 . . . . . . . . . . . . . . . L Near 1B2B UNIX unixbootdrive . . . . . . . . . L Near 2564 UNIX unkni . . . . . . . . . . . . . L Near 0263 UNIX up0 . . . . . . . . . . . . . . L Near 1DB5 UNIX u . . . . . . . . . . . . . . . L Near 38CC UNIX vp_clr . . . . . . . . . . . . . L Near 019F UNIX waitf1 . . . . . . . . . . . . . L Near 1B87 UNIX waitf . . . . . . . . . . . . . L Near 1B86 UNIX wakeup . . . . . . . . . . . . . L Near 0F59 UNIX wdir . . . . . . . . . . . . . . L Near 097D UNIX wfd . . . . . . . . . . . . . . L Near 16E3 UNIX whd . . . . . . . . . . . . . . L Near 16EF UNIX wlist . . . . . . . . . . . . . L Near 2CA2 UNIX wlpr . . . . . . . . . . . . . . L Near 13B2 UNIX wmem . . . . . . . . . . . . . . L Near 13B5 UNIX wret . . . . . . . . . . . . . . L Near 13AA UNIX write_c_current . . . . . . . . L Near 1C62 UNIX write_tty . . . . . . . . . . . L Near 1AAB UNIX writei . . . . . . . . . . . . . L Near 133A UNIX wslot . . . . . . . . . . . . . L Near 17F7 UNIX wswap . . . . . . . . . . . . . L Near 0E81 UNIX wtty_nc . . . . . . . . . . . . L Near 1392 UNIX wttys . . . . . . . . . . . . . L Near 1389 UNIX wtty . . . . . . . . . . . . . . L Near 137D UNIX xmtt . . . . . . . . . . . . . . L Near 13AC UNIX year . . . . . . . . . . . . . . L Near 2C0C UNIX 0 Warnings 0 Errors