     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.6
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.15 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 19/07/2022 (v0.2.1.6) ]
    13                                  ;	 04/02/2016 - Retro UNIX 386 v1.1 (Retro UNIX Kernel v0.2.1.0)	
    14                                  ;	 31/12/2021 - BugFix and Code Optimization (v0.2.1.1)
    15                                  ;	 03/03/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022
    16                                  ;	 04/04/2022 - Inode Table/List Address Modification (v0.2.1.2) -u5.s-
    17                                  ;	 22/04/2022 - BugFix ('mget' -u5.s-)
    18                                  ;	 29/04/2022 - BugFix ('syschmod' -u2.s-) (v0.2.1.2)
    19                                  ;	 ; (v0.2.1.3)
    20                                  ;	 09/05/2022 - u2.s (sysstat), u7.s (sysumount), diskinit.inc  
    21                                  ;	 15/05/2022 - u2.s (namei), u7.s (sysumount)
    22                                  ;	 01/06/2022 - BugFix ('set_date_time' -u0.s-) (v0.2.1.3)
    23                                  ;	 ; (v0.2.1.4)
    24                                  ;	 13/06/2022 - LPT1 (/dev/lpr) printing modification (v0.2.1.4)
    25                                  ;	 14/06/2022 - BugFix (video.inc,'set_cpos' <- u9.s 'putc' carry flg)
    26                                  ;	 ; (v0.2.1.5)
    27                                  ;	 08/07/2022 - diskio.s (diskio simplified by removing the unused code) 
    28                                  ;	 ; (v0.2.1.6) 
    29                                  ;	 15/07/2022 - Simplified and Improved Buffer Handling -u8.s-
    30                                  ;	 16/07/2022 - Code Optimization
    31                                  ;	 17/07/2022 - Code Optimization
    32                                  ;	 18/07/2022 - Code Optimization
    33                                  ;	 19/07/2022 - BugFix (File Offset after disk write error, u6.s, u8.s)	
    34                                  ;
    35                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    36                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    37                                  ; <Bell Laboratories (17/3/1972)>
    38                                  ; <Preliminary Release of UNIX Implementation Document>
    39                                  ;
    40                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    41                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    42                                  ;
    43                                  ; ****************************************************************************
    44                                  ; 31/12/2021 - 15/07/2022
    45                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    46                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    47                                  
    48                                  ; 02/01/2022 - Code Optimization
    49                                  ; Runix Kernel v0.2.1.2
    50                                  ; 24/12/2021 - BugFix and Code Optimization
    51                                  ; Runix Kernel v0.2.1.1 
    52                                  
    53                                  ; 24/12/2013
    54                                  
    55                                  ; Entering protected mode:
    56                                  ; Derived from 'simple_asm.txt' source code file and 
    57                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    58                                  ; (gregor.brunmar@home.se)
    59                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    60                                  ;
    61                                  
    62                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    63                                  ; by Michael Chourdakis (2009) 
    64                                  ; http://www.codeproject.com/Articles/45788/
    65                                  ; http://www.michaelchourdakis.com
    66                                  ;
    67                                  
    68                                  ; Global Descriptor Table:
    69                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    70                                  ; by Linus Torvalds (1991-1992)
    71                                  ;
    72                                  
    73                                  KLOAD	equ 10000h ; Kernel loading address
    74                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    75                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    76                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    77                                  ; 19/03/2015
    78                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    79                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    80                                  ; 24/03/2015
    81                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    82                                  ; 19/03/2015
    83                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    84                                  		     ; (at the end of the 1st 4MB)
    85                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    86                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    87                                  
    88                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    89                                  ;; 27/12/2013
    90                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    91                                  
    92                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    93                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    94                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    95                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    96                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    97                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    98                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    99                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
   100                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
   101                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
   102                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
   103                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
   104                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
   105                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
   106                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
   107                                  ;----------------------------------------
   108                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
   109                                  ;-----------------------------------------------------------------------------
   110                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
   111                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
   112                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
   113                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
   114                                  
   115                                  ; Memory Allocation Table Address
   116                                  ; 05/11/2014
   117                                  ; 31/10/2014
   118                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   119                                  					; the 1st 1 MB memory space.
   120                                  					; (This address must be aligned
   121                                  					;  on 128 KB boundary, if it will be
   122                                  					;  changed later.)
   123                                  					; ((lower 17 bits of 32 bit M.A.T.
   124                                  					;   address must be ZERO)).
   125                                  					; ((((Reason: 32 bit allocation 
   126                                  					;     instructions, dword steps)))
   127                                  					; (((byte >> 12 --> page >> 5)))  
   128                                  ;04/11/2014	
   129                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   130                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   131                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   132                                  ;
   133                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   134                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   135                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   136                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   137                                  
   138                                  ; 17/02/2015 (unix386.s)
   139                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   140                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   141                                  ;
   142                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   143                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   144                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   145                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   146                                  
   147                                  
   148                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   149                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   150                                  ;
   151                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   152                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   153                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   154                                  		      ; otherwise it is standard FDPT with physical values 	
   155                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   156                                  		      ; (obsolete for IDE/ATA drives)
   157                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   158                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   159                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   160                                  			; Bit 4 : Reserved. Always 0
   161                                  			; Bit 3 : Set to 1 if more than 8 heads
   162                                  			; Bit 2-0 : Reserved. Alsways 0
   163                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   164                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   165                                  
   166                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   167                                  ; (11 bytes long) will be used by diskette handler/bios
   168                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   169                                  
   170                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   171                                  
   172                                  [ORG 0]
   173                                  
   174                                  KSTART: ; 01/01/2022
   175                                   
   176                                  	; 12/11/2014
   177                                  	; Save boot drive number (that is default root drive)
   178 00000000 8816[585D]              	mov	[boot_drv], dl ; physical drv number
   179                                  
   180                                  	; Determine installed memory
   181                                  	; 31/10/2014
   182                                  	;
   183 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   184 00000007 CD15                    	int	15h	   ; for large configurations
   185 00000009 7308                    	jnc	short chk_ms
   186 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   187 0000000D CD15                    	int	15h
   188                                  	;	   
   189                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   190                                  	;out	70h, al ; select CMOS register
   191                                  	;in	al, 71h ; read data (1 byte)
   192                                  	;mov	cl, al
   193                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   194                                  	;out	70h, al ; select CMOS register
   195                                  	;in	al, 71h ; read data (1 byte)
   196                                  	;mov	ch, al
   197                                   	;      
   198 0000000F 89C1                    	mov	cx, ax
   199 00000011 31D2                    	xor	dx, dx
   200                                  chk_ms:
   201 00000013 890E[C45F]              	mov	[mem_1m_1k], cx
   202 00000017 8916[C85F]              	mov	[mem_16m_64k], dx
   203                                  	; 05/11/2014
   204                                  	;and	dx, dx
   205                                  	;jz	short L2
   206 0000001B 81F90004                        cmp     cx, 1024
   207 0000001F 7351                    	jnb	short L0
   208                                  		 ; insufficient memory_error	
   209                                  		 ; Minimum 2 MB memory is needed... 
   210                                  	; 05/11/2014
   211                                  	; (real mode error printing)
   212 00000021 FB                      	sti
   213 00000022 BE[3600]                	mov	si, msg_out_of_memory
   214 00000025 BB0700                  	mov	bx, 7
   215 00000028 B40E                    	mov	ah, 0Eh	; write tty
   216                                  oom_1:
   217 0000002A AC                      	lodsb
   218 0000002B 08C0                    	or	al, al
   219 0000002D 7404                    	jz	short oom_2
   220 0000002F CD10                    	int	10h
   221 00000031 EBF7                    	jmp	short oom_1
   222                                  oom_2:
   223 00000033 F4                              hlt
   224 00000034 EBFD                    	jmp	short oom_2
   225                                  
   226                                  ; 02/01/2022
   227                                  ; 05/11/2014
   228                                  msg_out_of_memory:
   229 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   230 00000039 496E73756666696369-             db      'Insufficient memory !'
   230 00000042 656E74206D656D6F72-
   230 0000004B 792021             
   231 0000004E 0D0A                    	db	0Dh, 0Ah
   232                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   233 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   233 00000059 324D42206D656D6F72-
   233 00000062 79206973206E656564-
   233 0000006B 65642E29           
   234 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   235                                  
   236                                  L0:
   237                                  %include 'diskinit.inc' ; 07/03/2015
   238                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKINIT.INC
   239                              <1> ; Last Modification: 12/07/2022
   240                              <1> 
   241                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   242                              <1> 
   243                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   244                              <1> 
   245                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   246                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   247                              <1> ;L0:
   248                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   249                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   250 00000072 BA7F00              <1> 	mov	dx, 7Fh
   251                              <1> L1:	
   252 00000075 FEC2                <1> 	inc	dl
   253 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   254                              <1> 			; Phoenix EDD v1.1 - EDD v3
   255 00000079 BBAA55              <1> 	mov	bx, 55AAh
   256 0000007C CD13                <1> 	int 	13h
   257 0000007E 721A                <1> 	jc	short L2
   258                              <1> 
   259 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   260 00000084 7514                <1> 	jne	short L2
   261 00000086 FE06[5B5D]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   262 0000008A 8816[5A5D]          <1>         mov     [last_drv], dl  ; last hard disk number
   263 0000008E BB[DE5C]            <1> 	mov	bx, hd0_type - 80h
   264 00000091 01D3                <1> 	add	bx, dx	 
   265 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   266                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   267                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   268                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   269                              <1>                          ;            (EDD) ready (DPTE ready)
   270                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   271                              <1>                          ;            (EDD-3)
   272                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   273 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   274 00000098 72DB                <1> 	jb	short L1
   275                              <1> L2:
   276                              <1> 	; 23/11/2014
   277                              <1> 	; 19/11/2014
   278 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   279                              <1> 	; 04/02/2016 (esi -> si)
   280 0000009C BE[5C5D]            <1> 	mov	si, fd0_type
   281                              <1> L3:
   282                              <1> 	; 14/01/2015
   283 0000009F 8816[595D]          <1> 	mov	[drv], dl
   284                              <1> 	;
   285 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   286 000000A5 CD13                <1> 	int	13h	
   287 000000A7 7210                <1> 	jc	short L4
   288                              <1> 		; BL = drive type (for floppy drives)
   289                              <1> 		; DL = number of floppy drives
   290                              <1> 		;		
   291                              <1> 		; ES:DI = Address of DPT from BIOS
   292                              <1> 		;
   293 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   294                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   295                              <1> 	; 14/01/2015
   296 000000AB E8BB01              <1> 	call	set_disk_parms
   297                              <1> 	; 10/12/2014
   298 000000AE 81FE[5C5D]          <1> 	cmp	si, fd0_type
   299 000000B2 7705                <1> 	ja	short L4
   300 000000B4 46                  <1> 	inc	si ; fd1_type
   301 000000B5 B201                <1> 	mov	dl, 1
   302 000000B7 EBE6                <1> 	jmp	short L3
   303                              <1> L4:
   304                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   305 000000B9 B27F                <1> 	mov	dl, 7Fh
   306                              <1> 	; 24/12/2014 (Temporary)
   307 000000BB 803E[5B5D]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   308                              <1> 	;ja	L10       ; yes, all fixed disk operations
   309                              <1> 			  ; will be performed according to
   310                              <1> 			  ; present EDD specification
   311                              <1> 	; 02/01/2022
   312 000000C0 7603                <1> 	jna	short L5
   313 000000C2 E99100              <1> 	jmp	L10
   314                              <1> L5:
   315 000000C5 FEC2                <1> 	inc 	dl
   316 000000C7 8816[595D]          <1>         mov     [drv], dl
   317 000000CB 8816[5A5D]          <1>         mov     [last_drv], dl ; 14/01/2015
   318 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   319 000000D1 CD13                <1> 	int	13h	; (conventional function)
   320                              <1> 	;jc	L13	; fixed disk drive not ready
   321                              <1> 	; 02/01/2022
   322 000000D3 7303                <1> 	jnc	short L6
   323 000000D5 E98301              <1> 	jmp	L13
   324                              <1> L6:
   325 000000D8 8816[5B5D]          <1>         mov     [hdc], dl ; number of drives
   326                              <1> 	;; 14/01/2013
   327                              <1> 	;;push	cx
   328 000000DC E88A01              <1> 	call	set_disk_parms
   329                              <1> 	;;pop	cx
   330                              <1> 	;
   331                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   332 000000DF 8A16[595D]          <1>         mov     dl, [drv]
   333 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   334 000000E6 80FA80              <1> 	cmp	dl, 80h
   335 000000E9 7603                <1> 	jna	short L7
   336 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   337                              <1> L7:	
   338 000000EE 31C0                <1> 	xor	ax, ax
   339 000000F0 8ED8                <1> 	mov	ds, ax
   340 000000F2 8B37                <1>         mov     si, [bx]
   341 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   342 000000F7 8ED8                <1> 	mov	ds, ax
   343 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   344                              <1> 	;jne	L12 ; invalid FDPT
   345                              <1> 	; 02/01/2022
   346 000000FC 7403                <1> 	je	short L7_8
   347 000000FE E95601              <1> 	jmp	L12
   348                              <1> L7_8:
   349 00000101 BF0000              <1> 	mov	di, HD0_DPT
   350 00000104 80FA80              <1> 	cmp	dl, 80h
   351 00000107 7603                <1> 	jna	short L8
   352 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   353                              <1> L8:
   354                              <1> 	; 30/12/2014
   355 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   356 0000010F 8EC0                <1> 	mov	es, ax
   357                              <1> 	; 24/12/2014
   358 00000111 B90800              <1> 	mov	cx, 8
   359 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   360 00000116 8CC8                <1> 	mov	ax, cs
   361 00000118 8ED8                <1> 	mov	ds, ax
   362                              <1> 	; 02/02/2015
   363 0000011A 8A0E[595D]          <1>         mov     cl, [drv]
   364 0000011E 88CB                <1> 	mov	bl, cl
   365 00000120 B8F001              <1> 	mov	ax, 1F0h
   366 00000123 80E301              <1> 	and	bl, 1
   367 00000126 7406                <1> 	jz	short L9
   368 00000128 C0E304              <1> 	shl	bl, 4
   369 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   370                              <1> L9:
   371 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   372 0000012F 050602              <1> 	add	ax, 206h
   373 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   374 00000133 88D8                <1> 	mov	al, bl
   375 00000135 04A0                <1> 	add	al, 0A0h
   376 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   377                              <1> 	;
   378 00000138 FE06[595D]          <1> 	inc	byte [drv]
   379 0000013C BB[DE5C]            <1> 	mov	bx, hd0_type - 80h
   380 0000013F 01CB                <1> 	add	bx, cx
   381 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   382 00000144 A0[5B5D]            <1> 	mov	al, [hdc]
   383 00000147 FEC8                <1> 	dec	al
   384                              <1> 	;jz	L13
   385                              <1> 	; 02/01/2022
   386 00000149 7408                <1> 	jz	short L9_10
   387 0000014B 80FA80              <1> 	cmp	dl, 80h
   388                              <1>         ;jna	L5
   389                              <1> 	;jmp	L13
   390                              <1> 	; 02/01/2022
   391 0000014E 7703                <1> 	ja	short L9_10
   392 00000150 E972FF              <1> 	jmp	L5
   393                              <1> L9_10:
   394 00000153 E90501              <1>         jmp     L13
   395                              <1> L10:
   396 00000156 FEC2                <1> 	inc 	dl
   397                              <1> 	; 25/12/2014
   398 00000158 8816[595D]          <1> 	mov	[drv], dl
   399 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   400 0000015E CD13                <1> 	int	13h	; (conventional function)
   401                              <1> 	;jc	L13
   402                              <1> 	; 02/01/2022
   403 00000160 72F1                <1> 	jc	short L9_10
   404                              <1> 	; 14/01/2015
   405 00000162 8A16[595D]          <1> 	mov	dl, [drv]
   406 00000166 52                  <1> 	push	dx
   407 00000167 51                  <1> 	push	cx
   408 00000168 E8FE00              <1> 	call	set_disk_parms
   409 0000016B 59                  <1> 	pop	cx
   410 0000016C 5A                  <1> 	pop	dx
   411                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   412                              <1> 	; 04/02/2016 (esi -> si)
   413                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   414                              <1> 	;		 ; at the '_end' of kernel.
   415                              <1> 	;mov	word [si], 30
   416                              <1> 	; 06/07/2016
   417 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   418                              <1> 	; 09/07/2016
   419 00000170 B81E00              <1> 	mov	ax, 001Eh
   420 00000173 8824                <1> 	mov	[si], ah ; 0
   421 00000175 46                  <1> 	inc	si
   422 00000176 8904                <1> 	mov	word [si], ax
   423                              <1>  	; word [si] = 30
   424                              <1> 	;
   425 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   426 0000017A CD13                <1> 	int	13h
   427                              <1>         ;jc	L13
   428                              <1> 	; 02/01/2022
   429 0000017C 72D5                <1> 	jc	short L9_10
   430                              <1> 	; 04/02/2016 (ebx -> bx)
   431                              <1> 	; 14/01/2015
   432                              <1> 	;sub	bx, bx
   433 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   434 00000180 88D3                <1> 	mov	bl, dl
   435 00000182 80EB80              <1> 	sub	bl, 80h
   436 00000185 81C3[5E5D]          <1> 	add	bx, hd0_type
   437 00000189 8A07                <1> 	mov 	al, [bx]
   438 0000018B 0C80                <1> 	or	al, 80h
   439 0000018D 8807                <1> 	mov 	[bx], al	
   440 0000018F 81EB[5C5D]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   441 00000193 81C3[7E5D]          <1> 	add	bx, drv.status
   442 00000197 8807                <1> 	mov	[bx], al
   443                              <1> 	; 04/02/2016 (eax -> ax)
   444 00000199 8B4410              <1> 	mov	ax, [si+16]
   445 0000019C 854412              <1> 	test	ax, [si+18]
   446 0000019F 7413                <1> 	jz	short L10_A0h 
   447                              <1> 			; 'CHS only' disks on EDD system 
   448                              <1> 			;  are reported with ZERO disk size
   449 000001A1 81EB[7E5D]          <1> 	sub	bx, drv.status
   450 000001A5 C1E302              <1> 	shl	bx, 2
   451 000001A8 81C3[625D]          <1> 	add	bx, drv.size ; disk size (in sectors)
   452 000001AC 8907                <1> 	mov	[bx], ax
   453 000001AE 8B4412              <1> 	mov	ax, [si+18]
   454                              <1> 	;mov	[bx], ax
   455                              <1> 	; 02/01/2022 (BugFix)
   456 000001B1 894702              <1> 	mov	[bx+2], ax
   457                              <1> 
   458                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   459                              <1> 	 ; for CHS disks (28/02/2015)
   460                              <1> 	; 30/12/2014
   461 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   462 000001B7 88D0                <1> 	mov	al, dl
   463 000001B9 83E003              <1> 	and 	ax, 3
   464 000001BC C0E005              <1> 	shl	al, 5 ; *32
   465 000001BF 01C7                <1> 	add 	di, ax
   466 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   467 000001C4 8EC0                <1> 	mov	es, ax
   468                              <1> 	;
   469 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   470 000001C8 88CC                <1> 	mov	ah, cl	
   471 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   472 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   473 000001CE AB                  <1> 	stosw		
   474 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   475 000001D1 FEC0                <1> 	inc	al
   476 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   477 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   478 000001D6 AA                  <1> 	stosb
   479 000001D7 8A440C              <1> 	mov	al, [si+12]
   480 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   481 000001DB 31C0                <1>  	xor	ax, ax
   482                              <1> 	;dec	ax	 ; 02/01/2015 
   483 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   484                              <1> 	;xor	al, al	 ; 02/01/2015	
   485 000001DE AA                  <1> 	stosb		 ; reserved
   486 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   487                              <1> 		         ; (do not disable retries, 
   488                              <1> 			 ; more than 8 heads)
   489 000001E1 AA                  <1> 	stosb
   490 000001E2 8B4404              <1> 	mov	ax, [si+4]
   491 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   492                              <1> 	;push	ax	 ; 02/01/2015
   493 000001E6 8A4408              <1> 	mov	al, [si+8]
   494 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   495 000001EA 29C0                <1> 	sub 	ax, ax
   496                              <1> 	;pop	ax	 ; 02/01/2015	
   497 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   498 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   499 000001EF 243F                <1> 	and 	al, 3Fh	
   500 000001F1 AA                  <1> 	stosb
   501                              <1> 	;sub	al, al	 ; checksum
   502                              <1> 	;stosb
   503                              <1> 	;
   504 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   505 000001F5 AD                  <1> 	lodsw
   506 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   507 000001F7 AD                  <1> 	lodsw
   508 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   509                              <1> 	;
   510                              <1> 	; checksum calculation
   511 000001F9 89FE                <1> 	mov	si, di
   512 000001FB 06                  <1> 	push	es
   513 000001FC 1F                  <1> 	pop	ds
   514                              <1> 	;mov	cx, 16
   515 000001FD B90F00              <1> 	mov 	cx, 15
   516 00000200 29CE                <1> 	sub	si, cx
   517 00000202 30E4                <1> 	xor	ah, ah
   518                              <1> 	;del	cl
   519                              <1> L11:		
   520 00000204 AC                  <1> 	lodsb
   521 00000205 00C4                <1> 	add	ah, al
   522 00000207 E2FB                <1> 	loop	L11
   523                              <1> 	;
   524 00000209 88E0                <1> 	mov	al, ah
   525 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   526 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   527                              <1> 	;
   528 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   529 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   530                              <1> 	;
   531                              <1> 	; 23/02/2015
   532 00000210 57                  <1> 	push	di
   533                              <1> 	; ES:DI points to DPTE (FDPTE) location
   534                              <1> 	;mov	cx, 8
   535 00000211 B108                <1> 	mov	cl, 8
   536 00000213 F3A5                <1> 	rep	movsw	
   537                              <1> 	;
   538                              <1> 	; 23/02/2015
   539                              <1> 	; (P)ATA drive and LBA validation
   540                              <1> 	; (invalidating SATA drives and setting
   541                              <1> 	; CHS type I/O for old type fixed disks)
   542 00000215 5B                  <1> 	pop	bx
   543 00000216 8CC8                <1> 	mov	ax, cs
   544 00000218 8ED8                <1> 	mov	ds, ax
   545 0000021A 268B07              <1> 	mov	ax, [es:bx]
   546 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   547 00000220 7418                <1> 	je	short L11a
   548 00000222 3D7001              <1> 	cmp	ax, 170h
   549 00000225 7413                <1> 	je	short L11a
   550                              <1> 	; invalidation 
   551                              <1> 	; (because base port address is not 1F0h or 170h)
   552 00000227 30FF                <1> 	xor	bh, bh
   553 00000229 88D3                <1> 	mov	bl, dl
   554 0000022B 80EB80              <1> 	sub	bl, 80h
   555 0000022E C687[5E5D]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   556 00000233 808F[805D]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   557 00000238 EB14                <1> 	jmp	short L11b
   558                              <1> L11a:	
   559                              <1> 	; LBA validation
   560 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   561 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   562 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   563                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   564 00000242 28FF                <1> 	sub	bh, bh
   565 00000244 88D3                <1> 	mov	bl, dl
   566 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   567 00000249 80A7[805D]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   568                              <1> 				; bit 0 = LBA ready bit
   569                              <1> 	; 'diskio' procedure will check this bit !
   570                              <1> L11b:
   571 0000024E 3A16[5A5D]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   572 00000252 7307                <1>         jnb     short L13
   573 00000254 E9FFFE              <1>         jmp     L10
   574                              <1> L12:
   575                              <1> 	; Restore data registers
   576 00000257 8CC8                <1> 	mov	ax, cs
   577 00000259 8ED8                <1> 	mov	ds, ax	
   578                              <1> L13:
   579                              <1> 	; 13/12/2014
   580 0000025B 0E                  <1> 	push	cs
   581 0000025C 07                  <1> 	pop	es
   582                              <1> L14:
   583 0000025D B411                <1> 	mov 	ah, 11h
   584 0000025F CD16                <1> 	int 	16h
   585                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   586                              <1> 	; 02/01/2022
   587 00000261 7447                <1> 	jz	short L16
   588 00000263 B010                <1> 	mov	al, 10h
   589 00000265 CD16                <1> 	int 	16h
   590 00000267 EBF4                <1> 	jmp 	short L14
   591                              <1> L15:
   592                              <1> 
   593                              <1> ; //////
   594                              <1> 
   595                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   596                              <1> %if 0
   597                              <1> 	; 24/11/2014
   598                              <1> 	; 19/11/2014
   599                              <1> 	; 14/11/2014
   600                              <1> 	; Temporary code for disk searching code check
   601                              <1> 	;
   602                              <1> 	; This code will show existing (usable) drives and also
   603                              <1> 	; will show EDD interface support status for hard disks		
   604                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   605                              <1> 	; no need to get it again in protected mode...) 
   606                              <1> 	;	
   607                              <1> 	; 13/11/2014
   608                              <1> 	mov	bx, 7
   609                              <1> 	mov	ah, 0Eh
   610                              <1> 	mov	al, [fd0_type]
   611                              <1> 	and	al, al
   612                              <1> 	jz	short L15a
   613                              <1> 	mov	dl, al
   614                              <1> 	mov	al, 'F'
   615                              <1> 	int 	10h
   616                              <1> 	mov	al, 'D'
   617                              <1> 	int 	10h
   618                              <1> 	mov	al, '0'
   619                              <1> 	int 	10h
   620                              <1> 	mov	al, ' '
   621                              <1> 	int	10h
   622                              <1> 	call	L15c
   623                              <1> 	mov	al, ' '
   624                              <1> 	int	10h
   625                              <1> 	;
   626                              <1> 	mov	al, [fd1_type]
   627                              <1> 	and	al, al
   628                              <1> 	jz	short L15a
   629                              <1> 	mov	dl, al
   630                              <1> 	mov	al, 'F'
   631                              <1> 	int 	10h
   632                              <1> 	mov	al, 'D'
   633                              <1> 	int 	10h
   634                              <1> 	mov	al, '1'
   635                              <1> 	int 	10h
   636                              <1> 	mov	al, ' '
   637                              <1> 	int	10h
   638                              <1> 	call	L15c
   639                              <1> 	mov	al, ' '
   640                              <1> 	int	10h
   641                              <1> 	mov	al, ' '
   642                              <1> 	int	10h
   643                              <1> L15a:
   644                              <1> 	mov	al, [hd0_type]
   645                              <1> 	and	al, al
   646                              <1> 	jz	short L15b
   647                              <1> 	mov	dl, al
   648                              <1> 	mov	al, 'H'
   649                              <1> 	int 	10h
   650                              <1> 	mov	al, 'D'
   651                              <1> 	int 	10h
   652                              <1> 	mov	al, '0'
   653                              <1> 	int 	10h
   654                              <1> 	mov	al, ' '
   655                              <1> 	int 	10h
   656                              <1> 	call	L15c
   657                              <1> 	mov	al, ' '
   658                              <1> 	int	10h
   659                              <1> 	;
   660                              <1> 	mov	al, [hd1_type]
   661                              <1> 	and	al, al
   662                              <1> 	jz	short L15b
   663                              <1> 	mov	dl, al
   664                              <1> 	mov	al, 'H'
   665                              <1> 	int 	10h
   666                              <1> 	mov	al, 'D'
   667                              <1> 	int 	10h
   668                              <1> 	mov	al, '1'
   669                              <1> 	int 	10h
   670                              <1> 	mov	al, ' '
   671                              <1> 	int 	10h
   672                              <1> 	call	L15c
   673                              <1> 	mov	al, ' '
   674                              <1> 	int	10h
   675                              <1> 	;
   676                              <1> 	mov	al, [hd2_type]
   677                              <1> 	and	al, al
   678                              <1> 	jz	short L15b
   679                              <1> 	mov	dl, al
   680                              <1> 	mov	al, 'H'
   681                              <1> 	int 	10h
   682                              <1> 	mov	al, 'D'
   683                              <1> 	int 	10h
   684                              <1> 	mov	al, '2'
   685                              <1> 	int 	10h
   686                              <1> 	mov	al, ' '
   687                              <1> 	int 	10h
   688                              <1> 	call	L15c
   689                              <1> 	mov	al, ' '
   690                              <1> 	int	10h
   691                              <1> 	;
   692                              <1> 	mov	al, [hd3_type]
   693                              <1> 	and	al, al
   694                              <1> 	jz	short L15b
   695                              <1> 	mov	dl, al
   696                              <1> 	mov	al, 'H'
   697                              <1> 	int 	10h
   698                              <1> 	mov	al, 'D'
   699                              <1> 	int 	10h
   700                              <1> 	mov	al, '3'
   701                              <1> 	int 	10h
   702                              <1> 	mov	al, ' '
   703                              <1> 	int 	10h
   704                              <1> 	call	L15c
   705                              <1> 	mov	al, ' '
   706                              <1> 	int	10h
   707                              <1> 	;
   708                              <1> L15b:
   709                              <1> 	mov	al, 0Dh
   710                              <1> 	int 	10h	
   711                              <1> 	mov	al, 0Ah
   712                              <1> 	int 	10h
   713                              <1> 	;;xor	ah, ah
   714                              <1> 	;;int 	16h	
   715                              <1> 	;
   716                              <1>         ;jmp	L16  ; jmp short L16
   717                              <1>         ; 02/01/2022
   718                              <1> 	jmp	short L16
   719                              <1> 	;
   720                              <1> L15c:
   721                              <1> 	mov	dh, dl
   722                              <1> 	shr	dh, 4
   723                              <1> 	add	dh, 30h
   724                              <1> 	and	dl, 15
   725                              <1> 	add	dl, 30h
   726                              <1> 	mov	al, dh
   727                              <1> 	int	10h
   728                              <1> 	mov	al, dl
   729                              <1> 	int	10h
   730                              <1> 	retn
   731                              <1> 	;
   732                              <1> 	; end of temporary code for disk searching code check
   733                              <1> 
   734                              <1> %endif
   735                              <1> 
   736                              <1> ; //////
   737                              <1> 
   738                              <1> set_disk_parms:
   739                              <1> 	; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
   740                              <1> 	; 09/05/2022
   741                              <1> 	;	disksize = cylinders*spt*heads (*)
   742                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders)
   743                              <1> 	;
   744                              <1> 	; 04/02/2016 (ebx -> bx)
   745                              <1> 	; 10/07/2015
   746                              <1> 	; 14/01/2015
   747                              <1> 	;push	bx
   748 00000269 28FF                <1> 	sub	bh, bh
   749 0000026B 8A1E[595D]          <1> 	mov	bl, [drv]
   750 0000026F 80FB80              <1> 	cmp	bl, 80h
   751 00000272 7203                <1> 	jb	short sdp0
   752 00000274 80EB7E              <1> 	sub	bl, 7Eh
   753                              <1> sdp0:	
   754 00000277 81C3[7E5D]          <1> 	add	bx, drv.status
   755 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   756                              <1> 	;
   757 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   758 00000280 88CC                <1> 	mov	ah, cl ; 
   759 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   760 00000285 81EB[7E5D]          <1> 	sub	bx, drv.status
   761 00000289 D0E3                <1> 	shl	bl, 1
   762                              <1> 	; 12/07/2022
   763                              <1> 	;add	bx, drv.cylinders
   764 0000028B 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count
   765                              <1> 	;mov	[bx], ax
   766 0000028C 50                  <1> 	push	ax ; ** cylinders
   767                              <1> 	;sub	bx, drv.cylinders
   768                              <1> 	;add	bx, drv.heads
   769 0000028D 30E4                <1> 	xor	ah, ah
   770 0000028F 88F0                <1> 	mov	al, dh ; heads
   771 00000291 40                  <1> 	inc	ax
   772                              <1> 	;mov	[bx], ax
   773                              <1>         ;sub	bx, drv.heads
   774                              <1>         ;add	bx, drv.spt
   775 00000292 30ED                <1> 	xor	ch, ch
   776 00000294 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   777                              <1> 	;mov	[bx], cx
   778                              <1>         ;sub	bx, drv.spt
   779 00000297 D1E3                <1> 	shl	bx, 1
   780 00000299 81C3[625D]          <1> 	add	bx, drv.size ; disk size (in sectors)
   781                              <1> 	; LBA size = cylinders * heads * secpertrack
   782 0000029D F7E1                <1> 	mul	cx 
   783 0000029F 89C2                <1> 	mov	dx, ax	; heads*spt
   784 000002A1 58                  <1> 	pop	ax ; ** cylinders
   785                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   786                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   787 000002A2 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)
   788 000002A4 8907                <1> 	mov	[bx], ax
   789 000002A6 895702              <1> 	mov	[bx+2], dx
   790                              <1> 	;
   791                              <1> 	;pop	bx
   792 000002A9 C3                  <1> 	retn
   793                              <1> 
   794                              <1> ;align 2
   795                              <1> 
   796                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   797                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   798                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   799                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   800                              <1> 
   801                              <1> ;last_drv:
   802                              <1> ;	db  0
   803                              <1> ;drv_status:
   804                              <1> ;	db  0,0,0,0,0,0
   805                              <1> ;	db 0
   806                              <1> 
   807                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   808                              <1> 
   809                              <1> L16:
   238                                  
   239                                  	; 10/11/2014
   240 000002AA FA                           	cli	; Disable interrupts (clear interrupt flag)
   241                                  		; Reset Interrupt MASK Registers (Master&Slave)
   242                                  	;mov	al, 0FFh	; mask off all interrupts
   243                                  	;out	21h, al		; on master PIC (8259)
   244                                  	;jmp 	$+2  ; (delay)
   245                                  	;out	0A1h, al	; on slave PIC (8259)
   246                                  	;
   247                                  	; Disable NMI 
   248 000002AB B080                    	mov   	al, 80h 
   249 000002AD E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   250                                  	;23/02/2015
   251 000002AF 90                      	nop			;
   252                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   253                                  				; for preventing unknown state (!?)
   254                                  
   255                                  	; 02/01/2022
   256                                  	%define KERNELFSIZE KEND-KSTART 
   257                                  	;
   258                                   	; 20/08/2014
   259                                  	; Moving the kernel 64 KB back (to physical address 0)
   260                                  	; DS = CS = 1000h
   261                                  	; 05/11/2014
   262 000002B0 31C0                    	xor	ax, ax
   263 000002B2 8EC0                    	mov	es, ax ; ES = 0
   264                                  	;
   265                                  	;;mov	cx, (KEND - KLOAD)/4
   266                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   267 000002B4 B9E62F                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   268 000002B7 31F6                    	xor	si, si
   269 000002B9 31FF                    	xor	di, di
   270                                  	;rep	movsd
   271 000002BB F3A5                    	rep	movsw ; 02/01/2022
   272                                  	;
   273 000002BD 06                      	push	es ; 0
   274 000002BE 68[C202]                	push	L17
   275 000002C1 CB                      	retf
   276                                  	;
   277                                  L17:
   278                                  	; Turn off the floppy drive motor
   279 000002C2 BAF203                          mov     dx, 3F2h
   280 000002C5 EE                              out     dx, al ; 0 ; 31/12/2013
   281                                  
   282                                  	; Enable access to memory above one megabyte
   283                                  L18:
   284 000002C6 E464                    	in	al, 64h
   285 000002C8 A802                    	test	al, 2
   286 000002CA 75FA                            jnz     short L18
   287 000002CC B0D1                    	mov	al, 0D1h	; Write output port
   288 000002CE E664                    	out	64h, al
   289                                  L19:
   290 000002D0 E464                    	in	al, 64h
   291 000002D2 A802                    	test	al, 2
   292 000002D4 75FA                            jnz     short L19
   293 000002D6 B0DF                    	mov	al, 0DFh	; Enable A20 line
   294 000002D8 E660                    	out	60h, al
   295                                  ;L20:
   296                                  	;
   297                                  	; Load global descriptor table register
   298                                  
   299                                          ;mov     ax, cs
   300                                          ;mov     ds, ax
   301                                  
   302 000002DA 2E0F0116[805A]                  lgdt    [cs:gdtd]
   303                                  
   304 000002E0 0F20C0                          mov     eax, cr0
   305                                  	; or 	eax, 1
   306 000002E3 40                      	inc     ax
   307 000002E4 0F22C0                  	mov     cr0, eax
   308                                  
   309                                  	; Jump to 32 bit code
   310                                  	
   311 000002E7 66                      	db 66h 			; Prefix for 32-bit
   312 000002E8 EA                      	db 0EAh 		; Opcode for far jump
   313 000002E9 [EF020000]              	dd StartPM 		; Offset to start, 32-bit
   314                                  				; (1000h:StartPM = StartPM + 10000h)
   315 000002ED 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   316                                  				; assuming that StartPM resides in code32
   317                                  
   318                                  [BITS 32] 
   319                                  
   320                                  StartPM:
   321                                  	; Kernel Base Address = 0 ; 30/12/2013
   322 000002EF 66B81000                	mov ax, KDATA           ; Save data segment identifier
   323 000002F3 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   324 000002F5 8EC0                           	mov es, ax              ; Move data segment into ES register
   325 000002F7 8EE0                           	mov fs, ax              ; Move data segment into FS register
   326 000002F9 8EE8                          	mov gs, ax              ; Move data segment into GS register
   327 000002FB 8ED0                            mov ss, ax              ; Move data segment into SS register
   328 000002FD BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   329                                  
   330                                  clear_bss: ; Clear uninitialized data area
   331                                  	; 11/03/2015
   332 00000302 31C0                    	xor	eax, eax ; 0
   333                                  	;mov	ecx, (bss_end - bss_start)/4
   334                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   335                                  	; 02/01/2022
   336 00000304 B9C1060000              	mov	ecx, BSS_SIZE/4
   337 00000309 BF[D05F0000]            	mov	edi, bss_start
   338 0000030E F3AB                    	rep	stosd  		
   339                                  
   340                                  memory_init:
   341                                  	; Initialize memory allocation table and page tables
   342                                  	;
   343                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   344                                  	; 16/11/2014
   345                                  	; 15/11/2014
   346                                  	; 07/11/2014
   347                                  	; 06/11/2014
   348                                  	; 05/11/2014
   349                                  	; 04/11/2014
   350                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   351                                  	;
   352                                  ;	xor	eax, eax
   353                                  ;	xor 	ecx, ecx
   354 00000310 B108                    	mov	cl, 8
   355 00000312 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   356 00000317 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   357                                  				   ; for the first 1 MB memory
   358                                  	;
   359 00000319 8B0D[C45F0000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   360                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   361                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   362                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   363 0000031F C1E902                  	shr	ecx, 2	; 02/01/2022
   364 00000322 890D[40620000]          	mov	[free_pages], ecx
   365 00000328 8B15[C85F0000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   366                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   367                                  				   ; between 16 MB and 4 GB.
   368                                  	;or	dx, dx
   369 0000032E 09D2                    	or	edx, edx ; 02/01/2022
   370 00000330 7412                    	jz	short mi_0
   371                                  	;
   372                                  	;mov	ax, dx
   373 00000332 89D0                    	mov	eax, edx ; 02/01/2022
   374 00000334 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   375 00000337 0105[40620000]          	add	[free_pages], eax
   376 0000033D 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   377 00000342 EB06                    	jmp	short mi_1
   378                                  mi_0:
   379                                  	;mov	ax, cx
   380 00000344 89C8                    	mov	eax, ecx ; 02/01/2022	 
   381 00000346 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   382                                  mi_1:
   383 0000034A A3[3C620000]            	mov	[memory_size], eax ; Total available memory in pages
   384                                  				   ; 1 alloc. tbl. bit = 1 memory page
   385                                  				   ; 32 allocation bits = 32 mem. pages
   386                                  	;
   387 0000034F 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   388 00000354 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   389                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   390                                  				   ;  --> x M.A.T. pages, if y = 0
   391                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   392 00000357 A3[50620000]            	mov	[mat_size], eax ; 02/01/2022
   393 0000035C C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   394                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   395 0000035F 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   396                                  	; Set/Calculate Kernel's Page Directory Address
   397 00000361 81C300001000            	add	ebx, MEM_ALLOC_TBL
   398 00000367 891D[38620000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   399                                  				   ; just after the last M.A.T. page
   400                                  	;
   401 0000036D 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   402 00000370 A3[48620000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   403                                  	;			   ; (allocation status search must be
   404                                  				   ; stopped after here)
   405 00000375 31C0                    	xor	eax, eax
   406 00000377 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   407                                  	;push	cx
   408 00000378 51                      	push	ecx ; 02/01/2022 
   409 00000379 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   410                                  				   ; count of 32 allocation bits
   411 0000037C F3AB                    	rep	stosd
   412                                  	;pop	cx
   413 0000037E 59                      	pop	ecx ; 02/01/2022
   414 0000037F 40                      	inc	eax		   ; 0
   415 00000380 80E11F                  	and	cl, 31		   ; remain bits
   416 00000383 7412                    	jz	short mi_4
   417 00000385 8907                    	mov	[edi], eax	   ; reset
   418                                  mi_2:
   419 00000387 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   420 0000038A FEC9                    	dec	cl
   421 0000038C 7404                    	jz	short mi_3
   422 0000038E FEC0                    	inc	al
   423 00000390 EBF5                    	jmp	short mi_2
   424                                  mi_3:
   425 00000392 28C0                    	sub	al, al	   	   ; 0
   426 00000394 83C704                  	add	edi, 4		   ; 15/11/2014
   427                                  mi_4:
   428 00000397 09D2                    	or	edx, edx ; 02/01/2022
   429                                  	;or	dx, dx		  ; check 16M to 4G memory space
   430 00000399 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   431                                  	;	
   432 0000039B B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   433                                  	;	
   434 000003A0 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   435 000003A2 7405                    	jz	short mi_5	  ; jump if EDI points to 
   436                                  				  ;         end of first 16 MB	
   437                                  	;shr	ecx, 1		  ; convert to dword count
   438                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   439 000003A4 C1E902                  	shr	ecx, 2	; 02/01/2022
   440 000003A7 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   441                                  				  ; (memory hole under 16 MB)
   442                                  mi_5:
   443 000003A9 89D1                    	mov	ecx, edx ; 02/01/2022
   444                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   445 000003AB D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   446 000003AD 9C                      	pushf			  ; 16/11/2014		
   447 000003AE 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   448 000003AF F3AB                    	rep	stosd
   449 000003B1 40                      	inc	eax		  ; 0
   450 000003B2 9D                      	popf			  ; 16/11/2014
   451 000003B3 7305                    	jnc	short mi_6
   452 000003B5 6648                    	dec	ax		  ; eax = 0000FFFFh
   453 000003B7 AB                      	stosd
   454 000003B8 6640                    	inc	ax		  ; 0		
   455                                  mi_6:
   456 000003BA 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   457 000003BC 7309                    	jnb	short mi_7	  ; end of memory allocation table
   458                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   459 000003BE 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   460 000003C0 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   461                                  	;shr	ecx, 1		  ; to dword count
   462                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   463 000003C2 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   464 000003C5 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   465                                  mi_7:
   466                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   467 000003C7 BA00001000              	mov	edx, MEM_ALLOC_TBL
   468                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   469                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   470 000003CC 8B0D[50620000]          	mov	ecx, [mat_size] ; 02/01/2022
   471                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   472 000003D2 89D7                    	mov	edi, edx
   473 000003D4 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   474                                  				  ; byte offset in M.A.T.
   475                                  				  ; (1 M.A.T. byte points to 
   476                                  				  ;	      32768 bytes)
   477                                  				  ; Note: MEM_ALLOC_TBL address 
   478                                  				  ; must be aligned on 128 KB 
   479                                  				  ; boundary!
   480 000003D7 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   481                                  	; eax = 0
   482 000003D9 290D[40620000]          	sub	[free_pages], ecx ; 07/11/2014
   483                                  mi_8:
   484 000003DF 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   485                                  	;dec	bl
   486 000003E2 FEC9                    	dec	cl
   487 000003E4 7404                    	jz	short mi_9
   488 000003E6 FEC0                    	inc	al
   489 000003E8 EBF5                    	jmp	short mi_8
   490                                  mi_9:
   491                                  	;
   492                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   493                                  	;		(allocate pages for system page tables)
   494                                  
   495                                  	; edx = MEM_ALLOC_TBL
   496 000003EA 8B0D[3C620000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   497 000003F0 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   498 000003F6 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   499                                  				 ; page table count (PDE count)
   500                                  	;
   501 000003F9 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   502                                  	;
   503 000003FA 41                      	inc	ecx		 ; +1 for kernel page directory	
   504                                  	;
   505 000003FB 290D[40620000]          	sub	[free_pages], ecx ; 07/11/2014
   506                                  	;
   507 00000401 8B35[38620000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   508 00000407 C1EE0C                  	shr	esi, 12		 ; convert to page number
   509                                  mi_10:
   510 0000040A 89F0                    	mov	eax, esi	 ; allocation bit offset
   511 0000040C 89C3                    	mov	ebx, eax
   512 0000040E C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   513 00000411 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   514                                  				 ;   to align on dword boundary
   515 00000414 83E01F                  	and	eax, 31		 ; set allocation bit position 
   516                                  				 ;  (bit 0 to bit 31)
   517                                  	;
   518 00000417 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   519                                  	;
   520 00000419 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   521                                  	;
   522 0000041C 46                      	inc	esi		 ; next page table
   523 0000041D E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   524                                  				 ; (ecx = page table count + 1)
   525                                  	;
   526 0000041F 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   527                                  	;
   528                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   529                                  	;
   530                                  	; Initialize Kernel's Page Directory
   531 00000420 8B3D[38620000]          	mov	edi, [k_page_dir]
   532 00000426 89F8                    	mov	eax, edi
   533 00000428 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   534                                  		     	      ; supervisor + read&write + present
   535 0000042A 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   536                                  mi_11:
   537 0000042C 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   538                                  			        ; EAX points to next page table
   539 00000431 AB                      	stosd
   540 00000432 E2F8                    	loop	mi_11
   541 00000434 29C0                    	sub	eax, eax	; Empty PDE
   542                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   543                                  	; 02/01/2022
   544 00000436 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   545 00000438 29D1                    	sub	ecx, edx
   546 0000043A 7402                    	jz	short mi_12
   547 0000043C F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   548                                  	;
   549                                  	; Initialization of Kernel's Page Directory is OK, here.
   550                                  mi_12:
   551                                  	; Initialize Kernel's Page Tables
   552                                  	;
   553                                  	; (EDI points to address of page table 0)
   554                                  	; eax = 0
   555 0000043E 8B0D[3C620000]          	mov	ecx, [memory_size] ; memory size in pages
   556 00000444 89CA                    	mov	edx, ecx	; (***)
   557 00000446 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   558                                  			     ; supervisor + read&write + present
   559                                  mi_13:
   560 00000448 AB                      	stosd
   561 00000449 0500100000              	add	eax, 4096	
   562 0000044E E2F8                    	loop	mi_13
   563                                  	; 02/01/2022
   564 00000450 66B9FF03                	mov	cx, 1023
   565 00000454 21CA                    	and	edx, ecx
   566                                  	;and	dx, 1023	; (***)
   567 00000456 7407                    	jz	short mi_14
   568                                  	;mov	cx, 1024	
   569                                  	; 02/01/2022
   570                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   571 00000458 41                      	inc	ecx ; ecx = 1024
   572 00000459 29D1                    	sub	ecx, edx
   573                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   574 0000045B 31C0                    	xor	eax, eax
   575 0000045D F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   576                                  				; of the last page table
   577                                  mi_14:
   578                                  	;  Initialization of Kernel's Page Tables is OK, here.
   579                                  	;
   580 0000045F 89F8                    	mov	eax, edi	; end of the last page table page
   581                                  			        ; (beginging of user space pages)
   582 00000461 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   583 00000464 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   584                                  				; aligning on dword boundary
   585                                  	 
   586 00000466 A3[4C620000]            	mov	[first_page], eax
   587 0000046B A3[44620000]            	mov	[next_page], eax ; The first free page pointer
   588                                  				 ; for user programs
   589                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   590                                  	;
   591                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   592                                  	;
   593                                  	
   594                                  	; Enable paging
   595                                  	;
   596 00000470 A1[38620000]                    mov     eax, [k_page_dir]
   597 00000475 0F22D8                  	mov	cr3, eax
   598 00000478 0F20C0                  	mov	eax, cr0
   599 0000047B 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   600 00000480 0F22C0                  	mov	cr0, eax
   601                                          ;jmp    KCODE:StartPMP
   602                                  
   603 00000483 EA                      	db 0EAh 		; Opcode for far jump
   604 00000484 [8A040000]                      dd StartPMP		; 32 bit offset
   605 00000488 0800                    	dw KCODE		; kernel code segment descriptor
   606                                  
   607                                  StartPMP:
   608                                  	; 06/11//2014
   609                                  	; Clear video page 0
   610                                  	;
   611                                  	; Temporary Code
   612                                  	;
   613                                  	;mov	ecx, 80*25/2
   614 0000048A 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   615 0000048E BF00800B00              	mov	edi, 0B8000h
   616 00000493 57                      	push	edi ; * ; 02/01/2022
   617 00000494 31C0                    	xor	eax, eax	; black background, black fore color
   618 00000496 F3AB                    	rep	stosd
   619                                  	
   620                                  	; 19/08/2014
   621                                  	; Kernel Base Address = 0
   622                                  	; It is mapped to (physically) 0 in the page table.
   623                                  	; So, here is exactly 'StartPMP' address.
   624                                  	;
   625                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   626                                  	;;mov	esi, msgPM
   627                                  	;; 14/08/2015 (kernel version message will appear
   628                                  	;;	       when protected mode and paging is enabled)
   629 00000498 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   630 0000049A BE[945D0000]            	mov	esi, msgKVER
   631 0000049F 5F                      	pop	edi ; * ; 02/01/2022
   632                                  	;mov	edi, 0B8000h ; 27/08/2014
   633                                  	; 20/08/2014
   634 000004A0 E891010000              	call	printk
   635                                  
   636                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   637                                  	; // Set IRQ offsets
   638                                  	;
   639                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   640                                  	;
   641                                  					;; ICW1
   642 000004A5 B011                    	mov	al, 11h			; Initialization sequence
   643 000004A7 E620                    	out	20h, al			; 	8259A-1
   644                                  	; jmp 	$+2
   645 000004A9 E6A0                    	out	0A0h, al		; 	8259A-2
   646                                  					;; ICW2
   647 000004AB B020                    	mov	al, 20h			; Start of hardware ints (20h)
   648 000004AD E621                    	out	21h, al			;	for 8259A-1
   649                                  	; jmp 	$+2
   650 000004AF B028                    	mov	al, 28h			; Start of hardware ints (28h)
   651 000004B1 E6A1                    	out	0A1h, al		; 	for 8259A-2
   652                                  					;
   653 000004B3 B004                    	mov	al, 04h			;; ICW3
   654 000004B5 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   655                                  	; jmp 	$+2
   656 000004B7 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   657 000004B9 E6A1                    	out	0A1h, al		;
   658                                  					;; ICW4
   659 000004BB B001                    	mov	al, 01h	 		;
   660 000004BD E621                    	out	21h, al			; 	8086 mode, normal EOI	
   661                                  	; jmp 	$+2
   662 000004BF E6A1                    	out	0A1h, al		;	for both chips.
   663                                  
   664                                  	;mov	al, 0FFh	; mask off all interrupts for now
   665                                  	;out	21h, al
   666                                  	;; jmp 	$+2
   667                                  	;out	0A1h, al
   668                                  
   669                                  	; 02/04/2015
   670                                  	; 26/03/2015 System call (INT 30h) modification
   671                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   672                                  	;
   673                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   674                                  	;  setup_idt:
   675                                  	;
   676                                          ;; 16/02/2015
   677                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   678                                  	; 21/08/2014 (timer_int)
   679 000004C1 BE[8C5A0000]            	mov	esi, ilist
   680 000004C6 8D3D[D05F0000]          	lea	edi, [idt]
   681                                  	; 26/03/2015
   682 000004CC B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   683                                  	; 02/04/2015
   684 000004D1 BB00000800              	mov	ebx,  80000h
   685                                  rp_sidt1:
   686 000004D6 AD                      	lodsd
   687 000004D7 89C2                    	mov	edx, eax
   688 000004D9 66BA008E                	mov	dx, 8E00h
   689 000004DD 6689C3                  	mov	bx, ax
   690 000004E0 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   691                                         			        ; /* interrupt gate - dpl=0, present */
   692 000004E2 AB                      	stosd	; selector & offset bits 0-15 	
   693 000004E3 89D0                    	mov	eax, edx
   694 000004E5 AB                      	stosd	; attributes & offset bits 16-23
   695 000004E6 E2EE                    	loop	rp_sidt1
   696 000004E8 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   697                                  rp_sidt2:
   698 000004EA AD                      	lodsd
   699 000004EB 21C0                    	and	eax, eax
   700 000004ED 7413                    	jz	short rp_sidt3
   701 000004EF 89C2                    	mov	edx, eax
   702 000004F1 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   703 000004F5 6689C3                  	mov	bx, ax
   704 000004F8 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   705 000004FA AB                      	stosd
   706 000004FB 89D0                    	mov	eax, edx
   707 000004FD AB                      	stosd
   708 000004FE E2EA                    	loop	rp_sidt2
   709 00000500 EB16                    	jmp	short sidt_OK
   710                                  rp_sidt3:
   711 00000502 B8[5A090000]            	mov	eax, ignore_int
   712 00000507 89C2                    	mov	edx, eax
   713 00000509 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   714 0000050D 6689C3                  	mov	bx, ax
   715 00000510 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   716                                  rp_sidt4:
   717 00000512 AB                      	stosd
   718 00000513 92                      	xchg	eax, edx
   719 00000514 AB                      	stosd
   720 00000515 92                      	xchg	edx, eax
   721 00000516 E2FA                    	loop	rp_sidt4
   722                                  sidt_OK: 
   723 00000518 0F011D[865A0000]        	lidt 	[idtd]
   724                                  	;
   725                                  	; TSS descriptor setup ; 24/03/2015
   726 0000051F B8[D0610000]            	mov	eax, task_state_segment
   727 00000524 66A3[7A5A0000]          	mov	[gdt_tss0], ax
   728 0000052A C1C010                  	rol	eax, 16
   729 0000052D A2[7C5A0000]            	mov	[gdt_tss1], al
   730 00000532 8825[7F5A0000]          	mov	[gdt_tss2], ah
   731 00000538 66C705[36620000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   731 00000540 00                 
   732                                  		; 
   733                                  		; IO Map Base address (When this address points
   734                                  		; to end of the TSS, CPU does not use IO port 
   735                                  		; permission bit map for RING 3 IO permissions, 
   736                                  		; access to any IO ports in ring 3 will be forbidden.)
   737                                   		;
   738                                  	;mov	[tss.esp0], esp ; TSS offset 4
   739                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   740 00000541 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   741                                  			 ; occurs (or a system call -software INT- is requested)
   742                                  			 ; while cpu running in ring 3 (in user mode).				
   743                                  			 ; (Kernel stack pointer and segment will be loaded
   744                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   745 00000545 0F00D8                  	ltr	ax  ; Load task register
   746                                  	;
   747                                  esp0_set0:
   748                                  	; 30/07/2015
   749 00000548 8B0D[3C620000]          	mov 	ecx, [memory_size] ; memory size in pages
   750 0000054E C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   751 00000551 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   752                                  			  ; (kernel mode virtual address)
   753 00000557 7605                    	jna	short esp0_set1
   754                                  	;
   755                                  	; If available memory > CORE (end of the 1st 4 MB)
   756                                  	; set stack pointer to CORE
   757                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   758                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   759 00000559 B900004000              	mov	ecx, CORE
   760                                  esp0_set1:
   761 0000055E 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   762                                  esp0_set_ok:
   763                                  	; 30/07/2015 (**tss.esp0**) 
   764 00000560 8925[D4610000]          	mov	[tss.esp0], esp
   765 00000566 66C705[D8610000]10-             mov     word [tss.ss0], KDATA
   765 0000056E 00                 
   766                                  	; 14/08/2015
   767                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   768                                  	;
   769                                  	;cli	; Disable interrupts (for CPU)
   770                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   771                                  	;
   772 0000056F 30C0                    	xor	al, al		; Enable all hardware interrupts!
   773 00000571 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   774 00000573 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   775 00000575 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   776                                  				; (Even if related hardware component
   777                                  				;  does not exist!)
   778                                  	; Enable NMI 
   779 00000577 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   780 00000579 E670                    	out  	70h, al
   781                                  	; 23/02/2015
   782 0000057B 90                      	nop
   783 0000057C E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   784                                  				; for preventing unknown state (!?)
   785                                  	;
   786                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   787                                  	;
   788                                  	; 02/09/2014
   789                                  	;xor	bx, bx
   790                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   791                                  	; 27/02/2022	
   792 0000057E 31DB                    	xor	ebx, ebx
   793 00000580 31D2                    	xor	edx, edx
   794 00000582 B602                    	mov	dh, 2
   795 00000584 E8230F0000              	call	set_cpos
   796                                  	;
   797                                  	; 06/11/2014
   798                                  	; Temporary Code
   799                                  	;
   800 00000589 E898100000              	call	memory_info
   801                                  	; 14/08/2015
   802                                  	;call getch ; 28/02/2015
   803                                  drv_init:
   804 0000058E FB                      	sti	; Enable Interrupts 
   805                                  	; 06/02/2015
   806 0000058F 8B15[5E5D0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   807 00000595 668B1D[5C5D0000]        	mov	bx, [fd0_type] ; fd0, fd1
   808                                  	; 22/02/2015
   809 0000059C 6621DB                  	and	bx, bx
   810 0000059F 751B                    	jnz	short di1
   811                                  	;
   812 000005A1 09D2                    	or 	edx, edx
   813 000005A3 7529                    	jnz	short di2
   814                                  	;
   815                                  setup_error:
   816 000005A5 BE[7D5E0000]            	mov 	esi, setup_error_msg
   817                                  psem:	
   818 000005AA AC                      	lodsb
   819 000005AB 08C0                    	or	al, al
   820                                  	;jz	short haltx ; 22/02/2015
   821 000005AD 7426                    	jz	short di3
   822 000005AF 56                      	push	esi
   823 000005B0 31DB                    	xor	ebx, ebx ; 0
   824                                  			; Video page 0 (bl=0)
   825 000005B2 B407                    	mov	ah, 07h ; Black background, 
   826                                  			; light gray forecolor
   827 000005B4 E8E90D0000              	call	write_tty
   828 000005B9 5E                      	pop	esi
   829 000005BA EBEE                    	jmp	short psem
   830                                  
   831                                  di1:
   832                                  	; supress 'jmp short T6'
   833                                  	;  (activate fdc motor control code)
   834 000005BC 66C705[B7060000]90-     	mov	word [T5], 9090h ; nop
   834 000005C4 90                 
   835                                  	;
   836                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   837                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   838                                  	;stosw
   839                                  	;mov 	ax, cs
   840                                  	;stosw
   841                                  	;; 16/02/2015
   842                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   843                                  	;
   844 000005C5 E8021A0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   845                                  	;
   846 000005CA 09D2                    	or	edx, edx
   847 000005CC 7407                            jz      short di3
   848                                  di2:
   849 000005CE E82B1A0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   850 000005D3 72D0                            jc      short setup_error
   851                                  di3:
   852 000005D5 E820100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   853                                  	;
   854 000005DA E8C0530000              	call	display_disks ; 07/03/2015  (Temporary)
   855                                  ;haltx:
   856                                  	; 14/08/2015
   857                                  	;call	getch ; 22/02/2015
   858 000005DF FB                      	sti	; Enable interrupts (for CPU)
   859                                  	; 14/08/2015
   860                                  	;mov 	ecx, 0FFFFFFFh
   861                                  	; 24/12/2021
   862 000005E0 B9FFFF2F00              	mov 	ecx, 02FFFFFh
   863                                  md_info_msg_wait:
   864 000005E5 51                      	push 	ecx
   865 000005E6 B001                    	mov	al, 1
   866 000005E8 8A25[66620000]          	mov 	ah, [ptty] ; active (current) video page
   867 000005EE E897500000              	call	getc_n
   868 000005F3 59                      	pop	ecx
   869 000005F4 7502                    	jnz	short md_info_msg_ok
   870 000005F6 E2ED                    	loop	md_info_msg_wait
   871                                  md_info_msg_ok:
   872                                  	; 30/06/2015
   873 000005F8 E8BF230000              	call	sys_init
   874                                  	;
   875                                  	;jmp 	cpu_reset ; 22/02/2015
   876                                  hang:
   877                                  	; 24/12/2021
   878 000005FD 29C0                    	sub	eax, eax
   879                                  _hang:	
   880                                  	; 23/02/2015
   881                                  	;sti			; Enable interrupts
   882 000005FF F4                      	hlt
   883                                  	;
   884                                  	;nop
   885                                  	;; 03/12/2014
   886                                  	;; 28/08/2014
   887                                  	;mov	ah, 11h
   888                                  	;call	getc
   889                                  	;jz      _c8
   890                                  	;
   891                                  	; 23/02/2015
   892                                  	; 06/02/2015
   893                                  	; 07/09/2014
   894 00000600 31DB                    	xor	ebx, ebx
   895 00000602 8A1D[66620000]          	mov	bl, [ptty]	; active_page
   896 00000608 89DE                    	mov	esi, ebx
   897                                  	;shl 	si, 1
   898                                  	; 17/07/2022
   899 0000060A D1E6                    	shl	esi, 1
   900 0000060C 81C6[68620000]          	add	esi, ttychr
   901 00000612 668B06                  	mov	ax, [esi]
   902                                  	;and	ax, ax
   903                                  	;;jz	short _c8
   904                                  	;jz	short hang
   905                                  	; 24/12/2021
   906 00000615 21C0                    	and	eax, eax
   907 00000617 74E6                    	jz	short _hang
   908 00000619 66C7060000              	mov	word [esi], 0
   909 0000061E 80FB03                  	cmp	bl, 3		; Video page 3
   910                                  	;jb	short _c8
   911 00000621 72DA                    	jb	short hang
   912                                  	;	
   913                                  	; 02/09/2014
   914 00000623 B40E                    	mov	ah, 0Eh		; Yellow character 
   915                                  				; on black background
   916                                  	; 24/12/2021 (32 bit reg push-pop)
   917                                  	; 07/09/2014
   918                                  nxtl:
   919 00000625 53                      	push	ebx
   920                                  	;
   921                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   922                                  				; bh = 0 (video mode)
   923                                  				; Retro UNIX 386 v1 - Video Mode 0
   924                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   925 00000626 50                      	push	eax
   926 00000627 E8760D0000              	call 	write_tty
   927 0000062C 58                      	pop	eax
   928                                  	;pop	bx
   929 0000062D 5B                      	pop	ebx
   930 0000062E 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   931                                  	;jne	short _c8
   932 00000630 75CB                    	jne	short hang
   933 00000632 B00A                    	mov	al, 0Ah		; next line
   934 00000634 EBEF                    	jmp	short nxtl
   935                                  	
   936                                  ;_c8:
   937                                  ;	; 25/08/2014
   938                                  ;	cli			; Disable interrupts
   939                                  ;	mov	al, [scounter + 1]
   940                                  ;	and	al, al
   941                                  ;	jnz	hang
   942                                  ;	call	rtc_p
   943                                  ;	jmp     hang
   944                                  
   945                                  
   946                                  	; 27/08/2014
   947                                  	; 20/08/2014
   948                                  printk:
   949                                          ;mov    edi, [scr_row]
   950                                  pkl:
   951 00000636 AC                      	lodsb
   952 00000637 08C0                    	or 	al, al
   953 00000639 7404                    	jz	short pkr
   954 0000063B 66AB                    	stosw
   955 0000063D EBF7                    	jmp	short pkl
   956                                  pkr:
   957 0000063F C3                      	retn
   958                                  
   959                                  ; 25/07/2015
   960                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   961                                  ; 17/02/2015
   962                                  ; 06/02/2015 (unix386.s)
   963                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   964                                  ;
   965                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   966                                  ;
   967                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   968                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   969                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   970                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   971                                  ;									       :
   972                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   973                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   974                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   975                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   976                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   977                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   978                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   979                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   980                                  ;-------------------------------------------------------------------------------
   981                                  ;
   982                                  
   983                                  timer_int:	; IRQ 0
   984                                  ;int_08h:	; Timer
   985                                  	; 14/10/2015
   986                                  	; Here, we are simulating system call entry (for task switch)
   987                                  	; (If multitasking is enabled, 
   988                                  	; 'clock' procedure may jump to 'sysrelease')
   989 00000640 1E                      	push	ds
   990 00000641 06                      	push	es
   991 00000642 0FA0                    	push	fs
   992 00000644 0FA8                    	push	gs
   993 00000646 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   994 00000647 66B91000                	mov     cx, KDATA
   995 0000064B 8ED9                            mov     ds, cx
   996 0000064D 8EC1                            mov     es, cx
   997 0000064F 8EE1                            mov     fs, cx
   998 00000651 8EE9                            mov     gs, cx
   999                                  	;
  1000 00000653 0F20D9                  	mov	ecx, cr3
  1001 00000656 890D[F9060000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
  1002                                  	;
  1003 0000065C 3B0D[38620000]          	cmp 	ecx, [k_page_dir]
  1004 00000662 741F                    	je	short T3
  1005                                  	;
  1006                                  	; timer interrupt has been occurred while OS is in user mode
  1007 00000664 A3[FC650000]            	mov 	[u.r0], eax
  1008 00000669 89E1                    	mov	ecx, esp
  1009 0000066B 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
  1010 0000066E 890D[F4650000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
  1011 00000674 8925[F8650000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
  1012                                  	;
  1013 0000067A 8B0D[38620000]          	mov	ecx, [k_page_dir]
  1014 00000680 0F22D9                  	mov	cr3, ecx
  1015                                  T3:
  1016 00000683 FB                      	sti				; INTERRUPTS BACK ON
  1017 00000684 66FF05[B4620000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
  1018 0000068B 7507                    	JNZ	short T4		; GO TO TEST_DAY
  1019 0000068D 66FF05[B6620000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
  1020                                  T4:					; TEST_DAY
  1021 00000694 66833D[B6620000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
  1022 0000069C 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1023 0000069E 66813D[B4620000]B0-     	CMP	word [TIMER_LOW],0B0H
  1023 000006A6 00                 
  1024 000006A7 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1025                                  
  1026                                  ;-----	TIMER HAS GONE 24 HOURS
  1027                                  	;;SUB	AX,AX
  1028                                  	;MOV	[TIMER_HIGH],AX
  1029                                  	;MOV	[TIMER_LOW],AX
  1030 000006A9 29C0                    	sub	eax, eax
  1031 000006AB A3[B4620000]            	mov	[TIMER_LH], eax
  1032                                  	;	
  1033 000006B0 C605[B8620000]01        	MOV	byte [TIMER_OFL],1
  1034                                  
  1035                                  ;-----	TEST FOR DISKETTE TIME OUT
  1036                                  
  1037                                  T5:
  1038                                  	; 23/12/2014
  1039 000006B7 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1040                                  					; (9090h) if a floppy disk
  1041                                  					; is detected.
  1042                                  	;mov	al,[CS:MOTOR_COUNT]
  1043 000006B9 A0[BB620000]            	mov	al, [MOTOR_COUNT]
  1044 000006BE FEC8                    	dec	al
  1045                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1046 000006C0 A2[BB620000]            	mov	[MOTOR_COUNT], al
  1047                                  	;mov	[ORG_MOTOR_COUNT], al
  1048 000006C5 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1049 000006C7 B0F0                    	mov 	al,0F0h
  1050                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1051 000006C9 2005[BA620000]          	and	[MOTOR_STATUS], al
  1052                                  	;and	[ORG_MOTOR_STATUS], al
  1053 000006CF B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1054                                  					; bit 2 = enable controller
  1055                                  					;	1 = normal operation
  1056                                  					;	0 = reset	
  1057                                  					; bit 0, 1 = drive select
  1058                                  					; bit 4-7 = motor running bits 
  1059 000006D1 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1060 000006D5 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1061                                  T6:	
  1062                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1063                                  					; TIMER TICK INTERRUPT
  1064                                  	;;inc	word [wait_count] ;;27/02/2015
  1065                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1066                                  	;;;;cli
  1067                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1068 000006D6 FF15[F1060000]          	call	[x_timer] ; 14/05/2015
  1069                                  T7:
  1070                                  	; 14/10/2015
  1071 000006DC B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1072 000006DE FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1073 000006DF E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1074                                  	;
  1075 000006E1 A1[F9060000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1076 000006E6 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1077                                  	;
  1078 000006E9 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1079                                  	;
  1080 000006EA 0FA9                    	pop	gs
  1081 000006EC 0FA1                    	pop	fs
  1082 000006EE 07                      	pop	es
  1083 000006EF 1F                      	pop	ds
  1084 000006F0 CF                      	iretd	; return from interrupt
  1085                                  
  1086                                  
  1087                                  ; ////////////////
  1088                                  
  1089                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1090                                  x_timer:
  1091 000006F1 [FD060000]              	dd 	u_timer			; 14/05/2015
  1092                                  	;dd	clock
  1093                                  
  1094                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1095                                  x_rtci:
  1096 000006F5 [330A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1097                                  
  1098                                  ; 14/10/2015
  1099 000006F9 00000000                cr3reg: dd 0
  1100                                  
  1101                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1102                                  	; 06/02/2015
  1103                                  	; 07/09/2014
  1104                                  	; 21/08/2014
  1105                                  u_timer:
  1106                                  ;timer_int:	; IRQ 0
  1107                                  	; 06/02/2015
  1108                                  	;push	eax
  1109                                  	;push	edx
  1110                                  	;push	ecx
  1111                                  	;push	ebx
  1112                                  	;push	ds
  1113                                  	;push	es
  1114                                  	;mov	eax, KDATA
  1115                                  	;mov	ds, ax
  1116                                  	;mov	es, ax
  1117 000006FD FF05[7C620000]          	inc	dword [tcount]
  1118 00000703 BB[065E0000]            	mov	ebx, tcountstr + 4
  1119                                  	;mov	ax, [tcount]
  1120                                  	; 24/12/2021
  1121 00000708 A1[7C620000]            	mov	eax, [tcount]
  1122 0000070D B90A000000              	mov	ecx, 10
  1123                                  rp_divtcnt:
  1124 00000712 31D2                    	xor	edx, edx
  1125 00000714 F7F1                    	div	ecx
  1126 00000716 80C230                  	add	dl, 30h
  1127 00000719 8813                    	mov	[ebx], dl
  1128                                  	;or	ax, ax
  1129                                  	; 24/12/2021
  1130 0000071B 09C0                    	or	eax, eax
  1131 0000071D 7403                    	jz	short print_lzero
  1132 0000071F 4B                      	dec	ebx
  1133 00000720 EBF0                    	jmp	short rp_divtcnt
  1134                                  print_lzero:
  1135 00000722 81FB[025E0000]          	cmp	ebx, tcountstr
  1136 00000728 7606                    	jna	short print_tcount
  1137 0000072A 4B                      	dec	ebx
  1138 0000072B C60330                   	mov	byte [ebx], 30h
  1139 0000072E EBF2                    	jmp	short print_lzero
  1140                                  print_tcount:
  1141 00000730 56                      	push	esi
  1142 00000731 57                      	push	edi
  1143 00000732 BE[DE5D0000]            	mov	esi, timer_msg ; Timer interrupt message
  1144                                  	; 07/09/2014
  1145                                  	;mov	bx, 1	; Video page 1
  1146                                  	; 24/12/2021
  1147 00000737 29DB                    	sub	ebx, ebx
  1148                                  	;inc	bl ; ebx = 1
  1149                                  	; 02/01/2022
  1150 00000739 B306                    	mov	bl, 6	; Video page 6
  1151                                  ptmsg:
  1152 0000073B AC                      	lodsb
  1153 0000073C 08C0                    	or	al, al
  1154 0000073E 740D                    	jz	short ptmsg_ok
  1155 00000740 56                      	push	esi
  1156                                  	;push	bx
  1157                                  	; 24/12/2021
  1158 00000741 53                              push	ebx
  1159 00000742 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1160 00000744 E8590C0000              	call 	write_tty
  1161                                  	;pop	bx
  1162                                  	; 24/12/2021
  1163 00000749 5B                      	pop	ebx
  1164 0000074A 5E                      	pop	esi
  1165 0000074B EBEE                    	jmp	short ptmsg
  1166                                  	;; 27/08/2014
  1167                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1168                                  	;call	printk
  1169                                  	;
  1170                                  ptmsg_ok:
  1171                                  	; 07/09/2014
  1172                                  	;xor	dx, dx		; column 0, row 0
  1173                                  	; 24/12/2021
  1174 0000074D 31D2                    	xor	edx, edx
  1175 0000074F E8580D0000              	call	set_cpos	; set cursor position to 0,0 
  1176                                  	; 23/02/2015
  1177                                  	; 25/08/2014
  1178                                  	;mov	ebx, scounter		; (seconds counter)
  1179                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1180                                  ;	dec	byte [scounter+1]
  1181                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1182                                  ;	jns	short u_timer_retn
  1183                                  	; 26/02/2015
  1184                                  ;	call	rtc_p
  1185                                  ;	mov	ebx, scounter		; (seconds counter)
  1186                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1187                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1188                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1189                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1190                                  ;	mov	byte [ebx], 5
  1191                                  ;	inc	byte [ebx+1] ; 19
  1192                                  ;;timer_eoi:
  1193                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1194                                  ;;	out	20h, al	; 8259 PORT
  1195                                  	;
  1196                                  ;u_timer_retn:  ; 06/02/2015
  1197 00000754 5F                      	pop	edi
  1198 00000755 5E                      	pop	esi
  1199                                  	;pop	es
  1200                                  	;pop	ds
  1201                                  	;pop	ebx
  1202                                  	;pop	ecx
  1203                                  	;pop	edx
  1204                                  	;pop	eax
  1205                                  	;iret
  1206 00000756 C3                      	retn	; 06/02/2015
  1207                                  
  1208                                  	; 28/08/2014
  1209                                  irq0:
  1210 00000757 6A00                            push 	dword 0
  1211 00000759 EB48                    	jmp	short which_irq
  1212                                  irq1:
  1213 0000075B 6A01                            push 	dword 1
  1214 0000075D EB44                    	jmp	short which_irq
  1215                                  irq2:
  1216 0000075F 6A02                            push 	dword 2
  1217 00000761 EB40                    	jmp	short which_irq
  1218                                  irq3:
  1219                                  	; 20/11/2015
  1220                                  	; 24/10/2015
  1221 00000763 2EFF15[D4300000]        	call	dword [cs:com2_irq3]
  1222 0000076A 6A03                    	push 	dword 3
  1223 0000076C EB35                    	jmp	short which_irq
  1224                                  irq4:
  1225                                  	; 20/11/2015
  1226                                  	; 24/10/2015
  1227 0000076E 2EFF15[D0300000]        	call	dword [cs:com1_irq4]
  1228 00000775 6A04                            push 	dword 4
  1229 00000777 EB2A                    	jmp	short which_irq
  1230                                  irq5:
  1231 00000779 6A05                            push 	dword 5
  1232 0000077B EB26                    	jmp	short which_irq
  1233                                  irq6:
  1234 0000077D 6A06                            push 	dword 6
  1235 0000077F EB22                    	jmp	short which_irq
  1236                                  irq7:
  1237 00000781 6A07                            push 	dword 7
  1238 00000783 EB1E                    	jmp	short which_irq
  1239                                  irq8:
  1240 00000785 6A08                            push 	dword 8
  1241 00000787 EB1A                    	jmp	short which_irq
  1242                                  irq9:
  1243 00000789 6A09                            push 	dword 9
  1244 0000078B EB16                    	jmp	short which_irq
  1245                                  irq10:
  1246 0000078D 6A0A                            push 	dword 10
  1247 0000078F EB12                    	jmp	short which_irq
  1248                                  irq11:
  1249 00000791 6A0B                            push 	dword 11
  1250 00000793 EB0E                    	jmp	short which_irq
  1251                                  irq12:
  1252 00000795 6A0C                            push 	dword 12
  1253 00000797 EB0A                    	jmp	short which_irq
  1254                                  irq13:
  1255 00000799 6A0D                            push 	dword 13
  1256 0000079B EB06                    	jmp	short which_irq
  1257                                  irq14:
  1258 0000079D 6A0E                            push 	dword 14
  1259 0000079F EB02                    	jmp	short which_irq
  1260                                  irq15:
  1261 000007A1 6A0F                            push 	dword 15
  1262                                  	;jmp	short which_irq
  1263                                  
  1264                                  	; 19/10/2015
  1265                                  	; 29/08/2014
  1266                                  	; 21/08/2014
  1267                                  which_irq:
  1268 000007A3 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1269 000007A6 53                      	push	ebx
  1270 000007A7 56                      	push	esi
  1271 000007A8 57                      	push	edi
  1272 000007A9 1E                      	push 	ds
  1273 000007AA 06                      	push 	es
  1274                                  	;
  1275 000007AB 88C3                    	mov	bl, al
  1276                                  	;
  1277 000007AD B810000000              	mov	eax, KDATA
  1278 000007B2 8ED8                    	mov	ds, ax
  1279 000007B4 8EC0                    	mov	es, ax
  1280                                  	; 19/10/2015
  1281 000007B6 FC                      	cld
  1282                                          ; 27/08/2014
  1283 000007B7 8105[8C5D0000]A000-             add     dword [scr_row], 0A0h
  1283 000007BF 0000               
  1284                                  	;
  1285 000007C1 B417                    	mov	ah, 17h	; blue (1) background, 
  1286                                  			; light gray (7) forecolor
  1287 000007C3 8B3D[8C5D0000]                  mov     edi, [scr_row]
  1288 000007C9 B049                    	mov	al, 'I'
  1289 000007CB 66AB                    	stosw
  1290 000007CD B052                    	mov	al, 'R'
  1291 000007CF 66AB                    	stosw
  1292 000007D1 B051                    	mov	al, 'Q'
  1293 000007D3 66AB                    	stosw
  1294 000007D5 B020                    	mov	al, ' '
  1295 000007D7 66AB                    	stosw
  1296 000007D9 88D8                    	mov	al, bl
  1297 000007DB 3C0A                    	cmp	al, 10
  1298 000007DD 7208                    	jb	short iix
  1299 000007DF B031                    	mov	al, '1'
  1300 000007E1 66AB                    	stosw
  1301 000007E3 88D8                    	mov	al, bl
  1302 000007E5 2C0A                    	sub	al, 10
  1303                                  iix:
  1304 000007E7 0430                    	add	al, '0'
  1305 000007E9 66AB                    	stosw
  1306 000007EB B020                    	mov	al, ' '
  1307 000007ED 66AB                    	stosw
  1308 000007EF B021                    	mov	al, '!'
  1309 000007F1 66AB                    	stosw
  1310 000007F3 B020                    	mov	al, ' '
  1311 000007F5 66AB                    	stosw
  1312                                  	; 23/02/2015
  1313 000007F7 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1314                                  	;jna	iiret
  1315                                  	; 02/01/2022
  1316 000007FA 7604                    	jna	short iiz
  1317                                  iiy:
  1318 000007FC B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1319 000007FE E6A0                    	out	0A0h, al ; the 2nd 8259
  1320                                  iiz:
  1321 00000800 E983010000              	jmp     iiret
  1322                                  	;
  1323                                  	; 22/08/2014
  1324                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1325                                  	;out	20h, al	; 8259 PORT
  1326                                  	;
  1327                                  	;pop	es
  1328                                  	;pop	ds
  1329                                  	;pop	edi
  1330                                  	;pop	esi
  1331                                  	;pop	ebx
  1332                                  	;pop 	eax
  1333                                  	;iret
  1334                                  
  1335                                  	; 02/04/2015
  1336                                  	; 25/08/2014
  1337                                  exc0:
  1338 00000805 6A00                            push 	dword 0
  1339 00000807 E990000000                      jmp     cpu_except
  1340                                  exc1:
  1341 0000080C 6A01                            push 	dword 1
  1342 0000080E E989000000                      jmp     cpu_except
  1343                                  exc2:
  1344 00000813 6A02                            push 	dword 2
  1345 00000815 E982000000                      jmp     cpu_except
  1346                                  exc3:
  1347 0000081A 6A03                            push 	dword 3
  1348 0000081C EB7E                            jmp     cpu_except
  1349                                  exc4:
  1350 0000081E 6A04                            push 	dword 4
  1351 00000820 EB7A                            jmp     cpu_except
  1352                                  exc5:
  1353 00000822 6A05                            push 	dword 5
  1354 00000824 EB76                            jmp     cpu_except
  1355                                  exc6:
  1356 00000826 6A06                            push 	dword 6
  1357 00000828 EB72                            jmp     cpu_except
  1358                                  exc7:
  1359 0000082A 6A07                            push 	dword 7
  1360 0000082C EB6E                            jmp     cpu_except
  1361                                  exc8:
  1362                                  	; [esp] = Error code
  1363 0000082E 6A08                            push 	dword 8
  1364 00000830 EB5C                            jmp     cpu_except_en
  1365                                  exc9:
  1366 00000832 6A09                            push 	dword 9
  1367 00000834 EB66                            jmp     cpu_except
  1368                                  exc10:
  1369                                  	; [esp] = Error code
  1370 00000836 6A0A                            push 	dword 10
  1371 00000838 EB54                            jmp     cpu_except_en
  1372                                  exc11:
  1373                                  	; [esp] = Error code
  1374 0000083A 6A0B                            push 	dword 11
  1375 0000083C EB50                            jmp     cpu_except_en
  1376                                  exc12:
  1377                                  	; [esp] = Error code
  1378 0000083E 6A0C                            push 	dword 12
  1379 00000840 EB4C                            jmp     cpu_except_en
  1380                                  exc13:
  1381                                  	; [esp] = Error code
  1382 00000842 6A0D                            push 	dword 13
  1383 00000844 EB48                            jmp     cpu_except_en
  1384                                  exc14:
  1385                                  	; [esp] = Error code
  1386 00000846 6A0E                            push 	dword 14
  1387 00000848 EB44                    	jmp	short cpu_except_en
  1388                                  exc15:
  1389 0000084A 6A0F                            push 	dword 15
  1390 0000084C EB4E                            jmp     cpu_except
  1391                                  exc16:
  1392 0000084E 6A10                            push 	dword 16
  1393 00000850 EB4A                            jmp     cpu_except
  1394                                  exc17:
  1395                                  	; [esp] = Error code
  1396 00000852 6A11                            push 	dword 17
  1397 00000854 EB38                    	jmp	short cpu_except_en
  1398                                  exc18:
  1399 00000856 6A12                            push 	dword 18
  1400 00000858 EB42                    	jmp	short cpu_except
  1401                                  exc19:
  1402 0000085A 6A13                            push 	dword 19
  1403 0000085C EB3E                    	jmp	short cpu_except
  1404                                  exc20:
  1405 0000085E 6A14                            push 	dword 20
  1406 00000860 EB3A                    	jmp	short cpu_except
  1407                                  exc21:
  1408 00000862 6A15                            push 	dword 21
  1409 00000864 EB36                    	jmp	short cpu_except
  1410                                  exc22:
  1411 00000866 6A16                            push 	dword 22
  1412 00000868 EB32                    	jmp	short cpu_except
  1413                                  exc23:
  1414 0000086A 6A17                            push 	dword 23
  1415 0000086C EB2E                    	jmp	short cpu_except
  1416                                  exc24:
  1417 0000086E 6A18                            push 	dword 24
  1418 00000870 EB2A                    	jmp	short cpu_except
  1419                                  exc25:
  1420 00000872 6A19                            push 	dword 25
  1421 00000874 EB26                    	jmp	short cpu_except
  1422                                  exc26:
  1423 00000876 6A1A                            push 	dword 26
  1424 00000878 EB22                    	jmp	short cpu_except
  1425                                  exc27:
  1426 0000087A 6A1B                            push 	dword 27
  1427 0000087C EB1E                    	jmp	short cpu_except
  1428                                  exc28:
  1429 0000087E 6A1C                            push 	dword 28
  1430 00000880 EB1A                    	jmp	short cpu_except
  1431                                  exc29:
  1432 00000882 6A1D                            push 	dword 29
  1433 00000884 EB16                    	jmp	short cpu_except
  1434                                  exc30:
  1435 00000886 6A1E                            push 	dword 30
  1436 00000888 EB04                    	jmp	short cpu_except_en
  1437                                  exc31:
  1438 0000088A 6A1F                            push 	dword 31
  1439 0000088C EB0E                            jmp     short cpu_except
  1440                                  
  1441                                  	; 02/01/2022
  1442                                  	; 19/10/2015
  1443                                  	; 19/09/2015
  1444                                  	; 01/09/2015
  1445                                  	; 28/08/2015
  1446                                  	; 28/08/2014
  1447                                  cpu_except_en:
  1448 0000088E 87442404                	xchg	eax, [esp+4] ; Error code
  1449 00000892 36A3[E4620000]          	mov	[ss:error_code], eax
  1450 00000898 58                      	pop	eax  ; Exception number
  1451 00000899 870424                  	xchg	eax, [esp]
  1452                                  		; eax = eax before exception
  1453                                  		; [esp] -> exception number
  1454                                  		; [esp+4] -> EIP to return
  1455                                  	; 19/10/2015
  1456                                  	; 19/09/2015
  1457                                  	; 01/09/2015
  1458                                  	; 28/08/2015
  1459                                  	; 29/08/2014
  1460                                  	; 28/08/2014
  1461                                  	; 25/08/2014
  1462                                  	; 21/08/2014
  1463                                  cpu_except:	; CPU Exceptions
  1464 0000089C FC                      	cld
  1465 0000089D 870424                  	xchg	eax, [esp] 
  1466                                  		; eax = Exception number
  1467                                  		; [esp] = eax (before exception)
  1468 000008A0 53                      	push	ebx
  1469 000008A1 56                      	push	esi
  1470 000008A2 57                      	push	edi
  1471 000008A3 1E                      	push 	ds
  1472 000008A4 06                      	push 	es
  1473                                  	; 28/08/2015
  1474 000008A5 66BB1000                	mov	bx, KDATA
  1475 000008A9 8EDB                    	mov	ds, bx
  1476 000008AB 8EC3                    	mov	es, bx
  1477 000008AD 0F20DB                  	mov	ebx, cr3
  1478 000008B0 53                      	push	ebx ; (*) page directory
  1479                                  	; 19/10/2015
  1480 000008B1 FC                      	cld
  1481                                  	; 25/03/2015
  1482 000008B2 8B1D[38620000]          	mov	ebx, [k_page_dir]
  1483 000008B8 0F22DB                  	mov	cr3, ebx
  1484                                  	; 28/08/2015
  1485 000008BB 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1486 000008BE 7513                    	jne	short cpu_except_nfp
  1487 000008C0 E8B31E0000              	call	page_fault_handler
  1488 000008C5 21C0                    	and 	eax, eax
  1489                                  	;jz	iiretp ; 01/09/2015
  1490                                  	; 02/01/2022
  1491 000008C7 7505                    	jnz	short cpu_except_pf
  1492 000008C9 E9B6000000              	jmp	iiretp
  1493                                  cpu_except_pf:
  1494 000008CE B80E000000              	mov	eax, 0Eh ; 14
  1495                                  cpu_except_nfp:
  1496                                  	; 02/04/2015
  1497 000008D3 BB[FD050000]            	mov	ebx, hang
  1498 000008D8 875C241C                	xchg	ebx, [esp+28]
  1499                                  		; EIP (points to instruction which faults)
  1500                                  	  	; New EIP (hang)
  1501 000008DC 891D[E8620000]          	mov	[FaultOffset], ebx
  1502 000008E2 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1503 000008EA 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1504                                  	;
  1505 000008F2 88C4                    	mov	ah, al
  1506 000008F4 240F                    	and	al, 0Fh
  1507 000008F6 3C09                    	cmp	al, 9
  1508 000008F8 7602                    	jna	short h1ok
  1509 000008FA 0407                    	add	al, 'A'-':'
  1510                                  h1ok:
  1511 000008FC D0EC                    	shr	ah, 1
  1512 000008FE D0EC                    	shr	ah, 1
  1513 00000900 D0EC                    	shr	ah, 1
  1514 00000902 D0EC                    	shr	ah, 1
  1515 00000904 80FC09                  	cmp	ah, 9
  1516 00000907 7603                    	jna	short h2ok
  1517 00000909 80C407                  	add	ah, 'A'-':'
  1518                                  h2ok:	
  1519 0000090C 86E0                    	xchg 	ah, al	
  1520 0000090E 66053030                	add	ax, '00'
  1521 00000912 66A3[1A5E0000]          	mov	[excnstr], ax
  1522                                  	;
  1523                                  	; 29/08/2014
  1524 00000918 A1[E8620000]            	mov	eax, [FaultOffset]
  1525 0000091D 51                      	push	ecx
  1526 0000091E 52                      	push	edx
  1527 0000091F 89E3                    	mov	ebx, esp
  1528                                  	; 28/08/2015
  1529 00000921 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1530                                  			  ; to hexadecimal string
  1531                                  	;mov	ecx, 10	    ; divisor to convert
  1532                                  			    ; binary number to decimal string
  1533                                  b2d1:
  1534 00000926 31D2                    	xor	edx, edx
  1535 00000928 F7F1                    	div	ecx
  1536                                  	;push	dx
  1537                                  	; 02/01/2022
  1538 0000092A 52                      	push	edx
  1539 0000092B 39C8                    	cmp	eax, ecx
  1540 0000092D 73F7                    	jnb	short b2d1
  1541 0000092F BF[255E0000]            	mov	edi, EIPstr ; EIP value
  1542                                  			    ; points to instruction which faults
  1543                                  	; 28/08/2015
  1544 00000934 89C2                    	mov	edx, eax
  1545                                  b2d2:
  1546                                  	;add	al, '0'
  1547 00000936 8A82[DE160000]          	mov	al, [edx+hexchrs]
  1548 0000093C AA                      	stosb		    ; write hexadecimal digit to its place
  1549 0000093D 39E3                    	cmp	ebx, esp
  1550 0000093F 7605                    	jna	short b2d3
  1551                                  	; 02/01/2022
  1552 00000941 58                      	pop	eax
  1553                                  	;pop	ax
  1554 00000942 88C2                    	mov	dl, al
  1555 00000944 EBF0                    	jmp	short b2d2
  1556                                  b2d3:
  1557 00000946 B068                    	mov 	al, 'h' ; 28/08/2015
  1558 00000948 AA                      	stosb
  1559 00000949 B020                    	mov	al, 20h	    ; space
  1560 0000094B AA                      	stosb
  1561 0000094C 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1562 0000094E AA                      	stosb
  1563                                  	;
  1564 0000094F 5A                      	pop	edx
  1565 00000950 59                      	pop	ecx
  1566                                  	;
  1567 00000951 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1568                                  			; white (F) forecolor
  1569 00000953 BE[0A5E0000]            	mov	esi, exc_msg ; message offset
  1570                                  	;
  1571 00000958 EB11                    	jmp	short piemsg
  1572                                  	;
  1573                                          ;add    dword [scr_row], 0A0h
  1574                                          ;mov    edi, [scr_row]
  1575                                          ;
  1576                                  	;call 	printk
  1577                                  	;
  1578                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1579                                  	;out	20h, al	; 8259 PORT
  1580                                  	;
  1581                                  	;pop	es
  1582                                  	;pop	ds
  1583                                  	;pop	edi
  1584                                  	;pop	esi
  1585                                  	;pop 	eax
  1586                                  	;iret
  1587                                  	
  1588                                  	; 28/08/2015
  1589                                  	; 23/02/2015
  1590                                  	; 20/08/2014
  1591                                  ignore_int:
  1592 0000095A 50                      	push	eax
  1593 0000095B 53                      	push	ebx ; 23/02/2015
  1594 0000095C 56                      	push	esi
  1595 0000095D 57                      	push	edi
  1596 0000095E 1E                      	push 	ds
  1597 0000095F 06                      	push 	es
  1598                                  	; 28/08/2015
  1599 00000960 0F20D8                  	mov	eax, cr3
  1600 00000963 50                      	push	eax ; (*) page directory
  1601                                  	;
  1602 00000964 B467                    	mov	ah, 67h	; brown (6) background, 
  1603                                  			; light gray (7) forecolor
  1604 00000966 BE[C85D0000]            	mov	esi, int_msg ; message offset
  1605                                  piemsg:
  1606                                          ; 27/08/2014
  1607 0000096B 8105[8C5D0000]A000-             add     dword [scr_row], 0A0h
  1607 00000973 0000               
  1608 00000975 8B3D[8C5D0000]                  mov     edi, [scr_row]
  1609                                          ;
  1610 0000097B E8B6FCFFFF              	call 	printk
  1611                                  	;
  1612                                  	; 23/02/2015
  1613 00000980 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1614 00000982 E6A0                    	out	0A0h, al ; the 2nd 8259
  1615                                  iiretp: ; 01/09/2015
  1616                                  	; 28/08/2015
  1617 00000984 58                      	pop	eax ; (*) page directory
  1618 00000985 0F22D8                  	mov	cr3, eax
  1619                                  	;
  1620                                  iiret:
  1621                                  	; 22/08/2014
  1622 00000988 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1623 0000098A E620                    	out	20h, al	; 8259 PORT
  1624                                  	;
  1625 0000098C 07                      	pop	es
  1626 0000098D 1F                      	pop	ds
  1627 0000098E 5F                      	pop	edi
  1628 0000098F 5E                      	pop	esi
  1629 00000990 5B                      	pop	ebx ; 29/08/2014
  1630 00000991 58                      	pop 	eax
  1631 00000992 CF                      	iretd
  1632                                  
  1633                                  	; 26/02/2022
  1634                                  	; 26/02/2015
  1635                                  	; 07/09/2014
  1636                                  	; 25/08/2014
  1637                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1638                                  	; 22/08/2014
  1639 00000993 50                      	push	eax
  1640 00000994 53                      	push	ebx ; 29/08/2014
  1641 00000995 56                      	push	esi
  1642 00000996 57                      	push	edi
  1643 00000997 1E                      	push 	ds
  1644 00000998 06                      	push 	es
  1645                                  	;
  1646 00000999 B810000000              	mov	eax, KDATA
  1647 0000099E 8ED8                    	mov	ds, ax
  1648 000009A0 8EC0                    	mov	es, ax
  1649                                  	;
  1650                                  	; 25/08/2014
  1651                                  	;call	rtc_p
  1652                                  	; 26/02/2022
  1653 000009A2 FF15[F5060000]          	call	[x_rtci]
  1654                                  	;
  1655                                  	; 22/02/2015 - dsectpm.s
  1656                                  	; [ source: http://wiki.osdev.org/RTC ]
  1657                                  	; read status register C to complete procedure
  1658                                  	;(it is needed to get a next IRQ 8) 
  1659 000009A8 B00C                    	mov	al, 0Ch ; 
  1660 000009AA E670                    	out	70h, al ; select register C
  1661 000009AC 90                      	nop
  1662 000009AD E471                    	in	al, 71h ; just throw away contents
  1663                                  	; 22/02/2015
  1664 000009AF B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1665 000009B1 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1666                                  	;
  1667 000009B3 EBD3                    	jmp	short iiret	
  1668                                  
  1669                                  	; 22/08/2014
  1670                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1671                                  	; (INT 1Ah)
  1672                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1673                                  time_of_day:
  1674 000009B5 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1675 000009BA 726F                            jc      short rtc_retn 
  1676 000009BC B000                    	mov	al, CMOS_SECONDS
  1677 000009BE E847010000              	call	CMOS_READ
  1678 000009C3 A2[AC620000]            	mov	[time_seconds], al 
  1679 000009C8 B002                    	mov	al, CMOS_MINUTES
  1680 000009CA E83B010000              	call	CMOS_READ
  1681 000009CF A2[AD620000]            	mov	[time_minutes], al 
  1682 000009D4 B004                    	mov	al, CMOS_HOURS
  1683 000009D6 E82F010000              	call	CMOS_READ
  1684 000009DB A2[AE620000]                    mov     [time_hours], al
  1685 000009E0 B006                    	mov	al, CMOS_DAY_WEEK 
  1686 000009E2 E823010000              	call	CMOS_READ
  1687 000009E7 A2[AF620000]            	mov	[date_wday], al
  1688 000009EC B007                     	mov	al, CMOS_DAY_MONTH
  1689 000009EE E817010000              	call	CMOS_READ
  1690 000009F3 A2[B0620000]            	mov	[date_day], al
  1691 000009F8 B008                    	mov	al, CMOS_MONTH
  1692 000009FA E80B010000              	call	CMOS_READ
  1693 000009FF A2[B1620000]            	mov	[date_month], al
  1694 00000A04 B009                    	mov	al, CMOS_YEAR
  1695 00000A06 E8FF000000              	call	CMOS_READ
  1696 00000A0B A2[B2620000]            	mov	[date_year], al
  1697 00000A10 B032                    	mov	al, CMOS_CENTURY
  1698 00000A12 E8F3000000              	call	CMOS_READ
  1699 00000A17 A2[B3620000]            	mov	[date_century], al
  1700                                  	;
  1701 00000A1C B000                    	mov	al, CMOS_SECONDS
  1702 00000A1E E8E7000000              	call 	CMOS_READ
  1703 00000A23 3A05[AC620000]          	cmp	al, [time_seconds]
  1704 00000A29 758A                    	jne	short time_of_day
  1705                                  
  1706                                  rtc_retn:
  1707 00000A2B C3                      	retn
  1708                                  
  1709                                  rtci_default:
  1710                                  	; 26/02/2022 (Temporary!)
  1711                                  	; (default real time clock handler in multitasking mode)
  1712                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1713 00000A2C FF05[F0620000]          	inc	dword [rtc_ticks] ; real time clock counter
  1714                                  			; (not used in anywhere of kernel for now!)
  1715 00000A32 C3                      	retn
  1716                                  
  1717                                  rtc_p:	
  1718                                  	; 07/09/2014
  1719                                  	; 29/08/2014
  1720                                  	; 27/08/2014
  1721                                  	; 25/08/2014
  1722                                   	; Print Real Time Clock content
  1723                                  	;
  1724                                  	;
  1725 00000A33 E87DFFFFFF              	call	time_of_day
  1726 00000A38 72F1                    	jc	short rtc_retn
  1727                                  	;
  1728 00000A3A 3A05[7C5E0000]          	cmp	al, [ptime_seconds]
  1729 00000A40 74E9                            je      short rtc_retn ; 29/08/2014
  1730                                  	;
  1731 00000A42 A2[7C5E0000]            	mov	[ptime_seconds], al
  1732                                  	;
  1733 00000A47 A0[B3620000]            	mov	al, [date_century]
  1734 00000A4C E8EA000000              	call	bcd_to_ascii
  1735 00000A51 66A3[495E0000]          	mov	[datestr+6], ax
  1736 00000A57 A0[B2620000]            	mov	al, [date_year]
  1737 00000A5C E8DA000000              	call	bcd_to_ascii
  1738 00000A61 66A3[4B5E0000]          	mov	[datestr+8], ax
  1739 00000A67 A0[B1620000]            	mov	al, [date_month]
  1740 00000A6C E8CA000000              	call	bcd_to_ascii
  1741 00000A71 66A3[465E0000]          	mov	[datestr+3], ax
  1742 00000A77 A0[B0620000]            	mov	al, [date_day]
  1743 00000A7C E8BA000000              	call	bcd_to_ascii
  1744 00000A81 66A3[435E0000]          	mov	[datestr], ax
  1745                                  	;
  1746 00000A87 0FB61D[AF620000]        	movzx	ebx, byte [date_wday]
  1747 00000A8E C0E302                  	shl 	bl, 2
  1748 00000A91 81C3[5C5E0000]          	add	ebx, daytmp
  1749 00000A97 8B03                    	mov	eax, [ebx]
  1750 00000A99 A3[4E5E0000]            	mov	[daystr], eax
  1751                                  	;
  1752 00000A9E A0[AE620000]            	mov	al, [time_hours]
  1753 00000AA3 E893000000              	call	bcd_to_ascii
  1754 00000AA8 66A3[525E0000]          	mov	[timestr], ax
  1755 00000AAE A0[AD620000]            	mov	al, [time_minutes]
  1756 00000AB3 E883000000              	call	bcd_to_ascii
  1757 00000AB8 66A3[555E0000]          	mov	[timestr+3], ax
  1758 00000ABE A0[AC620000]            	mov	al, [time_seconds]
  1759 00000AC3 E873000000              	call	bcd_to_ascii
  1760 00000AC8 66A3[585E0000]          	mov	[timestr+6], ax
  1761                                  	;		
  1762 00000ACE BE[315E0000]            	mov	esi, rtc_msg ; message offset
  1763                                  	; 23/02/2015
  1764 00000AD3 52                      	push	edx
  1765 00000AD4 51                      	push	ecx
  1766                                  	; 07/09/2014
  1767                                  	;mov	bx, 2	; Video page 2
  1768                                  	; 02/01/2022
  1769 00000AD5 29DB                    	sub	ebx, ebx
  1770 00000AD7 B307                    	mov	bl, 7	; Video page 7 
  1771                                  prtmsg:
  1772 00000AD9 AC                      	lodsb
  1773 00000ADA 08C0                    	or	al, al
  1774 00000ADC 740D                    	jz	short prtmsg_ok
  1775 00000ADE 56                      	push	esi
  1776                                  	; 02/01/2022
  1777 00000ADF 53                      	push	ebx
  1778                                  	;push	bx
  1779 00000AE0 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1780                                  			; white (F) forecolor
  1781 00000AE2 E8BB080000              	call 	write_tty
  1782                                  	;pop	bx
  1783                                  	; 02/01/2022
  1784 00000AE7 5B                      	pop	ebx
  1785 00000AE8 5E                      	pop	esi
  1786 00000AE9 EBEE                    	jmp	short prtmsg
  1787                                  	;
  1788                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1789                                  	;call	printk
  1790                                  prtmsg_ok:
  1791                                  	; 07/09/2014
  1792                                  	;xor	dx, dx		; column 0, row 0
  1793                                  	; 02/01/2022
  1794 00000AEB 31D2                    	xor	edx, edx
  1795 00000AED E8BA090000              	call	set_cpos	; set curspor position to 0,0 
  1796                                  	; 23/02/2015
  1797 00000AF2 59                      	pop	ecx
  1798 00000AF3 5A                      	pop	edx
  1799 00000AF4 C3                      	retn
  1800                                  
  1801                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1802                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1803                                  default_irq7:
  1804                                  	; 24/12/2021
  1805                                  	;push	ax
  1806 00000AF5 50                      	push	eax
  1807 00000AF6 B00B                    	mov	al, 0Bh  ; In-Service register
  1808 00000AF8 E620                    	out	20h, al
  1809 00000AFA EB00                            jmp short $+2
  1810 00000AFC EB00                    	jmp short $+2
  1811 00000AFE E420                    	in	al, 20h
  1812 00000B00 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1813 00000B02 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1814 00000B04 B020                            mov     al, 20h ; EOI
  1815 00000B06 E620                    	out	20h, al 
  1816                                  irq7_iret:
  1817                                  	;pop	ax
  1818                                  	; 24/12/2021
  1819 00000B08 58                      	pop	eax
  1820 00000B09 CF                      	iretd	
  1821                                  	
  1822                                  	; 24/12/2021
  1823                                  	; 22/08/2014
  1824                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1825                                  CMOS_READ:
  1826 00000B0A 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1827 00000B0B D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1828 00000B0D F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1829 00000B0E D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1830 00000B10 FA                      	cli		; DISABLE INTERRUPTS
  1831 00000B11 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1832 00000B13 90                      	nop		; I/O DELAY
  1833 00000B14 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1834                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1835                                  	; 24/12/2021
  1836 00000B16 50                      	push	eax
  1837                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1838                                  		     ; ----- 10/06/85 (test4.asm)
  1839 00000B17 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1840                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1841 00000B19 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1842 00000B1B E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1843                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1844                                  	; 24/12/2021
  1845 00000B1D 58                      	pop	eax
  1846 00000B1E 9D                      	popf	
  1847 00000B1F C3                      	retn		; RETURN WITH FLAGS RESTORED
  1848                                  
  1849                                  	; 22/08/2014
  1850                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1851                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1852 00000B20 51                      	push	ecx
  1853 00000B21 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1854                                  		; mov cx, 800	
  1855                                  UPD_10:
  1856 00000B26 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1857 00000B28 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1858 00000B29 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1859 00000B2E A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1860 00000B30 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1861 00000B32 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1862 00000B33 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1863 00000B35 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1864                                  		; xor ax, ax
  1865 00000B37 F9                      	stc				; SET CARRY FOR ERROR
  1866                                  UPD_90:
  1867 00000B38 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1868 00000B39 FA                      	cli				; INTERRUPTS OFF DURING SET
  1869 00000B3A C3                      	retn				; RETURN WITH CY FLAG SET
  1870                                  
  1871                                  bcd_to_ascii:
  1872                                  	; 25/08/2014
  1873                                  	; INPUT ->
  1874                                  	;	al = Packed BCD number
  1875                                  	; OUTPUT ->
  1876                                  	;	ax  = ASCII word/number
  1877                                  	;
  1878                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1879                                  	;
  1880 00000B3B D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1881                                  					; AH = AL / 10h
  1882                                  					; AL = AL MOD 10h
  1883 00000B3D 660D3030                	or ax,'00'                      ; Make it ASCII based
  1884                                  
  1885 00000B41 86E0                            xchg ah, al 
  1886                                  	
  1887 00000B43 C3                      	retn	
  1888                                  	
  1889                                  
  1890                                  %include 'keyboard.inc' ; 07/03/2015
  1891                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KEYBOARD.INC
  1892                              <1> ; Last Modification: 13/06/2022
  1893                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1894                              <1> ;
  1895                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1896                              <1> 
  1897                              <1> ; 23/02/2022
  1898                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1899                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1900                              <1> ; 30/06/2015
  1901                              <1> ; 11/03/2015
  1902                              <1> ; 28/02/2015
  1903                              <1> ; 25/02/2015
  1904                              <1> ; 20/02/2015
  1905                              <1> ; 18/02/2015
  1906                              <1> ; 03/12/2014
  1907                              <1> ; 07/09/2014
  1908                              <1> ; KEYBOARD INTERRUPT HANDLER
  1909                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1910                              <1> 
  1911                              <1> ;getch:
  1912                              <1> ;	; 18/02/2015
  1913                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1914                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1915                              <1> ;	; routine, later... (multi tasking ability)
  1916                              <1> ;	; 28/02/2015
  1917                              <1> ;	sti	; enable interrupts
  1918                              <1> ;	;
  1919                              <1> ;	;push	esi
  1920                              <1> ;	;push	ebx
  1921                              <1> ;	;xor	ebx, ebx
  1922                              <1> ;	;mov	bl, [ptty]  ; active_page
  1923                              <1> ;	;mov	esi, ebx
  1924                              <1> ;	;shl 	si, 1
  1925                              <1> ;	;add	esi, ttychr
  1926                              <1> ;getch_1:
  1927                              <1> ;	;mov	ax, [esi]
  1928                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1929                              <1> ;	and	ax, ax
  1930                              <1> ;	jz	short getch_2
  1931                              <1> ;	mov	word [ttychr], 0
  1932                              <1> ;	;mov	word [esi], 0
  1933                              <1> ;	;pop	ebx
  1934                              <1> ;	;pop	esi
  1935                              <1> ;	retn
  1936                              <1> ;getch_2:
  1937                              <1> ;	hlt	; not proper for multi tasking!
  1938                              <1> ;		; (temporary halt for now)
  1939                              <1> ;		; 'sleep' on tty 
  1940                              <1> ;		; will (must) be located here		
  1941                              <1> ;	nop
  1942                              <1> ;	jmp	short getch_1
  1943                              <1> 
  1944                              <1> keyb_int:
  1945                              <1> 	; 23/02/2022
  1946                              <1> 	; 30/06/2015
  1947                              <1> 	; 25/02/2015
  1948                              <1> 	; 20/02/2015
  1949                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1950                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1951                              <1> 	; 30/06/2014
  1952                              <1> 	; 10/05/2013	
  1953                              <1>       	; Retro Unix 8086 v1 feature only!
  1954                              <1> 	; 03/03/2014
  1955                              <1> 	
  1956 00000B44 1E                  <1> 	push	ds
  1957 00000B45 53                  <1> 	push	ebx
  1958 00000B46 50                  <1> 	push	eax
  1959                              <1> 	;
  1960                              <1> 	; 23/02/2022
  1961 00000B47 9C                  <1> 	pushfd
  1962 00000B48 0E                  <1> 	push	cs
  1963                              <1> 	;mov	ax, KDATA
  1964 00000B49 31C0                <1> 	xor	eax, eax
  1965 00000B4B B010                <1> 	mov	al, KDATA
  1966 00000B4D 8ED8                <1> 	mov	ds, ax
  1967                              <1> 	;
  1968                              <1> 	;pushfd
  1969                              <1> 	;push	cs
  1970 00000B4F E810020000          <1> 	call	kb_int   ; int_09h
  1971                              <1> 	;
  1972 00000B54 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1973                              <1> 	;call	getc
  1974 00000B56 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1975 00000B5B 744E                <1> 	jz	short keyb_int4
  1976                              <1> 	;
  1977 00000B5D B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1978                              <1> 	;call	getc
  1979 00000B5F E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1980                              <1> 	;
  1981                              <1> 	; 20/02/2015
  1982 00000B64 0FB61D[66620000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1983                              <1> 	;
  1984 00000B6B 20C0                <1> 	and 	al, al
  1985 00000B6D 751D                <1> 	jnz	short keyb_int1
  1986                              <1> 	;
  1987 00000B6F 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1988 00000B72 7218                <1> 	jb	short keyb_int1
  1989 00000B74 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1990 00000B77 7713                <1> 	ja	short keyb_int1
  1991                              <1> 	;
  1992 00000B79 88D8                <1> 	mov	al, bl
  1993 00000B7B 0468                <1> 	add	al, 68h
  1994 00000B7D 38E0                <1> 	cmp	al, ah
  1995 00000B7F 7409                <1> 	je	short keyb_int0
  1996 00000B81 88E0                <1> 	mov	al, ah
  1997 00000B83 2C68                <1> 	sub	al, 68h
  1998 00000B85 E8370A0000          <1> 	call	tty_sw
  1999                              <1> 	;movzx	ebx, [ptty]  ; active_page
  2000                              <1> keyb_int0: ; 30/06/2015
  2001                              <1> 	;xor	ax, ax
  2002                              <1> 	; 23/02/2022
  2003 00000B8A 31C0                <1> 	xor	eax, eax
  2004                              <1> keyb_int1:
  2005 00000B8C D0E3                <1> 	shl	bl, 1
  2006 00000B8E 81C3[68620000]      <1> 	add	ebx, ttychr
  2007                              <1> 	;
  2008                              <1> 	;23/02/2022
  2009 00000B94 09C0                <1> 	or	eax, eax
  2010                              <1> 	;or	ax, ax
  2011 00000B96 7406                <1> 	jz	short keyb_int2
  2012                              <1> 	;
  2013 00000B98 66833B00            <1> 	cmp 	word [ebx], 0
  2014 00000B9C 7703                <1>         ja      short keyb_int3 
  2015                              <1> keyb_int2:
  2016 00000B9E 668903              <1>         mov	[ebx], ax  ; Save ascii code
  2017                              <1> 			   ; and scan code of the character
  2018                              <1> 			   ; for current tty (or last tty
  2019                              <1> 			   ; just before tty switch).
  2020                              <1> keyb_int3:
  2021 00000BA1 A0[66620000]        <1>         mov     al, [ptty]
  2022 00000BA6 E8333B0000          <1> 	call	wakeup
  2023                              <1> 	;
  2024                              <1> keyb_int4:
  2025 00000BAB 58                  <1> 	pop	eax
  2026 00000BAC 5B                  <1> 	pop	ebx
  2027 00000BAD 1F                  <1> 	pop	ds
  2028 00000BAE CF                  <1> 	iret
  2029                              <1> 
  2030                              <1> ; 18/02/2015
  2031                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2032                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2033                              <1> ; scancode and ascii code of the character 
  2034                              <1> ; in the tty input (ttychr) buffer. 
  2035                              <1> ; Test procedures must call 'getch' for tty input
  2036                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2037                              <1> ; due to infinite (key press) waiting loop.
  2038                              <1> ; 
  2039                              <1> ; 03/12/2014
  2040                              <1> ; 26/08/2014
  2041                              <1> ; KEYBOARD I/O
  2042                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2043                              <1> 
  2044                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2045                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2046                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2047                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2048                              <1> 
  2049                              <1> int_16h: ; 30/06/2015
  2050                              <1> ;getc:
  2051 00000BAF 9C                  <1> 	pushfd	; 28/08/2014
  2052 00000BB0 0E                  <1> 	push 	cs
  2053 00000BB1 E826000000          <1> 	call 	getc_int
  2054 00000BB6 C3                  <1> 	retn
  2055                              <1> 
  2056                              <1> ; 24/12/2021
  2057                              <1> 
  2058                              <1> 	;-----	SHIFT STATUS
  2059                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2060 00000BB7 8A25[945C0000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2061 00000BBD 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2062                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2063                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2064 00000BC0 C0E405              <1>         shl	ah, 5
  2065 00000BC3 A0[945C0000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2066 00000BC8 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2067 00000BCA 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2068 00000BCC A0[965C0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2069 00000BD1 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2070 00000BD3 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2071                              <1> _K3:
  2072 00000BD5 A0[935C0000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2073 00000BDA EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2074                              <1> 
  2075                              <1> getc_int:
  2076                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2077                              <1> 	; 28/02/2015
  2078                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2079                              <1> 	;	      instead of pc-at bios - 1985-)
  2080                              <1> 	; 28/08/2014 (_k1d)
  2081                              <1> 	; 30/06/2014
  2082                              <1> 	; 03/03/2014
  2083                              <1> 	; 28/02/2014
  2084                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2085                              <1> 	; rombios source code (21/04/1986)
  2086                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2087                              <1> 	;
  2088                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2089                              <1> 	;
  2090                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2091                              <1> 	; KEYBOARD I/O								      :
  2092                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2093                              <1> 	; INPUT									      :
  2094                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2095                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2096                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2097                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2098                              <1> 	;-----------------------------------------------------------------------------:
  2099                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2100                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2101                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2102                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2103                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2104                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2105                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2106                              <1> 	;-----------------------------------------------------------------------------:	
  2107                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2108                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2109                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2110                              <1> 	;-----------------------------------------------------------------------------:	
  2111                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2112                              <1> 	;	      (AL) = 05H                                                      :
  2113                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2114                              <1> 	;		       							      :
  2115                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2116                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2117                              <1> 	;                     --------------------------------------------            :
  2118                              <1> 	;			00H        30.0        10H        7.5                 :
  2119                              <1> 	;			01H        26.7        11H        6.7                 :
  2120                              <1> 	;			02H        24.0        12H        6.0                 :
  2121                              <1> 	;			03H        21.8        13H        5.5                 :
  2122                              <1> 	;			04H        20.0        14H        5.0                 :
  2123                              <1> 	;			05H        18.5        15H        4.6                 :
  2124                              <1> 	;			06H        17.1        16H        4.3                 :
  2125                              <1> 	;			07H        16.0        17H        4.0                 :
  2126                              <1> 	;			08H        15.0        18H        3.7                 :
  2127                              <1> 	;			09H        13.3        19H        3.3                 :
  2128                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2129                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2130                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2131                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2132                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2133                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2134                              <1> 	;									      :
  2135                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2136                              <1> 	;		       							      :
  2137                              <1> 	;                     REGISTER     DELAY                                      :
  2138                              <1> 	;                      VALUE       VALUE                                      :
  2139                              <1> 	;                     ------------------                                      :
  2140                              <1> 	;			00H        250 ms                                     :
  2141                              <1> 	;			01H        500 ms                                     :
  2142                              <1> 	;			02H        750 ms                                     :
  2143                              <1> 	;			03H       1000 ms                                     :
  2144                              <1> 	;-----------------------------------------------------------------------------:
  2145                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2146                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2147                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2148                              <1> 	;		           (CH) = SCAN CODE                                   :
  2149                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2150                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2151                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2152                              <1> 	;-----------------------------------------------------------------------------:		
  2153                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2154                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2155                              <1> 	;-----------------------------------------------------------------------------:
  2156                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2157                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2158                              <1> 	;-----------------------------------------------------------------------------:	
  2159                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2160                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2161                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2162                              <1> 	; OUTPUT					                              :
  2163                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2164                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2165                              <1> 	;------------------------------------------------------------------------------
  2166                              <1> 	
  2167 00000BDC FB                  <1> 	sti				; INTERRUPTS BACK ON
  2168 00000BDD 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2169 00000BDE 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2170                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2171 00000BDF 66BB1000            <1>         mov     bx, KDATA 
  2172 00000BE3 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2173 00000BE5 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2174 00000BE7 742D                <1> 	jz	short _K1		; ASCII_READ
  2175 00000BE9 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2176 00000BEB 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2177 00000BED FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2178 00000BEF 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2179 00000BF1 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2180 00000BF3 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2181 00000BF5 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2182 00000BF8 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2183                              <1> _KIO1:	
  2184 00000BFA 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2185 00000BFD 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2186 00000BFF FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2187 00000C01 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2188 00000C03 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2189 00000C05 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2190                              <1> _KIO_EXIT:
  2191                              <1> 	;pop	ecx			; RECOVER REGISTER
  2192 00000C07 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2193 00000C08 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2194 00000C09 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2195                              <1> 
  2196                              <1> 	;-----	ASCII CHARACTER
  2197                              <1> _K1E:	
  2198 00000C0A E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2199 00000C0F E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2200 00000C14 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2201                              <1> _K1:	
  2202 00000C16 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2203 00000C1B E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2204 00000C20 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2205                              <1> _K1A:
  2206 00000C22 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2207                              <1> 
  2208                              <1> 	;-----	ASCII STATUS
  2209                              <1> _K2E:	
  2210 00000C24 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2211 00000C29 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2212 00000C2B 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2213 00000C2C E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2214 00000C31 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2215                              <1> _K2:	
  2216 00000C33 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2217 00000C38 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2218 00000C3A 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2219 00000C3B E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2220 00000C40 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2221 00000C42 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2222 00000C43 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2223 00000C48 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2224                              <1> _K2A:
  2225 00000C4A 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2226                              <1> _K2B:
  2227                              <1> 	;pop	ecx			; RECOVER REGISTER
  2228 00000C4B 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2229 00000C4C 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2230 00000C4D CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2231                              <1> 
  2232                              <1> ; 24/12/2021
  2233                              <1> ;	;-----	SHIFT STATUS
  2234                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2235                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2236                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2237                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2238                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2239                              <1> ;       shl	ah, 5
  2240                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2241                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2242                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2243                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2244                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2245                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2246                              <1> ;_K3:
  2247                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2248                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2249                              <1> 
  2250                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2251                              <1> _K300:
  2252 00000C50 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2253 00000C52 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2254 00000C54 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2255 00000C57 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2256 00000C59 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2257 00000C5C 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2258 00000C5E B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2259 00000C60 E87C060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2260                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2261                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2262 00000C65 C0E705              <1> 	shl	bh, 5
  2263 00000C68 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2264 00000C6A 08F8                <1> 	or	al, bh			; AND DELAY
  2265 00000C6C E870060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2266 00000C71 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2267                              <1> 
  2268                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2269                              <1> _K500:
  2270 00000C73 56                  <1> 	push	esi			; SAVE SI (esi)
  2271 00000C74 FA                  <1> 	cli				; 
  2272 00000C75 8B1D[A45C0000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2273 00000C7B 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2274 00000C7D E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2275 00000C82 3B1D[A05C0000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2276 00000C88 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2277 00000C8A 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2278 00000C8D 891D[A45C0000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2279 00000C93 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2280 00000C95 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2281                              <1> _K502:
  2282 00000C97 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2283                              <1> _K504:
  2284 00000C99 FB                  <1> 	sti				
  2285 00000C9A 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2286 00000C9B E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2287                              <1> 
  2288                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2289                              <1> _K1S:
  2290 00000CA0 FA                  <1> 	cli	; 03/12/2014
  2291 00000CA1 8B1D[A05C0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2292 00000CA7 3B1D[A45C0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2293                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2294 00000CAD 750F                <1> 	jne	short _k1x ; 03/12/2014
  2295                              <1> 	;
  2296                              <1> 	; 03/12/2014
  2297                              <1> 	; 28/08/2014
  2298                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2299                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2300                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2301                              <1> _K1T:                                   ; ASCII READ
  2302 00000CAF FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2303 00000CB0 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2304                              <1> _K1U:	
  2305 00000CB1 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2306 00000CB2 8B1D[A05C0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2307 00000CB8 3B1D[A45C0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2308                              <1> _k1x:
  2309 00000CBE 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2310 00000CBF 9C                  <1> 	pushf				; SAVE FLAGS
  2311 00000CC0 E8D0060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2312 00000CC5 8A1D[955C0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2313 00000CCB 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2314 00000CCD 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2315 00000CD0 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2316 00000CD2 E86A060000          <1> 	call	SND_LED1
  2317 00000CD7 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2318                              <1> _K1V:
  2319 00000CD8 9D                  <1> 	popf				; RESTORE FLAGS
  2320 00000CD9 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2321 00000CDA 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2322                              <1> 	;
  2323 00000CDC 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2324 00000CDF E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2325 00000CE4 891D[A05C0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2326 00000CEA C3                  <1> 	retn				; RETURN
  2327                              <1> 
  2328                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2329                              <1> _K2S:
  2330 00000CEB FA                  <1> 	cli				; INTERRUPTS OFF
  2331 00000CEC 8B1D[A05C0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2332 00000CF2 3B1D[A45C0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2333 00000CF8 668B03              <1> 	mov	ax, [ebx]
  2334 00000CFB 9C                  <1> 	pushf				; SAVE FLAGS
  2335                              <1> 	;push	ax			; SAVE CODE
  2336                              <1> 	; 24/12/2021
  2337 00000CFC 50                  <1> 	push	eax
  2338 00000CFD E893060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2339 00000D02 8A1D[955C0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2340 00000D08 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2341 00000D0A 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2342 00000D0D 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2343 00000D0F E816060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2344                              <1> _K2T:
  2345                              <1> 	;pop	ax			; RESTORE CODE
  2346                              <1> 	; 24/12/2021
  2347 00000D14 58                  <1> 	pop	eax
  2348 00000D15 9D                  <1> 	popf				; RESTORE FLAGS
  2349 00000D16 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2350 00000D17 C3                  <1> 	retn				; RETURN
  2351                              <1> 
  2352                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2353                              <1> _KIO_E_XLAT:
  2354 00000D18 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2355 00000D1A 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2356 00000D1C 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2357 00000D1E 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2358 00000D20 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2359                              <1> _KIO_E_RET:				
  2360 00000D22 C3                  <1> 	retn				; GO BACK
  2361                              <1> 
  2362                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2363                              <1> _KIO_S_XLAT:
  2364 00000D23 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2365 00000D26 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2366 00000D28 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2367 00000D2A 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2368 00000D2C 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2369 00000D2E 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2370 00000D30 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2371                              <1> _kio_ret: ; 03/12/2014
  2372 00000D32 F8                  <1> 	clc
  2373 00000D33 C3                  <1> 	retn
  2374                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2375                              <1> _KIO_S1:				
  2376 00000D34 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2377                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2378 00000D36 C3                  <1> 	retn
  2379                              <1> _KIO_S2:		
  2380 00000D37 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2381 00000D3A 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2382 00000D3C 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2383 00000D3E 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2384 00000D40 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2385 00000D42 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2386 00000D44 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2387                              <1> _KIO_S3:
  2388 00000D46 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2389                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2390 00000D48 75E8                <1> 	jne	short _kio_ret
  2391 00000D4A 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2392 00000D4C 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2393 00000D4E 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2394                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2395                              <1> _KIO_USE:
  2396                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2397 00000D50 C3                  <1> 	retn				; RETURN	
  2398                              <1> _KIO_DIS:
  2399 00000D51 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2400 00000D52 C3                  <1> 	retn				; RETURN
  2401                              <1> 
  2402                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2403                              <1> _K4:    
  2404 00000D53 43                  <1> 	inc     ebx
  2405 00000D54 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2406 00000D55 3B1D[9C5C0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2407                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2408 00000D5B 7206                <1> 	jb	short _K5
  2409 00000D5D 8B1D[985C0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2410                              <1> _K5:
  2411 00000D63 C3                  <1> 	retn
  2412                              <1> 
  2413                              <1> ; 20/02/2015
  2414                              <1> ; 05/12/2014
  2415                              <1> ; 26/08/2014
  2416                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2417                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2418                              <1> ;
  2419                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2420                              <1> ; rombios source code (06/10/1985)
  2421                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2422                              <1> 
  2423                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2424                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2425                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2426                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2427                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2428                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2429                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2430                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2431                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2432                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2433                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2434                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2435                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2436                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2437                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2438                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2439                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2440                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2441                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2442                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2443                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2444                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2445                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2446                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2447                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2448                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2449                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2450                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2451                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2452                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2453                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2454                              <1> F11_M		equ	87		; F11 KEY MAKE
  2455                              <1> F12_M		equ	88		; F12 KEY MAKE
  2456                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2457                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2458                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2459                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2460                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2461                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2462                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2463                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2464                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2465                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2466                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2467                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2468                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2469                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2470                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2471                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2472                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2473                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2474                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2475                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2476                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2477                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2478                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2479                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2480                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2481                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2482                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2483                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2484                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2485                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2486                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2487                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2488                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2489                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2490                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2491                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2492                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2493                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2494                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2495                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2496                              <1> ;
  2497                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2498                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2499                              <1> INTA00		equ	020h		; 8259 PORT
  2500                              <1> 
  2501                              <1> 
  2502                              <1> kb_int:
  2503                              <1> 
  2504                              <1> ; 13/06/2022
  2505                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2506                              <1> ; 17/10/2015 ('ctrlbrk') 
  2507                              <1> ; 05/12/2014
  2508                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2509                              <1> 	;	      instead of pc-at bios - 1985-)
  2510                              <1> ; 26/08/2014
  2511                              <1> ;
  2512                              <1> ; 03/06/86  KEYBOARD BIOS
  2513                              <1> ;
  2514                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2515                              <1> ;										;
  2516                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2517                              <1> ;										;
  2518                              <1> ;--------------------------------------------------------------------------------
  2519                              <1> 
  2520                              <1> KB_INT_1:
  2521 00000D64 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2522                              <1> 	;push	ebp
  2523 00000D65 50                  <1> 	push	eax
  2524 00000D66 53                  <1> 	push	ebx
  2525 00000D67 51                  <1> 	push	ecx
  2526 00000D68 52                  <1> 	push	edx
  2527 00000D69 56                  <1> 	push	esi
  2528 00000D6A 57                  <1> 	push	edi
  2529 00000D6B 1E                  <1> 	push	ds
  2530 00000D6C 06                  <1> 	push	es
  2531 00000D6D FC                  <1> 	cld				; FORWARD DIRECTION
  2532 00000D6E 66B81000            <1> 	mov	ax, KDATA
  2533 00000D72 8ED8                <1> 	mov	ds, ax
  2534 00000D74 8EC0                <1> 	mov	es, ax
  2535                              <1> 	;
  2536                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2537 00000D76 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2538 00000D78 E852050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2539 00000D7D FA                  <1> 	cli				; DISABLE INTERRUPTS
  2540 00000D7E B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2541                              <1> KB_INT_01:
  2542 00000D83 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2543 00000D85 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2544 00000D87 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2545                              <1> 	;
  2546                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2547 00000D89 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2548                              <1> 	;
  2549                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2550                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2551                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2552                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2553                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2554                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2555                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2556                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2557                              <1> 	;
  2558                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2559                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2560 00000D8B FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2561 00000D8C 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2562 00000D8E 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2563                              <1> 	;
  2564                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2565 00000D90 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2566 00000D92 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2567                              <1> 	;
  2568                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2569 00000D94 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2570 00000D95 800D[955C0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2571 00000D9C E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2572                              <1> 	;
  2573                              <1> 	;-----	RESEND THE LAST BYTE
  2574                              <1> KB_INT_4:
  2575 00000DA1 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2576 00000DA2 800D[955C0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2577 00000DA9 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2578                              <1> 	;
  2579                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2580                              <1> KB_INT_2:
  2581                              <1> 	;push 	ax			; SAVE DATA IN
  2582                              <1> 	; 24/12/2021
  2583 00000DAE 50                  <1> 	push	eax
  2584 00000DAF E8E1050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2585 00000DB4 8A1D[955C0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2586 00000DBA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2587 00000DBC 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2588 00000DBF 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2589 00000DC1 E864050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2590                              <1> UP0:
  2591                              <1> 	;pop	ax			; RESTORE DATA IN
  2592                              <1> 	; 24/12/2021
  2593 00000DC6 58                  <1> 	pop	eax
  2594                              <1> ;------------------------------------------------------------------------
  2595                              <1> ;	START OF KEY PROCESSING						;
  2596                              <1> ;------------------------------------------------------------------------
  2597 00000DC7 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2598                              <1> 	;
  2599                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2600 00000DC9 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2601                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2602                              <1> 	; 24/12/2021
  2603 00000DCB 7505                <1> 	jne	short K16
  2604 00000DCD E9E9040000          <1> 	jmp	K62
  2605                              <1> K16:	
  2606 00000DD2 8A3D[965C0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2607                              <1> 	;
  2608                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2609 00000DD8 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2610 00000DDB 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2611 00000DDD 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2612 00000DDF 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2613 00000DE1 7507                <1> 	jne	short RST_RD_ID
  2614 00000DE3 800D[965C0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2615                              <1> RST_RD_ID:
  2616 00000DEA 8025[965C0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2617 00000DF1 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2618                              <1> 	; 24/12/2021
  2619                              <1> 	;jmp	K26
  2620                              <1> 	;
  2621                              <1> TST_ID_2:
  2622 00000DF3 8025[965C0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2623 00000DFA 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2624 00000DFC 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2625 00000DFE 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2626 00000E00 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2627                              <1> 	; 24/12/2021
  2628                              <1> 	;jne	K26
  2629                              <1> 	;
  2630                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2631 00000E02 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2632 00000E05 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2633 00000E07 800D[935C0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2634 00000E0E E817050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2635                              <1> KX_BIT:
  2636 00000E13 800D[965C0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2637 00000E1A E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2638                              <1> 	;
  2639                              <1> NOT_ID:
  2640 00000E1F 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2641 00000E21 750E                <1> 	jne	short TEST_E1
  2642 00000E23 800D[965C0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2643 00000E2A EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2644                              <1> 	; 24/12/2021
  2645 00000E2C E9DA010000          <1> 	jmp	K26A	
  2646                              <1> TEST_E1:	
  2647 00000E31 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2648 00000E33 750C                <1> 	jne	short NOT_HC
  2649 00000E35 800D[965C0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2650 00000E3C E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2651                              <1> 	;
  2652                              <1> NOT_HC:
  2653 00000E41 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2654 00000E43 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2655 00000E46 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2656                              <1> 	;
  2657 00000E48 BF[7E5B0000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2658 00000E4D AE                  <1> 	scasb
  2659                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2660                              <1> 	; 24/12/2021
  2661 00000E4E 7458                <1> 	je	short K16B
  2662 00000E50 AE                  <1> 	scasb
  2663 00000E51 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2664 00000E53 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2665                              <1> 	; 24/12/2021
  2666                              <1> 	;jmp	K26
  2667                              <1> 	;
  2668                              <1> NOT_LC_E0:
  2669 00000E55 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2670 00000E58 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2671 00000E5A B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2672 00000E5F BF[7C5B0000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2673 00000E64 F2AE                <1> 	repne	scasb			; CHECK IT
  2674 00000E66 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2675                              <1> 	; 24/12/2021
  2676                              <1> 	;je	K26A			
  2677                              <1> 	;
  2678 00000E68 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2679 00000E6A 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2680                              <1> 	; 24/12/2021
  2681                              <1> 	;jne	K26
  2682 00000E6C F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2683 00000E6F 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2684                              <1> 	; 24/12/2021
  2685                              <1> 	;jnz	K26
  2686                              <1>         ; 20/02/2015 
  2687 00000E71 F605[945C0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2688 00000E78 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2689                              <1> 	; 24/12/2021
  2690                              <1> 	;jnz	K26
  2691 00000E7A E9D2020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2692                              <1> 	;
  2693                              <1> 	;-----	TEST FOR SYSTEM KEY
  2694                              <1> T_SYS_KEY:
  2695 00000E7F 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2696 00000E81 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2697                              <1> 	;
  2698 00000E83 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2699 00000E86 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2700                              <1> 	;
  2701 00000E88 F605[945C0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2702 00000E8F 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2703                              <1> 	;jnz	K26			
  2704                              <1> 	;
  2705 00000E91 800D[945C0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2706 00000E98 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2707 00000E9A E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2708                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2709 00000E9C B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2710 00000E9E E82C040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2711                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2712                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2713                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2714                              <1> 	;INT	15H			; USER INTERRUPT	
  2715 00000EA3 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2716                              <1> 	;
  2717 00000EA8 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2718                              <1> 	;
  2719                              <1> K16C:
  2720 00000EAD 8025[945C0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2721 00000EB4 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2722 00000EB6 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2723                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2724                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2725                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2726                              <1> 	;
  2727                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2728                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2729                              <1> 	;INT	15H			; USER INTERRUPT
  2730                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2731                              <1> 	;
  2732 00000EB8 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2733                              <1> 	;
  2734                              <1> 	;-----	TEST FOR SHIFT KEYS
  2735                              <1> K16A:
  2736 00000EBD 8A1D[935C0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2737 00000EC3 BF[785B0000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2738 00000EC8 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2739 00000ECD F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2740 00000ECF 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2741                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2742                              <1> 	; 24/12/2021
  2743 00000ED1 7405                <1> 	je	short K17
  2744 00000ED3 E914010000          <1> 	jmp	K25
  2745                              <1> 	;
  2746                              <1> 	;------	SHIFT KEY FOUND
  2747                              <1> K17:
  2748 00000ED8 81EF[795B0000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2749 00000EDE 8AA7[805B0000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2750 00000EE4 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2751 00000EE6 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2752                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2753                              <1> 	; 24/12/2021
  2754 00000EE8 7405                <1> 	jz	short K17C
  2755 00000EEA E999000000          <1> 	jmp	K23
  2756                              <1> 	;
  2757                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2758                              <1> K17C:
  2759 00000EEF 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2760 00000EF2 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2761                              <1> 	;
  2762                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2763 00000EF4 0825[935C0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2764 00000EFA A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2765 00000EFC 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2766                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2767                              <1> 	; 24/12/2021
  2768 00000EFE E901010000          <1> 	jmp	K26
  2769                              <1> K17D:
  2770 00000F03 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2771 00000F06 740B                <1> 	jz 	short K17E		; NO, JUMP
  2772 00000F08 0825[965C0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2773 00000F0E E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2774                              <1> K17E:
  2775 00000F13 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2776 00000F15 0825[945C0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2777 00000F1B E9E4000000          <1> 	jmp	K26
  2778                              <1> 	;
  2779                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2780                              <1> K18:					; SHIFT-TOGGLE
  2781 00000F20 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2782 00000F23 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2783                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2784                              <1> 	; 24/12/2021
  2785 00000F25 E9C2000000          <1> 	jmp	K25
  2786                              <1> K18A:
  2787 00000F2A 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2788 00000F2C 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2789 00000F2E F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2790 00000F31 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2791                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2792                              <1> 	; 24/12/2021
  2793 00000F33 E9B4000000          <1> 	jmp	K25
  2794                              <1> K18B:
  2795 00000F38 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2796 00000F3B 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2797                              <1> K19:	
  2798 00000F3D F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2799 00000F40 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2800 00000F42 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2801 00000F45 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2802                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2803 00000F47 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2804 00000F49 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2805                              <1> K21:					; MIGHT BE NUMERIC
  2806 00000F4E F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2807 00000F51 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2808                              <1> 	;
  2809                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2810 00000F53 8425[945C0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2811                              <1> 	;jnz	K26
  2812                              <1> 	; 24/12/2021
  2813 00000F59 7405                <1> 	jz	short K22A
  2814 00000F5B E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2815                              <1> K22A:
  2816 00000F60 0825[945C0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2817 00000F66 3025[935C0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2818                              <1> 	;
  2819                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2820 00000F6C F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2821 00000F6F 7407                <1> 	jz	short K22B		; GO IF NOT
  2822                              <1> 	;
  2823                              <1> 	; 24/12/2021
  2824                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2825 00000F71 50                  <1> 	push	eax
  2826 00000F72 E8B3030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2827                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2828 00000F77 58                  <1> 	pop	eax
  2829                              <1> K22B:
  2830 00000F78 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2831                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2832                              <1> 	; 24/12/2021
  2833 00000F7A 7405                <1> 	je	short K22C
  2834 00000F7C E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2835                              <1> K22C:
  2836 00000F81 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2837 00000F83 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2838                              <1> 	;
  2839                              <1> 	;-----	BREAK SHIFT FOUND
  2840                              <1> K23:					; BREAK-SHIFT-FOUND
  2841 00000F88 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2842 00000F8B F6D4                <1> 	not	ah			; INVERT MASK
  2843 00000F8D 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2844 00000F8F 2025[935C0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2845 00000F95 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2846 00000F98 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2847                              <1> 	;
  2848 00000F9A F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2849 00000F9D 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2850 00000F9F 2025[965C0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2851 00000FA5 EB08                <1> 	jmp	short K23B		; CONTINUE
  2852                              <1> K23A:
  2853 00000FA7 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2854 00000FA9 2025[945C0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2855                              <1> K23B:
  2856 00000FAF 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2857 00000FB1 A0[965C0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2858 00000FB6 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2859 00000FB8 0A05[945C0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2860 00000FBE D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2861 00000FC0 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2862 00000FC2 0805[935C0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2863 00000FC8 88E0                <1> 	mov	al, ah
  2864                              <1> K23D:
  2865 00000FCA 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2866 00000FCC 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2867                              <1> 	;	
  2868                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2869 00000FCE A0[975C0000]        <1> 	mov	al, [ALT_INPUT]
  2870 00000FD3 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2871 00000FD5 8825[975C0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2872 00000FDB 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2873 00000FDD 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2874 00000FDF E9B4020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2875                              <1> 	;
  2876                              <1> K24:					; BREAK-TOGGLE
  2877 00000FE4 2025[945C0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2878 00000FEA EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2879                              <1> 	;
  2880                              <1> 	;-----	TEST FOR HOLD STATE
  2881                              <1> 					; AL, AH = SCAN CODE
  2882                              <1> K25:					; NO-SHIFT-FOUND
  2883 00000FEC 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2884 00000FEE 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2885 00000FF0 F605[945C0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2886 00000FF7 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2887 00000FF9 3C45                <1> 	cmp	al, NUM_KEY
  2888 00000FFB 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2889 00000FFD 8025[945C0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2890                              <1> 	;
  2891                              <1> K26:
  2892 00001004 8025[965C0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2893                              <1> K26A:					; INTERRUPT-RETURN
  2894 0000100B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2895 0000100C B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2896 0000100E E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2897                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2898 00001010 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2899 00001012 E8B8020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2900                              <1> K27A:
  2901 00001017 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2902 00001018 07                  <1> 	pop	es			; RESTORE REGISTERS
  2903 00001019 1F                  <1> 	pop	ds
  2904 0000101A 5F                  <1> 	pop	edi
  2905 0000101B 5E                  <1> 	pop	esi
  2906 0000101C 5A                  <1> 	pop	edx
  2907 0000101D 59                  <1> 	pop	ecx
  2908 0000101E 5B                  <1> 	pop	ebx
  2909 0000101F 58                  <1> 	pop	eax
  2910                              <1> 	;pop	ebp
  2911 00001020 CF                  <1> 	iret				; RETURN
  2912                              <1> 
  2913                              <1> 	;-----	NOT IN	HOLD STATE
  2914                              <1> K28:					; NO-HOLD-STATE
  2915 00001021 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2916 00001023 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2917                              <1> 	;
  2918 00001025 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2919 00001028 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2920                              <1>         ; 24/12/2021
  2921                              <1> 	;jz      K38
  2922                              <1> 	;
  2923 0000102A F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2924 0000102D 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2925                              <1> 	; 28/02/2015
  2926 0000102F F605[945C0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2927 00001036 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2928                              <1> 	; 24/12/2021
  2929                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2930                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2931 00001038 E9CD000000          <1> K28A:	jmp	K38
  2932                              <1> 	;
  2933                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2934                              <1> K29:					; TEST-RESET
  2935 0000103D F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2936 00001040 740B                <1> 	jz	short K31		; NO_RESET
  2937 00001042 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2938 00001044 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2939                              <1> 	;
  2940                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2941                              <1>  	; 26/08/2014
  2942                              <1> cpu_reset:
  2943                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2944                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2945 00001046 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2946 00001048 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2947                              <1> khere:
  2948 0000104A F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2949 0000104B EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2950                              <1> 
  2951                              <1> 	;
  2952                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2953                              <1> K31:					; NO-RESET
  2954 0000104D 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2955 0000104F 7507                <1> 	jne	short K311		; NOT THERE
  2956 00001051 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2957 00001053 E932020000          <1>         jmp     K57                     ; BUFFER_FILL
  2958                              <1> K311:
  2959 00001058 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2960 0000105A 7509                <1> 	jne	short K312		; NOT THERE
  2961 0000105C 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2962 00001060 E925020000          <1>         jmp     K57                     ; BUFFER_FILL
  2963                              <1> K312:
  2964 00001065 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2965 00001067 7471                <1>         je	short K37B              ; GO PROCESS
  2966 00001069 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2967 0000106B 746D                <1>         je	short K37B              ; GO PROCESS
  2968                              <1> 	;
  2969                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2970                              <1> K32:					; ALT-KEY-PAD
  2971 0000106D BF[545B0000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2972 00001072 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2973 00001077 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2974 00001079 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2975 0000107B F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2976                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2977                              <1> 	; 24/12/2021
  2978 0000107E 751C                <1> 	jnz	short K32B
  2979 00001080 81EF[555B0000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2980 00001086 A0[975C0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2981 0000108B B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2982 0000108D F6E4                <1> 	mul	ah
  2983 0000108F 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2984 00001092 A2[975C0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2985                              <1> K32A:
  2986 00001097 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2987                              <1> K32B:
  2988                              <1> 	; 24/12/2021
  2989 0000109C EB66                <1> 	jmp	K37C
  2990                              <1> 	;
  2991                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2992                              <1> K33:					; NO-ALT-KEYPAD
  2993 0000109E C605[975C0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2994 000010A5 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2995 000010AA F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2996 000010AC 744F                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2997                              <1> 	;
  2998                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2999                              <1> K34:					; ALT-TOP-ROW
  3000 000010AE 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  3001 000010B0 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  3002 000010B2 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  3003 000010B4 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  3004 000010B6 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  3005 000010B9 EB42                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3006                              <1> 	;
  3007                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  3008                              <1> K35:					; ALT-FUNCTION
  3009 000010BB 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  3010 000010BD 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  3011 000010BF 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  3012 000010C1 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  3013 000010C3 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  3014 000010C6 EB35                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  3015                              <1> K35A:
  3016 000010C8 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  3017 000010CB 7425                <1> 	jz	short K37		; NO, JUMP
  3018 000010CD 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3019 000010CF 7510                <1>         jne     short K35B              ; NOT THERE
  3020 000010D1 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3021 000010D5 E9B0010000          <1> 	jmp	K57			; BUFFER FILL
  3022                              <1> K37B:
  3023 000010DA B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3024 000010DC E9A9010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3025                              <1> K35B:
  3026 000010E1 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3027 000010E3 741F                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3028 000010E5 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3029 000010E7 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3030                              <1>         ; 24/12/2021
  3031                              <1> 	;jne	K26
  3032 000010E9 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3033 000010ED E998010000          <1> 	jmp	K57			; BUFFER FILL
  3034                              <1> K37:
  3035 000010F2 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3036 000010F4 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3037 000010F6 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3038 000010F8 779D                <1>         ja	short K32A		; IF SO, IGNORE
  3039                              <1> 	; 13/06/2022
  3040                              <1>         ;ja	K26
  3041 000010FA 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3042                              <1> K37A:
  3043 000010FD B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3044 000010FF E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3045                              <1> K37C:
  3046 00001104 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3047 00001106 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3048 00001108 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3049                              <1> 	;
  3050                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3051                              <1> K38:					; NOT-ALT-SHIFT
  3052                              <1> 					; BL STILL HAS SHIFT FLAGS
  3053 0000110A F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3054 0000110D 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3055                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3056                              <1> 	; 24/12/2021
  3057 0000110F E9AB000000          <1> 	jmp	K44
  3058                              <1> 	;
  3059                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3060                              <1> 	;-----	TEST FOR BREAK
  3061                              <1> K38A:
  3062 00001114 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3063 00001116 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3064 00001118 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3065 0000111B 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3066 0000111D F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3067 00001120 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3068                              <1> K38B:
  3069 00001122 8B1D[A05C0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3070 00001128 891D[A45C0000]      <1> 	mov	[BUFFER_TAIL], ebx
  3071 0000112E C605[925C0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3072                              <1> 	;
  3073                              <1> 	;-----	ENABLE KEYBOARD
  3074 00001135 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3075 00001137 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3076                              <1> 	;
  3077                              <1> 	; CTRL+BREAK code here !!!
  3078                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3079                              <1> 	; 17/10/2015	
  3080 0000113C E88C190000          <1> 	call	ctrlbrk ; control+break subroutine
  3081                              <1> 	;
  3082                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3083                              <1> 	; 24/12/2021
  3084 00001141 29C0                <1> 	sub	eax, eax
  3085 00001143 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3086                              <1> 	;
  3087                              <1> 	;-----	TEST FOR PAUSE
  3088                              <1> K39:					; NO_BREAK
  3089 00001148 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3090 0000114B 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3091 0000114D 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3092 0000114F 7533                <1> 	jne	short K41		; NO-PAUSE
  3093                              <1> K39P:
  3094 00001151 800D[945C0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3095                              <1> 	;
  3096                              <1> 	;-----	ENABLE KEYBOARD
  3097 00001158 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3098 0000115A E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3099                              <1> K39A:
  3100 0000115F B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3101 00001161 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3102                              <1> 	;
  3103                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3104 00001163 803D[905C0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3105 0000116A 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3106 0000116C 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3107 00001170 A0[915C0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3108 00001175 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3109                              <1> 	;
  3110                              <1> K40:					; PAUSE-LOOP
  3111 00001176 F605[945C0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3112 0000117D 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3113                              <1> 	;
  3114 0000117F E98CFEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3115                              <1>         ;
  3116                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3117                              <1> K41:					; NO-PAUSE
  3118 00001184 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3119 00001186 7513                <1> 	jne	short K42		; NOT-KEY-55
  3120 00001188 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3121 0000118B 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3122 0000118D F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3123 00001190 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3124                              <1> K41A:	
  3125 00001192 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3126 00001196 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3127                              <1> 	;
  3128                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3129                              <1> K42:					; NOT-KEY-55
  3130 0000119B 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3131 0000119D 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3132 0000119F 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3133 000011A1 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3134 000011A3 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3135 000011A6 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3136 000011A8 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3137 000011AC E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3138                              <1> K42A:
  3139                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3140 000011B1 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3141                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3142                              <1> 	;;jb	K56 ; 20/02/2015
  3143                              <1> 	;;jmp	K64 ; 20/02/2015
  3144                              <1> K42B:
  3145 000011B3 BB[885B0000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3146                              <1> 	;;jmp	K64
  3147                              <1> 	;jb	K56 ;; 20/02/2015	
  3148                              <1> 	; 24/12/2021
  3149 000011B8 7267                <1> 	jb	short K45F
  3150 000011BA E9B9000000          <1> 	jmp	K64	
  3151                              <1>         ;
  3152                              <1> 	;-----	NOT IN CONTROL SHIFT
  3153                              <1> K44:					; NOT-CTL-SHIFT
  3154 000011BF 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3155 000011C1 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3156 000011C3 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3157 000011C6 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3158 000011C8 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3159 000011CB 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3160 000011CD EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3161                              <1> K44A:
  3162 000011CF F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3163 000011D2 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3164                              <1> 	;
  3165                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3166                              <1> K44B:
  3167 000011D4 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3168 000011D6 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3169 000011DB B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3170 000011DD E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3171                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3172                              <1> 	;PUSH 	BP			; SAVE POINTER
  3173                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3174                              <1> 	;POP	BP			; RESTORE POINTER
  3175 000011DF 8025[965C0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3176 000011E6 E925FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3177                              <1> 	;
  3178                              <1> 	;-----	HANDLE IN-CORE KEYS
  3179                              <1> K45:					; NOT-PRINT-SCREEN
  3180 000011EB 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3181 000011ED 7734                <1> 	ja	short K46		; JUMP IF NOT
  3182 000011EF 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3183 000011F1 7505                <1> 	jne	short K45A		; NO, JUMP
  3184 000011F3 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3185 000011F6 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3186                              <1> K45A:
  3187 000011F8 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3188 000011FD BF[5E5B0000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3189 00001202 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3190                              <1> 		; 20/02/2015
  3191 00001204 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3192                              <1> 	;
  3193 00001206 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3194 00001209 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3195                              <1> K45B:
  3196 0000120B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3197 0000120E 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3198                              <1> 					; NO, LOWERCASE
  3199                              <1> K45C:
  3200 00001210 BB[E05B0000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3201 00001215 EB51                <1> 	jmp	short K56	
  3202                              <1> K45D:					; ALMOST-CAPS-STATE
  3203 00001217 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3204 0000121A 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3205                              <1> K45E:
  3206 0000121C BB[385C0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3207 00001221 EB45                <1> K45F:	jmp	short K56
  3208                              <1> 	;
  3209                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3210                              <1> K46:					; NOT IN-CORE AREA
  3211 00001223 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3212                              <1> 	;ja	short K47		; JUMP IF NOT
  3213                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3214 00001225 7635                <1> 	jna	short K53		
  3215                              <1> 	;
  3216                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3217                              <1> K47:					; NOT F1 - F10
  3218 00001227 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3219 00001229 772D                <1> 	ja	short K52		; JUMP IF NOT
  3220                              <1> 	;
  3221                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3222                              <1> K48:
  3223 0000122B 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3224 0000122D 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3225 0000122F 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3226 00001231 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3227 00001233 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3228 00001236 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3229                              <1> 	;		
  3230 00001238 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3231 0000123B 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3232 0000123D F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3233                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3234 00001240 75DA                <1> 	jnz	short K45E
  3235                              <1> 	;
  3236                              <1> 	;-----	BASE CASE FOR KEYPAD
  3237                              <1> K49:					
  3238 00001242 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3239 00001244 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3240 00001246 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3241 00001248 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3242                              <1> K49A:
  3243 0000124A BB[E05B0000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3244 0000124F EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3245                              <1> 	;
  3246                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3247                              <1> K50:					; ALMOST-NUM-STATE
  3248 00001251 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3249 00001254 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3250 00001256 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3251                              <1> 	;
  3252                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3253                              <1> K52:					; NOT A NUMPAD KEY
  3254 00001258 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3255                              <1> 	;jne	short K53		; JUMP IF NOT
  3256                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3257 0000125A 74AF                <1> 	je	short K45B		
  3258                              <1> 	;
  3259                              <1> 	;-----	MUST BE F11 OR F12 
  3260                              <1> K53:					; F1 - F10 COME HERE, TOO
  3261 0000125C F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3262 0000125F 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3263                              <1> 		; 20/02/2015 
  3264 00001261 BB[385C0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3265 00001266 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3266                              <1> 	;
  3267                              <1> 	;-----	TRANSLATE THE CHARACTER
  3268                              <1> K56:					; TRANSLATE-CHAR
  3269 00001268 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3270 0000126A D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3271 0000126B F605[965C0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3272 00001272 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3273 00001274 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3274 00001276 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3275                              <1> 	;
  3276                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3277                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3278 00001278 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3279 0000127A D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3280 0000127B 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3281 0000127D B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3282 0000127F F605[965C0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3283 00001286 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3284 00001288 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3285                              <1> 	;
  3286                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3287                              <1> K57:					; BUFFER_FILL
  3288 0000128A 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3289 0000128C 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3290                              <1> 	; 24/12/2021
  3291                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3292 0000128E 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3293                              <1> 	; 24/12/2021
  3294 00001291 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3295                              <1> 	;je	K26			; INTERRUPT_RETURN
  3296                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3297 00001293 E96CFDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3298                              <1> K61:					; NOT-CAPS-STATE
  3299 00001298 8B1D[A45C0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3300 0000129E 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3301 000012A0 E8AEFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3302 000012A5 3B1D[A05C0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3303 000012AB 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3304 000012AD 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3305 000012B0 891D[A45C0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3306 000012B6 E949FDFFFF          <1> 	jmp	K26
  3307                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3308                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3309                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3310                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3311                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3312                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3313                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3314                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3315                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3316                              <1> 	;;jmp   K27                    
  3317                              <1> 	;
  3318                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3319                              <1> K62:
  3320 000012BB B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3321 000012BD E620                <1> 	out	INTA00, al
  3322 000012BF 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3323 000012C3 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3324 000012C5 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3325 000012CA E941FDFFFF          <1> 	jmp     K27			; EXIT   
  3326                              <1> 
  3327                              <1> SHIP_IT:
  3328                              <1> 	;---------------------------------------------------------------------------------
  3329                              <1> 	; SHIP_IT
  3330                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3331                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3332                              <1> 	;---------------------------------------------------------------------------------
  3333                              <1> 	;
  3334                              <1> 	;push	ax			; SAVE DATA TO SEND
  3335                              <1> 	; 24/12/2021
  3336 000012CF 50                  <1> 	push	eax
  3337                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3338 000012D0 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3339                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3340 000012D1 B900000100          <1> 	mov	ecx, 10000h			
  3341                              <1> S10:
  3342 000012D6 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3343 000012D8 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3344 000012DA E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3345                              <1> 
  3346                              <1> 	;pop	ax			; GET DATA TO SEND
  3347                              <1> 	; 24/12/2021
  3348 000012DC 58                  <1> 	pop	eax
  3349 000012DD E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3350 000012DF FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3351 000012E0 C3                  <1> 	retn				; RETURN TO CALLER
  3352                              <1> 
  3353                              <1> SND_DATA:
  3354                              <1> 	; ---------------------------------------------------------------------------------
  3355                              <1> 	; SND_DATA
  3356                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3357                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3358                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3359                              <1> 	; ---------------------------------------------------------------------------------
  3360                              <1> 	;
  3361                              <1> 	;push	ax			; SAVE REGISTERS
  3362                              <1> 	;push	bx
  3363                              <1> 	; 24/12/2021
  3364 000012E1 50                  <1> 	push	eax
  3365 000012E2 53                  <1> 	push	ebx
  3366 000012E3 51                  <1> 	push	ecx
  3367 000012E4 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3368 000012E6 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3369                              <1> SD0:
  3370 000012E8 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3371 000012E9 8025[955C0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3372                              <1> 	;
  3373                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3374 000012F0 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3375                              <1> SD5:
  3376 000012F5 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3377 000012F7 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3378 000012F9 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3379                              <1> 	;
  3380 000012FB 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3381 000012FD E660                <1> 	out	PORT_A, al		; SEND BYTE
  3382 000012FF FB                  <1> 	sti				; ENABLE INTERRUPTS
  3383                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3384 00001300 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3385                              <1> SD1:
  3386 00001305 F605[955C0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3387 0000130C 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3388 0000130E E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3389                              <1> SD2:
  3390 00001310 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3391 00001312 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3392 00001314 800D[955C0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3393 0000131B EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3394                              <1> SD3:
  3395 0000131D F605[955C0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3396 00001324 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3397                              <1> SD4:	
  3398 00001326 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3399                              <1> 	;pop	bx
  3400                              <1> 	;pop	ax
  3401                              <1> 	; 24/12/2021
  3402 00001327 5B                  <1> 	pop	ebx
  3403 00001328 58                  <1> 	pop	eax
  3404 00001329 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3405                              <1> 
  3406                              <1> SND_LED:
  3407                              <1> 	; ---------------------------------------------------------------------------------
  3408                              <1> 	; SND_LED
  3409                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3410                              <1> 	;
  3411                              <1> 	;----------------------------------------------------------------------------------
  3412                              <1> 	;
  3413 0000132A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3414 0000132B F605[955C0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3415 00001332 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3416                              <1> 	;
  3417 00001334 800D[955C0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3418 0000133B B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3419 0000133D E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3420 0000133F EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3421                              <1> SND_LED1:
  3422 00001341 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3423 00001342 F605[955C0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3424 00001349 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3425                              <1> 	;
  3426 0000134B 800D[955C0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3427                              <1> SL0:
  3428 00001352 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3429 00001354 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3430 00001359 FA                  <1> 	cli
  3431 0000135A E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3432 0000135F 8025[955C0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3433 00001366 0805[955C0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3434 0000136C F605[955C0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3435 00001373 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3436                              <1> 	;
  3437 00001375 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3438 0000137A FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3439 0000137B F605[955C0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3440 00001382 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3441                              <1> SL2:
  3442 00001384 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3443 00001386 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3444 0000138B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3445                              <1> SL3:
  3446 0000138C 8025[955C0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3447                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3448 00001393 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3449 00001394 C3                  <1> 	retn				; RETURN TO CALLER
  3450                              <1> 
  3451                              <1> MAKE_LED:
  3452                              <1> 	;---------------------------------------------------------------------------------
  3453                              <1> 	; MAKE_LED
  3454                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3455                              <1> 	;	THE MODE INDICATORS.
  3456                              <1> 	;---------------------------------------------------------------------------------
  3457                              <1> 	;
  3458                              <1> 	;push 	cx			; SAVE CX
  3459 00001395 A0[935C0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3460 0000139A 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3461                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3462                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3463 0000139C C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3464 0000139F 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3465                              <1> 	;pop	cx
  3466 000013A1 C3                  <1> 	retn				; RETURN TO CALLER
  3467                              <1> 
  3468                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3469                              <1> 
  3470                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1891                                  
  1892                                  %include 'video.inc' ; 07/03/2015
  1893                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - VIDEO.INC
  1894                              <1> ; Last Modification: 14/06/2022
  1895                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1896                              <1> ;
  1897                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1898                              <1> 
  1899                              <1> ; 14/06/2022
  1900                              <1> ; 26/02/2022
  1901                              <1> ; 07/02/2022
  1902                              <1> ; 02/02/2022 (simplified scroll up)
  1903                              <1> ; 16/01/2016
  1904                              <1> ; 30/06/2015
  1905                              <1> ; 27/06/2015
  1906                              <1> ; 11/03/2015
  1907                              <1> ; 02/09/2014
  1908                              <1> ; 30/08/2014
  1909                              <1> ; VIDEO FUNCTIONS
  1910                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1911                              <1> 
  1912                              <1> write_tty:
  1913                              <1> 	; 02/02/2022
  1914                              <1> 	; 13/08/2015
  1915                              <1> 	; 02/09/2014
  1916                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1917                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1918                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1919                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1920                              <1> 	;
  1921                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1922                              <1> 	;	   AL = Character to be written
  1923                              <1> 	;	   EBX = Video Page (0 to 7)
  1924                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1925                              <1> 
  1926                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1927                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1928                              <1> 
  1929                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1930                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1931                              <1> ;
  1932                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1933                              <1> ;
  1934                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1935                              <1> ;										:
  1936                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1937                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1938                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1939                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1940                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1941                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1942                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1943                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1944                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1945                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1946                              <1> ;   THE 0 COLOR IS USED.							:
  1947                              <1> ;   ENTRY --									:
  1948                              <1> ;     (AH) = CURRENT CRT MODE							:
  1949                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1950                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1951                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1952                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1953                              <1> ;   EXIT -- 									:
  1954                              <1> ;     ALL REGISTERS SAVED							:
  1955                              <1> ;--------------------------------------------------------------------------------
  1956                              <1> 
  1957 000013A2 FA                  <1> 	cli
  1958                              <1> 	;
  1959                              <1> 	; READ CURSOR (04/12/2013)
  1960                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1961 000013A3 08FF                <1> 	or	bh, bh
  1962                              <1> 	;jnz	beeper
  1963                              <1> 	; 02/02/2022
  1964 000013A5 7405                <1> 	jz	short u14
  1965 000013A7 E992000000          <1> 	jmp	beeper
  1966                              <1> u14:
  1967                              <1> 	; 02/02/2022
  1968                              <1> 	;; 01/09/2014
  1969                              <1> 	;cmp	byte [CRT_MODE], 3
  1970                              <1> 	;je	short m3
  1971                              <1> 	;;
  1972                              <1> 	;call	set_mode
  1973                              <1> m3:
  1974 000013AC 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1975                              <1> 	;shl	si, 1
  1976                              <1> 	; 02/02/2022
  1977 000013AE D1E6                <1> 	shl	esi, 1
  1978 000013B0 81C6[56620000]      <1> 	add	esi, cursor_posn
  1979 000013B6 668B16              <1> 	mov	dx, [esi]
  1980                              <1> 	;
  1981                              <1> 	; dx now has the current cursor position
  1982                              <1> 	;
  1983 000013B9 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1984 000013BB 7647                <1> 	jbe	short u8
  1985                              <1> 	;
  1986                              <1> 	; write the char to the screen
  1987                              <1> u0:	
  1988                              <1> 	; ah = attribute/color
  1989                              <1> 	; al = character
  1990                              <1> 	; bl = video page number (0 to 7)
  1991                              <1> 	; bh = 0
  1992                              <1> 	;
  1993 000013BD E8D2010000          <1> 	call	write_c_current
  1994                              <1> 	;
  1995                              <1> 	; position the cursor for next char
  1996 000013C2 FEC2                <1> 	inc	dl		; next column
  1997                              <1> 	;cmp	dl, [CRT_COLS]
  1998 000013C4 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1999                              <1>         ;jne	set_cpos
  2000                              <1> 	; 02/02/2022
  2001 000013C7 7405                <1> 	je	short u13
  2002 000013C9 E9DE000000          <1> 	jmp	set_cpos
  2003                              <1> u13:
  2004 000013CE B200                <1> 	mov	dl, 0		; column = 0
  2005                              <1> u10:				; (line feed found)
  2006 000013D0 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  2007 000013D3 7228                <1> 	jb 	short u6
  2008                              <1> 	;
  2009                              <1> 	; scroll required
  2010                              <1> u1:	
  2011                              <1> 	; SET CURSOR POSITION (04/12/2013)
  2012 000013D5 E8D2000000          <1> 	call	set_cpos
  2013                              <1> 	;
  2014                              <1> 	; determine value to fill with during scroll
  2015                              <1> u2:
  2016                              <1> 	; READ_AC_CURRENT		:
  2017                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  2018                              <1> 	;    AT THE CURRENT CURSOR POSITION
  2019                              <1> 	;
  2020                              <1> 	; INPUT				
  2021                              <1> 	;	(AH) = CURRENT CRT MODE
  2022                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2023                              <1> 	;	(DS) = DATA SEGMENT
  2024                              <1> 	;	(ES) = REGEN SEGMENT
  2025                              <1> 	; OUTPUT			
  2026                              <1> 	;	(AL) = CHARACTER READ
  2027                              <1> 	;	(AH) = ATTRIBUTE READ
  2028                              <1> 	;
  2029                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2030                              <1> 	;
  2031                              <1> 	; bl = video page number
  2032                              <1> 	;
  2033 000013DA E829010000          <1> 	call	find_position	; get regen location and port address
  2034                              <1> 	; dx = status port
  2035                              <1> 	; esi = cursor location/address
  2036                              <1> p11:
  2037 000013DF FB                  <1> 	sti			; enable interrupts
  2038 000013E0 90                  <1> 	nop			; allow for small interupts window
  2039 000013E1 FA                  <1> 	cli			; blocks interrupts for single loop
  2040 000013E2 EC                  <1> 	in	al, dx		; get status from adapter
  2041 000013E3 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2042 000013E5 75F8                <1> 	jnz	short p11	; wait until it is
  2043                              <1> p12:				; now wait for either retrace high
  2044 000013E7 EC                  <1> 	in	al, dx		; get status
  2045 000013E8 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2046 000013EA 74FB                <1> 	jz	short p12	; wait until either is active	
  2047                              <1> p13:
  2048 000013EC 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2049 000013F2 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2050                              <1> 	;
  2051                              <1> 	; al = character, ah = attribute
  2052                              <1> 	;
  2053 000013F5 FB                  <1> 	sti
  2054                              <1> 	; bl = video page number 	
  2055                              <1> u3:
  2056                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2057                              <1> 	;;sub	cx, cx		; upper left corner
  2058                              <1> 	;;mov	dh, 25-1 	; lower right row
  2059                              <1> 	;;;mov	dl, [CRT_COLS]
  2060                              <1> 	;mov	dl, 80		; lower right column	
  2061                              <1> 	;;dec	dl
  2062                              <1> 	;;mov	dl, 79
  2063                              <1> 
  2064                              <1> 	;;call	scroll_up	; 04/12/2013
  2065                              <1> 	;;; 11/03/2015
  2066                              <1> 	; 02/09/2014
  2067                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2068                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2069                              <1> 	; 11/03/2015
  2070                              <1> 	;sub	cx, cx
  2071                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2072                              <1> 	;
  2073                              <1> 	; 02/02/2022 (simplied scroll up)
  2074                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2075                              <1> 	;
  2076 000013F6 B001                <1> 	mov	al, 1		; scroll 1 line up
  2077                              <1> 		; ah = attribute
  2078 000013F8 E935010000          <1> 	jmp	scroll_up
  2079                              <1> ;u4:
  2080                              <1> 	;;int	10h		; video-call return
  2081                              <1> 				; scroll up the screen
  2082                              <1> 				; tty return
  2083                              <1> ;u5:
  2084                              <1> 	;retn			; return to the caller
  2085                              <1> 
  2086                              <1> u6:				; set-cursor-inc
  2087 000013FD FEC6                <1> 	inc	dh		; next row
  2088                              <1> 				; set cursor
  2089                              <1> ;u7:					
  2090                              <1> 	;;mov	ah, 02h
  2091                              <1> 	;;jmp	short u4 	; establish the new cursor
  2092                              <1> 	;call	set_cpos
  2093                              <1> 	;jmp 	short u5
  2094 000013FF E9A8000000          <1> 	jmp     set_cpos
  2095                              <1> 
  2096                              <1> 	; check for control characters
  2097                              <1> u8:
  2098 00001404 7434                <1> 	je	short u9
  2099 00001406 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2100 00001408 74C6                <1> 	je	short u10
  2101 0000140A 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2102 0000140C 7430                <1> 	je	short u11
  2103 0000140E 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2104                              <1> 	;jne	short u0
  2105 00001410 7420                <1> 	je	short bs	; 12/12/2013
  2106                              <1> 	; 12/12/2013 (tab stop)
  2107 00001412 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2108 00001414 75A7                <1> 	jne	short u0
  2109 00001416 88D0                <1> 	mov	al, dl
  2110 00001418 6698                <1> 	cbw
  2111 0000141A B108                <1> 	mov	cl, 8
  2112 0000141C F6F1                <1> 	div	cl
  2113 0000141E 28E1                <1> 	sub	cl, ah
  2114                              <1> ts:
  2115                              <1> 	; 02/09/2014
  2116                              <1> 	; 01/09/2014
  2117 00001420 B020                <1> 	mov	al, 20h
  2118                              <1> tsloop:
  2119                              <1> 	;push	cx
  2120                              <1> 	;push	ax
  2121                              <1> 	; 02/02/2022
  2122 00001422 51                  <1> 	push	ecx
  2123 00001423 50                  <1> 	push	eax
  2124 00001424 30FF                <1> 	xor 	bh, bh
  2125                              <1> 	;mov	bl, [active_page]
  2126 00001426 E881FFFFFF          <1> 	call	m3
  2127                              <1> 	; 02/02/2022
  2128 0000142B 58                  <1> 	pop	eax
  2129 0000142C 59                  <1>  	pop	ecx
  2130                              <1> 	;pop	ax  ; ah = attribute/color
  2131                              <1> 	;pop	cx
  2132 0000142D FEC9                <1> 	dec	cl
  2133 0000142F 75F1                <1> 	jnz	short tsloop
  2134 00001431 C3                  <1> 	retn
  2135                              <1> bs:	
  2136                              <1> 	; back space found
  2137 00001432 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2138                              <1> 	;je	short u7 	; set_cursor
  2139 00001434 7476                <1> 	jz	short set_cpos
  2140                              <1> 	;dec	dx     		; no -- just move it back
  2141                              <1> 	; 02/02/2022
  2142 00001436 FECA                <1> 	dec	dl
  2143                              <1> 	;jmp	short u7
  2144 00001438 EB72                <1> 	jmp	short set_cpos
  2145                              <1> 
  2146                              <1> 	; carriage return found
  2147                              <1> u9:
  2148 0000143A B200                <1> 	mov	dl, 0 		; move to first column
  2149                              <1> 	;jmp	short u7
  2150 0000143C EB6E                <1> 	jmp	short set_cpos
  2151                              <1> 
  2152                              <1> 	; line feed found
  2153                              <1> ;u10:
  2154                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2155                              <1> ;	jne	short u6 	; no, just set the cursor
  2156                              <1> ;       jmp     u1              ; yes, scroll the screen
  2157                              <1> 
  2158                              <1> beeper: 
  2159                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2160                              <1> 	; 18/01/2014
  2161                              <1> 	; 03/12/2013
  2162                              <1> 	; bell found
  2163                              <1> u11:
  2164 0000143E FB                  <1> 	sti
  2165 0000143F 3A1D[66620000]      <1> 	cmp	bl, [active_page]
  2166 00001445 7551                <1> 	jne	short u12	; Do not sound the beep 
  2167                              <1> 				; if it is not written on the active page
  2168 00001447 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2169 0000144B B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2170                              <1> 	;call	beep		; sound the pod bell
  2171                              <1> 	;jmp	short u5 	; tty_return
  2172                              <1> 	;retn
  2173                              <1> 	
  2174                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2175                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2176                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2177                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2178                              <1> 
  2179                              <1> beep:
  2180                              <1> 	; 07/02/2015
  2181                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2182                              <1> 	; 18/01/2014
  2183                              <1> 	; 03/12/2013
  2184                              <1> 	;
  2185                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2186                              <1> 	;
  2187                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2188                              <1> 	;
  2189                              <1> 	; ENTRY:
  2190                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2191                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2192                              <1> 	; EXIT:			:
  2193                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2194                              <1> 
  2195 0000144D 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2196 0000144E FA                  <1> 	cli			; block interrupts during update
  2197 0000144F B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2198 00001451 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2199 00001453 EB00                <1> 	jmp	$+2		; I/O delay
  2200 00001455 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2201 00001457 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2202 00001459 EB00                <1> 	jmp	$+2		; I/O delay
  2203 0000145B 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2204 0000145D E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2205 0000145F E461                <1> 	in	al, PORT_B	; get current setting of port
  2206 00001461 88C4                <1> 	mov	ah, al		; save that setting
  2207 00001463 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2208 00001465 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2209                              <1> 	;popf	; 18/01/2014
  2210 00001467 FB                  <1> 	sti
  2211                              <1> g7:				; 1/64 second per count (bl)
  2212 00001468 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2213 0000146D E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2214 00001472 FECB                <1> 	dec	bl		; (bl) length count expired?
  2215 00001474 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2216                              <1> 	;
  2217                              <1> 	;pushf			; save interrupt status
  2218 00001476 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2219 00001477 E461                <1> 	in	al, PORT_B	; get current port value
  2220                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2221 00001479 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2222 0000147B 20C4                <1>         and	ah, al		; someone turned them off during beep
  2223 0000147D 88E0                <1> 	mov	al, ah		; recover value of port
  2224                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2225 0000147F 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2226 00001481 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2227                              <1> 	;popf			; restore interrupt flag state
  2228 00001483 FB                  <1> 	sti
  2229 00001484 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2230 00001489 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2231                              <1> 	;pushf			; save interrupt status
  2232 0000148E FA                  <1> 	cli			; block interrupts during update
  2233 0000148F E461                <1> 	in	al, PORT_B	; get current port value in case	
  2234 00001491 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2235 00001493 08E0                <1> 	or	al, ah		; recover value of port_b
  2236 00001495 E661                <1> 	out	PORT_B, al	; restore speaker status
  2237 00001497 9D                  <1> 	popf			; restore interrupt flag state
  2238                              <1> u12:	
  2239 00001498 C3                  <1> 	retn
  2240                              <1> 
  2241                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2242                              <1> 
  2243                              <1> WAITF:
  2244                              <1> waitf:
  2245                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2246                              <1> 	; 03/12/2013
  2247                              <1> 	;
  2248                              <1> ;	push	ax		; save work register (ah)	
  2249                              <1> ;waitf1:
  2250                              <1> 				; use timer 1 output bits
  2251                              <1> ;	in	al, PORT_B	; read current counter output status
  2252                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2253                              <1> ;	cmp	al, ah		; did it just change
  2254                              <1> ;	je	short waitf1	; wait for a change in output line
  2255                              <1> ;	;
  2256                              <1> ;	mov	ah, al		; save new lflag state
  2257                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2258                              <1> ;	;
  2259                              <1> ;	pop	ax		; restore (ah)
  2260                              <1> ;	retn			; return (cx)=0
  2261                              <1> 
  2262                              <1> ; 02/02/2022
  2263                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2264                              <1> ; 17/12/2014 (dsectrm2.s)
  2265                              <1> ; WAITF
  2266                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2267                              <1> ;
  2268                              <1> ;---WAITF-----------------------------------------------------------------------
  2269                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2270                              <1> ; ENTRY:
  2271                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2272                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2273                              <1> ; EXIT:
  2274                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2275                              <1> ;	(CX) = 0	
  2276                              <1> ;-------------------------------------------------------------------------------
  2277                              <1> 
  2278                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2279                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2280                              <1> 
  2281                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2282 00001499 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2283                              <1> 	;push	ax
  2284                              <1> 	; 16/12/2014
  2285                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2286 0000149A D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2287                              <1> ;17/12/2014	
  2288                              <1> ;WAITF1:
  2289                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2290                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2291                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2292                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2293                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2294                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2295                              <1> 	;
  2296                              <1> 	; 17/12/2014
  2297                              <1> 	;
  2298                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2299                              <1> 	;
  2300                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2301                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2302                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2303                              <1> WR_STATE_0:
  2304 0000149C E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2305 0000149E A810                <1> 	TEST	AL,010H
  2306 000014A0 74FA                <1> 	JZ	SHORT WR_STATE_0
  2307                              <1> WR_STATE_1:
  2308 000014A2 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2309 000014A4 A810                <1> 	TEST	AL,010H
  2310 000014A6 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2311 000014A8 E2F2                <1>         LOOP    WR_STATE_0
  2312                              <1> 	;
  2313                              <1> 	;pop	ax
  2314 000014AA 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2315 000014AB C3                  <1> 	RETn				; (CX) = 0
  2316                              <1> 
  2317                              <1> set_cpos:
  2318                              <1> 	; 14/06/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.4)
  2319                              <1> 	; 26/02/2022
  2320                              <1> 	; 02/02/2022
  2321                              <1> 	; 27/06/2015
  2322                              <1> 	; 01/09/2014
  2323                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2324                              <1> 	;
  2325                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2326                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2327                              <1> 	;
  2328                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2329                              <1> 	;
  2330                              <1> 	; SET_CPOS
  2331                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2332                              <1> 	;	NEW X-Y VALUES PASSED
  2333                              <1> 	; INPUT
  2334                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2335                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2336                              <1> 	; OUTPUT
  2337                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2338                              <1> 	;
  2339 000014AC 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2340 000014AF D0E0                <1>         shl     al, 1   ; word offset
  2341 000014B1 BE[56620000]        <1> 	mov	esi, cursor_posn
  2342 000014B6 01C6                <1>         add     esi, eax
  2343 000014B8 668916              <1> 	mov	[esi], dx ; save the pointer
  2344 000014BB 381D[66620000]      <1> 	cmp	[active_page], bl
  2345 000014C1 7531                <1> 	jne	short m17
  2346                              <1> 
  2347                              <1> 	; 14/06/2022
  2348                              <1> 	;cli ; 26/02/2022
  2349                              <1> 
  2350                              <1> 	;call	m18	;h CURSOR SET
  2351                              <1> ;m17:			; SET_CPOS_RETURN
  2352                              <1> 	; 01/09/2014
  2353                              <1> 	;retn
  2354                              <1> 		; DX = row/column
  2355                              <1> m18:
  2356 000014C3 E832000000          <1> 	call	position ; determine location in regen buffer	
  2357                              <1> 	;mov	cx, [CRT_START]
  2358                              <1> 	; 26/02/2022
  2359 000014C8 0FB70D[54620000]    <1> 	movzx	ecx, word [CRT_START]
  2360 000014CF 01C1                <1> 	add	ecx, eax
  2361                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2362                              <1> 			; to the start address (offset) for this page
  2363                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2364                              <1> 	; 26/02/2022
  2365 000014D1 D1E9                <1> 	shr	ecx, 1
  2366 000014D3 B40E                <1> 	mov	ah, 14	; register number for cursor
  2367                              <1> 	
  2368                              <1> 	; 14/06/2022
  2369                              <1> 	;call	m16	; output value to the 6845
  2370                              <1> 	;sti	; 26/02/2022
  2371                              <1> 	;retn
  2372                              <1> 
  2373                              <1> 	; 14/06/2022
  2374                              <1> 	; 26/02/2022
  2375                              <1> 	; 02/02/2022
  2376                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2377                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2378                              <1> m16:
  2379                              <1> 	; 14/06/2022
  2380 000014D5 FA                  <1> 	cli	; 26/02/2022
  2381                              <1> 	;mov	dx, [addr_6845] ; address register
  2382 000014D6 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2383 000014DA 88E0                <1> 	mov	al, ah	; get value
  2384 000014DC EE                  <1> 	out	dx, al	; register set
  2385                              <1> 	;inc	dx	; data register
  2386                              <1> 	; 02/02/2022
  2387 000014DD FEC2                <1> 	inc	dl
  2388 000014DF EB00                <1> 	jmp	$+2	; i/o delay
  2389 000014E1 88E8                <1> 	mov	al, ch	; data
  2390 000014E3 EE                  <1> 	out	dx, al	
  2391                              <1> 	;dec	dx
  2392                              <1> 	; 02/02/2022	
  2393 000014E4 FECA                <1> 	dec	dl
  2394 000014E6 88E0                <1> 	mov	al, ah
  2395 000014E8 FEC0                <1> 	inc	al	; point to other data register
  2396 000014EA EE                  <1> 	out	dx, al	; set for second register
  2397                              <1> 	;inc	dx
  2398                              <1> 	; 02/02/2022
  2399 000014EB FEC2                <1> 	inc	dl
  2400 000014ED EB00                <1> 	jmp	$+2	; i/o delay
  2401 000014EF 88C8                <1> 	mov	al, cl	; second data value
  2402 000014F1 EE                  <1> 	out	dx, al
  2403                              <1> 	; 14/06/2022
  2404 000014F2 FB                  <1> 	sti	; 26/02/2022
  2405                              <1> ;m17:
  2406 000014F3 C3                  <1> 	retn
  2407                              <1> m17:
  2408                              <1> 	; 14/06/2022
  2409                              <1> 	; ('write_tty' must not return to 'putc'/'wtty' with cf)
  2410 000014F4 F8                  <1> 	clc
  2411 000014F5 C3                  <1> 	retn
  2412                              <1> 
  2413                              <1> set_ctype:
  2414                              <1> 	; 07/02/2022
  2415                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2416                              <1> 	;
  2417                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2418                              <1> 
  2419                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2420                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2421                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2422                              <1> ;          OR NO CURSOR AT ALL
  2423                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2424                              <1> 
  2425                              <1> ;------------------------------------------------
  2426                              <1> ; SET_CTYPE
  2427                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2428                              <1> ; INPUT
  2429                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2430                              <1> ; OUTPUT	
  2431                              <1> ;	NONE
  2432                              <1> ;------------------------------------------------
  2433                              <1> 
  2434 000014F6 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2435                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2436                              <1> 	;call	m16	; output cx register
  2437                              <1> 	;retn
  2438                              <1> 	; 07/02/2022
  2439 000014F8 EBDB                <1> 	jmp	short m16
  2440                              <1> 
  2441                              <1> position:
  2442                              <1> 	; 26/02/2022
  2443                              <1> 	; 02/02/2022
  2444                              <1> 	; 27/06/2015
  2445                              <1> 	; 02/09/2014
  2446                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2447                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2448                              <1> 	;
  2449                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2450                              <1> 	;
  2451                              <1> 	; POSITION
  2452                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2453                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2454                              <1> 	; INPUT
  2455                              <1> 	;	AX = ROW, COLUMN POSITION
  2456                              <1> 	; OUTPUT
  2457                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2458                              <1> 
  2459                              <1> 		; DX = ROW, COLUMN POSITION
  2460                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2461 000014FA 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2462 000014FC B050                <1> 	mov	al, 80	; determine bytes to row	
  2463 000014FE F6E6                <1> 	mul	dh	; row value
  2464                              <1> 	;xor	dh, dh	; 0
  2465                              <1> 	;add	ax, dx	; add column value to the result
  2466                              <1> 	; 26/02/2022
  2467 00001500 00D0                <1> 	add	al, dl
  2468 00001502 80D400              <1> 	adc	ah, 0	
  2469                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2470                              <1> 	; 02/02/2022
  2471 00001505 D1E0                <1> 	shl	eax, 1
  2472                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2473 00001507 C3                  <1> 	retn
  2474                              <1> 
  2475                              <1> find_position:
  2476                              <1> 	; 02/02/2022
  2477                              <1> 	; 27/06/2015
  2478                              <1> 	; 07/09/2014
  2479                              <1> 	; 02/09/2014
  2480                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2481                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2482 00001508 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2483 0000150B 89CE                <1> 	mov	esi, ecx
  2484                              <1> 	;shl	si, 1
  2485                              <1> 	; 02/02/2022
  2486 0000150D D1E6                <1> 	shl	esi, 1
  2487 0000150F 668B96[56620000]    <1> 	mov	dx, [esi+cursor_posn]
  2488 00001516 7409                <1> 	jz	short p21
  2489                              <1> 	;xor	si, si
  2490                              <1> 	; 02/02/2022
  2491 00001518 31F6                <1> 	xor	esi, esi
  2492                              <1> p20:
  2493                              <1> 	;add	si, [CRT_LEN]
  2494 0000151A 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2495 0000151F E2F9                <1> 	loop	p20
  2496                              <1> p21:
  2497 00001521 6621D2              <1> 	and	dx, dx
  2498 00001524 7407                <1> 	jz	short p22
  2499 00001526 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2500 0000152B 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2501                              <1> p22:	
  2502                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2503                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2504                              <1> 	;add	dx, 6	; point at status port
  2505 0000152D 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2506                              <1> 	; cx = 0
  2507 00001531 C3                  <1> 	retn
  2508                              <1> 
  2509                              <1> scroll_up:
  2510                              <1> 	; 02/02/2022 (simplified scroll up)
  2511                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2512                              <1> 	; 16/01/2016
  2513                              <1> 	; 07/09/2014
  2514                              <1> 	; 02/09/2014
  2515                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2516                              <1> 	; 04/04/2014
  2517                              <1> 	; 04/12/2013
  2518                              <1> 	;
  2519                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2520                              <1> 	;
  2521                              <1> 	; SCROLL UP
  2522                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2523                              <1> 	;	ON THE SCREEN
  2524                              <1> 	; INPUT
  2525                              <1> 	;	(AH) = CURRENT CRT MODE
  2526                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2527                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2528                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2529                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2530                              <1> 	;	(DS) = DATA SEGMENT
  2531                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2532                              <1> 	; OUTPUT
  2533                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2534                              <1> 	;
  2535                              <1> 	;	bh = 0  (02/09/2014)
  2536                              <1> 	;
  2537                              <1> 	; ((ah = 3))
  2538                              <1> 	; cl = left upper column
  2539                              <1> 	; ch = left upper row
  2540                              <1> 	; dl = right lower column
  2541                              <1> 	; dh = right lower row
  2542                              <1> 	;
  2543                              <1> 	; al = line count 
  2544                              <1> 	; ah = attribute to be used on blanked line
  2545                              <1> 	; bl = video page number (0 to 7)
  2546                              <1> 	; 
  2547                              <1> 
  2548                              <1> 	; 02/02/2022 'scroll_up' code
  2549                              <1> 	; ------------------------------------------------------
  2550                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2551                              <1> 
  2552                              <1> 	; INPUT:
  2553                              <1> 	;		
  2554                              <1> 	; al = line count 
  2555                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2556                              <1> 	; ah = attribute to be used on blanked line
  2557                              <1> 	; bl = video page number (0 to 7)
  2558                              <1> 
  2559                              <1> 	;cli
  2560 00001532 31C9                <1> 	xor	ecx, ecx
  2561 00001534 88C1                <1> 	mov	cl, al ; line count (cl)
  2562 00001536 BE00800B00          <1> 	mov	esi, 0B8000h
  2563 0000153B 3A1D[66620000]      <1> 	cmp	bl, [active_page]
  2564 00001541 7411                <1> 	je	short n1
  2565 00001543 20DB                <1> 	and	bl, bl
  2566 00001545 7422                <1> 	jz	short n3
  2567 00001547 88DD                <1> 	mov	ch, bl ; video page number
  2568                              <1> n0:
  2569 00001549 6681C6A00F          <1> 	add	si, 25*80*2
  2570 0000154E FECD                <1> 	dec	ch
  2571 00001550 75F7                <1> 	jnz	short n0
  2572 00001552 EB15                <1> 	jmp	short n3
  2573                              <1> n1:
  2574 00001554 660335[54620000]    <1> 	add	si, [CRT_START]
  2575                              <1> 	;
  2576 0000155B 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2577                              <1> n2:			 ; wait_display_enable
  2578 0000155F EC                  <1> 	in	al, dx	 ; get port
  2579 00001560 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2580 00001562 74FB                <1> 	jz	short n2 ; wait_display_enable
  2581 00001564 B025                <1> 	mov	al, 25h
  2582 00001566 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2583 00001568 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2584                              <1> n3:
  2585                              <1> 	; cl = line count
  2586                              <1> 	; ah = attribute/color
  2587 00001569 89F7                <1> 	mov	edi, esi
  2588 0000156B 20C9                <1> 	and	cl, cl
  2589 0000156D 741F                <1> 	jz	short n6
  2590 0000156F 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2591 00001574 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2592 00001578 F366A5              <1> 	rep	movsw
  2593 0000157B B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2594                              <1> n4:
  2595                              <1> 	; ah = character attribute/cocor
  2596 0000157D B020                <1> 	mov	al, 20h ; fill with blanks
  2597 0000157F F366AB              <1> 	rep	stosw
  2598                              <1> 
  2599 00001582 3A1D[66620000]      <1> 	cmp	bl, [active_page]
  2600 00001588 7503                <1> 	jne	short n5
  2601                              <1> 
  2602                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2603 0000158A B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2604                              <1> 	;mov	dx, 03D8h ; always set color card port
  2605 0000158C EE                  <1> 	out	dx, al
  2606                              <1> n5:
  2607 0000158D C3                  <1> 	retn
  2608                              <1> n6:
  2609                              <1> 	; clear video page
  2610 0000158E 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2611 00001592 EBE9                <1> 	jmp	short n4
  2612                              <1> 
  2613                              <1> 	; 26/02/2022
  2614                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2615                              <1> 	; ------------------------------------------------------
  2616                              <1> 
  2617                              <1> 	; Test	Line Count
  2618                              <1> 	or	al, al
  2619                              <1> 	jz	short al_set
  2620                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2621                              <1> 	sub	bh, ch
  2622                              <1> 	inc	bh	; adjust difference by 1
  2623                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2624                              <1> 	jne	short al_set ; if not the we're all set
  2625                              <1> 	xor	al, al	; otherwise set al to zero
  2626                              <1> al_set:
  2627                              <1> 	xor	bh, bh	; 0
  2628                              <1> 	;push	ax
  2629                              <1> 	push	eax ; 26/02/2022
  2630                              <1> 	;mov 	esi, [crt_base]
  2631                              <1>         mov     esi, 0B8000h  
  2632                              <1>         cmp     bl, [active_page]
  2633                              <1> 	jne	short n0
  2634                              <1> 	;
  2635                              <1>         mov     ax, [CRT_START]
  2636                              <1>         add     si, ax
  2637                              <1>         jmp     short n1
  2638                              <1> n0:
  2639                              <1>         and     bl, bl
  2640                              <1> 	jz	short n1
  2641                              <1> 	mov	al, bl
  2642                              <1> n0x:
  2643                              <1>         ;add    si, [CRT_LEN]
  2644                              <1>         ;add    esi, 80*25*2 
  2645                              <1>         add     si, 80*25*2
  2646                              <1>         dec	al
  2647                              <1> 	jnz	short n0x
  2648                              <1> n1:	
  2649                              <1>         ; Scroll position
  2650                              <1> 	;push	dx ; 26/02/2022
  2651                              <1> 	mov	dx, cx	; now, upper left position in DX
  2652                              <1> 	call	position
  2653                              <1> 	add	esi, eax
  2654                              <1> 	mov	edi, esi
  2655                              <1> 	;pop	dx	; lower right position in DX
  2656                              <1> 	sub	dx, cx
  2657                              <1> 	inc	dh	; dh = #rows 
  2658                              <1> 	inc	dl	; dl = #cols in block
  2659                              <1> 	;pop	ax	; al = line count, ah = attribute
  2660                              <1> 	pop	eax ; 26/02/2022
  2661                              <1> 	xor	ecx, ecx
  2662                              <1> 	mov	cx, ax
  2663                              <1> 	;mov	ah, [CRT_COLS]
  2664                              <1> 	mov	ah, 80
  2665                              <1> 	mul	ah	; determine offset to from address
  2666                              <1> 	add	ax, ax  ; *2 for attribute byte
  2667                              <1> 	;
  2668                              <1> 	;push	ax	; offset 
  2669                              <1> 	;push	dx
  2670                              <1> 	; 26/02/2022
  2671                              <1> 	push	eax
  2672                              <1> 	push	edx
  2673                              <1> 	;
  2674                              <1> 	; 04/04/2014
  2675                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2676                              <1> n8:                      ; wait_display_enable
  2677                              <1>         in      al, dx   ; get port
  2678                              <1> 	test	al, RVRT ; wait for vertical retrace
  2679                              <1> 	jz	short n8 ; wait_display_enable
  2680                              <1> 	mov	al, 25h
  2681                              <1> 	mov	dl, 0D8h ; address control port
  2682                              <1> 	out	dx, al	; turn off video during vertical retrace
  2683                              <1> 	;pop	dx	; #rows, #cols
  2684                              <1>        	;pop	ax	; offset
  2685                              <1> 	; 26/02/2022
  2686                              <1> 	pop	edx
  2687                              <1> 	pop	eax
  2688                              <1> 	xchg	ax, cx	; 
  2689                              <1> 	; ecx = offset, al = line count, ah = attribute
  2690                              <1> ;n9:
  2691                              <1> 	or	al, al
  2692                              <1>         jz      short n3 
  2693                              <1>         add     esi, ecx ; from address for scroll
  2694                              <1> 	mov	bh, dh  ; #rows in block
  2695                              <1> 	sub	bh, al	; #rows to be moved
  2696                              <1> n2:
  2697                              <1> 	; Move rows
  2698                              <1> 	mov	cl, dl	; get # of cols to move
  2699                              <1> 	push	esi
  2700                              <1> 	push	edi	; save start address
  2701                              <1> n10:
  2702                              <1> 	movsw		; move that line on screen
  2703                              <1> 	dec	cl
  2704                              <1>         jnz     short n10
  2705                              <1> 	pop	edi
  2706                              <1> 	pop	esi	; recover addresses
  2707                              <1>         ;mov    cl, [CRT_COLS] 
  2708                              <1> 	;add	cl, cl
  2709                              <1>         ;mov    ecx, 80*2
  2710                              <1>         mov     cx, 80*2
  2711                              <1>         add     esi, ecx  ; next line
  2712                              <1>         add     edi, ecx
  2713                              <1> 	dec	bh	 ; count of lines to move
  2714                              <1> 	jnz	short n2 ; row loop
  2715                              <1> 	; bh = 0
  2716                              <1> 	mov	dh, al	 ; #rows	
  2717                              <1> n3:
  2718                              <1> 	; attribute in ah
  2719                              <1> 	mov	al, ' '	 ; fill with blanks
  2720                              <1> n3x:
  2721                              <1> 	; Clear rows
  2722                              <1>                 ; dh =  #rows
  2723                              <1>         mov	cl, dl	; get # of cols to clear
  2724                              <1>         push    edi     ; save address
  2725                              <1> n11:
  2726                              <1>         stosw           ; store fill character
  2727                              <1> 	dec	cl
  2728                              <1>         jnz     short n11
  2729                              <1>         pop     edi     ; recover address
  2730                              <1> 	;mov	cl, [CRT_COLS]
  2731                              <1> 	;add	cl, cl
  2732                              <1>         ;mov    ecx, 80*2
  2733                              <1>         mov	cl, 80*2
  2734                              <1>         add     edi, ecx
  2735                              <1> 	dec	dh
  2736                              <1> 	jnz	short n3x ; 16/01/2016
  2737                              <1> 	;
  2738                              <1> 	cmp	bl, [active_page]
  2739                              <1> 	jne	short n6
  2740                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2741                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2742                              <1> 	mov	dx, 03D8h ; always set color card port
  2743                              <1> 	out	dx, al
  2744                              <1> n6:
  2745                              <1> 	retn
  2746                              <1> 
  2747                              <1> %endif
  2748                              <1> 
  2749                              <1> write_c_current:
  2750                              <1> 	; 02/02/2022
  2751                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2752                              <1> 	; 18/01/2014
  2753                              <1> 	; 04/12/2013
  2754                              <1> 	;
  2755                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2756                              <1> 	;
  2757                              <1> 	; WRITE_C_CURRENT
  2758                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2759                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2760                              <1> 	; INPUT	
  2761                              <1> 	;	(AH) = CURRENT CRT MODE
  2762                              <1> 	;	(BH) = DISPLAY PAGE
  2763                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2764                              <1> 	;	(AL) = CHAR TO WRITE
  2765                              <1> 	;	(DS) = DATA SEGMENT
  2766                              <1> 	;	(ES) = REGEN SEGMENT
  2767                              <1> 	; OUTPUT
  2768                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2769                              <1> 
  2770 00001594 FA                  <1> 	cli		
  2771                              <1> 	; bl = video page
  2772                              <1> 	; al = character
  2773                              <1> 	; ah = color/attribute
  2774                              <1> 	;push	dx
  2775                              <1> 	;push	ax	; save character & attribute/color
  2776                              <1> 	; 02/02/2022
  2777 00001595 52                  <1> 	push	edx
  2778 00001596 50                  <1> 	push	eax
  2779 00001597 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2780                              <1> 	; esi = regen location
  2781                              <1> 	; dx = status port
  2782                              <1> 	;
  2783                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2784                              <1> 	;
  2785                              <1> p41:			; wait for horizontal retrace is low or vertical
  2786 0000159C FB                  <1> 	sti		; enable interrupts first
  2787 0000159D 3A1D[66620000]      <1>         cmp     bl, [active_page]
  2788 000015A3 7510                <1> 	jne	short p44 
  2789 000015A5 FA                  <1> 	cli 		; block interrupts for single loop
  2790 000015A6 EC                  <1> 	in	al, dx	; get status from the adapter
  2791 000015A7 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2792 000015A9 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2793 000015AB A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2794 000015AD 75ED                <1> 	jnz	short p41 ; wait until it is
  2795                              <1> p42:			; wait for either retrace high
  2796 000015AF EC                  <1> 	in	al, dx	; get status again
  2797 000015B0 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2798 000015B2 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2799                              <1> p43:	
  2800 000015B4 FB                  <1> 	sti
  2801                              <1> p44:
  2802                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2803                              <1> 	; 02/02/2022
  2804 000015B5 58                  <1> 	pop	eax
  2805 000015B6 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2806                              <1> 			; Retro UNIX 386 v1 feature only!
  2807 000015BC 668906              <1> 	mov	[esi], ax
  2808                              <1> 	;pop	dx
  2809                              <1> 	; 02/02/2022
  2810 000015BF 5A                  <1> 	pop	edx
  2811 000015C0 C3                  <1> 	retn
  2812                              <1> 
  2813                              <1> %if 0	; 02/02/2022
  2814                              <1> 
  2815                              <1> set_mode:
  2816                              <1> 	; 02/02/2022
  2817                              <1> 	; 16/01/2016
  2818                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2819                              <1> 	;
  2820                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2821                              <1> 
  2822                              <1> ;------------------------------------------------------
  2823                              <1> ; SET MODE					      :
  2824                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2825                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2826                              <1> ; INPUT						      :
  2827                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2828                              <1> ; OUTPUT					      :
  2829                              <1> ;	NONE					      :
  2830                              <1> ;------------------------------------------------------
  2831                              <1> 
  2832                              <1> 	push	edi ; 16/01/2016
  2833                              <1> 	push	ebx
  2834                              <1> 	push	edx
  2835                              <1> 	push	ecx ; 16/01/2016
  2836                              <1>         push    eax
  2837                              <1> 
  2838                              <1> 	;mov	dx, 03D4h 	; address or color card
  2839                              <1> 	mov	al, 3
  2840                              <1> ;M8:
  2841                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2842                              <1> 	mov	al, 29h
  2843                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2844                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2845                              <1> 	;push	dx  		; save port value
  2846                              <1> 	;add	dx, 4		; point to control register
  2847                              <1> 	mov	dx, 3D8h
  2848                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2849                              <1> 	;pop	dx
  2850                              <1> ;M9:
  2851                              <1> 	mov	ebx, video_params ; initialization table
  2852                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2853                              <1> 	;xchg 	ah, al
  2854                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2855                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2856                              <1> 	
  2857                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2858                              <1> 	; 02/02/2022
  2859                              <1> 	; dx = 3D8h
  2860                              <1> 	xor	ecx, ecx
  2861                              <1> 	mov	cl, 16
  2862                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2863                              <1> M10:			;  initialization loop
  2864                              <1> 	mov	al, ah 	; get 6845 register number
  2865                              <1> 	out	dx, al
  2866                              <1> 	;inc	dx      ; point to data port
  2867                              <1> 	; 02/02/2022
  2868                              <1> 	inc	dl ; 3D9h
  2869                              <1> 	inc	ah	; next register value
  2870                              <1> 	mov	al, [ebx] ; get table value
  2871                              <1> 	out	dx, al	; out to chip
  2872                              <1> 	inc	ebx	; next in table
  2873                              <1> 	;dec	dx	; back to pointer register
  2874                              <1> 	; 02/02/2022
  2875                              <1> 	dec	dl ; 3D8h
  2876                              <1> 	loop	M10	; do the whole table
  2877                              <1> 	
  2878                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2879                              <1> 	;xor	ax, ax  
  2880                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2881                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2882                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2883                              <1> 	; black background, light gray characeter color, space character
  2884                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2885                              <1> ;M13:			  ; clear buffer
  2886                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2887                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2888                              <1> 
  2889                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2890                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2891                              <1> 			 ; prepare to output to video enable port
  2892                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2893                              <1> 	; 02/02/2022
  2894                              <1> 	;mov	dx, 3D8h
  2895                              <1> 	; 
  2896                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2897                              <1> 	mov	al, 29h
  2898                              <1> 	out	dx, al	 ; set video enable port
  2899                              <1> 
  2900                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2901                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2902                              <1> 	;
  2903                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2904                              <1> 	;
  2905                              <1> ;-----	SET CURSOR POSITIONS
  2906                              <1> 	;push	edi
  2907                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2908                              <1> 	mov	edi, cursor_posn
  2909                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2910                              <1> 	xor	eax, eax
  2911                              <1> 	rep 	stosd	; fill with zeroes
  2912                              <1> 	;pop	edi
  2913                              <1> 
  2914                              <1> ;-----	SET UP OVERSCAN REGISTER
  2915                              <1> 	inc	dx	; set overscan port to a default
  2916                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2917                              <1> ;M14:
  2918                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2919                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2920                              <1> 
  2921                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2922                              <1> 	;
  2923                              <1> 	pop	eax
  2924                              <1> 	pop	ecx ; 16/01/2016
  2925                              <1> 	pop	edx
  2926                              <1> 	pop	ebx
  2927                              <1> 	pop	edi ; 16/01/2016
  2928                              <1> 	retn
  2929                              <1> 
  2930                              <1> %endif
  2931                              <1> 	
  2932                              <1> tty_sw:
  2933                              <1> 	; 02/02/2022
  2934                              <1> 	; 30/06/2015
  2935                              <1> 	; 27/06/2015 
  2936                              <1> 	; 07/09/2014
  2937                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2938                              <1> 	;
  2939                              <1> 	; (Modified registers : EAX)
  2940                              <1> 	;
  2941                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2942                              <1> 	;
  2943                              <1> ;act_disp_page:
  2944                              <1> 	; 30/06/2015
  2945                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2946                              <1> 	; 10/12/2013
  2947                              <1> 	; 04/12/2013
  2948                              <1> 	;
  2949                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2950                              <1> 	;
  2951                              <1> 	; ACT_DISP_PAGE
  2952                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2953                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2954                              <1> 	; INPUT
  2955                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2956                              <1> 	; OUTPUT
  2957                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2958                              <1> 
  2959                              <1> 	;cli
  2960                              <1> 
  2961 000015C1 53                  <1> 	push	ebx
  2962                              <1> 	;push	cx
  2963                              <1> 	;push	dx
  2964                              <1> 	; 02/02/2022
  2965 000015C2 51                  <1> 	push	ecx
  2966 000015C3 52                  <1> 	push	edx
  2967                              <1> 	;
  2968 000015C4 A2[66620000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2969                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2970                              <1> 	;mov	cx, 25*80*2
  2971                              <1> 	; 02/02/2022
  2972 000015C9 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2973                              <1> 	; 27/06/2015
  2974 000015CE 0FB6D8              <1> 	movzx	ebx, al
  2975                              <1> 	; 02/02/2022
  2976 000015D1 89D8                <1> 	mov	eax, ebx
  2977                              <1> 	;
  2978                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2979                              <1> 	;mul 	cx	; display page times regen length
  2980                              <1> 	; 02/02/2022
  2981 000015D3 F7E1                <1> 	mul	ecx	
  2982                              <1> 	; 10/12/2013
  2983 000015D5 66A3[54620000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2984                              <1> 	;mov	cx, ax	; start address to cx
  2985                              <1> 	; 02/02/2022
  2986 000015DB 89C1                <1> 	mov	ecx, eax
  2987                              <1> 	;sar	cx, 1
  2988                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2989                              <1> 	; 02/02/2022
  2990 000015DD D1E9                <1> 	shr	ecx, 1
  2991 000015DF B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2992 000015E1 E8EFFEFFFF          <1> 	call	m16
  2993                              <1> 	;sal	bx, 1
  2994                              <1> 	; 01/09/2014
  2995 000015E6 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2996 000015E8 81C3[56620000]      <1> 	add	ebx, cursor_posn
  2997 000015EE 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2998 000015F1 E8CDFEFFFF          <1> 	call	m18
  2999                              <1> 	;
  3000                              <1> 	;pop	dx
  3001                              <1> 	;pop	cx
  3002                              <1> 	; 02/02/2022
  3003 000015F6 5A                  <1> 	pop	edx
  3004 000015F7 59                  <1> 	pop	ecx
  3005 000015F8 5B                  <1> 	pop	ebx
  3006                              <1> 	;
  3007                              <1> 	;sti
  3008                              <1> 	;
  3009 000015F9 C3                  <1> 	retn
  3010                              <1> 
  3011                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  3012                              <1> 
  3013                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1893                                  
  1894                                  setup_rtc_int:
  1895                                  ; source: http://wiki.osdev.org/RTC
  1896 000015FA FA                      	cli		; disable interrupts
  1897                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1898                                  	; in order to change this ...
  1899                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1900                                  	; (rate must be above 2 and not over 15)
  1901                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1902 000015FB B08A                    	mov	al, 8Ah 
  1903 000015FD E670                    	out	70h, al ; set index to register A, disable NMI
  1904 000015FF 90                      	nop
  1905 00001600 E471                    	in	al, 71h ; get initial value of register A
  1906 00001602 88C4                    	mov 	ah, al
  1907 00001604 80E4F0                  	and	ah, 0F0h
  1908 00001607 B08A                    	mov	al, 8Ah 
  1909 00001609 E670                    	out	70h, al ; reset index to register A
  1910 0000160B 88E0                    	mov	al, ah
  1911 0000160D 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1912 0000160F E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1913                                  	; enable RTC interrupt
  1914 00001611 B08B                    	mov	al, 8Bh ;
  1915 00001613 E670                    	out	70h, al ; select register B and disable NMI
  1916 00001615 90                      	nop
  1917 00001616 E471                    	in	al, 71h ; read the current value of register B
  1918 00001618 88C4                    	mov	ah, al  ;
  1919 0000161A B08B                    	mov 	al, 8Bh ;
  1920 0000161C E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1921 0000161E 88E0                    	mov	al, ah  ;
  1922 00001620 0C40                    	or	al, 40h ;
  1923 00001622 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1924 00001624 FB                      	sti
  1925 00001625 C3                      	retn
  1926                                  
  1927                                  ; Write memory information
  1928                                  ; Temporary Code
  1929                                  ; 06/11/2014
  1930                                  ; 14/08/2015 
  1931                                  memory_info:	
  1932 00001626 A1[3C620000]            	mov	eax, [memory_size] ; in pages
  1933 0000162B 50                      	push	eax
  1934 0000162C C1E00C                  	shl	eax, 12		   ; in bytes
  1935 0000162F BB0A000000              	mov	ebx, 10
  1936 00001634 89D9                    	mov	ecx, ebx	   ; 10
  1937 00001636 BE[A55E0000]            	mov	esi, mem_total_b_str	
  1938 0000163B E8AE000000              	call	bintdstr
  1939 00001640 58                      	pop	eax
  1940 00001641 B107                    	mov	cl, 7
  1941 00001643 BE[C95E0000]            	mov	esi, mem_total_p_str
  1942 00001648 E8A1000000              	call	bintdstr	
  1943                                  	; 14/08/2015
  1944 0000164D E8B9000000              	call	calc_free_mem
  1945                                  	; edx = calculated free pages
  1946                                  	; ecx = 0
  1947 00001652 A1[40620000]            	mov 	eax, [free_pages]
  1948 00001657 39D0                    	cmp	eax, edx ; calculated free mem value 
  1949                                  		; and initial free mem value are same or not?
  1950 00001659 751D                    	jne 	short pmim ; print mem info with '?' if not
  1951 0000165B 52                      	push 	edx ; free memory in pages	
  1952                                  	;mov 	eax, edx
  1953 0000165C C1E00C                  	shl	eax, 12 ; convert page count
  1954                                  			; to byte count
  1955 0000165F B10A                    	mov	cl, 10
  1956 00001661 BE[E95E0000]            	mov	esi, free_mem_b_str
  1957 00001666 E883000000              	call	bintdstr
  1958 0000166B 58                      	pop	eax
  1959 0000166C B107                    	mov	cl, 7
  1960 0000166E BE[0D5F0000]            	mov	esi, free_mem_p_str
  1961 00001673 E876000000              	call	bintdstr
  1962                                  pmim:
  1963 00001678 BE[935E0000]            	mov	esi, msg_memory_info
  1964                                  pmim_nb:	
  1965 0000167D AC                      	lodsb
  1966 0000167E 08C0                    	or	al, al
  1967 00001680 740D                    	jz	short pmim_ok
  1968 00001682 56                      	push	esi
  1969 00001683 31DB                    	xor	ebx, ebx ; 0
  1970                                  			; Video page 0 (bl=0)
  1971 00001685 B407                    	mov	ah, 07h ; Black background, 
  1972                                  			; light gray forecolor
  1973 00001687 E816FDFFFF              	call	write_tty
  1974 0000168C 5E                      	pop	esi
  1975 0000168D EBEE                    	jmp	short pmim_nb
  1976                                  pmim_ok:
  1977 0000168F C3                      	retn
  1978                                  
  1979                                  ; Convert binary number to hexadecimal string
  1980                                  ; 10/05/2015  
  1981                                  ; dsectpm.s (28/02/2015)
  1982                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1983                                  ; 01/12/2014
  1984                                  ; 25/11/2014
  1985                                  ;
  1986                                  bytetohex:
  1987                                  	; INPUT ->
  1988                                  	; 	AL = byte (binary number)
  1989                                  	; OUTPUT ->
  1990                                  	;	AX = hexadecimal string
  1991                                  	;
  1992 00001690 53                      	push	ebx
  1993 00001691 31DB                    	xor	ebx, ebx
  1994 00001693 88C3                    	mov	bl, al
  1995 00001695 C0EB04                  	shr	bl, 4
  1996 00001698 8A9B[DE160000]          	mov	bl, [ebx+hexchrs]
  1997 0000169E 86D8                    	xchg	bl, al
  1998 000016A0 80E30F                  	and	bl, 0Fh
  1999 000016A3 8AA3[DE160000]          	mov	ah, [ebx+hexchrs]
  2000 000016A9 5B                      	pop	ebx	
  2001 000016AA C3                      	retn
  2002                                  
  2003                                  wordtohex:
  2004                                  	; INPUT ->
  2005                                  	; 	AX = word (binary number)
  2006                                  	; OUTPUT ->
  2007                                  	;	EAX = hexadecimal string
  2008                                  	;
  2009 000016AB 53                      	push	ebx
  2010 000016AC 31DB                    	xor	ebx, ebx
  2011 000016AE 86E0                    	xchg	ah, al
  2012 000016B0 6650                    	push	ax
  2013 000016B2 88E3                    	mov	bl, ah
  2014 000016B4 C0EB04                  	shr	bl, 4
  2015 000016B7 8A83[DE160000]          	mov	al, [ebx+hexchrs]
  2016 000016BD 88E3                    	mov	bl, ah
  2017 000016BF 80E30F                  	and	bl, 0Fh
  2018 000016C2 8AA3[DE160000]          	mov	ah, [ebx+hexchrs]
  2019 000016C8 C1E010                  	shl	eax, 16
  2020 000016CB 6658                    	pop	ax
  2021 000016CD 5B                      	pop	ebx
  2022 000016CE EBC0                    	jmp	short bytetohex
  2023                                  	;mov	bl, al
  2024                                  	;shr	bl, 4
  2025                                  	;mov	bl, [ebx+hexchrs]
  2026                                  	;xchg	bl, al	 	
  2027                                  	;and	bl, 0Fh
  2028                                  	;mov	ah, [ebx+hexchrs]
  2029                                  	;pop	ebx	
  2030                                  	;retn
  2031                                  
  2032                                  dwordtohex:
  2033                                  	; INPUT ->
  2034                                  	; 	EAX = dword (binary number)
  2035                                  	; OUTPUT ->
  2036                                  	;	EDX:EAX = hexadecimal string
  2037                                  	;
  2038 000016D0 50                      	push	eax
  2039 000016D1 C1E810                  	shr	eax, 16
  2040 000016D4 E8D2FFFFFF              	call	wordtohex
  2041 000016D9 89C2                    	mov	edx, eax
  2042 000016DB 58                      	pop	eax
  2043                                  	;call	wordtohex
  2044                                  	;retn
  2045                                  	; 02/01/2022
  2046 000016DC EBCD                    	jmp	short wordtohex
  2047                                  
  2048                                  ; 10/05/2015
  2049                                  hex_digits:
  2050                                  hexchrs:
  2051 000016DE 303132333435363738-     	db '0123456789ABCDEF'
  2051 000016E7 39414243444546     
  2052                                  
  2053                                  ; Convert binary number to decimal/numeric string
  2054                                  ; 06/11/2014
  2055                                  ; Temporary Code
  2056                                  ;
  2057                                  
  2058                                  bintdstr:
  2059                                  	; EAX = binary number
  2060                                  	; ESI = decimal/numeric string address
  2061                                  	; EBX = divisor (10)
  2062                                  	; ECX = string length (<=10)
  2063 000016EE 01CE                    	add	esi, ecx
  2064                                  btdstr0:
  2065 000016F0 4E                      	dec	esi
  2066 000016F1 31D2                    	xor	edx, edx
  2067 000016F3 F7F3                    	div	ebx
  2068 000016F5 80C230                  	add	dl, 30h
  2069 000016F8 8816                    	mov	[esi], dl
  2070 000016FA FEC9                    	dec	cl
  2071 000016FC 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2072 000016FE 09C0                    	or	eax, eax
  2073 00001700 75EE                    	jnz	short btdstr0
  2074                                  btdstr1:
  2075 00001702 4E                      	dec	esi
  2076 00001703 C60620                          mov     byte [esi], 20h ; blank space
  2077 00001706 FEC9                    	dec	cl
  2078 00001708 75F8                    	jnz	short btdstr1
  2079                                  btdstr2:
  2080 0000170A C3                      	ret
  2081                                  
  2082                                  ; Calculate free memory pages on M.A.T.
  2083                                  ; 06/11/2014
  2084                                  ; Temporary Code
  2085                                  ;
  2086                                  
  2087                                  calc_free_mem:
  2088 0000170B 31D2                    	xor	edx, edx
  2089                                  	;xor	ecx, ecx
  2090                                  	;mov	cx, [mat_size] ; in pages
  2091                                  	; 02/01/2022
  2092 0000170D 8B0D[50620000]          	mov	ecx, [mat_size] ; in pages
  2093 00001713 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2094 00001716 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2095                                  cfm0:
  2096 0000171B AD                      	lodsd
  2097 0000171C 51                      	push	ecx
  2098 0000171D B920000000              	mov	ecx, 32
  2099                                  cfm1:
  2100 00001722 D1E8                    	shr	eax, 1
  2101 00001724 7301                    	jnc	short cfm2
  2102 00001726 42                      	inc	edx
  2103                                  cfm2:
  2104 00001727 E2F9                    	loop	cfm1
  2105 00001729 59                      	pop	ecx
  2106 0000172A E2EF                    	loop	cfm0
  2107 0000172C C3                      	ret
  2108                                  
  2109                                  %include 'diskio.inc'  ; 07/03/2015
  2110                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.6) - DISKIO.INC
  2111                              <1> ; Last Modification: 18/07/2022
  2112                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2113                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2114                              <1> 
  2115                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2116                              <1> 
  2117                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2118                              <1> 
  2119                              <1> ; 11/07/2022
  2120                              <1> ;; 06/02/2015
  2121                              <1> ;diskette_io:
  2122                              <1> ;	pushfd
  2123                              <1> ;	push 	cs
  2124                              <1> ;	call 	DISKETTE_IO_1
  2125                              <1> ;	retn
  2126                              <1> 	
  2127                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2128                              <1> ;//////////////////////////////////////////////////////
  2129                              <1> 
  2130                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2131                              <1> ;		Function in AL
  2132                              <1> ;			0 = reset
  2133                              <1> ;			1 = read
  2134                              <1> ;			2 = write
  2135                              <1> ;		Disk drive number in DL
  2136                              <1> ;			0 & 1 = floppy disks	
  2137                              <1> ;			80h .. 83h = hard disks
  2138                              <1> ;		Sector address (LBA) in ECX
  2139                              <1> ;		Buffer address in EBX
  2140                              <1> ;		R/W sector count is (always) 1
  2141                              <1> ;
  2142                              <1> ;		Return:
  2143                              <1> ;			Status in AH (>0 = error code)
  2144                              <1> ;			if CF = 1 -> error code in AH
  2145                              <1> ;			if CF = 0 -> successful
  2146                              <1> ;			AL = undefined
  2147                              <1> ;
  2148                              <1> ;		Modified registers: (only) EAX
  2149                              <1> 
  2150                              <1> ; 10/07/2022
  2151                              <1> ; 08/07/2022 - (diskio code has been simplified/shortened 
  2152                              <1> ;		by removing unused IBM PC-AT disk functions)
  2153                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2154                              <1> ; 20/02/2015
  2155                              <1> ; 06/02/2015 (unix386.s)
  2156                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2157                              <1> ;
  2158                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2159                              <1> ;
  2160                              <1> ; ADISK.EQU
  2161                              <1> 
  2162                              <1> ;----- Wait control constants 
  2163                              <1> 
  2164                              <1> ;amount of time to wait while RESET is active.
  2165                              <1> 
  2166                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2167                              <1> 					;at 250 KBS xfer rate.
  2168                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2169                              <1> 
  2170                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2171                              <1> 					;status register to become valid
  2172                              <1> 					;before re-reading.
  2173                              <1> 
  2174                              <1> ;After sending a byte to NEC, status register may remain
  2175                              <1> ;incorrectly set for 24 us.
  2176                              <1> 
  2177                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2178                              <1> 					;RQM low.
  2179                              <1> 
  2180                              <1> ; COMMON.MAC
  2181                              <1> ;
  2182                              <1> ;	Timing macros
  2183                              <1> ;
  2184                              <1> 
  2185                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2186                              <1> 		jmp short $+2
  2187                              <1> %endmacro		
  2188                              <1> 
  2189                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2190                              <1> 		jmp short $+2
  2191                              <1> 		jmp short $+2
  2192                              <1> %endmacro
  2193                              <1> 
  2194                              <1> %macro		NEWIODELAY 0
  2195                              <1> 		out 0EBh,al
  2196                              <1> %endmacro 
  2197                              <1> 
  2198                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2199                              <1> ;;; WAIT_FOR_MEM
  2200                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2201                              <1> ;WAIT_FDU_INT_HI	equ	1
  2202                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2203                              <1> ;;; WAIT_FOR_PORT
  2204                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2205                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2206                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2207                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2208                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2209                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2210                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2211                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2212                              <1> ;;; WAIT_REFRESH
  2213                              <1> ;amount of time to wait for head settle, per unit in parameter
  2214                              <1> ;table = 1 ms.
  2215                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2216                              <1> 
  2217                              <1> 
  2218                              <1> ; //////////////// DISKETTE I/O ////////////////
  2219                              <1> 
  2220                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2221                              <1> 
  2222                              <1> ;----------------------------------------
  2223                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2224                              <1> ;----------------------------------------
  2225                              <1> 
  2226                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2227                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2228                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2229                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2230                              <1> 
  2231                              <1> ;----------------------------------------
  2232                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2233                              <1> ;-------------------------------------------------------------------------------
  2234                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2235                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2236                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2237                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2238                              <1> 
  2239                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2240                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2241                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2242                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2243                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2244                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2245                              <1> 
  2246                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2247                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2248                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2249                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2250                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2251                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2252                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2253                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2254                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2255                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2256                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2257                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2258                              <1> 
  2259                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2260                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2261                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2262                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2263                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2264                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2265                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2266                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2267                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2268                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2269                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2270                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2271                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2272                              <1> 
  2273                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2274                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2275                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2276                              <1> 
  2277                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2278                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2279                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2280                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2281                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2282                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2283                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2284                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2285                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2286                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2287                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2288                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2289                              <1> 
  2290                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2291                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2292                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2293                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2294                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2295                              <1> 
  2296                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2297                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2298                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2299                              <1> INTA01		EQU	021H		; 8259 PORT
  2300                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2301                              <1> INTB01		EQU	0A1H		;
  2302                              <1> 
  2303                              <1> ;-------------------------------------------------------------------------------
  2304                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2305                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2306                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2307                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2308                              <1> ;-------------------------------------------------------------------------------
  2309                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2310                              <1> 
  2311                              <1> ;-------------------------------------------------------------------------------
  2312                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2313                              <1> 
  2314                              <1> ; 10/07/2022
  2315                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2316                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2317                              <1> ; (unix386.s <-- dsectrm2.s)
  2318                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2319                              <1> 
  2320                              <1> ; 10/12/2014
  2321                              <1> ;
  2322                              <1> ;int40h:
  2323                              <1> ;	pushf
  2324                              <1> ;	push 	cs
  2325                              <1> ;	;cli
  2326                              <1> ;	call 	DISKETTE_IO_1
  2327                              <1> ;	retn
  2328                              <1> 
  2329                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2330                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2331                              <1> ;
  2332                              <1> 
  2333                              <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022-------------------------
  2334                              <1> ; DISKETTE I/O
  2335                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2336                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2337                              <1> ; INPUT
  2338                              <1> ;	(AH)= 00H RESET DISKETTE SYSTEM
  2339                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2340                              <1> ;		ON ALL DRIVES
  2341                              <1> ;------------------------------------------------------------------------------- 
  2342                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY
  2343                              <1> ;-------------------------------------------------------------------------------
  2344                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY
  2345                              <1> ;-------------------------------------------------------------------------------
  2346                              <1> ;
  2347                              <1> ;	REGISTERS FOR READ/WRITE
  2348                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2349                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2350                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2351                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2352                              <1> ;		320/360	320/360	    0-39
  2353                              <1> ;		320/360	1.2M	    0-39
  2354                              <1> ;		1.2M	1.2M	    0-79
  2355                              <1> ;		720K	720K	    0-79
  2356                              <1> ;		1.44M	1.44M	    0-79	
  2357                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED)
  2358                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2359                              <1> ;		320/360	320/360	     1-8/9
  2360                              <1> ;		320/360	1.2M	     1-8/9
  2361                              <1> ;		1.2M	1.2M	     1-15
  2362                              <1> ;		720K	720K	     1-9
  2363                              <1> ;		1.44M	1.44M	     1-18		
  2364                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2365                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2366                              <1> ;		320/360	320/360	        8/9
  2367                              <1> ;		320/360	1.2M	        8/9
  2368                              <1> ;		1.2M	1.2M		15
  2369                              <1> ;		720K	720K		9
  2370                              <1> ;		1.44M	1.44M		18
  2371                              <1> ;
  2372                              <1> ;	(EBX) - ADDRESS OF BUFFER
  2373                              <1> ;
  2374                              <1> ;-------------------------------------------------------------------------------
  2375                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2376                              <1> ;	AH = STATUS OF OPERATION
  2377                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2378                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2379                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)
  2380                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2381                              <1> ;	FOR READ/WRITE/VERIFY
  2382                              <1> ;		DS,BX,DX,CX PRESERVED
  2383                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2384                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2385                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2386                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2387                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2388                              <1> ;-------------------------------------------------------------------------------
  2389                              <1> ;
  2390                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2391                              <1> ;
  2392                              <1> ;   -----------------------------------------------------------------
  2393                              <1> ;   |       |       |       |       |       |       |       |       |
  2394                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2395                              <1> ;   |       |       |       |       |       |       |       |       |
  2396                              <1> ;   -----------------------------------------------------------------
  2397                              <1> ;	|	|	|	|	|	|	|	|
  2398                              <1> ;	|	|	|	|	|	-----------------
  2399                              <1> ;	|	|	|	|	|		|
  2400                              <1> ;	|	|	|	|    RESERVED		|
  2401                              <1> ;	|	|	|	|		  PRESENT STATE
  2402                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2403                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2404                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2405                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2406                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2407                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2408                              <1> ;	|	|	|	|	110: RESERVED
  2409                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2410                              <1> ;	|	|	|	|
  2411                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2412                              <1> ;	|	|	|
  2413                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED
  2414                              <1> ;	|	|					 (360K IN 1.2M DRIVE)
  2415                              <1> ;	|	|
  2416                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2417                              <1> ;
  2418                              <1> ;						00: 500 KBS
  2419                              <1> ;						01: 300 KBS
  2420                              <1> ;						10: 250 KBS
  2421                              <1> ;						11: RESERVED
  2422                              <1> ;
  2423                              <1> ;
  2424                              <1> 
  2425                              <1> struc MD
  2426 00000000 ??                  <1> 	.SPEC1:	  resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2427 00000001 ??                  <1> 	.SPEC2:	  resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2428 00000002 ??                  <1> 	.OFF_TIM: resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2429 00000003 ??                  <1> 	.BYT_SEC: resb	1	; 512 BYTES/SECTOR
  2430 00000004 ??                  <1> 	.SEC_TRK: resb	1	; EOT (LAST SECTOR ON TRACK)
  2431 00000005 ??                  <1> 	.GAP:	  resb	1	; GAP LENGTH
  2432 00000006 ??                  <1> 	.DTL:	  resb	1	; DTL
  2433 00000007 ??                  <1> 	.GAP3:	  resb	1	; GAP LENGTH FOR FORMAT
  2434 00000008 ??                  <1> 	.FIL_BYT: resb	1	; FILL BYTE FOR FORMAT
  2435 00000009 ??                  <1> 	.HD_TIM:  resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2436 0000000A ??                  <1> 	.STR_TIM: resb	1	; MOTOR START TIME (1/8 SECONDS)
  2437 0000000B ??                  <1> 	.MAX_TRK: resb	1	; MAX. TRACK NUMBER
  2438 0000000C ??                  <1> 	.RATE:	  resb	1	; DATA TRANSFER RATE
  2439                              <1> endstruc
  2440                              <1> 
  2441                              <1> BIT7OFF	EQU	7FH
  2442                              <1> BIT7ON	EQU	80H
  2443                              <1> 
  2444                              <1> ; 11/07/2022 - (direct call instead of int 13h simulation)
  2445                              <1> ;		Function in AL
  2446                              <1> ;			0 = reset
  2447                              <1> ;			1 = read
  2448                              <1> ;			2 = write
  2449                              <1> ;		Disk drive number in DL
  2450                              <1> ;			0 & 1 = floppy disks	
  2451                              <1> ;			80h .. 83h = hard disks
  2452                              <1> ;		Sector address (LBA) in ECX
  2453                              <1> ;		Buffer address in EBX
  2454                              <1> ;		R/W sector count is (always) 1
  2455                              <1> ;
  2456                              <1> ;		Return:
  2457                              <1> ;			Status in AH (>0 = error code)
  2458                              <1> ;			if CF = 1 -> error code in AH
  2459                              <1> ;			if CF = 0 -> successful
  2460                              <1> ;			AL = undefined
  2461                              <1> ;
  2462                              <1> ;		Modified registers: (only) EAX
  2463                              <1> 
  2464                              <1> ; 11/07/2022
  2465                              <1> ;;int13h: ; 16/02/2015
  2466                              <1> ;; 16/02/2015 - 21/02/2015
  2467                              <1> ;int40h:
  2468                              <1> ;	pushfd
  2469                              <1> ;	push 	cs
  2470                              <1> ;	call 	DISKETTE_IO_1
  2471                              <1> ;	retn	
  2472                              <1> 
  2473                              <1> DISKETTE_IO_1:
  2474                              <1> 
  2475                              <1> 	;sti				; INTERRUPTS BACK ON
  2476                              <1> 	; 11/07/2022
  2477                              <1> 	; save registers
  2478 0000172D 55                  <1> 	push	ebp			; ANY
  2479                              <1> 
  2480                              <1> 	; 11/07/2022
  2481                              <1> 	;push	edi			; ANY
  2482                              <1> 	;push	edx			; DRIVE NUMBER (DL)
  2483                              <1> 	;push	ebx			; BUFFER ADDRESS
  2484                              <1> 	;push	ecx			; SECTOR ADDRESS (LBA)
  2485                              <1> 	;push	esi			; ANY
  2486                              <1> 
  2487                              <1> 	; 11/07/2022
  2488 0000172E 89DD                <1> 	mov	ebp, ebx ; buffer address
  2489 00001730 C605[BC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS
  2490 00001737 0FB6FA              <1> 	movzx	edi, dl ; drive number (0 or 1)
  2491                              <1> 	
  2492 0000173A 08C0                <1> 	or	al, al			; RESET ?
  2493 0000173C 7507                <1> 	jnz	short DISKETTE_RW_1	; NO
  2494                              <1> 
  2495 0000173E E84D010000          <1> 	call	DSK_RESET
  2496                              <1> 
  2497 00001743 EB37                <1> 	jmp	short DISKETTE_RW_2	
  2498                              <1> 
  2499                              <1> DISKETTE_RW_1:
  2500                              <1> 	; 12/07/2022
  2501                              <1> 	; 11/07/2022
  2502                              <1> 	; ecx = sector address (LBA, < 2880)
  2503                              <1> 	; ebp = buffer address
  2504                              <1> 	; edi = drive number (0 or 1)
  2505                              <1> 	;  al = function (read = 1 or write = 2)
  2506                              <1> 
  2507 00001745 88C2                <1> 	mov	dl, al ; *
  2508                              <1> convert_to_chs:
  2509                              <1> 	;;;
  2510 00001747 B004                <1> 	mov	al, 4 ; MD.SEC_TRK ; sector per track (drv.spt)
  2511 00001749 E8D9050000          <1> 	call	GET_PARM
  2512                              <1> 	; 12/07/2022
  2513 0000174E 88E6                <1> 	mov	dh, ah ; spt
  2514 00001750 89C8                <1> 	mov	eax, ecx ; sector address (LBA) 
  2515 00001752 F6F6                <1> 	div	dh  ; AX/DH
  2516 00001754 88E1                <1> 	mov	cl, ah ; sector number - 1
  2517 00001756 FEC1                <1> 	inc	cl  ; sector number (1 based)
  2518 00001758 28ED                <1> 	sub	ch, ch ; head = 0 
  2519                              <1> 	; heads = 2
  2520 0000175A D0E8                <1> 	shr	al, 1 ; al = al/2
  2521 0000175C 80D500              <1> 	adc	ch, 0 ; head = 1 or head = 0
  2522 0000175F C1E110              <1> 	shl	ecx, 16
  2523 00001762 88C1                <1> 	mov	cl, al ; track (cylinder)
  2524 00001764 88D5                <1> 	mov	ch, dl ; function number 
  2525 00001766 89CE                <1> 	mov	esi, ecx ; byte 0 = track, byte 1 = function
  2526                              <1> 			 ; byte 2 = sector, byte 3 = head
  2527 00001768 C1C610              <1> 	rol	esi, 16
  2528                              <1> 			 ; byte 0 = sector, byte 1 = head
  2529                              <1> 			 ; byte 2 = track, byte 3 = function		
  2530                              <1> 	;;; 
  2531 0000176B 80FA02              <1> 	cmp	dl, 2 ; *
  2532 0000176E 7407                <1> 	je	short DISKETTE_W
  2533                              <1> DISKETTE_R:	
  2534                              <1> 	; dl = 1 ; *
  2535 00001770 E809000000          <1> 	call	DSK_READ
  2536 00001775 EB05                <1> 	jmp	short DISKETTE_RW_2
  2537                              <1> DISKETTE_W:
  2538 00001777 E80F000000          <1> 	call	DSK_WRITE
  2539                              <1> DISKETTE_RW_2:
  2540                              <1> 	; 11/07/2022
  2541                              <1> 	; Restore registers
  2542                              <1> 	;pop	esi
  2543                              <1> 	;pop	ecx
  2544                              <1> 	;pop	ebx
  2545                              <1> 	;pop	edx
  2546                              <1> 	;pop	edi
  2547                              <1> 
  2548                              <1> 	; 11/07/2022
  2549 0000177C 5D                  <1> 	pop	ebp
  2550 0000177D C3                  <1> 	retn
  2551                              <1> 
  2552                              <1> ;-------------------------------------------------------------------------------
  2553                              <1> ; DISK_READ	(AH = 01H)  ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2554                              <1> ;	DISKETTE READ.
  2555                              <1> ;
  2556                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2557                              <1> ;		SI-HI	: HEAD #
  2558                              <1> ;		SI-LOW	: # OF SECTORS
  2559                              <1> ;		ES	: BUFFER SEGMENT
  2560                              <1> ;		[BP]	: SECTOR #
  2561                              <1> ;		[BP+1]	: TRACK #
  2562                              <1> ;		[BP+2]	: BUFFER OFFSET
  2563                              <1> ;
  2564                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2565                              <1> ;-------------------------------------------------------------------------------
  2566                              <1> 
  2567                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2568                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2569                              <1> 
  2570                              <1> DSK_READ:
  2571 0000177E 8025[BA620000]7F    <1> 	and	byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION
  2572 00001785 66B846E6            <1> 	mov	ax, 0E646h		; AX = NEC COMMAND, DMA COMMAND
  2573                              <1> 	;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2574                              <1> 	;retn
  2575 00001789 EB0B                <1> 	jmp	short RD_WR_VF
  2576                              <1> 
  2577                              <1> ;-------------------------------------------------------------------------------
  2578                              <1> ; DISK_WRITE	(AH = 02H)
  2579                              <1> ;	DISKETTE WRITE.
  2580                              <1> ;
  2581                              <1> ; ON ENTRY:	EDI	: DRIVE #
  2582                              <1> ;		SI-HI	: HEAD #
  2583                              <1> ;		SI-LOW	: # OF SECTORS
  2584                              <1> ;		ES	: BUFFER SEGMENT
  2585                              <1> ;		[BP]	: SECTOR #
  2586                              <1> ;		[BP+1]	: TRACK #
  2587                              <1> ;		[BP+2]	: BUFFER OFFSET
  2588                              <1> ;
  2589                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2590                              <1> ;-------------------------------------------------------------------------------
  2591                              <1> 
  2592                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2593                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2594                              <1> 
  2595                              <1> DSK_WRITE:
  2596 0000178B 66B84AC5            <1> 	mov	ax, 0C54Ah		; AX = NEC COMMAND, DMA COMMAND
  2597 0000178F 800D[BA620000]80    <1>         or	byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION
  2598                              <1> 	;;call	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2599                              <1> 	;;retn
  2600                              <1> 	;jmp	short RD_WR_VF
  2601                              <1> 
  2602                              <1> ;-------------------------------------------------------------------------------
  2603                              <1> ; RD_WR_VF
  2604                              <1> ;	COMMON READ, WRITE
  2605                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  2606                              <1> ;
  2607                              <1> ; ON ENTRY:	AH = READ/WRITE NEC PARAMETER
  2608                              <1> ;		AL = READ/WRITE DMA PARAMETER
  2609                              <1> ;
  2610                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2611                              <1> ;-------------------------------------------------------------------------------
  2612                              <1> 
  2613                              <1> RD_WR_VF:
  2614                              <1> 	; 18/07/2022
  2615                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2616 00001796 50                  <1> 	push	eax ; 24/12/2021	; SAVE DMA, NEC PARAMETERS
  2617 00001797 E8C9010000          <1> 	call	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2618 0000179C E82B020000          <1> 	call	SETUP_STATE		; INITIALIZE START AND END RATE
  2619 000017A1 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2620                              <1> DO_AGAIN:
  2621 000017A2 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE PARAMETER
  2622 000017A3 E865020000          <1> 	call	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  2623 000017A8 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2624                              <1> 	; 24/12/2021
  2625 000017A9 7305                <1> 	jnc	short RWV
  2626 000017AB E9B6000000          <1> 	jmp	RWV_END			; MEDIA CHANGE ERROR OR TIME-OUT
  2627                              <1> RWV:
  2628 000017B0 50                  <1> 	push	eax ; 24/12/2021	; SAVE READ/WRITE/VERIFY PARAMETER
  2629 000017B1 8AB7[C7620000]      <1> 	mov	dh, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  2630 000017B7 80E6C0              <1> 	and	dh, RATE_MSK		; KEEP ONLY RATE
  2631 000017BA E85F050000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2632                              <1> 	; 20/02/2015
  2633 000017BF 7445                <1> 	jz	short RWV_ASSUME	; ERROR IN CMOS
  2634 000017C1 3C01                <1> 	cmp	al, 1			; 40 TRACK DRIVE?
  2635 000017C3 750D                <1> 	jne	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  2636 000017C5 F687[C7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  2637 000017CC 740F                <1> 	jz	short RWV_2		; YES, CMOS IS CORRECT
  2638                              <1> 	;mov	al, 2			; CHANGE TO 1.2M
  2639                              <1> 	; 12/07/2022
  2640 000017CE FEC0                <1> 	inc	al  ; al = 2
  2641 000017D0 EB0B                <1> 	jmp	short RWV_2
  2642                              <1> RWV_1:
  2643                              <1> 	; 12/07/2022
  2644                              <1> 	;jb	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  2645 000017D2 F687[C7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK?
  2646 000017D9 7502                <1> 	jnz	short RWV_2		; NO, 80 TRACK
  2647 000017DB B001                <1> 	mov	al, 1			; IT IS 40 TRACK, FIX CMOS VALUE
  2648                              <1> 	; 12/07/2022
  2649                              <1> 	;jmp	short RWV_3
  2650                              <1> RWV_2:
  2651                              <1> 	; 12/07/2022
  2652                              <1> 	;or	al, al			; TEST FOR NO DRIVE
  2653                              <1> 	;jz	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  2654                              <1> RWV_3:
  2655                              <1> 	; 12/07/2022
  2656                              <1> 	;mov	dl, al	; 11/07/2022
  2657 000017DD E81F010000          <1> 	call	DR_TYPE_CHECK		; RTN EBX = MEDIA/DRIVE PARAM TBL.
  2658 000017E2 7222                <1> 	jc	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  2659                              <1> 
  2660                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  2661                              <1> 
  2662 000017E4 57                  <1> 	push	edi			; SAVE DRIVE #
  2663                              <1> 	;xor	ebx, ebx		; EBX = INDEX TO DR_TYPE TABLE
  2664 000017E5 BB[DC5C0000]        <1> 	mov	ebx, DR_TYPE
  2665                              <1> 	;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2666 000017EA B106                <1> 	mov	cl, DR_CNT
  2667                              <1> RWV_DR_SEARCH:
  2668                              <1> 	;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2669 000017EC 8A23                <1> 	mov	ah, [ebx]
  2670 000017EE 80E47F              <1> 	and	ah, BIT7OFF		; MASK OUT MSB
  2671 000017F1 38E0                <1> 	cmp	al, ah			; DRIVE TYPE MATCH?
  2672                              <1> 	; 12/07/2022
  2673                              <1> 	;cmp	dl, ah ; 11/07/2022
  2674 000017F3 7509                <1> 	jne	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  2675                              <1> RWV_DR_FND:
  2676                              <1> 	;mov	edi, [DR_TYPE+ebx+1] 	; EDI = MEDIA/DRIVE PARAMETER TABLE
  2677 000017F5 43                  <1> 	inc	ebx
  2678 000017F6 8B3B                <1> 	mov	edi, [ebx]
  2679 000017F8 4B                  <1> 	dec	ebx
  2680                              <1> RWV_MD_SEARH:
  2681 000017F9 3A770C              <1>         cmp	dh, [edi+MD.RATE]       ; MATCH?
  2682 000017FC 741D                <1> 	je	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  2683                              <1> RWV_NXT_MD:
  2684 000017FE 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2685                              <1> 	;loop	RWV_DR_SEARCH
  2686 00001801 FEC9                <1> 	dec	cl
  2687 00001803 75E7                <1> 	jnz	short RWV_DR_SEARCH 
  2688 00001805 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2689                              <1> 
  2690                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  2691                              <1> 
  2692                              <1> RWV_ASSUME:
  2693 00001806 BB[FA5C0000]        <1> 	mov	ebx, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  2694 0000180B F687[C7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK
  2695 00001812 740A                <1> 	jz	short RWV_MD_FND1	; MUST BE 40 TRACK
  2696 00001814 BB[145D0000]        <1> 	mov	ebx, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  2697 00001819 EB03                <1> 	jmp	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  2698                              <1> 
  2699                              <1> ;-----	EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  2700                              <1> 	 			
  2701                              <1> RWV_MD_FND:
  2702 0000181B 89FB                <1> 	mov	ebx, edi		; EBX = MEDIA/DRIVE PARAMETER TABLE
  2703 0000181D 5F                  <1> 	pop	edi			; RESTORE DRIVE #
  2704                              <1> 	
  2705                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  2706                              <1> 
  2707                              <1> RWV_MD_FND1:
  2708 0000181E E824010000          <1> 	call	SEND_SPEC_MD
  2709 00001823 E851020000          <1> 	call	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  2710 00001828 7405                <1> 	jz	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  2711 0000182A E82C020000          <1> 	call	SEND_RATE		; SEND DATA RATE TO NEC
  2712                              <1> RWV_DBL:
  2713 0000182F 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2714 00001830 E847040000          <1> 	call	SETUP_DBL		; CHECK FOR DOUBLE STEP
  2715 00001835 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2716 00001836 7221                <1> 	jc	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  2717                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2718                              <1> 	;push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2719                              <1> 	; 08/07/2022
  2720 00001838 8B0424              <1> 	mov	eax, [esp]
  2721                              <1> 	; 18/07/2022
  2722                              <1> 	;push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2723 0000183B E84C020000          <1> 	call	DMA_SETUP		; SET UP THE DMA
  2724                              <1> 	;pop	ebx
  2725 00001840 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE NEC COMMAND
  2726 00001841 722D                <1> 	jc	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  2727 00001843 50                  <1> 	push	eax ; 24/12/2021	; SAVE NEC COMMAND
  2728 00001844 53                  <1> 	push	ebx			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  2729 00001845 E88C020000          <1> 	call	NEC_INIT		; INITIALIZE NEC
  2730 0000184A 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2731 0000184B 720C                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2732 0000184D E8B5020000          <1> 	call	RWV_COM			; OP CODE COMMON TO READ/WRITE
  2733 00001852 7205                <1> 	jc	short CHK_RET		; ERROR - EXIT
  2734 00001854 E8FC020000          <1> 	call	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  2735                              <1> CHK_RET:
  2736 00001859 E89B030000          <1> 	call	RETRY			; CHECK FOR, SETUP RETRY
  2737 0000185E 58                  <1> 	pop	eax ; 24/12/2021	; RESTORE READ/WRITE PARAMETER
  2738 0000185F 7305                <1> 	jnc	short RWV_END		; CY = 0 NO RETRY
  2739 00001861 E93CFFFFFF          <1>         jmp	DO_AGAIN                ; CY = 1 MEANS RETRY
  2740                              <1> RWV_END:
  2741 00001866 E846030000          <1> 	call	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  2742 0000186B E8D7030000          <1> 	call	NUM_TRANS		; AL = NUMBER TRANSFERRED
  2743                              <1> RWV_BAC:
  2744                              <1> 	; 08/07/2022			; BAD DMA ERROR ENTRY
  2745                              <1> 	;push	eax ; 24/12/2021	; SAVE NUMBER TRANSFERRED
  2746                              <1> 	;CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2747                              <1> 	;pop	eax ; 24/12/2021	; RESTORE NUMBER TRANSFERRED
  2748                              <1> 	;;call	SETUP_END		; VARIOUS CLEANUPS
  2749                              <1> 	;;retn
  2750                              <1> 	;jmp	SETUP_END
  2751                              <1> 
  2752                              <1> ;-------------------------------------------------------------------------------
  2753                              <1> ; SETUP_END
  2754                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  2755                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  2756                              <1> ;
  2757                              <1> ; ON EXIT:
  2758                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2759                              <1> ;-------------------------------------------------------------------------------
  2760                              <1> SETUP_END:
  2761                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 
  2762                              <1> 	;mov	dl, 2			; GET THE MOTOR WAIT PARAMETER
  2763                              <1> 	;push	ax			; SAVE NUMBER TRANSFERRED
  2764 00001870 50                  <1> 	push	eax ; 24/12/2021
  2765 00001871 B002                <1> 	mov	al, 2 ; 08/07/2022
  2766 00001873 E8AF040000          <1> 	call	GET_PARM
  2767 00001878 8825[BB620000]      <1> 	mov	[MOTOR_COUNT], ah	; STORE UPON RETURN
  2768                              <1> 	;pop	ax			; RESTORE NUMBER TRANSFERRED
  2769 0000187E 58                  <1> 	pop	eax ; 24/12/2021
  2770 0000187F 8A25[BC620000]      <1> 	mov	ah, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  2771 00001885 08E4                <1> 	or	ah, ah			; CHECK FOR ERROR
  2772 00001887 7406                <1> 	jz	short NUN_ERR		; NO ERROR
  2773 00001889 30C0                <1> 	xor 	al, al			; CLEAR NUMBER RETURNED
  2774                              <1> ;NUN_ERR: 
  2775 0000188B 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  2776 0000188E F5                  <1> 	cmc				; SUCCESS OR FAILURE
  2777                              <1> NUN_ERR:
  2778 0000188F C3                  <1> 	retn
  2779                              <1> 
  2780                              <1> ;-------------------------------------------------------------------------------
  2781                              <1> ; DISK_RESET	(AH = 00H)	
  2782                              <1> ;		RESET THE DISKETTE SYSTEM.
  2783                              <1> ;
  2784                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2785                              <1> ;-------------------------------------------------------------------------------
  2786                              <1> DSK_RESET:
  2787                              <1> 	; 17/07/2022
  2788                              <1> 	; 12/07/2022
  2789                              <1> 	; 11/07/2022
  2790                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2791 00001890 66BAF203            <1> 	mov	dx, 03F2h		; ADAPTER CONTROL PORT
  2792 00001894 FA                  <1> 	cli				; NO INTERRUPTS
  2793 00001895 A0[BA620000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2794 0000189A 243F                <1> 	and	al, 00111111b		; KEEP SELECTED AND MOTOR ON BITS
  2795 0000189C C0C004              <1> 	rol	al, 4			; MOTOR VALUE TO HIGH NIBBLE
  2796                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2797 0000189F 0C08                <1> 	or	al, 00001000b		; TURN ON INTERRUPT ENABLE
  2798 000018A1 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2799 000018A2 C605[B9620000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2800                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2801                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2802                              <1> 					;      PULSE WIDTH)
  2803                              <1> 	; 19/12/2014
  2804                              <1> 	NEWIODELAY
  2195 000018A9 E6EB                <2>  out 0EBh,al
  2805                              <1> 
  2806                              <1> 	; 17/12/2014 
  2807                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2808 000018AB B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2809                              <1> wdw1:
  2810                              <1> 	NEWIODELAY   ; 27/02/2015
  2195 000018B0 E6EB                <2>  out 0EBh,al
  2811 000018B2 E2FC                <1> 	loop	wdw1
  2812                              <1> 	;
  2813 000018B4 0C04                <1> 	or	al, 00000100b		; TURN OFF RESET BIT
  2814 000018B6 EE                  <1> 	out	dx, al			; RESET THE ADAPTER
  2815                              <1> 	; 16/12/2014
  2816                              <1> 	IODELAY
  2190 000018B7 EB00                <2>  jmp short $+2
  2191 000018B9 EB00                <2>  jmp short $+2
  2817                              <1> 	;
  2818                              <1> 	;sti				; ENABLE THE INTERRUPTS
  2819 000018BB E862060000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  2820 000018C0 7236                <1> 	jc	short DR_ERR		; IF ERROR, RETURN IT
  2821                              <1> 	;mov	cx, 11000000b		; CL = EXPECTED @NEC_STATUS
  2822                              <1> 	; 12/07/2022
  2823                              <1> 	;xor	ecx, ecx
  2824                              <1> 	; 17/07/2022
  2825                              <1> 	;xor	ch, ch
  2826 000018C2 B1C0                <1> 	mov	cl, 11000000b
  2827                              <1> NXT_DRV:
  2828                              <1> 	; 24/12/2021
  2829 000018C4 51                  <1> 	push	ecx			; SAVE FOR CALL
  2830 000018C5 B8[F7180000]        <1> 	mov	eax, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2831 000018CA 50                  <1> 	push	eax			;
  2832 000018CB B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  2833 000018CD E846050000          <1> 	call	NEC_OUTPUT
  2834 000018D2 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  2835 000018D3 E879060000          <1> 	call	RESULTS			; READ IN THE RESULTS
  2836                              <1> 	; 24/12/2021
  2837 000018D8 59                  <1> 	pop	ecx			; RESTORE AFTER CALL
  2838 000018D9 721D                <1> 	jc	short DR_ERR		; ERROR RETURN
  2839 000018DB 3A0D[BD620000]      <1> 	cmp	cl, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2840 000018E1 7515                <1> 	jnz	short DR_ERR		; EVERYTHING OK
  2841 000018E3 FEC1                <1> 	inc	cl			; NEXT EXPECTED @NEC_STATUS
  2842 000018E5 80F9C3              <1> 	cmp	cl, 11000011b		; ALL POSSIBLE DRIVES CLEARED
  2843 000018E8 76DA                <1> 	jbe	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2844                              <1> 	;
  2845 000018EA E82F000000          <1> 	call	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2846                              <1> RESBAC:
  2847 000018EF E87CFFFFFF          <1> 	call	SETUP_END		; VARIOUS CLEANUPS
  2848                              <1> 	
  2849                              <1> 	; 11/07/2022
  2850                              <1> 	; CF = 1 -> error (error code in AH)
  2851                              <1> 	; CF = 0 -> OK
  2852                              <1> 	
  2853                              <1> 	;; 24/12/2021
  2854                              <1> 	;mov	ebx, esi		; GET SAVED AL TO BL
  2855                              <1> 	;; 11/07/2022
  2856                              <1> 	;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 
  2857                              <1> 	;rol	ebx, 8
  2858                              <1> 	; bl = function (reset = 0)
  2859                              <1> 	;
  2860                              <1> 	;mov	al, bl			; PUT BACK FOR RETURN
  2861                              <1> 	
  2862                              <1> 	; 11/07/2022  
  2863 000018F4 B000                <1> 	mov	al, 0	; (reset function = 0)
  2864                              <1> 
  2865 000018F6 C3                  <1> 	retn
  2866                              <1> 
  2867                              <1> DR_POP_ERR:
  2868                              <1> 	; 24/12/2021
  2869 000018F7 59                  <1> 	pop	ecx			; CLEAR STACK
  2870                              <1> DR_ERR:
  2871 000018F8 800D[BC620000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE
  2872 000018FF EBEE                <1> 	jmp	short RESBAC		; RETURN FROM RESET
  2873                              <1> 
  2874                              <1> ;-------------------------------------------------------------------------------
  2875                              <1> ; FNC_ERR
  2876                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2877                              <1> ;	SET BAD COMMAND IN STATUS.
  2878                              <1> ;
  2879                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2880                              <1> ;-------------------------------------------------------------------------------
  2881                              <1> 
  2882                              <1> 	; 11/07/2022 - not needed (because diskio is used by kernel only)
  2883                              <1> 	
  2884                              <1> ;FNC_ERR:				; INVALID FUNCTION REQUEST
  2885                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2886                              <1> ;	; 24/12/2021
  2887                              <1> ;	mov	eax, esi		; RESTORE AL
  2888                              <1> ;	mov	ah, BAD_CMD		; SET BAD COMMAND ERROR
  2889                              <1> ;	mov	[DSKETTE_STATUS], ah	; STORE IN DATA AREA
  2890                              <1> ;	stc				; SET CARRY INDICATING ERROR
  2891                              <1> ;	retn
  2892                              <1> 
  2893                              <1> ;----------------------------------------------------------------
  2894                              <1> ; DR_TYPE_CHECK							:
  2895                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  2896                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  2897                              <1> ; ON ENTRY:							:
  2898                              <1> ;	AL = DRIVE TYPE						:
  2899                              <1> ; ON EXIT:							:
  2900                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  2901                              <1> ;	     EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE	:
  2902                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  2903                              <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 			:
  2904                              <1> ;----------------------------------------------------------------
  2905                              <1> DR_TYPE_CHECK:
  2906                              <1> 	; 12/07/2022
  2907                              <1> 	; 11/07/2022
  2908                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2909                              <1> 	; 24/12/2021
  2910                              <1> 	;push	eax ; 11/07/2022
  2911                              <1> 	;push	ecx ; 08/07/2022
  2912                              <1> 	;xor	ebx,ebx			; EBX = INDEX TO DR_TYPE TABLE
  2913 00001901 BB[DC5C0000]        <1> 	mov	ebx, DR_TYPE
  2914                              <1> 	;;mov	ecx, DR_CNT		; ECX = LOOP COUNT
  2915                              <1> 	;mov	cl, DR_CNT
  2916 00001906 B406                <1> 	mov	ah, DR_CNT ; 11/07/2022
  2917                              <1> TYPE_CHK:	
  2918                              <1> 	;;mov	ah, [DR_TYPE+ebx]	; GET DRIVE TYPE
  2919                              <1> 	;mov	ah, [ebx]
  2920                              <1> 	;cmp	al, ah			; DRIVE TYPE MATCH?
  2921 00001908 3A03                <1> 	cmp	al, [ebx] ; 11/07/2022
  2922 0000190A 740E                <1> 	je	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  2923                              <1> 	; 16/02/2015 (32 bit address modification)
  2924 0000190C 83C305              <1> 	add	ebx, 5			; CHECK NEXT DRIVE TYPE
  2925                              <1> 	;loop	TYPE_CHK
  2926                              <1> 	;dec	cl
  2927 0000190F FECC                <1> 	dec	ah ; 11/07/2022
  2928 00001911 75F5                <1> 	jnz	short TYPE_CHK
  2929                              <1> 	;
  2930 00001913 BB[3B5D0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  2931                              <1> 					; Default for GET_PARM (11/12/2014)
  2932                              <1> 	;
  2933 00001918 F9                  <1> 	stc				; DRIVE TYPE NOT FOUND IN TABLE
  2934                              <1> 	;jmp	short TYPE_RTN
  2935                              <1> 	; 12/07/2022
  2936 00001919 C3                  <1> 	retn
  2937                              <1> DR_TYPE_VALID:
  2938                              <1> 	;mov	ebx, [DR_TYPE+ebx+1] 	; EBX = MEDIA TABLE
  2939 0000191A 43                  <1> 	inc	ebx
  2940 0000191B 8B1B                <1> 	mov	ebx, [ebx]
  2941                              <1> TYPE_RTN:
  2942                              <1> 	;pop	ecx ; 08/07/2022
  2943                              <1> 	; 24/12/2021
  2944                              <1> 	;pop	eax ; 11/07/2022
  2945 0000191D C3                  <1> 	retn
  2946                              <1> 		
  2947                              <1> ;----------------------------------------------------------------
  2948                              <1> ; SEND_SPEC							:
  2949                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2950                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  2951                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  2952                              <1> ; ON EXIT:	NONE						:
  2953                              <1> ; REGISTERS ALTERED: ECX, EDX					:
  2954                              <1> ;----------------------------------------------------------------
  2955                              <1> SEND_SPEC:
  2956                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2957 0000191E 50                  <1> 	push	eax			; SAVE EAX
  2958 0000191F B8[45190000]        <1> 	mov	eax, SPECBAC		; LOAD ERROR ADDRESS
  2959 00001924 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2960 00001925 B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2961 00001927 E8EC040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2962                              <1> 	;sub	dl, dl			; FIRST SPECIFY BYTE
  2963 0000192C 28C0                <1> 	sub	al, al ; 08/07/2022
  2964 0000192E E8F4030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2965 00001933 E8E0040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2966                              <1> 	;mov	dl, 1			; SECOND SPECIFY BYTE
  2967 00001938 B001                <1> 	mov	al, 1 ; 08/07/2022
  2968 0000193A E8E8030000          <1> 	call	GET_PARM		; GET PARAMETER TO AH
  2969 0000193F E8D4040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2970 00001944 58                  <1> 	pop	eax			; POP ERROR RETURN
  2971                              <1> SPECBAC:
  2972 00001945 58                  <1> 	pop	eax			; RESTORE ORIGINAL EAX VALUE
  2973 00001946 C3                  <1> 	retn
  2974                              <1> 
  2975                              <1> ;----------------------------------------------------------------
  2976                              <1> ; SEND_SPEC_MD							:
  2977                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  2978                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (EBX)	:
  2979                              <1> ; ON ENTRY:	EBX = MEDIA/DRIVE PARAMETER TABLE		:
  2980                              <1> ; ON EXIT:	NONE						:
  2981                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022				:
  2982                              <1> ;----------------------------------------------------------------
  2983                              <1> SEND_SPEC_MD:
  2984                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2985                              <1> 	;push	eax ; 11/07/2022	; SAVE RATE DATA
  2986 00001947 B8[64190000]        <1> 	mov	eax, SPEC_ESBAC		; LOAD ERROR ADDRESS
  2987 0000194C 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  2988 0000194D B403                <1> 	mov	ah, 03h			; SPECIFY COMMAND
  2989 0000194F E8C4040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2990 00001954 8A23                <1>         mov	ah, [ebx+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  2991 00001956 E8BD040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2992 0000195B 8A6301              <1>         mov	ah, [ebx+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  2993 0000195E E8B5040000          <1> 	call	NEC_OUTPUT		; OUTPUT THE COMMAND
  2994 00001963 58                  <1> 	pop	eax			; POP ERROR RETURN
  2995                              <1> SPEC_ESBAC:
  2996                              <1> 	;pop	eax ; 11/07/2022	; RESTORE ORIGINAL EAX VALUE
  2997 00001964 C3                  <1> 	retn
  2998                              <1> 
  2999                              <1> ;-------------------------------------------------------------------------------
  3000                              <1> ; XLAT_NEW  
  3001                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3002                              <1> ;	MODE TO NEW ARCHITECTURE.
  3003                              <1> ;
  3004                              <1> ; ON ENTRY:	EDI = DRIVE #
  3005                              <1> ;-------------------------------------------------------------------------------
  3006                              <1> XLAT_NEW:
  3007                              <1> 	; 11/07/2022
  3008                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3009                              <1> 	;cmp	edi, 1				; VALID DRIVE
  3010                              <1> 	;ja	short XN_OUT			; IF INVALID BACK
  3011                              <1> 	;
  3012 00001965 80BF[C7620000]00    <1> 	cmp	byte [DSK_STATE+edi], 0		; NO DRIVE ?
  3013 0000196C 7401                <1> 	jz	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3014                              <1> 	;
  3015                              <1> 	;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  3016                              <1> 	;mov	ecx, edi			; ECX = DRIVE NUMBER
  3017                              <1> 	;or	cl, cl
  3018                              <1> 	;jz	short XN_0  ; 08/07/2022
  3019                              <1> 	;shl	cl, 2				; CL = SHIFT COUNT, A=0, B=4
  3020                              <1> 	;;mov	al, [HF_CNTRL]			; DRIVE INFORMATION
  3021                              <1> 	;ror	al, cl				; TO LOW NIBBLE
  3022                              <1> ;XN_0:	
  3023                              <1> 	;and	al, DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3024                              <1>         ;and	byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3025                              <1> 	;or	[DSK_STATE+edi], al		; UPDATE DRIVE STATE
  3026                              <1> XN_OUT:
  3027 0000196E C3                  <1> 	retn
  3028                              <1> DO_DET:
  3029                              <1> 	;;call	DRIVE_DET			; TRY TO DETERMINE
  3030                              <1> 	;;retn
  3031                              <1> 	;jmp	DRIVE_DET
  3032                              <1> 
  3033                              <1> ;-------------------------------------------------------------------------------
  3034                              <1> ; DRIVE_DET
  3035                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  3036                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  3037                              <1> ; ON ENTRY:	EDI = DRIVE #
  3038                              <1> ;-------------------------------------------------------------------------------
  3039                              <1> DRIVE_DET:
  3040                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3041 0000196F E8EE030000          <1> 	call	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  3042 00001974 E857050000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  3043 00001979 724E                <1> 	jc	short DD_BAC		; ASSUME NO DRIVE PRESENT
  3044 0000197B B530                <1> 	mov	ch, TRK_SLAP		; SEEK TO TRACK 48
  3045 0000197D E8CF040000          <1> 	call	SEEK
  3046 00001982 7245                <1> 	jc	short DD_BAC		; ERROR NO DRIVE
  3047 00001984 B50B                <1> 	mov	ch, QUIET_SEEK+1	; SEEK TO TRACK 10
  3048                              <1> SK_GIN:
  3049 00001986 FECD                <1> 	dec	ch			; DECREMENT TO NEXT TRACK
  3050                              <1> 	;push	cx		
  3051                              <1> 	; 24/12/2021
  3052 00001988 51                  <1> 	push	ecx			; SAVE TRACK
  3053 00001989 E8C3040000          <1> 	call	SEEK
  3054 0000198E 723A                <1> 	jc	short POP_BAC		; POP AND RETURN
  3055 00001990 B8[CA190000]        <1> 	mov	eax, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  3056 00001995 50                  <1> 	push	eax
  3057 00001996 B404                <1> 	mov	ah, SENSE_DRV_ST	; SENSE DRIVE STATUS COMMAND BYTE
  3058 00001998 E87B040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3059                              <1> 	; 08/07/2022
  3060 0000199D 89F8                <1> 	mov	eax, edi		; AL = DRIVE
  3061 0000199F 88C4                <1> 	mov	ah, al			; AH = DRIVE
  3062 000019A1 E872040000          <1> 	call	NEC_OUTPUT		; OUTPUT TO NEC
  3063 000019A6 E8A6050000          <1> 	call	RESULTS			; GO GET STATUS
  3064 000019AB 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3065                              <1> 	;pop	cx			; RESTORE TRACK
  3066                              <1> 	; 24/12/2021
  3067 000019AC 59                  <1> 	pop	ecx
  3068 000019AD F605[BD620000]10    <1> 	test	byte [NEC_STATUS], HOME	; TRACK 0 ?
  3069 000019B4 74D0                <1> 	jz	short SK_GIN		; GO TILL TRACK 0
  3070 000019B6 08ED                <1> 	or	ch, ch			; IS HOME AT TRACK 0
  3071 000019B8 7408                <1> 	jz	short IS_80		; MUST BE 80 TRACK DRIVE
  3072                              <1> 
  3073                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  3074                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  3075                              <1> 
  3076 000019BA 808F[C7620000]94    <1> 	or	byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250
  3077 000019C1 C3                  <1> 	retn				; ALL INFORMATION SET
  3078                              <1> IS_80:
  3079 000019C2 808F[C7620000]01    <1> 	or	byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  3080                              <1> DD_BAC:
  3081 000019C9 C3                  <1> 	retn
  3082                              <1> POP_BAC:
  3083                              <1> 	;pop	cx			; THROW AWAY
  3084                              <1> 	; 24/12/2021
  3085 000019CA 59                  <1> 	pop	ecx
  3086 000019CB C3                  <1> 	retn
  3087                              <1> 
  3088                              <1> ;-------------------------------------------------------------------------------
  3089                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3090                              <1> ;-------------------------------------------------------------------------------
  3091                              <1> SETUP_STATE:
  3092                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3093 000019CC F687[C7620000]10    <1> 	test	byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ?
  3094 000019D3 7537                <1> 	jnz	short J1C		; NO STATES IF DETERMINED
  3095 000019D5 66B84000            <1>        	mov	ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE
  3096 000019D9 F687[C7620000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE ?
  3097 000019E0 740D                <1> 	jz	short AX_SET		; DO NOT KNOW DRIVE
  3098 000019E2 F687[C7620000]02    <1> 	test	byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE?
  3099 000019E9 7504                <1> 	jnz	short AX_SET		; JUMP IF YES
  3100 000019EB 66B88080            <1>         mov	ax, RATE_250*257	; START A END RATE 250 FOR 360 DRIVE
  3101                              <1> AX_SET:	
  3102 000019EF 80A7[C7620000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3103 000019F6 08A7[C7620000]      <1> 	or	[DSK_STATE+edi], ah	; RATE FIRST TO TRY
  3104 000019FC 8025[C4620000]F3    <1> 	and	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3105 00001A03 C0C804              <1> 	ror	al, 4			; TO OPERATION LAST RATE LOCATION
  3106 00001A06 0805[C4620000]      <1> 	or	[LASTRATE], al		; LAST RATE
  3107                              <1> J1C:	
  3108 00001A0C C3                  <1> 	retn
  3109                              <1> 
  3110                              <1> ;-------------------------------------------------------------------------------
  3111                              <1> ; MED_CHANGE	
  3112                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3113                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3114                              <1> ;
  3115                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3116                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3117                              <1> ;-------------------------------------------------------------------------------
  3118                              <1> MED_CHANGE:
  3119                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3120 00001A0D E897050000          <1> 	call	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3121 00001A12 7446                <1> 	jz	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3122 00001A14 80A7[C7620000]EF    <1> 	and	byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3123                              <1> 
  3124                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3125                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3126                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3127                              <1> 
  3128 00001A1B 89F9                <1> 	mov	ecx, edi		; CL = DRIVE #
  3129 00001A1D B001                <1> 	mov	al, 1			; MOTOR ON BIT MASK
  3130 00001A1F D2E0                <1> 	shl	al, cl			; TO APPROPRIATE POSITION
  3131 00001A21 F6D0                <1> 	not	al			; KEEP ALL BUT MOTOR ON
  3132 00001A23 FA                  <1> 	cli				; NO INTERRUPTS
  3133 00001A24 2005[BA620000]      <1> 	and	[MOTOR_STATUS], al	; TURN MOTOR OFF INDICATOR
  3134 00001A2A FB                  <1> 	sti				; INTERRUPTS ENABLED
  3135 00001A2B E832030000          <1> 	call	MOTOR_ON		; TURN MOTOR ON
  3136                              <1> 
  3137                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3138                              <1> 
  3139 00001A30 E85BFEFFFF          <1> 	call	DSK_RESET		; RESET NEC
  3140 00001A35 B501                <1> 	mov	ch, 1			; MOVE TO CYLINDER 1
  3141 00001A37 E815040000          <1> 	call	SEEK			; ISSUE SEEK
  3142 00001A3C 30ED                <1> 	xor	ch, ch			; MOVE TO CYLINDER 0
  3143 00001A3E E80E040000          <1> 	call	SEEK			; ISSUE SEEK
  3144 00001A43 C605[BC620000]06    <1> 	mov	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3145                              <1> OK1:
  3146 00001A4A E85A050000          <1> 	call	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3147 00001A4F 7407                <1> 	jz	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3148                              <1> OK4:
  3149 00001A51 C605[BC620000]80    <1> 	mov	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3150                              <1> OK2:		
  3151 00001A58 F9                  <1> 	stc				; MEDIA CHANGED, SET CY
  3152 00001A59 C3                  <1> 	retn
  3153                              <1> MC_OUT:
  3154                              <1> 	;clc	; 08/07/2022		; NO MEDIA CHANGED, CLEAR CY
  3155 00001A5A C3                  <1> 	retn
  3156                              <1> 
  3157                              <1> ;-------------------------------------------------------------------------------
  3158                              <1> ; SEND_RATE
  3159                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3160                              <1> ; ON ENTRY:	EDI = DRIVE #
  3161                              <1> ; ON EXIT:	NONE
  3162                              <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022
  3163                              <1> ;-------------------------------------------------------------------------------
  3164                              <1> SEND_RATE:
  3165                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3166                              <1> 	;push	ax			; SAVE REG.
  3167                              <1> 	; 24/12/2021
  3168                              <1> 	;push	eax ; 11/07/2022
  3169 00001A5B 8025[C4620000]3F    <1> 	and	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3170 00001A62 8A87[C7620000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3171 00001A68 24C0                <1> 	and	al, SEND_MSK		; KEEP ONLY RATE BITS
  3172 00001A6A 0805[C4620000]      <1> 	or	[LASTRATE], al		; SAVE NEW RATE FOR NEXT CHECK
  3173 00001A70 C0C002              <1> 	rol	al, 2			; MOVE TO BIT OUTPUT POSITIONS
  3174 00001A73 66BAF703            <1> 	mov	dx, 03F7h		; OUTPUT NEW DATA RATE
  3175 00001A77 EE                  <1> 	out	dx, al
  3176                              <1> 	;pop	ax			; RESTORE REG.
  3177                              <1> 	; 24/12/2021
  3178                              <1> 	;pop	eax ; 11/07/2022
  3179 00001A78 C3                  <1> 	retn
  3180                              <1> 
  3181                              <1> ;-------------------------------------------------------------------------------
  3182                              <1> ; CHK_LASTRATE
  3183                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3184                              <1> ; ON ENTRY:
  3185                              <1> ;	EDI = DRIVE #
  3186                              <1> ; ON EXIT:
  3187                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3188                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3189                              <1> ; REGISTERS ALTERED: EAX ; 11/07/2022
  3190                              <1> ;-------------------------------------------------------------------------------
  3191                              <1> CHK_LASTRATE:
  3192                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3193                              <1> 	;push	ax			; SAVE REG.
  3194                              <1> 	; 24/12/2021
  3195                              <1> 	;push	eax ; 11/07/2022
  3196 00001A79 8A25[C4620000]      <1> 	mov	ah, [LASTRATE] ; 08/07/2022 (BugFix) 
  3197                              <1> 					; GET LAST DATA RATE SELECTED
  3198 00001A7F 8A87[C7620000]      <1> 	mov	al, [DSK_STATE+edi]	; GET RATE STATE OF THIS DRIVE
  3199 00001A85 6625C0C0            <1>        	and	ax, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3200 00001A89 38E0                <1> 	cmp	al, ah			; COMPARE TO PREVIOUSLY TRIED
  3201                              <1> 					; ZF = 1 RATE IS THE SAME
  3202                              <1> 	;pop	ax			; RESTORE REG.
  3203                              <1> 	; 24/12/2021
  3204                              <1> 	;pop	eax ; 11/07/2022
  3205 00001A8B C3                  <1> 	retn
  3206                              <1> 
  3207                              <1> ;-------------------------------------------------------------------------------
  3208                              <1> ; DMA_SETUP
  3209                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3210                              <1> ;
  3211                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3212                              <1> ;
  3213                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3214                              <1> ;-------------------------------------------------------------------------------
  3215                              <1> 
  3216                              <1> ; SI = Head #, # of Sectors or DASD Type
  3217                              <1> 
  3218                              <1> ; 22/08/2015
  3219                              <1> ; 08/02/2015 - Protected Mode Modification
  3220                              <1> ; 06/02/2015 - 07/02/2015
  3221                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3222                              <1> ; (DMA Addres = Physical Address)
  3223                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3224                              <1> ;
  3225                              <1> ; 04/02/2016 (clc)
  3226                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3227                              <1> ; 16/12/2014 (IODELAY)
  3228                              <1> 
  3229                              <1> DMA_SETUP:
  3230                              <1> 	; 18/07/2022
  3231                              <1> 	; 11/07/2022
  3232                              <1> 	;	ebp = buffer address
  3233                              <1> 	
  3234                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3235                              <1> 	;; 20/02/2015
  3236                              <1> 	;mov	edx, [ebp+4] ; 11/07/2022 ; Buffer address
  3237                              <1> 	; 08/07/2022 - not needed for Retro UNIX 386 v1.1
  3238                              <1> 	;test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3239                              <1> 	;jnz	short dma_bnd_err_stc
  3240                              <1> 
  3241                              <1> 	; al = dma command
  3242                              <1> 	
  3243                              <1> ;	; 18/07/2022
  3244                              <1> ;	;	(512 bytes/sector only!) 
  3245                              <1> ;	; 24/12/2021
  3246                              <1> ;	push	eax			; DMA command
  3247                              <1> ;	;push	edx ; 11/07/2022	; *
  3248                              <1> ;	;mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3249                              <1> ;	mov	al, 3 ; 08/07/2022
  3250                              <1> ;	call	GET_PARM		; 
  3251                              <1> ;	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3252                              <1> ;	;mov	ax, si			; Sector count
  3253                              <1> ;	;mov	ah, al			; AH = # OF SECTORS
  3254                              <1> ;	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3255                              <1> ;	;shr	ax, 1			; AX = # SECTORS * 128
  3256                              <1> ;	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3257                              <1> ;	; 08/07/2022
  3258                              <1> ;	; 24/12/2021
  3259                              <1> ;	;mov	edx, esi
  3260                              <1> ;	sub	eax, eax
  3261                              <1> ;	;mov	ah, dl
  3262                              <1> ;	;shr	eax, 1
  3263                              <1> ;	mov	al, 128
  3264                              <1> ;	shl	eax, cl
  3265                              <1> ;	;
  3266                              <1> ;	dec	eax			; -1 FOR DMA VALUE
  3267                              <1> ;	mov	ecx, eax
  3268                              <1> ;	;pop	edx ; 11/07/2022	; *
  3269                              <1> ;	; 24/12/2021
  3270                              <1> ;	pop	eax
  3271                              <1> 
  3272                              <1> 	; 08/07/2022
  3273                              <1> 	;cmp	al, 42h
  3274                              <1>         ;jne	short NOT_VERF
  3275                              <1> 	;mov	edx, 0FF0000h
  3276                              <1> 	;jmp	short J33
  3277                              <1> ;NOT_VERF:
  3278                              <1> 	; 11/07/2022
  3279 00001A8C 89EA                <1> 	mov	edx, ebp
  3280                              <1> 	;
  3281                              <1> 	;add	dx, cx			; check for (64K) overflow
  3282                              <1> 	; 18/07/2022
  3283                              <1> 	; (512 bytes/sector)
  3284 00001A8E 6681C2FF01          <1> 	add	dx, 511 
  3285 00001A93 7239                <1> 	jc	short dma_bnd_err
  3286                              <1> 	;
  3287                              <1> 	;sub	dx, cx ; 11/07/2022	; Restore start address
  3288                              <1> J33:
  3289                              <1> 	; 08/07/2022
  3290 00001A95 FA                  <1> 	cli				; DISABLE INTERRUPTS DURING DMA SET-UP
  3291 00001A96 E60C                <1> 	out	DMA+12, al		; SET THE FIRST/LAST F/F
  3292                              <1> 	IODELAY				; WAIT FOR I/O
  2190 00001A98 EB00                <2>  jmp short $+2
  2191 00001A9A EB00                <2>  jmp short $+2
  3293 00001A9C E60B                <1> 	out	DMA+11, al		; OUTPUT THE MODE BYTE
  3294                              <1> 	;mov	eax, edx		; Buffer address
  3295                              <1> 	; 11/07/2022
  3296 00001A9E 89E8                <1> 	mov	eax, ebp ; buffer address
  3297 00001AA0 E604                <1> 	out	DMA+4, al		; OUTPUT LOW ADDRESS
  3298                              <1> 	IODELAY				; WAIT FOR I/O
  2190 00001AA2 EB00                <2>  jmp short $+2
  2191 00001AA4 EB00                <2>  jmp short $+2
  3299 00001AA6 88E0                <1> 	mov	al, ah
  3300 00001AA8 E604                <1> 	out	DMA+4, al		; OUTPUT HIGH ADDRESS
  3301 00001AAA C1E810              <1> 	shr	eax, 16
  3302                              <1> 	IODELAY				; I/O WAIT STATE
  2190 00001AAD EB00                <2>  jmp short $+2
  2191 00001AAF EB00                <2>  jmp short $+2
  3303 00001AB1 E681                <1> 	out	081h, al		; OUTPUT highest BITS TO PAGE REGISTER
  3304                              <1> 	IODELAY
  2190 00001AB3 EB00                <2>  jmp short $+2
  2191 00001AB5 EB00                <2>  jmp short $+2
  3305                              <1> 	;;mov	ax, cx			; Byte count - 1
  3306                              <1> 	;mov	al, cl
  3307                              <1> 	; 18/07/2022
  3308                              <1> 	; (Byte count - 1 = 511)
  3309 00001AB7 B0FF                <1> 	mov	al, 0FFh ; 511-256
  3310 00001AB9 E605                <1> 	out	DMA+5, al		; LOW BYTE OF COUNT
  3311                              <1> 	IODELAY				; WAIT FOR I/O
  2190 00001ABB EB00                <2>  jmp short $+2
  2191 00001ABD EB00                <2>  jmp short $+2
  3312                              <1> 	;;mov	al, ah
  3313                              <1> 	;mov	al, ch
  3314                              <1> 	; 18/07/2022
  3315 00001ABF B001                <1> 	mov	al, 1 ; 256
  3316 00001AC1 E605                <1> 	out	DMA+5, al		; HIGH BYTE OF COUNT
  3317                              <1> 	IODELAY
  2190 00001AC3 EB00                <2>  jmp short $+2
  2191 00001AC5 EB00                <2>  jmp short $+2
  3318 00001AC7 FB                  <1> 	sti				; RE-ENABLE INTERRUPTS
  3319 00001AC8 B002                <1> 	mov	al, 2			; MODE FOR 8237
  3320 00001ACA E60A                <1> 	out	DMA+10, al		; INITIALIZE THE DISKETTE CHANNEL
  3321                              <1> 	
  3322 00001ACC F8                  <1> 	clc	; 04/02/2016
  3323                              <1> 	
  3324 00001ACD C3                  <1> 	retn
  3325                              <1> 
  3326                              <1> 	; 18/07/2022
  3327                              <1> ;dma_bnd_err_stc:
  3328                              <1> ;	stc
  3329                              <1> 
  3330                              <1> dma_bnd_err:
  3331 00001ACE C605[BC620000]09    <1> 	mov	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3332 00001AD5 C3                  <1> 	retn				; CY SET BY ABOVE IF ERROR
  3333                              <1> 
  3334                              <1> ;-------------------------------------------------------------------------------
  3335                              <1> ; NEC_INIT	
  3336                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3337                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3338                              <1> ;
  3339                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3340                              <1> ;
  3341                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3342                              <1> ;-------------------------------------------------------------------------------
  3343                              <1> NEC_INIT:
  3344                              <1> 	; 11/07/2022
  3345                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3346                              <1> 	;push	ax			; SAVE NEC COMMAND
  3347                              <1> 	; 24/12/2021
  3348 00001AD6 50                  <1> 	push	eax
  3349 00001AD7 E886020000          <1> 	call	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3350                              <1> 
  3351                              <1> ;-----	DO THE SEEK OPERATION
  3352                              <1> 
  3353                              <1> 	;mov	ch, [ebp+1]		; CH = TRACK #
  3354                              <1> 	; 11/07/2022
  3355 00001ADC 89F1                <1> 	mov	ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector
  3356 00001ADE C1E908              <1> 	shr	ecx, 8
  3357                              <1> 	; ch = track #	
  3358                              <1> 
  3359 00001AE1 E86B030000          <1> 	call	SEEK			; MOVE TO CORRECT TRACK
  3360                              <1> 	;pop	ax			; RECOVER COMMAND
  3361                              <1> 	; 24/12/2021
  3362 00001AE6 58                  <1> 	pop	eax
  3363 00001AE7 721D                <1> 	jc	short ER_1		; ERROR ON SEEK
  3364 00001AE9 BB[061B0000]        <1> 	mov	ebx, ER_1		; LOAD ERROR ADDRESS
  3365 00001AEE 53                  <1> 	push	ebx			; PUSH NEC_OUT ERROR RETURN
  3366                              <1> 
  3367                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3368                              <1> 
  3369 00001AEF E824030000          <1> 	call	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3370 00001AF4 89F0                <1> 	mov	eax, esi		; AH = HEAD #
  3371 00001AF6 89FB                <1> 	mov	ebx, edi		; BL = DRIVE #
  3372 00001AF8 C0E402              <1> 	sal	ah, 2			; MOVE IT TO BIT 2
  3373 00001AFB 80E404              <1> 	and	ah, 00000100b		; ISOLATE THAT BIT
  3374 00001AFE 08DC                <1> 	or	ah, bl			; OR IN THE DRIVE NUMBER
  3375 00001B00 E813030000          <1> 	call	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  3376 00001B05 5B                  <1> 	pop	ebx			; THROW AWAY ERROR RETURN
  3377                              <1> ER_1:
  3378 00001B06 C3                  <1> 	retn
  3379                              <1> 
  3380                              <1> ;-------------------------------------------------------------------------------
  3381                              <1> ; RWV_COM
  3382                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  3383                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  3384                              <1> ;
  3385                              <1> ; ON ENTRY:	EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  3386                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3387                              <1> ;-------------------------------------------------------------------------------
  3388                              <1> RWV_COM:
  3389                              <1> 	; 11/07/2022
  3390                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3391 00001B07 B8[541B0000]        <1> 	mov	eax, ER_2		; LOAD ERROR ADDRESS
  3392 00001B0C 50                  <1> 	push	eax			; PUSH NEC_OUT ERROR RETURN
  3393                              <1> 	;mov	ah, [ebp+1]		; OUTPUT TRACK #
  3394                              <1> 	; 11/07/2022
  3395 00001B0D 89F0                <1> 	mov	eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track
  3396 00001B0F C1E808              <1> 	shr	eax, 8
  3397                              <1> 	; ah = track # 
  3398 00001B12 E801030000          <1> 	call	NEC_OUTPUT
  3399 00001B17 89F0                <1> 	mov	eax, esi		; OUTPUT HEAD #
  3400                              <1> 	; ah = head #
  3401 00001B19 E8FA020000          <1> 	call	NEC_OUTPUT
  3402                              <1>         ;mov	ah, [ebp]		; OUTPUT SECTOR #
  3403 00001B1E 89F0                <1> 	mov	eax, esi
  3404 00001B20 88C4                <1> 	mov	ah, al
  3405                              <1>  	; ah = sector #
  3406 00001B22 E8F1020000          <1> 	CALL	NEC_OUTPUT
  3407                              <1> 	;mov	dl, 3			; BYTES/SECTOR PARAMETER FROM BLOCK
  3408 00001B27 B003                <1> 	mov	al, 3 ; 08/07/2022
  3409 00001B29 E8F9010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3410 00001B2E E8E5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3411                              <1> 	;mov	dl, 4			; EOT PARAMETER FROM BLOCK
  3412 00001B33 B004                <1> 	mov	al, 4 ; 08/07/2022
  3413 00001B35 E8ED010000          <1> 	call	GET_PARM 		; .. TO THE NEC
  3414 00001B3A E8D9020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3415 00001B3F 8A6305              <1>         mov	ah, [ebx+MD.GAP]	; GET GAP LENGTH
  3416                              <1> _R15:
  3417 00001B42 E8D1020000          <1> 	call	NEC_OUTPUT
  3418                              <1> 	;mov	dl, 6			; DTL PARAMETER PROM BLOCK
  3419 00001B47 B006                <1> 	mov	al, 6 ; 08/07/2022
  3420 00001B49 E8D9010000          <1> 	call	GET_PARM		; .. TO THE NEC
  3421 00001B4E E8C5020000          <1> 	call	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  3422 00001B53 58                  <1> 	pop	eax			; THROW AWAY ERROR EXIT
  3423                              <1> ER_2:
  3424 00001B54 C3                  <1> 	retn
  3425                              <1> 
  3426                              <1> ;-------------------------------------------------------------------------------
  3427                              <1> ; NEC_TERM
  3428                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  3429                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  3430                              <1> ;
  3431                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3432                              <1> ;-------------------------------------------------------------------------------
  3433                              <1> 
  3434                              <1> NEC_TERM:
  3435                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3436                              <1> 
  3437                              <1> ;-----	LET THE OPERATION HAPPEN
  3438                              <1> 
  3439 00001B55 56                  <1> 	push	esi			; SAVE HEAD #, # OF SECTORS
  3440 00001B56 E8C7030000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  3441 00001B5B 9C                  <1> 	pushfd	; 24/12/2021
  3442 00001B5C E8F0030000          <1> 	call	RESULTS			; GET THE NEC STATUS
  3443 00001B61 724B                <1> 	jc	short SET_END_POP
  3444 00001B63 9D                  <1> 	popfd	; 24/12/2021
  3445 00001B64 723E                <1> 	jc	short SET_END		; LOOK FOR ERROR
  3446                              <1> 
  3447                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  3448                              <1> 
  3449 00001B66 FC                  <1> 	cld				; SET THE CORRECT DIRECTION
  3450 00001B67 BE[BD620000]        <1> 	mov	esi, NEC_STATUS		; POINT TO STATUS FIELD
  3451 00001B6C AC                  <1> 	lodsb				; GET ST0
  3452 00001B6D 24C0                <1> 	and	al, 11000000b		; TEST FOR NORMAL TERMINATION
  3453 00001B6F 7433                <1> 	jz	short SET_END
  3454 00001B71 3C40                <1> 	cmp	al, 01000000b		; TEST FOR ABNORMAL TERMINATION
  3455 00001B73 7527                <1> 	jnz	short J18		; NOT ABNORMAL, BAD NEC
  3456                              <1> 
  3457                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  3458                              <1> 
  3459 00001B75 AC                  <1> 	lodsb				; GET ST1
  3460 00001B76 D0E0                <1> 	sal	al, 1			; TEST FOR EDT FOUND
  3461 00001B78 B404                <1> 	mov	ah, RECORD_NOT_FND
  3462 00001B7A 7222                <1> 	jc	short J19
  3463 00001B7C C0E002              <1> 	sal	al, 2
  3464 00001B7F B410                <1> 	mov	ah, BAD_CRC
  3465 00001B81 721B                <1> 	jc	short J19
  3466 00001B83 D0E0                <1> 	sal	al, 1			; TEST FOR DMA OVERRUN
  3467 00001B85 B408                <1> 	mov	ah, BAD_DMA
  3468 00001B87 7215                <1> 	jc	short J19
  3469 00001B89 C0E002              <1> 	sal	al, 2			; TEST FOR RECORD NOT FOUND
  3470 00001B8C B404                <1> 	mov	ah, RECORD_NOT_FND
  3471 00001B8E 720E                <1> 	jc	short J19
  3472 00001B90 D0E0                <1> 	sal	al, 1
  3473 00001B92 B403                <1> 	mov	ah, WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  3474 00001B94 7208                <1> 	jc	short J19
  3475 00001B96 D0E0                <1> 	sal	al, 1			; TEST MISSING ADDRESS MARK
  3476 00001B98 B402                <1> 	mov	ah, BAD_ADDR_MARK
  3477 00001B9A 7202                <1> 	jc	short J19
  3478                              <1> 
  3479                              <1> ;----- 	NEC MUST HAVE FAILED
  3480                              <1> J18:
  3481 00001B9C B420                <1> 	mov	ah, BAD_NEC
  3482                              <1> J19:
  3483 00001B9E 0825[BC620000]      <1> 	or	[DSKETTE_STATUS], ah
  3484                              <1> SET_END:
  3485 00001BA4 803D[BC620000]01    <1> 	cmp	byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION
  3486 00001BAB F5                  <1> 	cmc
  3487 00001BAC 5E                  <1> 	pop	esi
  3488 00001BAD C3                  <1> 	retn				; RESTORE HEAD #, # OF SECTORS
  3489                              <1> 
  3490                              <1> SET_END_POP:
  3491 00001BAE 9D                  <1> 	popfd	; 24/12/2021
  3492 00001BAF EBF3                <1> 	jmp	short SET_END
  3493                              <1> 
  3494                              <1> ;-------------------------------------------------------------------------------
  3495                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  3496                              <1> ;-------------------------------------------------------------------------------
  3497                              <1> DSTATE:
  3498                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3499 00001BB1 803D[BC620000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3500 00001BB8 753E                <1> 	jne	short SETBAC		; IF ERROR JUMP
  3501 00001BBA 808F[C7620000]10    <1> 	or	byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  3502 00001BC1 F687[C7620000]04    <1> 	test	byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ?
  3503 00001BC8 752E                <1> 	jnz	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  3504 00001BCA 8A87[C7620000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3505 00001BD0 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3506 00001BD2 3C80                <1> 	cmp	al, RATE_250		; RATE 250 ?
  3507 00001BD4 751B                <1> 	jne	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  3508                              <1> 
  3509                              <1> ;----- 	CHECK IF IT IS 1.44M
  3510                              <1> 
  3511 00001BD6 E843010000          <1> 	call	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3512                              <1> 	;;20/02/2015
  3513                              <1> 	;;jc	short M_12		; CMOS BAD
  3514 00001BDB 7414                <1> 	jz	short M_12 ;; 20/02/2015
  3515 00001BDD 3C04                <1> 	cmp	al, 4			; 1.44MB DRIVE ?
  3516 00001BDF 7410                <1> 	je	short M_12		; YES
  3517                              <1> M_720:
  3518 00001BE1 80A7[C7620000]FD    <1> 	and	byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  3519 00001BE8 808F[C7620000]04    <1> 	or	byte [DSK_STATE+edi], DRV_DET  ; MARK DRIVE DETERMINED
  3520 00001BEF EB07                <1> 	jmp	short SETBAC		; BACK
  3521                              <1> M_12:	
  3522 00001BF1 808F[C7620000]06    <1> 	or	byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 
  3523                              <1> 					; TURN ON DETERMINED & FMT CAPA
  3524                              <1> SETBAC:
  3525 00001BF8 C3                  <1> 	retn
  3526                              <1> 
  3527                              <1> ;-------------------------------------------------------------------------------
  3528                              <1> ; RETRY	
  3529                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  3530                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  3531                              <1> ;
  3532                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  3533                              <1> ;-------------------------------------------------------------------------------
  3534                              <1> RETRY:
  3535                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3536 00001BF9 803D[BC620000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION
  3537 00001C00 7444                <1> 	je	short NO_RETRY		; SUCCESSFUL OPERATION
  3538 00001C02 803D[BC620000]80    <1> 	cmp	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY
  3539 00001C09 743B                <1> 	je	short NO_RETRY
  3540 00001C0B 8AA7[C7620000]      <1> 	mov	ah, [DSK_STATE+edi]	; GET MEDIA STATE OF DRIVE
  3541 00001C11 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED/DETERMINED ?
  3542 00001C14 7530                <1> 	jnz	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  3543 00001C16 80E4C0              <1> 	and	ah, RATE_MSK		; ISOLATE RATE
  3544 00001C19 8A2D[C4620000]      <1> 	mov	ch, [LASTRATE]		; GET START OPERATION STATE
  3545 00001C1F C0C504              <1> 	rol	ch, 4			; TO CORRESPONDING BITS
  3546 00001C22 80E5C0              <1> 	and	ch, RATE_MSK		; ISOLATE RATE BITS
  3547 00001C25 38E5                <1> 	cmp	ch, ah			; ALL RATES TRIED
  3548 00001C27 741D                <1> 	je	short NO_RETRY		; IF YES, THEN TRUE ERROR
  3549                              <1> 
  3550                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  3551                              <1> ;	 00000000B (500) -> 10000000B	(250)
  3552                              <1> ;	 10000000B (250) -> 01000000B	(300)
  3553                              <1> ;	 01000000B (300) -> 00000000B	(500)
  3554                              <1> 
  3555 00001C29 80FC01              <1> 	cmp	ah, RATE_500+1		; SET CY FOR RATE 500
  3556 00001C2C D0DC                <1> 	rcr	ah, 1			; TO NEXT STATE
  3557 00001C2E 80E4C0              <1> 	and	ah, RATE_MSK		; KEEP ONLY RATE BITS
  3558 00001C31 80A7[C7620000]1F    <1> 	and	byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP)
  3559                              <1> 					; RATE, DBL STEP OFF
  3560 00001C38 08A7[C7620000]      <1> 	or	[DSK_STATE+edi], ah	; TURN ON NEW RATE
  3561 00001C3E C605[BC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY
  3562 00001C45 F9                  <1> 	stc				; SET CARRY FOR RETRY
  3563                              <1> NO_RETRY:	; 08/07/2022
  3564 00001C46 C3                  <1> 	retn				; RETRY RETURN
  3565                              <1> 
  3566                              <1> ;NO_RETRY:
  3567                              <1> 	;clc				; CLEAR CARRY NO RETRY
  3568                              <1> 	;RETn				; NO RETRY RETURN
  3569                              <1> 
  3570                              <1> ;-------------------------------------------------------------------------------
  3571                              <1> ; NUM_TRANS
  3572                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  3573                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  3574                              <1> ;
  3575                              <1> ; ON ENTRY:	[BP+1] = TRACK
  3576                              <1> ;		SI-HI  = HEAD
  3577                              <1> ;		[BP]   = START SECTOR
  3578                              <1> ;
  3579                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  3580                              <1> ;-------------------------------------------------------------------------------
  3581                              <1> NUM_TRANS:
  3582                              <1> 	; 11/07/2022
  3583                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3584 00001C47 30C0                <1> 	xor	al, al			; CLEAR FOR ERROR
  3585 00001C49 803D[BC620000]00    <1> 	cmp	byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR
  3586                              <1> 	; 24/12/2021
  3587 00001C50 7529                <1> 	jne	short NT_OUT		; IF ERROR 0 TRANSFERRED
  3588                              <1> 	;mov	dl, 4			; SECTORS/TRACK OFFSET TO DL
  3589 00001C52 B004                <1> 	mov	al, 4 ; 08/07/2022
  3590 00001C54 E8CE000000          <1> 	call	GET_PARM		; AH = SECTORS/TRACK
  3591                              <1> 	;mov	bl, [NEC_STATUS+5]	; GET ENDING SECTOR
  3592 00001C59 A0[C2620000]        <1> 	mov	al, [NEC_STATUS+5]
  3593 00001C5E 89F1                <1> 	mov	ecx, esi		; CH = HEAD # STARTED
  3594 00001C60 88CB                <1> 	mov	bl, cl ; 11/07/2022 ; sector #
  3595 00001C62 3A2D[C1620000]      <1> 	cmp	ch, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  3596 00001C68 750D                <1> 	jne	short DIF_HD		; IF ON SAME HEAD, THEN NO ADJUST
  3597                              <1> 	; 11/07/2022
  3598                              <1> 	;mov	ch, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  3599                              <1> 	;cmp	ch, [ebp+1]		; IS IT ASKED FOR TRACK
  3600                              <1> 	;jz	short SAME_TR		; IF SAME TRACK NO INCREASE
  3601 00001C6A C1E908              <1> 	shr	ecx, 8 ; byte 3 = track # --> byte 2
  3602 00001C6D 3A2D[C0620000]      <1> 	cmp	ch, [NEC_STATUS+3]
  3603 00001C73 7404                <1> 	je	short SAME_TRK		
  3604                              <1> 	; 11/07/2022
  3605                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3606 00001C75 00E0                <1> 	add	al, ah
  3607                              <1> DIF_HD:
  3608                              <1> 	;add	bl, ah			; ADD SECTORS/TRACK
  3609 00001C77 00E0                <1> 	add	al, ah
  3610                              <1> SAME_TRK:
  3611                              <1> 	;sub	bl, [ebp]		; SUBTRACT START FROM END
  3612                              <1> 	;mov	al, bl			; TO AL
  3613 00001C79 28D8                <1> 	sub	al, bl
  3614                              <1> NT_OUT:
  3615 00001C7B C3                  <1> 	retn
  3616                              <1> 
  3617                              <1> ;-------------------------------------------------------------------------------
  3618                              <1> ; SETUP_DBL
  3619                              <1> ;	CHECK DOUBLE STEP.
  3620                              <1> ;
  3621                              <1> ; ON ENTRY :	EDI = DRIVE #
  3622                              <1> ;
  3623                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  3624                              <1> ;-------------------------------------------------------------------------------
  3625                              <1> SETUP_DBL:
  3626                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3627 00001C7C 8AA7[C7620000]      <1> 	mov	ah, [DSK_STATE+edi]	; ACCESS STATE
  3628 00001C82 F6C410              <1> 	test	ah, MED_DET		; ESTABLISHED STATE ?
  3629 00001C85 7578                <1> 	jnz	short NO_DBL		; IF ESTABLISHED THEN DOUBLE DONE
  3630                              <1> 
  3631                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  3632                              <1> 
  3633 00001C87 C605[B9620000]00    <1> 	mov	byte [SEEK_STATUS], 0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  3634 00001C8E E8CF000000          <1> 	call	MOTOR_ON		; ENSURE MOTOR STAY ON
  3635 00001C93 B500                <1> 	mov	ch, 0			; LOAD TRACK 0
  3636 00001C95 E8B7010000          <1> 	call	SEEK			; SEEK TO TRACK 0
  3637 00001C9A E862000000          <1> 	call	READ_ID			; READ ID FUNCTION
  3638 00001C9F 7243                <1> 	jc	short SD_ERR		; IF ERROR NO TRACK 0
  3639                              <1> 
  3640                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  3641                              <1> 
  3642 00001CA1 66B95004            <1> 	mov	cx, 0450h 		; START, MAX TRACKS
  3643 00001CA5 F687[C7620000]01    <1> 	test	byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  3644 00001CAC 7402                <1> 	jz	short CNT_OK		; IF NOT COUNT IS SETUP
  3645 00001CAE B1A0                <1> 	mov	cl, 0A0h		; MAXIMUM TRACK 1.2 MB
  3646                              <1> 
  3647                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  3648                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  3649                              <1> ;	THEN SET DOUBLE STEP ON.
  3650                              <1> 
  3651                              <1> CNT_OK:
  3652 00001CB0 C605[BB620000]FF    <1>        	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 
  3653                              <1> 	; 24/12/2021
  3654 00001CB7 51                  <1> 	push	ecx			; SAVE TRACK, COUNT
  3655 00001CB8 C605[BC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS
  3656 00001CBF 31C0                <1> 	xor	eax, eax		; CLEAR EAX
  3657 00001CC1 D0ED                <1> 	shr	ch, 1			; HALVE TRACK, CY = HEAD
  3658 00001CC3 C0D003              <1> 	rcl	al, 3			; AX = HEAD IN CORRECT BIT
  3659                              <1> 	; 24/12/2021
  3660 00001CC6 50                  <1> 	push	eax			; SAVE HEAD
  3661 00001CC7 E885010000          <1> 	call	SEEK			; SEEK TO TRACK
  3662                              <1> 	; 24/12/2021
  3663 00001CCC 58                  <1> 	pop	eax			; RESTORE HEAD
  3664 00001CCD 09C7                <1> 	or	edi, eax		; DI = HEAD OR'ED DRIVE
  3665 00001CCF E82D000000          <1> 	call	READ_ID			; READ ID HEAD 0
  3666 00001CD4 9C                  <1> 	pushf				; SAVE RETURN FROM READ_ID
  3667 00001CD5 6681E7FB00          <1> 	and	di, 11111011b		; TURN OFF HEAD 1 BIT
  3668 00001CDA 9D                  <1> 	popf				; RESTORE ERROR RETURN
  3669                              <1> 	; 24/12/2021
  3670 00001CDB 59                  <1> 	pop	ecx			; RESTORE COUNT
  3671 00001CDC 7308                <1> 	jnc	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  3672 00001CDE FEC5                <1> 	inc	ch			; INC FOR NEXT TRACK
  3673 00001CE0 38CD                <1> 	cmp	ch, cl			; REACHED MAXIMUM YET
  3674 00001CE2 75CC                <1> 	jnz	short CNT_OK		; CONTINUE TILL ALL TRIED
  3675                              <1> 
  3676                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  3677                              <1> 
  3678                              <1> SD_ERR:	
  3679 00001CE4 F9                  <1> 	stc				; SET CARRY FOR ERROR
  3680 00001CE5 C3                  <1> 	retn				; SETUP_DBL ERROR EXIT
  3681                              <1> 
  3682                              <1> DO_CHK:
  3683 00001CE6 8A0D[C0620000]      <1> 	mov	cl, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  3684 00001CEC 888F[C9620000]      <1> 	mov	[DSK_TRK+edi], cl	; STORE TRACK NUMBER
  3685 00001CF2 D0ED                <1> 	shr	ch, 1			; HALVE TRACK
  3686 00001CF4 38CD                <1> 	cmp	ch, cl			; IS IT THE SAME AS ASKED FOR TRACK
  3687 00001CF6 7407                <1> 	jz	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  3688 00001CF8 808F[C7620000]20    <1> 	or	byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  3689                              <1> NO_DBL:
  3690 00001CFF F8                  <1> 	clc				; CLEAR ERROR FLAG
  3691 00001D00 C3                  <1> 	retn
  3692                              <1> 
  3693                              <1> ;-------------------------------------------------------------------------------
  3694                              <1> ; READ_ID
  3695                              <1> ;	READ ID FUNCTION.
  3696                              <1> ;
  3697                              <1> ; ON ENTRY:	EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  3698                              <1> ;
  3699                              <1> ; ON EXIT: 	EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  3700                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3701                              <1> ;-------------------------------------------------------------------------------
  3702                              <1> READ_ID:
  3703                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3704 00001D01 B8[1D1D0000]        <1> 	mov	eax, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  3705 00001D06 50                  <1> 	push	eax
  3706 00001D07 B44A                <1> 	mov	ah, 4Ah			; READ ID COMMAND
  3707 00001D09 E80A010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3708 00001D0E 89F8                <1> 	mov	eax, edi		; DRIVE # TO AH, HEAD 0
  3709 00001D10 88C4                <1> 	mov	ah, al
  3710 00001D12 E801010000          <1> 	call	NEC_OUTPUT		; TO CONTROLLER
  3711 00001D17 E839FEFFFF          <1> 	call	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  3712 00001D1C 58                  <1> 	pop	eax			; THROW AWAY ERROR ADDRESS
  3713                              <1> ER_3:
  3714 00001D1D C3                  <1> 	retn
  3715                              <1> 
  3716                              <1> ;-------------------------------------------------------------------------------
  3717                              <1> ; CMOS_TYPE
  3718                              <1> ;	RETURNS CMOS DISKETTE TYPE
  3719                              <1> ;
  3720                              <1> ; ON ENTRY:	EDI = DRIVE #
  3721                              <1> ;
  3722                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  3723                              <1> ;-------------------------------------------------------------------------------
  3724                              <1> 
  3725                              <1> CMOS_TYPE: ; 11/12/2014
  3726                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3727 00001D1E 8A87[5C5D0000]      <1> 	mov	al, [edi+fd0_type] ; diskette type
  3728 00001D24 20C0                <1> 	and 	al, al ; 18/12/2014
  3729 00001D26 C3                  <1> 	retn
  3730                              <1> 
  3731                              <1> ;-------------------------------------------------------------------------------
  3732                              <1> ; GET_PARM
  3733                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  3734                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  3735                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  3736                              <1> ;	THE PARAMETER IN DL.
  3737                              <1> ;
  3738                              <1> ; ON ENTRY:	AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022
  3739                              <1> ;
  3740                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  3741                              <1> ;		AL DESTROYED
  3742                              <1> ;-------------------------------------------------------------------------------
  3743                              <1> GET_PARM:
  3744                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3745                              <1> 	;	 ENTRY:
  3746                              <1> 	;	     AL = INDEX
  3747                              <1> 	;	    EDI = DRIVE #
  3748                              <1> 	; 	 RETURN:
  3749                              <1> 	;	     AH = REQUESTED PARAMETER
  3750                              <1> 	;	     AL DESTROYED
  3751                              <1> 	
  3752                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3753                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  3754                              <1> 	;push	esi ; 11/07/2022
  3755 00001D27 53                  <1> 	push	ebx			; SAVE EBX	
  3756 00001D28 0FB6D8              <1> 	movzx	ebx, al			; EBX = INDEX
  3757                              <1>    	; 17/12/2014
  3758                              <1> 	;mov	ax, [cfd] ; current (AL) and previous fd (AH)
  3759                              <1> 	; 11/07/2022
  3760                              <1> 	;cmp	al, ah
  3761                              <1> 	;je	short gpndc
  3762                              <1> 
  3763                              <1> 	; 11/07/2022
  3764 00001D2B 89F8                <1> 	mov	eax, edi
  3765 00001D2D 3A05[515D0000]      <1> 	cmp	al, [pfd] ; is same with previous drive # ?
  3766 00001D33 7423                <1> 	je	short gpndc	
  3767                              <1> 
  3768 00001D35 A2[515D0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  3769                              <1> 
  3770 00001D3A 53                  <1> 	push	ebx ; 08/02/2015
  3771                              <1> 	
  3772                              <1> 	;mov	bl, al 
  3773                              <1> 	; 11/12/2014
  3774                              <1> 	;mov	al, [ebx+fd0_type]	; Drive type (0,1,2,3,4)
  3775                              <1> 	; 11/07/2022
  3776 00001D3B 8A87[5C5D0000]      <1> 	mov	al, [edi+fd0_type]	; Drive type (0,1,2,3,4)	
  3777                              <1> 	; 18/12/2014
  3778 00001D41 20C0                <1> 	and	al, al
  3779 00001D43 7507                <1> 	jnz	short gpdtc
  3780 00001D45 BB[3B5D0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  3781 00001D4A EB05                <1>         jmp     short gpdpu
  3782                              <1> gpdtc:	
  3783 00001D4C E8B0FBFFFF          <1> 	call	DR_TYPE_CHECK
  3784                              <1> 	; cf = 1 -> EBX points to 1.44MB fd parameter table (default)
  3785                              <1> gpdpu:
  3786 00001D51 891D[D85C0000]      <1> 	mov	[DISK_POINTER], ebx
  3787 00001D57 5B                  <1> 	pop	ebx
  3788                              <1> gpndc:
  3789                              <1> 	;mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  3790                              <1> 	;mov	ah, [esi+ebx]		; GET THE WORD
  3791                              <1> 	; 11/07/2022
  3792 00001D58 031D[D85C0000]      <1> 	add	ebx, [DISK_POINTER]
  3793 00001D5E 8A23                <1> 	mov	ah, [ebx] 
  3794 00001D60 5B                  <1> 	pop	ebx			; RESTORE EBX
  3795                              <1> 	;pop	esi ; 11/07/2022
  3796 00001D61 C3                  <1> 	retn
  3797                              <1> 
  3798                              <1> ;-------------------------------------------------------------------------------
  3799                              <1> ; MOTOR_ON
  3800                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  3801                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  3802                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  3803                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  3804                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  3805                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  3806                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  3807                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  3808                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  3809                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  3810                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  3811                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  3812                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  3813                              <1> ;
  3814                              <1> ; ON ENTRY:	EDI = DRIVE #
  3815                              <1> ; ON EXIT:	EAX, ECX, EDX DESTROYED
  3816                              <1> ;-------------------------------------------------------------------------------
  3817                              <1> MOTOR_ON:
  3818                              <1> 	; 12/07/2022
  3819                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3820 00001D62 53                  <1> 	push	ebx			; SAVE REG.
  3821 00001D63 E820000000          <1> 	call	TURN_ON			; TURN ON MOTOR
  3822 00001D68 721C                <1> 	jc	short MOT_IS_ON		; IF CY=1 NO WAIT
  3823                              <1> 	;call	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3824                              <1> 	; 08/07/2022
  3825                              <1> 	;call	XLAT_NEW ; 12/07/2022	; TRANSLATE STATE TO PRESENT ARCH,
  3826                              <1> 	;call	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  3827                              <1> 	;jc	short MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  3828                              <1> M_WAIT:
  3829                              <1> 	;mov	dl,10			; GET THE MOTOR WAIT PARAMETER
  3830 00001D6A B00A                <1> 	mov	al, 10 ; 08/07/2022
  3831 00001D6C E8B6FFFFFF          <1> 	call	GET_PARM
  3832                              <1> 	; 08/07/2022			; AH = MOTOR WAIT PARAMETER
  3833 00001D71 80FC08              <1> 	cmp	ah, 8			; SEE IF AT LEAST A SECOND IS SPECIFIED			
  3834                              <1> 	;jae	short GP2		; IF YES, CONTINUE
  3835 00001D74 7302                <1> 	jae	short J13
  3836 00001D76 B408                <1> 	mov	ah, 8			; ONE SECOND WAIT FOR MOTOR START UP
  3837                              <1> 
  3838                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  3839                              <1> GP2:	
  3840                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  3841                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  3842 00001D78 B95E200000          <1> 	mov	ecx, 8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  3843 00001D7D E817F7FFFF          <1> 	call	WAITF			; GO TO FIXED WAIT ROUTINE
  3844                              <1> 	;dec	al			; DECREMENT TIME VALUE
  3845 00001D82 FECC                <1> 	dec	ah
  3846 00001D84 75F2                <1> 	jnz	short J13		; ARE WE DONE YET
  3847                              <1> MOT_IS_ON:
  3848 00001D86 5B                  <1> 	pop	ebx			; RESTORE REG.
  3849 00001D87 C3                  <1> 	retn
  3850                              <1> 
  3851                              <1> ;-------------------------------------------------------------------------------
  3852                              <1> ; TURN_ON
  3853                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  3854                              <1> ;
  3855                              <1> ; ON ENTRY:	EDI = DRIVE #
  3856                              <1> ;
  3857                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  3858                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  3859                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  3860                              <1> ;-------------------------------------------------------------------------------
  3861                              <1> TURN_ON:
  3862                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3863 00001D88 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  3864 00001D8A 88D9                <1> 	mov	cl, bl			; CL = DRIVE #
  3865 00001D8C C0C304              <1> 	rol	bl, 4			; BL = DRIVE SELECT
  3866 00001D8F FA                  <1> 	cli				; NO INTERRUPTS WHILE DETERMINING STATUS
  3867 00001D90 C605[BB620000]FF    <1> 	mov	byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION
  3868 00001D97 A0[BA620000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3869 00001D9C 2430                <1> 	and	al, 00110000b		; KEEP ONLY DRIVE SELECT BITS
  3870 00001D9E B401                <1> 	mov	ah, 1			; MASK FOR DETERMINING MOTOR BIT
  3871 00001DA0 D2E4                <1> 	shl	ah, cl			; AH = MOTOR ON, A=00000001, B=00000010
  3872                              <1> 
  3873                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  3874                              <1> ;  BL = DRIVE SELECT DESIRED
  3875                              <1> ;  AH = MOTOR ON MASK DESIRED
  3876                              <1> 
  3877 00001DA2 38D8                <1> 	cmp	al, bl			; REQUESTED DRIVE ALREADY SELECTED ?
  3878 00001DA4 7508                <1> 	jne	short TURN_IT_ON	; IF NOT SELECTED JUMP
  3879 00001DA6 8425[BA620000]      <1> 	test	ah, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  3880 00001DAC 7535                <1> 	jnz	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  3881                              <1> 
  3882                              <1> TURN_IT_ON:
  3883 00001DAE 08DC                <1> 	or	ah, bl			; AH = DRIVE SELECT AND MOTOR ON
  3884 00001DB0 8A3D[BA620000]      <1> 	mov	bh, [MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  3885 00001DB6 80E70F              <1> 	and	bh, 00001111b		; KEEP ONLY MOTOR BITS
  3886 00001DB9 8025[BA620000]CF    <1> 	and	byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT
  3887 00001DC0 0825[BA620000]      <1> 	or	[MOTOR_STATUS], ah	; OR IN DRIVE SELECTED AND MOTOR ON
  3888 00001DC6 A0[BA620000]        <1> 	mov	al, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  3889 00001DCB 88C3                <1> 	mov	bl, al			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  3890 00001DCD 80E30F              <1> 	and	bl, 00001111b		; KEEP ONLY MOTOR BITS
  3891 00001DD0 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3892 00001DD1 243F                <1> 	and	al, 00111111b		; STRIP AWAY UNWANTED BITS
  3893 00001DD3 C0C004              <1> 	rol	al, 4			; PUT BITS IN DESIRED POSITIONS
  3894 00001DD6 0C0C                <1> 	or	al, 00001100b		; NO RESET, ENABLE DMA/INTERRUPT
  3895 00001DD8 66BAF203            <1> 	mov	dx, 03F2h		; SELECT DRIVE AND TURN ON MOTOR
  3896 00001DDC EE                  <1> 	out	dx, al
  3897 00001DDD 38FB                <1> 	cmp	bl, bh			; NEW MOTOR TURNED ON ?
  3898                              <1> 	;je	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  3899 00001DDF 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  3900 00001DE1 F8                  <1> 	clc				; RESET CARRY MEANING WAIT
  3901 00001DE2 C3                  <1> 	retn
  3902                              <1> 
  3903                              <1> NO_MOT_WAIT:
  3904 00001DE3 FB                  <1> 	sti
  3905                              <1> no_mot_w1: ; 27/02/2015
  3906 00001DE4 F9                  <1> 	stc				; SET NO WAIT REQUIRED
  3907                              <1> 	;sti				; INTERRUPTS BACK ON
  3908 00001DE5 C3                  <1> 	retn
  3909                              <1> 
  3910                              <1> ;-------------------------------------------------------------------------------
  3911                              <1> ; HD_WAIT
  3912                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  3913                              <1> ;
  3914                              <1> ; ON ENTRY:	DI = DRIVE #
  3915                              <1> ;
  3916                              <1> ; ON EXIT:	EAX, EBX, ECX, EDX DESTROYED
  3917                              <1> ;-------------------------------------------------------------------------------
  3918                              <1> HD_WAIT:
  3919                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3920                              <1> 	;mov	dl, 9			; GET HEAD SETTLE PARAMETER
  3921 00001DE6 B009                <1> 	mov	al, 9	; 08/07/2022
  3922 00001DE8 E83AFFFFFF          <1> 	CALL	GET_PARM
  3923 00001DED 08E4                <1> 	or	ah, ah	; 17/12/2014	; CHECK FOR ANY WAIT?
  3924 00001DEF 7519                <1> 	jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3925 00001DF1 F605[BA620000]80    <1>         test	byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION
  3926                              <1> 	;jz	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  3927                              <1> 	;or	ah, ah			; CHECK FOR ANY WAIT?
  3928                              <1> 	;jnz	short DO_WAT		; IF THERE DO NOT ENFORCE
  3929 00001DF8 741D                <1> 	jz	short HW_DONE
  3930 00001DFA B40F                <1> 	mov	ah, HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  3931 00001DFC 8A87[C7620000]      <1> 	mov	al, [DSK_STATE+edi]	; LOAD STATE
  3932 00001E02 24C0                <1> 	and	al, RATE_MSK		; KEEP ONLY RATE
  3933 00001E04 3C80                <1> 	cmp	al, RATE_250		; 1.2 M DRIVE ?
  3934 00001E06 7502                <1> 	jnz	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  3935                              <1> ;GP3:
  3936 00001E08 B414                <1> 	mov	ah, HD320_SETTLE	; USE 320/360 HEAD SETTLE
  3937                              <1> ;	jmp	short DO_WAT
  3938                              <1> 
  3939                              <1> ;ISNT_WRITE:
  3940                              <1> ;	or	ah, ah			; CHECK FOR NO WAIT
  3941                              <1> ;	jz	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  3942                              <1> 
  3943                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  3944                              <1> DO_WAT:
  3945                              <1> ;	mov	al, ah			; AL = # MILLISECONDS
  3946                              <1> ;	;xor	ah, ah			; AX = # MILLISECONDS
  3947                              <1> J29:					; 	1 MILLISECOND LOOP
  3948                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  3949                              <1> 	;mov	ecx, 66			; COUNT AT 15.085737 US PER COUNT
  3950                              <1> 	; 08/07/2022
  3951 00001E0A 29C9                <1> 	sub	ecx, ecx
  3952 00001E0C B142                <1> 	mov	cl, 66
  3953 00001E0E E886F6FFFF          <1> 	call	WAITF			; DELAY FOR 1 MILLISECOND
  3954                              <1> 	;dec	al			; DECREMENT THE COUNT
  3955 00001E13 FECC                <1> 	dec	ah
  3956 00001E15 75F3                <1> 	jnz	short J29		; DO AL MILLISECOND # OF TIMES
  3957                              <1> HW_DONE:
  3958 00001E17 C3                  <1> 	retn
  3959                              <1> 
  3960                              <1> ;-------------------------------------------------------------------------------
  3961                              <1> ; NEC_OUTPUT
  3962                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  3963                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  3964                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  3965                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  3966                              <1> ; 
  3967                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  3968                              <1> ;
  3969                              <1> ; ON EXIT:	CY = 0  SUCCESS
  3970                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  3971                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  3972                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  3973                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  3974                              <1> ;
  3975                              <1> ;		EAX, ECX, EDX DESTROYED
  3976                              <1> ;-------------------------------------------------------------------------------
  3977                              <1> 
  3978                              <1> ; 09/12/2014 [Erdogan Tan] 
  3979                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  3980                              <1> ; Diskette Drive Controller Status Register (3F4h)
  3981                              <1> ;	This read only register facilitates the transfer of data between
  3982                              <1> ;	the system microprocessor and the controller.
  3983                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  3984                              <1> ;	  with the system micrprocessor.
  3985                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  3986                              <1> ;	  the transfer is to the controller.
  3987                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  3988                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  3989                              <1> ; Bit 3 - Reserved.
  3990                              <1> ; Bit 2 - Reserved.
  3991                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  3992                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 0 is in the seek mode.
  3993                              <1> 
  3994                              <1> ; Data Register (3F5h)
  3995                              <1> ; This read/write register passes data, commands and parameters, and provides
  3996                              <1> ; diskette status information.
  3997                              <1>   		
  3998                              <1> NEC_OUTPUT:
  3999                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4000                              <1> 	;push	ebx			; SAVE REG.
  4001 00001E18 BAF4030000          <1> 	mov	edx, 03F4h		; STATUS PORT
  4002                              <1> 	;xor	ecx, ecx		; COUNT FOR TIME OUT
  4003                              <1> 	; 16/12/2014
  4004                              <1> 	; waiting for (max.) 0.5 seconds
  4005                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4006                              <1> 	;
  4007                              <1> 	; 17/12/2014
  4008                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4009                              <1> 	;
  4010                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4011                              <1> 	;		go on.
  4012                              <1> 	;INPUT:
  4013                              <1> 	;	AH=Mask for isolation bits.
  4014                              <1> 	;	AL=pattern to look for.
  4015                              <1> 	;	DX=Port to test for
  4016                              <1> 	;	ECX=Number of memory refresh periods to delay.
  4017                              <1> 	;	     (normally 30 microseconds per period.)
  4018                              <1> 	;
  4019                              <1> 	;WFP_SHORT:  
  4020                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4021                              <1> 	;
  4022                              <1> 
  4023 00001E1D B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4024                              <1> ;
  4025                              <1> ;WFPS_OUTER_LP:
  4026                              <1> ;	;
  4027                              <1> ;WFPS_CHECK_PORT:
  4028                              <1> J23:
  4029 00001E22 EC                  <1> 	in	al, dx			; GET STATUS
  4030 00001E23 24C0                <1> 	and	al, 11000000b		; KEEP STATUS AND DIRECTION
  4031 00001E25 3C80                <1> 	cmp	al, 10000000b		; STATUS 1 AND DIRECTION 0 ?
  4032 00001E27 7418                <1> 	jz	short J27		; STATUS AND DIRECTION OK
  4033                              <1> WFPS_HI:
  4034 00001E29 E461                <1> 	in	al, PORT_B	; 061h	; SYS1	; wait for hi to lo
  4035 00001E2B A810                <1> 	test	al, 010h		; transition on memory
  4036 00001E2D 75FA                <1> 	jnz	short WFPS_HI		; refresh.
  4037                              <1> WFPS_LO:
  4038 00001E2F E461                <1> 	in	al, PORT_B		; SYS1
  4039 00001E31 A810                <1> 	test	al, 010h
  4040 00001E33 74FA                <1> 	jz	short WFPS_LO
  4041                              <1> 	;loop	short WFPS_CHECK_PORT
  4042 00001E35 E2EB                <1> 	loop	J23	; 27/02/2015	; REPEAT TILL DELAY FINISHED
  4043                              <1> 
  4044                              <1> 	; fail
  4045                              <1> 
  4046                              <1> ;WFPS_TIMEOUT:
  4047                              <1> 
  4048                              <1> ;-----	FALL THRU TO ERROR RETURN
  4049                              <1> 
  4050 00001E37 800D[BC620000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4051                              <1> 	;pop	ebx			; RESTORE REG.
  4052 00001E3E 58                  <1> 	pop	eax ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4053 00001E3F F9                  <1> 	stc				; INDICATE ERROR TO CALLER
  4054 00001E40 C3                  <1> 	retn
  4055                              <1> 
  4056                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4057                              <1> 
  4058                              <1> J27:	
  4059 00001E41 88E0                <1> 	mov	al, ah			; GET BYTE TO OUTPUT
  4060 00001E43 42                  <1> 	inc	edx			; DATA PORT = STATUS PORT + 1
  4061 00001E44 EE                  <1> 	out	dx, al			; OUTPUT THE BYTE
  4062                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4063                              <1> 	; 27/02/2015
  4064 00001E45 9C                  <1> 	pushfd	; 24/12/2021		; SAVE FLAGS
  4065                              <1> 	;mov	ecx, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4066 00001E46 29C9                <1> 	sub	ecx, ecx
  4067 00001E48 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4068 00001E4A E84AF6FFFF          <1> 	call 	WAITF			; NEC FLAGS UPDATE CYCLE
  4069 00001E4F 9D                  <1> 	popfd	; 24/12/2021		; RESTORE FLAGS FOR EXIT
  4070                              <1> 	;pop	ebx			; RESTORE REG
  4071 00001E50 C3                  <1> 	retn				; CY = 0 FROM TEST INSTRUCTION
  4072                              <1> 
  4073                              <1> ;-------------------------------------------------------------------------------
  4074                              <1> ; SEEK
  4075                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4076                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4077                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4078                              <1> ;
  4079                              <1> ; ON ENTRY:	EDI = DRIVE #
  4080                              <1> ;		CH = TRACK #
  4081                              <1> ;
  4082                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4083                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4084                              <1> ;-------------------------------------------------------------------------------
  4085                              <1> SEEK:
  4086                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4087 00001E51 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4088 00001E53 B001                <1> 	mov	al, 1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4089 00001E55 86CB                <1> 	xchg	cl, bl			; SET DRIVE VALUE INTO CL
  4090 00001E57 D2C0                <1> 	rol	al, cl			; SHIFT MASK BY THE DRIVE VALUE
  4091 00001E59 86CB                <1> 	xchg	cl, bl			; RECOVER DRIVE VALUE
  4092 00001E5B 8405[B9620000]      <1> 	test	al, [SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4093 00001E61 7526                <1> 	jnz	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4094                              <1> 
  4095 00001E63 0805[B9620000]      <1> 	or	[SEEK_STATUS], al	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4096 00001E69 E862000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4097 00001E6E 730E                <1> 	jnc	short AFT_RECAL		; RECALIBRATE DONE
  4098                              <1> 
  4099                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4100                              <1> 
  4101 00001E70 C605[BC620000]00    <1> 	mov	byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS
  4102 00001E77 E854000000          <1> 	call	RECAL			; RECALIBRATE DRIVE
  4103 00001E7C 7251                <1> 	jc	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4104                              <1> 
  4105                              <1> AFT_RECAL:
  4106 00001E7E C687[C9620000]00    <1> 	mov	byte [DSK_TRK+edi], 0	; SAVE NEW CYLINDER AS PRESENT POSITION
  4107 00001E85 08ED                <1> 	or	ch, ch			; CHECK FOR SEEK TO TRACK 0
  4108 00001E87 743F                <1> 	jz	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4109                              <1> 
  4110                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4111                              <1> 
  4112 00001E89 F687[C7620000]20    <1> J28A:	test	byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4113 00001E90 7402                <1> 	jz	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4114 00001E92 D0E5                <1> 	shl	ch, 1			; DOUBLE NUMBER OF STEP TO TAKE
  4115                              <1> 
  4116 00001E94 3AAF[C9620000]      <1> _R7:	cmp	ch, [DSK_TRK+edi]	; SEE IF ALREADY AT THE DESIRED TRACK
  4117 00001E9A 7433                <1> 	je	short RB		; IF YES, DO NOT NEED TO SEEK
  4118                              <1> 
  4119 00001E9C BA[CF1E0000]        <1> 	mov	edx, NEC_ERR		; LOAD RETURN ADDRESS
  4120 00001EA1 52                  <1> 	push	edx ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4121 00001EA2 88AF[C9620000]      <1> 	mov	[DSK_TRK+edi], ch	; SAVE NEW CYLINDER AS PRESENT POSITION
  4122 00001EA8 B40F                <1> 	mov	ah, 0Fh			; SEEK COMMAND TO NEC
  4123 00001EAA E869FFFFFF          <1> 	call	NEC_OUTPUT
  4124 00001EAF 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4125 00001EB1 88DC                <1> 	mov	ah, bl			; OUTPUT DRIVE NUMBER
  4126 00001EB3 E860FFFFFF          <1> 	call	NEC_OUTPUT
  4127 00001EB8 8AA7[C9620000]      <1> 	mov	ah, [DSK_TRK+edi]	; GET CYLINDER NUMBER
  4128 00001EBE E855FFFFFF          <1> 	call	NEC_OUTPUT
  4129 00001EC3 E827000000          <1> 	call	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4130                              <1> 
  4131                              <1> ;-----	WAIT FOR HEAD SETTLE
  4132                              <1> 
  4133                              <1> DO_WAIT:
  4134 00001EC8 9C                  <1> 	pushfd	; 24/12/2021		; SAVE STATUS
  4135 00001EC9 E818FFFFFF          <1> 	call	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4136 00001ECE 9D                  <1> 	popfd	; 24/12/2021		; RESTORE STATUS
  4137                              <1> RB:
  4138                              <1> NEC_ERR:
  4139                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4140                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4141 00001ECF C3                  <1> 	retn				; RETURN TO CALLER
  4142                              <1> 
  4143                              <1> ;-------------------------------------------------------------------------------
  4144                              <1> ; RECAL
  4145                              <1> ;	RECALIBRATE DRIVE
  4146                              <1> ;
  4147                              <1> ; ON ENTRY:	EDI = DRIVE #
  4148                              <1> ;
  4149                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4150                              <1> ;-------------------------------------------------------------------------------
  4151                              <1> RECAL:
  4152                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4153                              <1> 	;push	cx
  4154                              <1> 	; 24/12/2021
  4155 00001ED0 51                  <1> 	push	ecx
  4156 00001ED1 B8[ED1E0000]        <1> 	mov	eax, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4157 00001ED6 50                  <1> 	push	eax
  4158 00001ED7 B407                <1> 	mov	ah, 07h			; RECALIBRATE COMMAND
  4159 00001ED9 E83AFFFFFF          <1> 	call	NEC_OUTPUT
  4160 00001EDE 89FB                <1> 	mov	ebx, edi		; EBX = DRIVE #
  4161 00001EE0 88DC                <1> 	mov	ah, bl
  4162 00001EE2 E831FFFFFF          <1> 	call	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4163 00001EE7 E803000000          <1> 	call	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4164 00001EEC 58                  <1> 	pop	eax			; THROW AWAY ERROR
  4165                              <1> RC_BACK:
  4166                              <1> 	;pop	cx
  4167                              <1> 	; 24/12/2021
  4168 00001EED 59                  <1> 	pop	ecx
  4169 00001EEE C3                  <1> 	RETn
  4170                              <1> 
  4171                              <1> ;-------------------------------------------------------------------------------
  4172                              <1> ; CHK_STAT_2
  4173                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4174                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4175                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4176                              <1> ;
  4177                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4178                              <1> ;-------------------------------------------------------------------------------
  4179                              <1> CHK_STAT_2:
  4180                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4181 00001EEF B8[171F0000]        <1>         mov	eax, CS_BACK		; LOAD NEC_OUTPUT ERROR ADDRESS
  4182 00001EF4 50                  <1> 	push	eax
  4183 00001EF5 E828000000          <1> 	call	WAIT_INT		; WAIT FOR THE INTERRUPT
  4184 00001EFA 721A                <1> 	jc	short J34		; IF ERROR, RETURN IT
  4185 00001EFC B408                <1> 	mov	ah, 08h			; SENSE INTERRUPT STATUS COMMAND
  4186 00001EFE E815FFFFFF          <1> 	call	NEC_OUTPUT
  4187 00001F03 E849000000          <1> 	call	RESULTS			; READ IN THE RESULTS
  4188 00001F08 720C                <1> 	jc	short J34
  4189 00001F0A A0[BD620000]        <1> 	mov	al, [NEC_STATUS]	; GET THE FIRST STATUS BYTE
  4190 00001F0F 2460                <1> 	and	al, 01100000b		; ISOLATE THE BITS
  4191 00001F11 3C60                <1> 	cmp	al, 01100000b		; TEST FOR CORRECT VALUE
  4192 00001F13 7403                <1> 	jz	short J35		; IF ERROR, GO MARK IT
  4193 00001F15 F8                  <1> 	clc				; GOOD RETURN
  4194                              <1> J34:
  4195 00001F16 58                  <1> 	pop	eax			; THROW AWAY ERROR RETURN
  4196                              <1> CS_BACK:
  4197 00001F17 C3                  <1> 	retn
  4198                              <1> J35:
  4199 00001F18 800D[BC620000]40    <1> 	or	byte [DSKETTE_STATUS], BAD_SEEK
  4200 00001F1F F9                  <1> 	stc				; ERROR RETURN CODE
  4201 00001F20 EBF4                <1> 	jmp	short J34
  4202                              <1> 
  4203                              <1> ;-------------------------------------------------------------------------------
  4204                              <1> ; WAIT_INT
  4205                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4206                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4207                              <1> ;	IF THE DRIVE IS NOT READY.
  4208                              <1> ;
  4209                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4210                              <1> ;-------------------------------------------------------------------------------
  4211                              <1> 
  4212                              <1> ; 17/12/2014
  4213                              <1> ; 2.5 seconds waiting !
  4214                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4215                              <1> ; amount of time to wait for completion interrupt from NEC.
  4216                              <1> 
  4217                              <1> WAIT_INT:
  4218                              <1> 	; 12/07/2022
  4219                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4220 00001F22 FB                  <1> 	sti				; TURN ON INTERRUPTS, JUST IN CASE
  4221                              <1> 	; 12/07/2022
  4222                              <1> 	;clc				; CLEAR TIMEOUT INDICATOR
  4223                              <1>        ;mov	bl, 10			; CLEAR THE COUNTERS
  4224                              <1>        ;xor	cx, cx			; FOR 2 SECOND WAIT
  4225                              <1> 
  4226                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4227                              <1> 	;
  4228                              <1> 	;WAIT_FOR_MEM:	
  4229                              <1> 	;	Waits for a bit at a specified memory location pointed
  4230                              <1> 	;	to by ES:[DI] to become set.
  4231                              <1> 	;INPUT:
  4232                              <1> 	;	AH=Mask to test with.
  4233                              <1> 	;	ES:[DI] = memory location to watch.
  4234                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4235                              <1> 	;	     (normally 30 microseconds per period.)
  4236                              <1> 
  4237                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4238                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4239                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4240                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4241                              <1> 	; 27/02/2015
  4242 00001F23 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4243                              <1> WFMS_CHECK_MEM:
  4244 00001F28 F605[B9620000]80    <1> 	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4245 00001F2F 7516                <1>         jnz     short J37
  4246                              <1> WFMS_HI:
  4247 00001F31 E461                <1> 	in	al, PORT_B  ; 061h	; SYS1, wait for lo to hi
  4248 00001F33 A810                <1> 	test	al, 010h		; transition on memory
  4249 00001F35 75FA                <1> 	jnz	short WFMS_HI		; refresh.
  4250                              <1> WFMS_LO:
  4251 00001F37 E461                <1> 	in	al, PORT_B		; SYS1
  4252 00001F39 A810                <1> 	test	al, 010h
  4253 00001F3B 74FA                <1> 	jz	short WFMS_LO
  4254 00001F3D E2E9                <1>         loop	WFMS_CHECK_MEM
  4255                              <1> ;WFMS_OUTER_LP:
  4256                              <1> ;;	or	bl, bl			; check outer counter
  4257                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4258                              <1> ;	dec	bl
  4259                              <1> ;	jz	short J36A	
  4260                              <1> ;	jmp	short WFMS_CHECK_MEM
  4261                              <1> 
  4262                              <1> 	;17/12/2014
  4263                              <1> 	;16/12/2014
  4264                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4265                              <1> ;J36:
  4266                              <1> ;	test	byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4267                              <1> ;	jnz	short J37
  4268                              <1> 	;16/12/2014
  4269                              <1> 	;loop	J36			; COUNT DOWN WHILE WAITING
  4270                              <1> 	;dec	bl			; SECOND LEVEL COUNTER
  4271                              <1> 	;jnz	short J36
  4272                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4273                              <1> ;	jb	short J36
  4274                              <1> 
  4275                              <1> ;WFMS_TIMEOUT:
  4276                              <1> ;J36A:
  4277 00001F3F 800D[BC620000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4278 00001F46 F9                  <1> 	stc				; ERROR RETURN
  4279                              <1> J37:
  4280 00001F47 9C                  <1> 	pushf				; SAVE CURRENT CARRY
  4281 00001F48 8025[B9620000]7F    <1> 	and	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4282 00001F4F 9D                  <1> 	popf				; RECOVER CARRY
  4283 00001F50 C3                  <1> 	retn				; GOOD RETURN CODE
  4284                              <1> 
  4285                              <1> ;-------------------------------------------------------------------------------
  4286                              <1> ; RESULTS
  4287                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4288                              <1> ;	FOLLOWING AN INTERRUPT.
  4289                              <1> ;
  4290                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4291                              <1> ;		EAX, EBX, ECX, EDX DESTROYED
  4292                              <1> ;-------------------------------------------------------------------------------
  4293                              <1> RESULTS:
  4294                              <1> 	; 12/07/2022
  4295                              <1> 	; 11/07/2022
  4296                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4297 00001F51 57                  <1> 	push	edi
  4298 00001F52 BF[BD620000]        <1> 	mov	edi, NEC_STATUS		; POINTER TO DATA AREA
  4299 00001F57 B307                <1> 	mov	bl, 7			; MAX STATUS BYTES
  4300 00001F59 66BAF403            <1> 	mov	dx, 03F4h		; STATUS PORT
  4301                              <1> 
  4302                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4303                              <1> 
  4304                              <1> _R10: 
  4305                              <1> 	; 16/12/2014
  4306                              <1> 	; wait for (max) 0.5 seconds
  4307                              <1> 	;mov	bh, 2			; HIGH ORDER COUNTER
  4308                              <1> 	;xor	cx, cx			; COUNTER
  4309                              <1> 
  4310                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4311                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4312                              <1> 	; 27/02/2015
  4313                              <1> 
  4314 00001F5D B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4315                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4316                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4317                              <1> 
  4318                              <1> WFPSR_OUTER_LP:
  4319                              <1> 	;
  4320                              <1> WFPSR_CHECK_PORT:
  4321                              <1> J39:					; WAIT FOR MASTER
  4322 00001F62 EC                  <1> 	in	al, dx			; GET STATUS
  4323 00001F63 24C0                <1> 	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4324 00001F65 3CC0                <1> 	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4325 00001F67 7418                <1> 	jz	short J42		; STATUS AND DIRECTION OK
  4326                              <1> WFPSR_HI:
  4327 00001F69 E461                <1> 	in	al, PORT_B	;061h	; SYS1	; wait for hi to lo
  4328 00001F6B A810                <1> 	test	al, 010h		; transition on memory
  4329 00001F6D 75FA                <1> 	jnz	short WFPSR_HI		; refresh.
  4330                              <1> WFPSR_LO:
  4331 00001F6F E461                <1> 	in	al, PORT_B		; SYS1
  4332 00001F71 A810                <1> 	test	al, 010h
  4333 00001F73 74FA                <1> 	jz	short WFPSR_LO
  4334 00001F75 E2EB                <1>         loop	WFPSR_CHECK_PORT
  4335                              <1> 	
  4336                              <1> 	;; 27/02/2015
  4337                              <1> 	;;dec	bh
  4338                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4339                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4340                              <1> 
  4341                              <1> 	;;mov	byte [wait_count], 0
  4342                              <1> ;J39:					; WAIT FOR MASTER
  4343                              <1> ;	in	al, dx			; GET STATUS
  4344                              <1> ;	and	al, 11000000b		; KEEP ONLY STATUS AND DIRECTION
  4345                              <1> ;	cmp	al, 11000000b		; STATUS 1 AND DIRECTION 1 ?
  4346                              <1> ;	jz	short J42		; STATUS AND DIRECTION OK
  4347                              <1> 	;loop	J39			; LOOP TILL TIMEOUT
  4348                              <1> 	;dec	bh			; DECREMENT HIGH ORDER COUNTER
  4349                              <1> 	;jnz	short J39		; REPEAT TILL DELAY DONE
  4350                              <1> 	;
  4351                              <1> 	;;cmp	byte [wait_count], 10	; (10/18.2 seconds)
  4352                              <1> 	;;jb	short J39	
  4353                              <1> 
  4354                              <1> ;WFPSR_TIMEOUT:
  4355 00001F77 800D[BC620000]80    <1> 	or	byte [DSKETTE_STATUS], TIME_OUT
  4356 00001F7E F9                  <1> 	stc				; SET ERROR RETURN
  4357 00001F7F EB26                <1> 	jmp	short POPRES		; POP REGISTERS AND RETURN
  4358                              <1> 
  4359                              <1> ;-----	READ IN THE STATUS
  4360                              <1> 
  4361                              <1> J42:
  4362 00001F81 EB00                <1> 	JMP	$+2			; I/O DELAY
  4363                              <1> 	;inc	dx			; POINT AT DATA PORT
  4364 00001F83 FEC2                <1> 	inc	dl
  4365 00001F85 EC                  <1> 	in	al, dx			; GET THE DATA
  4366                              <1> 	; 16/12/2014
  4367                              <1> 	NEWIODELAY
  2195 00001F86 E6EB                <2>  out 0EBh,al
  4368                              <1> 	
  4369                              <1> 	;mov	[edi], al		; STORE THE BYTE
  4370                              <1> 	;inc	edi			; INCREMENT THE POINTER
  4371                              <1> 	; 11/07/2022
  4372 00001F88 AA                  <1> 	stosb
  4373                              <1> 
  4374                              <1> 	; 16/12/2014
  4375                              <1> ;	push	cx
  4376                              <1> ;	mov	cx, 30
  4377                              <1> ;wdw2:
  4378                              <1> ;	NEWIODELAY
  4379                              <1> ;	loop	wdw2
  4380                              <1> ;	pop	cx
  4381                              <1> 
  4382                              <1> 	;mov	ecx,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4383                              <1> 	; 12/07/2022
  4384 00001F89 29C9                <1> 	sub	ecx, ecx
  4385 00001F8B B103                <1> 	mov	cl, 3
  4386 00001F8D E807F5FFFF          <1> 	call	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4387                              <1> 	;dec	dx			; POINT AT STATUS PORT
  4388 00001F92 FECA                <1> 	dec	dl
  4389 00001F94 EC                  <1> 	in	al, dx			; GET STATUS
  4390                              <1> 	; 16/12/2014
  4391                              <1> 	NEWIODELAY
  2195 00001F95 E6EB                <2>  out 0EBh,al
  4392                              <1> 	;
  4393 00001F97 A810                <1> 	test	al, 00010000b		; TEST FOR NEC STILL BUSY
  4394 00001F99 740C                <1> 	jz	short POPRES		; RESULTS DONE ?
  4395                              <1> 
  4396 00001F9B FECB                <1> 	dec	bl			; DECREMENT THE STATUS COUNTER
  4397 00001F9D 75BE                <1>         jnz	short _R10              ; GO BACK FOR MORE
  4398 00001F9F 800D[BC620000]20    <1> 	or	byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES
  4399 00001FA6 F9                  <1> 	stc				; SET ERROR FLAG
  4400                              <1> 
  4401                              <1> ;-----	RESULT OPERATION IS DONE
  4402                              <1> POPRES:
  4403 00001FA7 5F                  <1> 	pop	edi
  4404 00001FA8 C3                  <1> 	retn				; RETURN WITH CARRY SET
  4405                              <1> 
  4406                              <1> ;-------------------------------------------------------------------------------
  4407                              <1> ; READ_DSKCHNG
  4408                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  4409                              <1> ;
  4410                              <1> ; ON ENTRY:	EDI = DRIVE #
  4411                              <1> ;
  4412                              <1> ; ON EXIT:	EDI = DRIVE #
  4413                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  4414                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  4415                              <1> ;		EAX, ECX, EDX DESTROYED
  4416                              <1> ;-------------------------------------------------------------------------------
  4417                              <1> READ_DSKCHNG:
  4418                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4419 00001FA9 E8B4FDFFFF          <1> 	call	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  4420 00001FAE 66BAF703            <1> 	mov	dx, 03F7h		; ADDRESS DIGITAL INPUT REGISTER
  4421 00001FB2 EC                  <1> 	in	al, dx			; INPUT DIGITAL INPUT REGISTER
  4422 00001FB3 A880                <1> 	test	al, DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  4423 00001FB5 C3                  <1> 	retn				; RETURN TO CALLER WITH ZERO FLAG SET
  4424                              <1> 
  4425                              <1> fdc_int:  
  4426                              <1> 	  ; 30/07/2015	
  4427                              <1> 	  ; 16/02/2015
  4428                              <1> ;int_0Eh: ; 11/12/2014
  4429                              <1> 
  4430                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  4431                              <1> ; DISK_INT
  4432                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  4433                              <1> ;
  4434                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  4435                              <1> ;-------------------------------------------------------------------------------
  4436                              <1> DISK_INT_1:
  4437                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4438                              <1> 	;push	eax			; SAVE WORK REGISTER
  4439                              <1> 	; 24/12/2021
  4440 00001FB6 50                  <1> 	push	eax
  4441 00001FB7 1E                  <1> 	push	ds
  4442 00001FB8 66B81000            <1> 	mov	ax, KDATA
  4443 00001FBC 8ED8                <1> 	mov 	ds, ax
  4444 00001FBE 800D[B9620000]80    <1>         or	byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  4445 00001FC5 B020                <1> 	mov	al, EOI			; END OF INTERRUPT MARKER
  4446 00001FC7 E620                <1> 	out	INTA00, al		; INTERRUPT CONTROL PORT
  4447 00001FC9 1F                  <1> 	pop	ds
  4448                              <1> 	;pop	ax			; RECOVER REGISTER
  4449                              <1> 	; 24/12/2021
  4450 00001FCA 58                  <1> 	pop	eax
  4451 00001FCB CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  4452                              <1> 
  4453                              <1> ;-------------------------------------------------------------------------------
  4454                              <1> ; DSKETTE_SETUP
  4455                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  4456                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  4457                              <1> ;-------------------------------------------------------------------------------
  4458                              <1> DSKETTE_SETUP:
  4459                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4460                              <1> 	;push	eax			; SAVE REGISTERS
  4461                              <1> 	;push	ebx
  4462                              <1> 	;push	ecx
  4463 00001FCC 52                  <1> 	push	edx
  4464                              <1> 	;push	edi
  4465                              <1> 	; 14/12/2014
  4466                              <1> 	;mov	dword [DISK_POINTER], MD_TBL6
  4467                              <1> 	;
  4468                              <1> 	;or	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  4469                              <1> 
  4470 00001FCD 31FF                <1> 	xor	edi, edi 		; INITIALIZE DRIVE POINTER
  4471 00001FCF 29C9                <1> 	sub	ecx, ecx
  4472 00001FD1 66890D[C7620000]    <1> 	mov	[DSK_STATE], cx ; 0	; INITIALIZE STATES
  4473                              <1> 	; 08/07/2022
  4474                              <1> 	;and	byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  4475 00001FD8 800D[C4620000]C0    <1> 	or	byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  4476 00001FDF 880D[B9620000]      <1> 	mov	[SEEK_STATUS], cl ; 0	; INDICATE RECALIBRATE NEEDED
  4477 00001FE5 880D[BB620000]      <1> 	mov	[MOTOR_COUNT], cl ; 0	; INITIALIZE MOTOR COUNT
  4478 00001FEB 880D[BA620000]      <1> 	mov	[MOTOR_STATUS], cl ; 0	; INITIALIZE DRIVES TO OFF STATE
  4479 00001FF1 880D[BC620000]      <1> 	mov	[DSKETTE_STATUS], cl ; 0 ; NO ERRORS
  4480                              <1> 	;
  4481                              <1> 	; 28/02/2015
  4482                              <1> 	;mov	word [cfd], 100h 
  4483 00001FF7 E894F8FFFF          <1> 	call	DSK_RESET
  4484 00001FFC 5A                  <1> 	pop	edx
  4485 00001FFD C3                  <1> 	retn
  4486                              <1> 
  4487                              <1> ;//////////////////////////////////////////////////////
  4488                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4489                              <1> ;
  4490                              <1> 
  4491                              <1> ; 12/07/2022
  4492                              <1> ;int13h: ; 21/02/2015
  4493                              <1> ;	pushfd
  4494                              <1> ;	push 	cs
  4495                              <1> ;	call 	DISK_IO
  4496                              <1> ;	retn
  4497                              <1> 
  4498                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  4499                              <1> ;/////////////////////////////////////////////////////////////////////
  4500                              <1> 
  4501                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4502                              <1> ; ((Direct call instead of int 13h simulation))
  4503                              <1> ;
  4504                              <1> ;		Function in AL
  4505                              <1> ;			0 = reset
  4506                              <1> ;			1 = read
  4507                              <1> ;			2 = write
  4508                              <1> ;		Disk drive number in DL
  4509                              <1> ;			0 & 1 = floppy disks	
  4510                              <1> ;			80h .. 83h = hard disks
  4511                              <1> ;		Sector address (LBA) in ECX
  4512                              <1> ;		Buffer address in EBX
  4513                              <1> ;		R/W sector count is (always) 1
  4514                              <1> ;
  4515                              <1> ;		Return:
  4516                              <1> ;			Status in AH (>0 = error code)
  4517                              <1> ;			if CF = 1 -> error code in AH
  4518                              <1> ;			if CF = 0 -> successful
  4519                              <1> ;			AL = undefined
  4520                              <1> ;
  4521                              <1> ;		Modified registers: (only) EAX
  4522                              <1> 
  4523                              <1> ; 10/07/2022
  4524                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4525                              <1> 
  4526                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  4527                              <1> ; 23/02/2015
  4528                              <1> ; 21/02/2015 (unix386.s)
  4529                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  4530                              <1> ;
  4531                              <1> ; Original Source Code:
  4532                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  4533                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  4534                              <1> ;
  4535                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  4536                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  4537                              <1> ;
  4538                              <1> 
  4539                              <1> ;The wait for controller to be not busy is 10 seconds.
  4540                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4541                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  4542                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  4543                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  4544                              <1> 
  4545                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  4546                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  4547                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  4548                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  4549                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  4550                              <1> 
  4551                              <1> ;The wait for Data request on read and write longs is
  4552                              <1> ;2000 us. (?)
  4553                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  4554                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  4555                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  4556                              <1> 
  4557                              <1> ; Port 61h (PORT_B)
  4558                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  4559                              <1> 
  4560                              <1> ; 23/12/2014
  4561                              <1> %define CMD_BLOCK       ebp-8  ; 21/02/2015
  4562                              <1> 
  4563                              <1> 	; 11/07/2022
  4564                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4565                              <1> 
  4566                              <1> ;--- INT 13H -------------------------------------------------------------------
  4567                              <1> ;									       :
  4568                              <1> ; FIXED DISK I/O INTERFACE						       :
  4569                              <1> ;									       :
  4570                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  4571                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  4572                              <1> ;									       :
  4573                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  4574                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  4575                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  4576                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  4577                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  4578                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  4579                              <1> ;									       :
  4580                              <1> ;------------------------------------------------------------------------------:
  4581                              <1> ;									       :
  4582                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  4583                              <1> ;									       :
  4584                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  4585                              <1> ;	(AH)= 01H  READ THE DESIRED SECTORS INTO MEMORY                        :
  4586                              <1> ;	(AH)= 02H  WRITE THE DESIRED SECTORS FROM MEMORY                       :
  4587                              <1> ;									       :
  4588                              <1> ;------------------------------------------------------------------------------:
  4589                              <1> ;									       :
  4590                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  4591                              <1> ;									       :
  4592                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  4593                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  4594                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  4595                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  4596                              <1> ;									       :
  4597                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  4598                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  4599                              <1> ;				 (10 BITS TOTAL)			       :
  4600                              <1> ;									       :
  4601                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  4602                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  4603                              <1> ;									       :
  4604                              <1> ;		(EBX)   -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  4605                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  4606                              <1> ;									       :
  4607                              <1> ;------------------------------------------------------------------------------:
  4608                              <1> ; OUTPUT								       :
  4609                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  4610                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  4611                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  4612                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  4613                              <1> ;									       :
  4614                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  4615                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  4616                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  4617                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  4618                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  4619                              <1> ;		REWRITTEN.						       :
  4620                              <1> ;									       :
  4621                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  4622                              <1> ;	   INPUT:							       :
  4623                              <1> ;	     (DL) = DRIVE NUMBER					       :
  4624                              <1> ;	   OUTPUT:							       :
  4625                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  4626                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  4627                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  4628                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  4629                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  4630                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  4631                              <1> ;									       :
  4632                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  4633                              <1> ;	INFORMATION.							       :
  4634                              <1> ;									       :
  4635                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  4636                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  4637                              <1> ;									       :
  4638                              <1> ;-------------------------------------------------------------------------------
  4639                              <1> 
  4640                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  4641                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  4642                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  4643                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  4644                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  4645                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  4646                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  4647                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  4648                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  4649                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  4650                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  4651                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  4652                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  4653                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  4654                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  4655                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  4656                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  4657                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  4658                              <1> 
  4659                              <1> ;--------------------------------------------------------
  4660                              <1> ;							:
  4661                              <1> ; FIXED DISK PARAMETER TABLE				:
  4662                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  4663                              <1> ;							:
  4664                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  4665                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  4666                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  4667                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  4668                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  4669                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  4670                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  4671                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  4672                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  4673                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  4674                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  4675                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  4676                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  4677                              <1> ;							:
  4678                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  4679                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  4680                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  4681                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  4682                              <1> ;							:
  4683                              <1> ;--------------------------------------------------------
  4684                              <1> 
  4685                              <1> ;--------------------------------------------------------
  4686                              <1> ;							:
  4687                              <1> ; HARDWARE SPECIFIC VALUES				:
  4688                              <1> ;							:
  4689                              <1> ;  -  CONTROLLER I/O PORT				:
  4690                              <1> ;							:
  4691                              <1> ;     > WHEN READ FROM: 				:
  4692                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  4693                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  4694                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  4695                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  4696                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  4697                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  4698                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  4699                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  4700                              <1> ;							:
  4701                              <1> ;     > WHEN WRITTEN TO:				:
  4702                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  4703                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  4704                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  4705                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  4706                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  4707                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  4708                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  4709                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  4710                              <1> ;							:
  4711                              <1> ;--------------------------------------------------------
  4712                              <1> 
  4713                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  4714                              <1> ;HF1_PORT	equ	0170h	
  4715                              <1> ;HF_REG_PORT	EQU	03F6H
  4716                              <1> ;HF1_REG_PORT	equ	0376h
  4717                              <1> 
  4718                              <1> HDC1_BASEPORT	equ	1F0h
  4719                              <1> HDC2_BASEPORT	equ	170h		
  4720                              <1> 
  4721                              <1> align 2
  4722                              <1> 
  4723                              <1> ;-----		STATUS REGISTER
  4724                              <1> 
  4725                              <1> ST_ERROR	EQU	00000001B	;
  4726                              <1> ST_INDEX	EQU	00000010B	;
  4727                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  4728                              <1> ST_DRQ		EQU	00001000B	;
  4729                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  4730                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  4731                              <1> ST_READY	EQU	01000000B	;
  4732                              <1> ST_BUSY 	EQU	10000000B	;
  4733                              <1> 
  4734                              <1> ;-----		ERROR REGISTER
  4735                              <1> 
  4736                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  4737                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  4738                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  4739                              <1> ;		EQU	00001000B	; NOT USED
  4740                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  4741                              <1> ;		EQU	00100000B	; NOT USED
  4742                              <1> ERR_DATA_ECC	EQU	01000000B
  4743                              <1> ERR_BAD_BLOCK	EQU	10000000B
  4744                              <1> 
  4745                              <1> 
  4746                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  4747                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  4748                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  4749                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  4750                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  4751                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  4752                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  4753                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  4754                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  4755                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  4756                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  4757                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  4758                              <1> 
  4759                              <1> ;MAX_FILE	EQU	2
  4760                              <1> ;S_MAX_FILE	EQU	2
  4761                              <1> MAX_FILE	equ	4		; 22/12/2014
  4762                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  4763                              <1> 
  4764                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  4765                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  4766                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  4767                              <1> 
  4768                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  4769                              <1> 
  4770                              <1> ;-----		COMMAND BLOCK REFERENCE
  4771                              <1> 
  4772                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  4773                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  4774                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  4775                              <1> ; 19/12/2014
  4776                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  4777                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  4778                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4779                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  4780                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  4781                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  4782                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  4783                              <1> 
  4784                              <1> align 2
  4785                              <1> 
  4786                              <1> ;----------------------------------------------------------------
  4787                              <1> ; FIXED DISK I/O SETUP						:
  4788                              <1> ;								:
  4789                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  4790                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  4791                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  4792                              <1> ;								:
  4793                              <1> ;----------------------------------------------------------------
  4794                              <1> 
  4795                              <1> 	; 12/07/2022
  4796                              <1> 	; 11/07/2022
  4797                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4798                              <1> 
  4799                              <1> DISK_SETUP:
  4800                              <1> 	;cli
  4801                              <1> 	;;mov	ax, ABS0 			; GET ABSOLUTE SEGMENT
  4802                              <1> 	;xor	ax, ax
  4803                              <1> 	;mov	ds, ax				; SET SEGMENT REGISTER
  4804                              <1> 	;mov	ax, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  4805                              <1> 	;mov	[DISK_VECTOR], ax		; INTO INT 40H
  4806                              <1> 	;mov	ax, [ORG_VECTOR+2]
  4807                              <1> 	;mov	[DISK_VECTOR+2], ax
  4808                              <1> 	;mov	word [ORG_VECTOR], DISK_IO	; FIXED DISK HANDLER
  4809                              <1> 	;mov	[ORG_VECTOR+2], cs
  4810                              <1> 	; 1st controller (primary master, slave) - IRQ 14
  4811                              <1> 	;;mov	word [HDISK_INT], HD_INT	; FIXED DISK INTERRUPT
  4812                              <1> 	;mov	word [HDISK_INT1], HD_INT	;
  4813                              <1> 	;;mov	[HDISK_INT+2], cs
  4814                              <1> 	;mov	[HDISK_INT1+2], cs
  4815                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  4816                              <1> 	;mov	word [HDISK_INT2], HD1_INT	;
  4817                              <1> 	;mov	[HDISK_INT2+2], cs
  4818                              <1> 	;
  4819                              <1> 	;;mov	word [HF_TBL_VEC], HD0_DPT	; PARM TABLE DRIVE 80
  4820                              <1> 	;;mov	word [HF_TBL_VEC+2], DPT_SEGM
  4821                              <1> 	;;mov	word [HF1_TBL_VEC], HD1_DPT	; PARM TABLE DRIVE 81
  4822                              <1> 	;;mov	word [HF1_TBL_VEC+2], DPT_SEGM
  4823                              <1> 	;push	cs
  4824                              <1> 	;pop	ds
  4825                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  4826                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  4827 00001FFE C705[D0620000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  4827 00002006 0900                <1>
  4828                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  4829                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  4830 00002008 C705[D4620000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  4830 00002010 0900                <1>
  4831                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  4832                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  4833 00002012 C705[D8620000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  4833 0000201A 0900                <1>
  4834                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  4835                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  4836 0000201C C705[DC620000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  4836 00002024 0900                <1>
  4837                              <1> 	;
  4838                              <1> 	;;in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  4839                              <1> 	;;;and	al, 0BFh
  4840                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  4841                              <1> 	;;;JMP	$+2
  4842                              <1> 	;;IODELAY
  4843                              <1> 	;;out	INTB01, al
  4844                              <1> 	;;IODELAY
  4845                              <1> 	;;in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  4846                              <1> 	;;and	al, 0FBh 		; SECOND CHIP
  4847                              <1> 	;;;JMP	$+2
  4848                              <1> 	;;IODELAY
  4849                              <1> 	;;out	INTA01, al
  4850                              <1> 	;
  4851                              <1> 	;sti
  4852                              <1> 	;;push	ds			; MOVE ABS0 POINTER TO
  4853                              <1> 	;;pop	es			; EXTRA SEGMENT POINTER
  4854                              <1> 	;;;call	DDS			; ESTABLISH DATA SEGMENT
  4855                              <1> 	;;mov	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  4856                              <1> 	;;mov	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  4857                              <1> 	;;mov	byte [CONTROL_BYTE],0
  4858                              <1> 	;;mov	byte [PORT_OFF],0	; ZERO CARD OFFSET
  4859                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  4860                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  4861                              <1> 	;mov	si, hd0_type
  4862 00002026 BE[5E5D0000]        <1> 	mov	esi, hd0_type
  4863                              <1> 	;;mov	cx, 4
  4864                              <1> 	;mov	ecx, 4
  4865                              <1> 	; 11/07/2022
  4866 0000202B 29C9                <1> 	sub	ecx, ecx
  4867 0000202D B104                <1> 	mov	cl, 4
  4868                              <1> hde_l:
  4869 0000202F AC                  <1> 	lodsb
  4870 00002030 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  4871 00002032 7206                <1> 	jb	short _L4
  4872 00002034 FE05[CC620000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  4873                              <1> _L4: ; 26/02/2015
  4874 0000203A E2F3                <1> 	loop	hde_l	
  4875                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  4876                              <1> ;L4:
  4877                              <1> 	; 
  4878                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  4879                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  4880                              <1> 	;;mov 	cl, 3
  4881                              <1> 	;;
  4882                              <1> 	;;mov	dl, 80h			; CHECK THE CONTROLLER
  4883                              <1> ;;hdc_dl:
  4884                              <1> 	;;mov	ah, 14h			; USE CONTROLLER DIAGNOSTIC COMMAND
  4885                              <1> 	;;int	13h			; CALL BIOS WITH DIAGNOSTIC COMMAND
  4886                              <1> 	;;;jc	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  4887                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  4888                              <1> 	;;jnc	short hdc_reset0
  4889                              <1> 	;;loop	hdc_dl
  4890                              <1> 	;;; 27/12/2014
  4891                              <1> 	;;stc
  4892                              <1> 	;;retn
  4893                              <1> 	;
  4894                              <1> ;;hdc_reset0:
  4895                              <1> 	; 18/01/2015
  4896 0000203C 8A0D[CC620000]      <1> 	mov	cl, [HF_NUM]
  4897 00002042 20C9                <1> 	and	cl, cl
  4898 00002044 740D                <1> 	jz	short POD_DONE
  4899                              <1> 	;
  4900 00002046 B27F                <1> 	mov	dl, 7Fh
  4901                              <1> hdc_reset1:
  4902 00002048 FEC2                <1> 	inc	dl
  4903                              <1> 	;; 31/12/2015
  4904                              <1> 	;;push	dx
  4905                              <1> 	;;push	cx
  4906                              <1> 	;;push	ds
  4907                              <1> 	;;sub	ax, ax
  4908                              <1> 	;;mov	ds, ax
  4909                              <1> 	;;mov	ax, [TIMER_LOW]		; GET START TIMER COUNTS
  4910                              <1> 	;;pop	ds
  4911                              <1> 	;;mov	bx, ax
  4912                              <1> 	;;add	ax, 6*182		; 60 SECONDS* 18.2
  4913                              <1> 	;;mov	cx, ax
  4914                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  4915                              <1> 	;;
  4916                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  4917                              <1> 	;;call	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  4918                              <1> 	;;pop	cx
  4919                              <1> 	;;pop	dx
  4920                              <1> 	;;
  4921                              <1> 	; 18/01/2015
  4922                              <1> 	;mov	ah, 0Dh ; ALTERNATE RESET
  4923                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4924                              <1> 	;mov	ah, 5 ; ALTERNATE RESET
  4925                              <1> 	;;int	13h
  4926                              <1> 	;call	int13h
  4927                              <1> 	; 12/07/2022
  4928 0000204A 30C0                <1> 	xor	al, al  ; reset
  4929 0000204C E803000000          <1> 	call	DISK_IO	
  4930                              <1> 	;
  4931 00002051 E2F5                <1> 	loop	hdc_reset1
  4932                              <1> POD_DONE:
  4933 00002053 C3                  <1> 	retn
  4934                              <1> 
  4935                              <1> ;----------------------------------------
  4936                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  4937                              <1> ;----------------------------------------
  4938                              <1> 
  4939                              <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4940                              <1> ; ((Direct call instead of int 13h simulation))
  4941                              <1> ;
  4942                              <1> ;		Function in AL
  4943                              <1> ;			0 = reset
  4944                              <1> ;			1 = read
  4945                              <1> ;			2 = write
  4946                              <1> ;		Disk drive number in DL
  4947                              <1> ;			0 & 1 = floppy disks	
  4948                              <1> ;			80h .. 83h = hard disks
  4949                              <1> ;		Sector address (LBA) in ECX
  4950                              <1> ;		Buffer address in EBX
  4951                              <1> ;		R/W sector count is (always) 1
  4952                              <1> ;
  4953                              <1> ;		Return:
  4954                              <1> ;			Status in AH (>0 = error code)
  4955                              <1> ;			if CF = 1 -> error code in AH
  4956                              <1> ;			if CF = 0 -> successful
  4957                              <1> ;			AL = undefined
  4958                              <1> ;
  4959                              <1> ;		Modified registers: (only) EAX
  4960                              <1> 	
  4961                              <1> 
  4962                              <1> ; 11/07/2022
  4963                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  4964                              <1> 
  4965                              <1> DISK_IO:
  4966                              <1> 	; 11/07/2022
  4967                              <1> 	; save registers
  4968 00002054 57                  <1> 	push	edi			; ANY
  4969 00002055 56                  <1> 	push	esi			; ANY
  4970 00002056 53                  <1> 	push	ebx			; BUFFER ADDRESS
  4971 00002057 51                  <1> 	push	ecx			; SECTOR ADDRESS (LBA)
  4972 00002058 52                  <1> 	push	edx			; DRIVE NUMBER (DL)
  4973                              <1> 
  4974                              <1> 	;cmp	dl, 80h			; TEST FOR FIXED DISK DRIVE
  4975                              <1> 	;;jae	short A1		; YES, HANDLE HERE
  4976                              <1> 	;;;;int	40H			; DISKETTE HANDLER
  4977                              <1> 	;;;call	int40h
  4978                              <1> 	;;jb	DISKETTE_IO_1
  4979                              <1> 	;; 24/12/2021
  4980                              <1> 	;jnb	short A1
  4981                              <1> 	;jmp	DISKETTE_IO_1
  4982                              <1> 
  4983                              <1> 	; 11/07/2022
  4984 00002059 80FA80              <1> 	cmp	dl, 80h
  4985 0000205C 730B                <1> 	jae	short A1
  4986                              <1> 
  4987 0000205E E8CAF6FFFF          <1> 	call	DISKETTE_IO_1
  4988                              <1> 
  4989                              <1> DISK_IO_RTN:
  4990                              <1> 	; restore registers
  4991 00002063 5A                  <1> 	pop	edx
  4992 00002064 59                  <1> 	pop	ecx
  4993 00002065 5B                  <1> 	pop	ebx
  4994 00002066 5E                  <1> 	pop	esi
  4995 00002067 5F                  <1> 	pop	edi
  4996 00002068 C3                  <1> 	retn	
  4997                              <1> 
  4998                              <1> ;RET_2:
  4999                              <1> ;	retf	4			; BACK TO CALLER
  5000                              <1> 
  5001                              <1> A1:
  5002                              <1> 	; 11/07/2022
  5003                              <1> 	;sti				; ENABLE INTERRUPTS
  5004                              <1> 	;cmp	dl, (80h + S_MAX_FILE - 1)
  5005                              <1> 	;ja	short RET_2
  5006                              <1> 	
  5007                              <1> 	; 18/01/2015
  5008                              <1> 	;;or	ah, ah
  5009                              <1> 	;or	al, al ; 11/07/2022 (reset function)
  5010                              <1> 	;jz	short A3 ; 08/07/2022
  5011                              <1> 	
  5012                              <1> 	;;cmp	ah, 5  ; Alternate reset
  5013                              <1> 	;cmp	al, 5  ; 11/07/2022
  5014                              <1> 	;je	short A2
  5015                              <1> 	
  5016                              <1> 	; 11/07/2022 - no need to check
  5017                              <1> 	;		 (only kernel calls diskio functions)
  5018                              <1> 	;;cmp	ah, M1L/4 ; cmp ah, 6
  5019                              <1> 	;jb	short A3
  5020                              <1> 	;; BAD COMMAND
  5021                              <1>         ;mov     byte [DISK_STATUS1], BAD_CMD
  5022                              <1> ;RET_2:
  5023                              <1> 	;retf	4
  5024                              <1> 
  5025                              <1> 	; 11/07/2022
  5026                              <1> 	;stc
  5027                              <1> 	;retn
  5028                              <1> A2:
  5029                              <1> 	;sub	ah, ah	; Reset
  5030                              <1> 	; 11/07/2022
  5031                              <1> 	;sub	al, al
  5032                              <1> A3:
  5033                              <1> 					; SAVE REGISTERS DURING OPERATION
  5034 00002069 C8080000            <1> 	enter	8,0			; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK
  5035                              <1> 	
  5036                              <1> 	; 11/07/2022
  5037                              <1> 	; 08/07/2022
  5038                              <1> 	;push	ebx			;  IN THE STACK, THE COMMAND BLOCK IS:
  5039                              <1> 	;push	ecx			;   @CMD_BLOCK == BYTE PTR [EBP]-8
  5040                              <1> 	;push	edx
  5041                              <1> 	;push	esi
  5042                              <1> 	;push	edi
  5043                              <1> 	
  5044 0000206D E80D000000          <1> 	call	DISK_IO_CONT		; PERFORM THE OPERATION
  5045                              <1> 
  5046 00002072 C9                  <1> 	leave	; 11/07/2022
  5047                              <1> 	
  5048 00002073 8A25[CB620000]      <1> 	mov	ah, [DISK_STATUS1]	; GET STATUS FROM OPERATION
  5049 00002079 80FC01              <1> 	cmp	ah, 1			; SET THE CARRY FLAG TO INDICATE
  5050 0000207C F5                  <1> 	cmc				; SUCCESS OR FAILURE
  5051                              <1> 	
  5052                              <1> 	;pop	edi			; RESTORE REGISTERS
  5053                              <1> 	;pop	esi
  5054                              <1>       	;pop	edx
  5055                              <1> 	;pop	ecx
  5056                              <1> 	;pop	ebx
  5057                              <1> 	
  5058                              <1> 	;leave				; ADJUST (ESP) AND RESTORE (EBP)
  5059                              <1> 	
  5060                              <1> 	; 11/07/2022
  5061                              <1> 	;retf	4			; THROW AWAY SAVED FLAGS
  5062                              <1> 
  5063 0000207D EBE4                <1> 	jmp	short DISK_IO_RTN
  5064                              <1> 
  5065                              <1> DISK_IO_CONT:
  5066                              <1> 	; 17/07/2022
  5067                              <1> 	; 11/07/2022
  5068                              <1> 	;	INPUT:
  5069                              <1> 	;	    AL = 0 : reset
  5070                              <1> 	;	    AL = 1 : read
  5071                              <1> 	;	    Al = 2 : write
  5072                              <1> 	; 	
  5073                              <1> 	; 10/07/2022
  5074                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5075                              <1> SU0:
  5076 0000207F C605[CB620000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; RESET THE STATUS INDICATOR
  5077                              <1> 	; 10/07/2022
  5078 00002086 89DE                <1> 	mov	esi, ebx ; 21/02/2015	; DATA (BUFFER) ADDRESS
  5079                              <1> 
  5080 00002088 8A1D[CC620000]      <1> 	mov	bl, [HF_NUM]		; GET NUMBER OF DRIVES
  5081 0000208E 80E27F              <1> 	and	dl, 7Fh			; GET DRIVE AS 0 OR 1
  5082                              <1> 					; (get drive number as 0 to 3)
  5083 00002091 38D3                <1> 	cmp	bl, dl
  5084                              <1>         ;;jbe	BAD_COMMAND_POP         ; INVALID DRIVE
  5085                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5086                              <1> 	; 24/12/2021
  5087 00002093 7705                <1> 	ja	short su0_su1
  5088 00002095 E98D000000          <1> 	jmp	BAD_COMMAND
  5089                              <1> su0_su1:
  5090                              <1>         ;;03/01/2015
  5091 0000209A 29DB                <1> 	sub	ebx, ebx
  5092 0000209C 88D3                <1> 	mov	bl, dl
  5093 0000209E 883D[E0620000]      <1> 	mov	[LBAMode], bh  ; 0
  5094                              <1> 	;test	byte [ebx+hd0_type], 1	; LBA ready ?
  5095                              <1> 	;jz	short su1		; no
  5096                              <1> 	;inc	byte [LBAMode]
  5097                              <1> ;su1:
  5098                              <1> 	; 21/02/2015 (32 bit modification)
  5099                              <1> 	; 04/01/2015
  5100                              <1> 	;push	ax ; ***
  5101                              <1> 	; 24/12/2021
  5102 000020A4 50                  <1> 	push	eax ; *** ; function (in AL) ; 11/07/2022
  5103                              <1> 	; 24/12/2021
  5104 000020A5 52                  <1> 	push	edx ; *
  5105 000020A6 50                  <1> 	push	eax ; function (in AL)	; 11/07/2022
  5106 000020A7 E8C4030000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5107                              <1> 	; 02/02/2015
  5108 000020AC 668B4310            <1> 	mov	ax, [ebx+16]   ; I/O port base address (1F0h, 170h)
  5109 000020B0 66A3[525D0000]      <1> 	mov	[HF_PORT], ax
  5110 000020B6 668B5312            <1> 	mov	dx, [ebx+18]   ; control port address (3F6h, 376h)
  5111 000020BA 668915[545D0000]    <1> 	mov	[HF_REG_PORT], dx
  5112 000020C1 8A4314              <1> 	mov	al, [ebx+20]   ; head register upper nibble (A0h,B0h,E0h,F0h)
  5113                              <1> 	; 23/02/2015
  5114 000020C4 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5115 000020C6 7406                <1> 	jz 	short su1
  5116 000020C8 FE05[E0620000]      <1> 	inc	byte [LBAMode] ; 1 
  5117                              <1> su1: 	 
  5118 000020CE C0E804              <1> 	shr 	al, 4
  5119 000020D1 2401                <1> 	and	al, 1			
  5120 000020D3 A2[565D0000]        <1> 	mov	[hf_m_s], al 
  5121                              <1> 	;
  5122                              <1> 	; 03/01/2015
  5123 000020D8 8A4308              <1> 	mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5124                              <1> 	;mov	dx, [HF_REG_PORT]	; Device Control register	
  5125 000020DB EE                  <1> 	out	dx, al			; SET EXTRA HEAD OPTION
  5126                              <1> 					; Control Byte: (= 08h, here)
  5127                              <1> 					; bit 0 - 0
  5128                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5129                              <1> 					; bit 2 - SRST (software RESET)
  5130                              <1> 					; bit 3 - use extra heads (8 to 15)
  5131                              <1> 					;         -always set to 1-	
  5132                              <1> 					; (bits 3 to 7 are reserved
  5133                              <1> 					;          for ATA devices)
  5134 000020DC 8A25[CD620000]      <1> 	mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5135 000020E2 80E4C0              <1> 	and	ah, 0C0h 		; CONTROL BYTE
  5136 000020E5 08C4                <1> 	or	ah, al
  5137 000020E7 8825[CD620000]      <1> 	mov	[CONTROL_BYTE], ah	
  5138                              <1> 	; 04/01/2015
  5139                              <1> 	;pop	ax
  5140                              <1> 	; 24/12/2021
  5141 000020ED 58                  <1> 	pop	eax ; function (in AL) ; 11/07/2022
  5142                              <1> 	;pop	dx ; * ;; 14/02/2015
  5143                              <1> 	; 24/12/2021
  5144 000020EE 5A                  <1> 	pop	edx ; *
  5145                              <1> 	;and	ah, ah	; Reset function ?
  5146 000020EF 20C0                <1> 	and	al, al	; 11/07/2022
  5147 000020F1 7506                <1> 	jnz	short su2
  5148                              <1> 	;pop	ax ; ***
  5149                              <1> 	; 24/12/2021
  5150 000020F3 58                  <1> 	pop	eax ; *** 	
  5151                              <1> 	;;pop	bx
  5152 000020F4 E9E4000000          <1>         jmp     DISK_RESET
  5153                              <1> su2:
  5154                              <1> 	; 11/07/2022
  5155                              <1> 	; ecx = sector address (lba)
  5156                              <1> 	;  dl = hard disk drive number (80h, 81h .. 83h)	 
  5157                              <1> 	;  al = function (0 = read, 1 = write)	
  5158                              <1> 
  5159 000020F9 803D[E0620000]00    <1> 	cmp	byte [LBAMode], 0
  5160 00002100 7620                <1> 	jna	short su3 ; convert LBA address to CHS parameters
  5161                              <1> 	
  5162                              <1> ;	; 02/02/2015 (LBA read/write function calls)
  5163                              <1> ;	;cmp	ah, 1Bh
  5164                              <1> ;	cmp	ah, 3 ; 08/07/2022
  5165                              <1> ;	jb	short lbarw1
  5166                              <1> ;	;;cmp	ah, 1Ch
  5167                              <1> ;	;cmp	ah, 4 ; 08/07/2022 
  5168                              <1> ;	;ja 	short invldfnc
  5169                              <1> ;	;;pop	dx ; * ; 14/02/2015
  5170                              <1> ;	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5171                              <1> 
  5172 00002102 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5173                              <1> 
  5174                              <1> 	; 11/07/2022
  5175                              <1> 	;; 14/02/2015
  5176                              <1> 	;mov	cl, dl ; 14/02/2015
  5177                              <1> 
  5178                              <1> 	;;mov	dx, bx
  5179                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5180                              <1> 	;;mov	bx, di
  5181                              <1> 	;mov	si, di ; Buffer offset
  5182                              <1> 
  5183                              <1> 	; 11/07/2022
  5184                              <1> 	;jmp	short lbarw2
  5185                              <1> 
  5186                              <1> ;lbarw1:
  5187                              <1> ;	; convert CHS to LBA
  5188                              <1> ;	;
  5189                              <1> ;	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5190                              <1> ;	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  5191                              <1> ;	;	+ Sector - 1
  5192                              <1> ;	;push	dx ; * ;; 14/02/2015
  5193                              <1> ;	; 24/12/2021
  5194                              <1> ;	push	edx ; *
  5195                              <1> ;	;xor	dh, dh
  5196                              <1> ;	xor	edx, edx
  5197                              <1> ;	mov	dl, [ebx+14]	; sectors per track (logical)
  5198                              <1> ;	;xor	ah, ah
  5199                              <1> ;	xor	eax, eax
  5200                              <1> ;	mov	al, [ebx+2]	; heads (logical) 
  5201                              <1> ;	dec	al
  5202                              <1> ;	;inc	ax		; 0 =  256
  5203                              <1> ;	inc	eax ; 24/12/2021
  5204                              <1> ;	mul 	dx
  5205                              <1> ;		; AX = # of Heads * Sectors/Track
  5206                              <1> ;	mov	dx, cx
  5207                              <1> ;	;and	cx, 3Fh	 ; sector (1 to 63)
  5208                              <1> ;	and	ecx, 3fh
  5209                              <1> ;	xchg	dl, dh
  5210                              <1> ;	shr	dh, 6
  5211                              <1> ;		; DX = cylinder (0 to 1023)
  5212                              <1> ;	;mul 	dx
  5213                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder
  5214                              <1> ;	mul	edx
  5215                              <1> ;	dec	cl  ; sector - 1
  5216                              <1> ;	;add	ax, cx
  5217                              <1> ;	;adc	dx, 0
  5218                              <1> ;		; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1
  5219                              <1> ;	add	eax, ecx
  5220                              <1> ;	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  5221                              <1> ;	; 24/12/2021
  5222                              <1> ;	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  5223                              <1> ;	;push	dx
  5224                              <1> ;	;push	ax
  5225                              <1> ;	push	eax
  5226                              <1> ;	mov	al, [ebx+14]  ; sectors per track (logical)	
  5227                              <1> ;	mul	ch
  5228                              <1> ;		; AX = Head * Sectors/Track
  5229                              <1> ;	cwd
  5230                              <1> ;	;pop	dx
  5231                              <1> ;	pop	edx
  5232                              <1> ;	;add	ax, dx
  5233                              <1> ;	;pop	dx
  5234                              <1> ;	;adc	dx, 0 ; add carry bit
  5235                              <1> ;	add	eax, edx
  5236                              <1> ;
  5237                              <1> ;lbarw2:
  5238                              <1> 	; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5239                              <1> 	
  5240 00002104 29D2                <1> 	sub	edx, edx ; 21/02/2015
  5241                              <1> 	
  5242                              <1> 	; 11/07/2022
  5243                              <1> 	;mov	dl, cl ; 21/02/2015
  5244                              <1>         
  5245 00002106 C645F800            <1> 	mov     byte [CMD_BLOCK], 0 ; Features Register
  5246                              <1> 				; NOTE: Features register (1F1h, 171h)
  5247                              <1> 				; is not used for ATA device R/W functions. 
  5248                              <1> 				; It is old/obsolete 'write precompensation'
  5249                              <1> 				; register and error register
  5250                              <1> 				; for old ATA/IDE devices.
  5251                              <1> 	; 18/01/2014
  5252                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  5253 0000210A 8A0D[565D0000]      <1> 	mov	cl, [hf_m_s]
  5254                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  5255                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  5256                              <1> 				; bit 6 = 1 = LBA mode
  5257                              <1> 				; bit 7 = 1
  5258 00002110 80C90E              <1> 	or	cl, 0Eh ; 1110b
  5259                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  5260 00002113 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  5261 00002118 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  5262                              <1> 	;or	dh, ch
  5263 0000211B 09C8                <1> 	or	eax, ecx	
  5264                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  5265                              <1> 				  ; (Sector Number Register)
  5266                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  5267                              <1> 				  ; (Cylinder Low Register)
  5268                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  5269                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  5270                              <1> 				  ; (Cylinder High Register)
  5271                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  5272                              <1> 				  ; (Drive/Head Register)
  5273                              <1> 	
  5274                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  5275 0000211D 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  5276                              <1> 	;14/02/2015
  5277                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  5278 00002120 EB3D                <1> 	jmp	short su4
  5279                              <1> su3:
  5280                              <1> 	; 02/02/2015 
  5281                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  5282                              <1> 	;cmp 	ah, 14h
  5283                              <1> 	;jna 	short chsfnc
  5284                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5285                              <1> 	;cmp	ah, 2
  5286                              <1> 	;jna	short chsfnc
  5287                              <1> 	; 11/07/2022 
  5288                              <1> 	; (al = function, read = 1 or write = 2)
  5289 00002122 3C02                <1> 	cmp	al, 2 
  5290 00002124 760B                <1> 	jna	short chsfnc
  5291                              <1> invldfnc:
  5292                              <1>         ; 14/02/2015  
  5293                              <1> 	;pop	es ; **
  5294                              <1>         ;pop	ax ; ***
  5295                              <1>         ; 24/12/2021
  5296 00002126 58                  <1> 	pop	eax ; ***
  5297                              <1> 	;;jmp	short BAD_COMMAND_POP
  5298                              <1> 	; 11/07/2022
  5299                              <1>         ;jmp     short BAD_COMMAND
  5300                              <1> 
  5301                              <1> 	; 11/07/2022
  5302                              <1> BAD_COMMAND:
  5303 00002127 C605[CB620000]01    <1> 	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5304                              <1> 	;mov	al, 0
  5305 0000212E 28C0                <1> 	sub	al, al ; 0
  5306 00002130 C3                  <1> 	retn
  5307                              <1> 
  5308                              <1> chsfnc:	
  5309 00002131 668B4305            <1> 	mov	ax, [ebx+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  5310                              <1> 	;shr	ax, 2
  5311                              <1> 	; 17/07/2022
  5312 00002135 C1E802              <1> 	shr	eax, 2
  5313 00002138 8845F8              <1> 	mov	[CMD_BLOCK], al
  5314                              <1> 	;
  5315                              <1> 	;;mov	al, [ebx+8]		; GET CONTROL BYTE MODIFIER
  5316                              <1> 	;;push	edx ; *
  5317                              <1> 	;;mov	dx, [HF_REG_PORT]
  5318                              <1> 	;;out	dx, al			; SET EXTRA HEAD OPTION
  5319                              <1> 	;;pop	edx ; * 
  5320                              <1> 	;;mov	ah, [CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5321                              <1> 	;;and	ah, 0C0h 		; CONTROL BYTE	
  5322                              <1> 	;;or	ah, al
  5323                              <1> 	;;mov	[CONTROL_BYTE], ah
  5324                              <1> 	;
  5325 0000213B 88C8                <1> 	mov	al, cl			; GET SECTOR NUMBER
  5326 0000213D 243F                <1> 	and	al, 3Fh
  5327 0000213F 8845FA              <1> 	mov	[CMD_BLOCK+2], al
  5328 00002142 886DFB              <1> 	mov	[CMD_BLOCK+3], ch 	; GET CYLINDER NUMBER
  5329 00002145 88C8                <1> 	mov	al, cl
  5330 00002147 C0E806              <1> 	shr	al, 6
  5331 0000214A 8845FC              <1> 	mov	[CMD_BLOCK+4], al	; CYLINDER HIGH ORDER 2 BITS
  5332                              <1> 	;;05/01/2015
  5333                              <1> 	;;mov	al, dl			; DRIVE NUMBER
  5334 0000214D A0[565D0000]        <1> 	mov	al, [hf_m_s]
  5335 00002152 C0E004              <1> 	shl	al, 4
  5336 00002155 80E60F              <1> 	and	dh, 0Fh			; HEAD NUMBER
  5337 00002158 08F0                <1> 	or	al, dh
  5338 0000215A 0CA0                <1> 	or	al, 80h+20h		; ECC AND 512 BYTE SECTORS
  5339 0000215C 8845FD              <1> 	mov	[CMD_BLOCK+5], al	; ECC/SIZE/DRIVE/HEAD
  5340                              <1> su4:
  5341                              <1> 	;; 14/02/2015
  5342                              <1>         ;;pop	ax
  5343                              <1>         ;;mov	[CMD_BLOCK+1], AL	; SECTOR COUNT
  5344                              <1>         ;;push	ax
  5345                              <1>         ;;mov	al, ah			; GET INTO LOW BYTE
  5346                              <1>         ;;xor	ah, ah			; ZERO HIGH BYTE
  5347                              <1>         ;;sal	ax, 1			; *2 FOR TABLE LOOKUP
  5348                              <1> 	;pop	ax ; ***
  5349                              <1> 	; 24/12/2021
  5350 0000215F 58                  <1> 	pop	eax ; *** ; function (in AL) ; 11/07/2022
  5351                              <1> 	
  5352                              <1> 	;mov	[CMD_BLOCK+1], al
  5353 00002160 C645F901            <1>         mov	byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w)
  5354                              <1> 
  5355                              <1> 	; 11/07/2022
  5356                              <1> 	;mov	ebx, esi
  5357                              <1> 	; (esi = buffer address)	
  5358                              <1> 
  5359 00002164 3C02                <1> 	cmp	al, 2
  5360 00002166 742D                <1> 	je	short DISK_WRITE
  5361                              <1> 
  5362                              <1> 	;jmp	short DISK_READ
  5363                              <1> 
  5364                              <1> ;	;xor	ebx, ebx
  5365                              <1> ;	;mov	bl, ah
  5366                              <1> ;
  5367                              <1> ;       ;xor	bh, bh
  5368                              <1> ;       ;sal	bx, 1
  5369                              <1> ;       sal	bx, 2	; 32 bit offset (21/02/2015)
  5370                              <1> ;	;;mov	si, ax			; PUT INTO SI FOR BRANCH
  5371                              <1> ;       ;;cmp	ax, M1L			; TEST WITHIN RANGE
  5372                              <1> ;       ;;jnb	short BAD_COMMAND_POP
  5373                              <1> ;   	; 08/07/2022
  5374                              <1> ;	;cmp	ebx, M1L
  5375                              <1> ;	;jnb	short BAD_COMMAND
  5376                              <1> ;
  5377                              <1> ;	xchg	ebx, esi
  5378                              <1> ;
  5379                              <1> ;	;;;pop	ax			; RESTORE AX
  5380                              <1> ;	;;;pop	bx			; AND DATA ADDRESS
  5381                              <1> ;	
  5382                              <1> ;	;;push	cx
  5383                              <1> ;	;;push	ax			; ADJUST ES:BX
  5384                              <1> ;	;mov	cx, bx			; GET 3 HIGH ORDER NIBBLES OF BX
  5385                              <1> ;	;shr	cx, 4
  5386                              <1> ;	;mov	ax, es
  5387                              <1> ;	;add	ax, cx
  5388                              <1> ;	;mov	es, ax
  5389                              <1> ;	;and	bx, 000Fh		; ES:BX CHANGED TO ES:000X
  5390                              <1> ;	;;pop	ax
  5391                              <1> ;	;;pop	cx
  5392                              <1> ;
  5393                              <1> ;	jmp	dword [esi+M1]
  5394                              <1> 
  5395                              <1> ;;BAD_COMMAND_POP:
  5396                              <1> ;;	pop	ax
  5397                              <1> ;;	pop	bx
  5398                              <1> ;
  5399                              <1> ;	; 11/07/2022
  5400                              <1> ;BAD_COMMAND:
  5401                              <1> ;	mov	byte [DISK_STATUS1], BAD_CMD  ; COMMAND ERROR
  5402                              <1> ;	;mov	al, 0
  5403                              <1> ;	sub	al, al ; 0
  5404                              <1> ;	retn
  5405                              <1> 
  5406                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5407                              <1> 
  5408                              <1> ;----------------------------------------
  5409                              <1> ;	DISK READ ROUTINE    (AH = 01H) :
  5410                              <1> ;----------------------------------------
  5411                              <1> ; 
  5412                              <1> DISK_READ:
  5413 00002168 C645FE20            <1> 	mov	byte [CMD_BLOCK+6], READ_CMD
  5414                              <1>         ;jmp	COMMANDI
  5415                              <1> 
  5416                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5417                              <1> 
  5418                              <1> ;----------------------------------------
  5419                              <1> ; COMMANDI				:
  5420                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  5421                              <1> ;	NSECTOR RETURNS ZERO		:
  5422                              <1> ;----------------------------------------
  5423                              <1> COMMANDI:
  5424                              <1> 	; 11/07/2022 
  5425                              <1> 	;	(check 64K boundary is not needed)
  5426                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5427                              <1> 	;jc	short CMD_ABORT
  5428                              <1> 	
  5429                              <1> 	;mov	di, bx
  5430                              <1> 	; 11/07/2022
  5431                              <1> 	; (esi = buffer address)
  5432                              <1> 	;mov	edi, ebx ; 21/02/2015
  5433 0000216C 89F7                <1> 	mov	edi, esi ; 11/07/2022	
  5434                              <1> 
  5435 0000216E E8A8010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5436 00002173 751F                <1> 	jnz	short CMD_ABORT
  5437                              <1> CMD_I1:
  5438 00002175 E813020000          <1> 	call	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  5439 0000217A 7518                <1> 	jnz	short TM_OUT		; TIME OUT
  5440                              <1> 	;;mov	cx,256			; SECTOR SIZE IN WORDS
  5441                              <1> 	;mov	ecx, 256 ; 21/02/2015	
  5442 0000217C 29C9                <1> 	sub	ecx, ecx
  5443 0000217E FEC5                <1> 	inc	ch
  5444                              <1> 	; ecx = 256
  5445                              <1> 	;mov	dx, HF_PORT
  5446 00002180 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5447 00002187 FA                  <1> 	cli
  5448 00002188 FC                  <1> 	cld
  5449 00002189 F3666D              <1> 	rep	insw			; GET THE SECTOR
  5450 0000218C FB                  <1> 	sti
  5451                              <1> 	
  5452                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT
  5453                              <1> 	;jz	short CMD_I3
  5454                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5455                              <1> 	;jc	short TM_OUT
  5456                              <1> 	;;mov	dx, HF_PORT
  5457                              <1> 	;mov	dx,[HF_PORT]
  5458                              <1> 	;xor	ecx, ecx	
  5459                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5460                              <1> 	;mov	cl, 4
  5461                              <1> ;CMD_I2: 
  5462                              <1> 	;inc	al, dx
  5463                              <1> 	;mov 	[edi], al ; 21/02/2015
  5464                              <1> 	;inc	edi
  5465                              <1> 	;loop	CMD_I2
  5466                              <1> CMD_I3: 
  5467 0000218D E817010000          <1> 	call	CHECK_STATUS
  5468 00002192 7500                <1> 	jnz	short CMD_ABORT		; ERROR RETURNED
  5469                              <1> 	; 11/07/2022
  5470                              <1> 	; (sector count = 1)
  5471                              <1> 	;dec	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  5472                              <1> 	;jnz	SHORT CMD_I1
  5473                              <1> CMD_ABORT:
  5474                              <1> TM_OUT: 
  5475 00002194 C3                  <1> 	retn
  5476                              <1> 
  5477                              <1> ;---------------------------------------------------
  5478                              <1> 
  5479                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5480                              <1> 
  5481                              <1> ;----------------------------------------
  5482                              <1> ;	DISK WRITE ROUTINE   (AH = 02H) :
  5483                              <1> ;----------------------------------------
  5484                              <1> 
  5485                              <1> DISK_WRITE:
  5486 00002195 C645FE30            <1> 	mov	byte [CMD_BLOCK+6], WRITE_CMD
  5487                              <1>         ;JMP	COMMANDO
  5488                              <1> 
  5489                              <1> ; 16/07/2022
  5490                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5491                              <1> 
  5492                              <1> ;----------------------------------------
  5493                              <1> ; COMMANDO				:
  5494                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  5495                              <1> ;	NSECTOR RETURNS ZERO		:
  5496                              <1> ;----------------------------------------
  5497                              <1> COMMANDO:
  5498                              <1> 	; 11/07/2022 
  5499                              <1> 	;	(check 64K boundary is not needed)
  5500                              <1> 	;call	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  5501                              <1> 	;jc	short CMD_ABORT
  5502                              <1> CMD_OF:
  5503                              <1> 	; 11/07/2022
  5504                              <1> 	; (esi = ebx = buffer address)
  5505                              <1> 	;mov	esi, ebx ; 21/02/2015
  5506 00002199 E87D010000          <1> 	call	COMMAND 		; OUTPUT COMMAND
  5507 0000219E 75F4                <1> 	jnz	short CMD_ABORT
  5508 000021A0 E83F020000          <1> 	call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5509 000021A5 72ED                <1> 	jc	short TM_OUT		; TOO LONG
  5510                              <1> CMD_O1:
  5511                              <1> 	; 16/07/2022
  5512 000021A7 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5513                              <1> 
  5514                              <1> 	; 10/07/2022
  5515                              <1> 	;mov	ecx, 256 ; 21/02/2015
  5516 000021AE 31C9                <1> 	xor	ecx, ecx
  5517 000021B0 FEC5                <1> 	inc	ch
  5518                              <1> 	; ecx = 256
  5519 000021B2 FA                  <1> 	cli
  5520 000021B3 FC                  <1> 	cld
  5521 000021B4 F3666F              <1> 	rep	outsw
  5522 000021B7 FB                  <1> 	sti
  5523                              <1> 
  5524                              <1> 	; 10/07/2022
  5525                              <1> 	;test	byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT
  5526                              <1> 	;jz	short CMD_O3
  5527                              <1> 	;
  5528                              <1> 	;call	WAIT_DRQ		; WAIT FOR DATA REQUEST
  5529                              <1> 	;jc	short TM_OUT
  5530                              <1> 	;;mov	dx, HF_PORT
  5531                              <1> 	;mov	dx, [HF_PORT]
  5532                              <1> 	;sub	ecx, ecx	
  5533                              <1> 	;;mov	ecx, 4  ; mov cx, 4	; OUTPUT THE ECC BYTES
  5534                              <1> 	;mov	cl, 4
  5535                              <1> ;CMD_O2:
  5536                              <1> 	;;lodsb
  5537                              <1> 	;mov	al, [esi]
  5538                              <1> 	;out	dx, al
  5539                              <1> 	;inc	esi
  5540                              <1> 	;loop	CMD_O2
  5541                              <1> 
  5542                              <1> CMD_O3:
  5543 000021B8 E8D0010000          <1> 	call	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  5544 000021BD 75D5                <1> 	jnz	short TM_OUT		; ERROR RETURNED
  5545 000021BF E8E5000000          <1> 	call	CHECK_STATUS
  5546 000021C4 75CE                <1> 	jnz	short CMD_ABORT
  5547                              <1> 
  5548                              <1> 	; 11/07/2022
  5549                              <1> 	; (sector count = 1)
  5550                              <1> 	;test	byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE
  5551                              <1> 	;jnz	short CMD_O1
  5552                              <1> 	
  5553                              <1> 	;mov	dx, HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  5554 000021C6 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5555 000021CD 80C202              <1> 	add	dl, 2
  5556                              <1> 	;inc	dl
  5557                              <1> 	;inc	dl
  5558 000021D0 EC                  <1> 	in	al, dx			;
  5559 000021D1 A8FF                <1> 	test	al, 0FFh 		;
  5560 000021D3 7407                <1> 	jz	short CMD_O4		; COUNT = 0  OK
  5561 000021D5 C605[CB620000]BB    <1> 	mov	byte [DISK_STATUS1], UNDEF_ERR 
  5562                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  5563                              <1> CMD_O4:
  5564 000021DC C3                  <1> 	retn
  5565                              <1> 
  5566                              <1> ; 10/07/2022
  5567                              <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5568                              <1> 
  5569                              <1> ;----------------------------------------
  5570                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  5571                              <1> ;----------------------------------------
  5572                              <1> 
  5573                              <1> ; 18-1-2015 : one controller reset (not other one)
  5574                              <1> 
  5575                              <1> DISK_RESET:
  5576 000021DD FA                  <1> 	cli
  5577 000021DE E4A1                <1> 	in	al, INTB01		; GET THE MASK REGISTER
  5578                              <1> 	;JMP	$+2
  5579                              <1> 	IODELAY
  2190 000021E0 EB00                <2>  jmp short $+2
  2191 000021E2 EB00                <2>  jmp short $+2
  5580                              <1> 	;and	al, 0BFh 		; ENABLE FIXED DISK INTERRUPT
  5581 000021E4 243F                <1> 	and	al, 3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  5582 000021E6 E6A1                <1> 	out	INTB01, al
  5583 000021E8 FB                  <1> 	sti				; START INTERRUPTS
  5584                              <1> 	; 14/02/2015
  5585                              <1> 	;mov	di, dx
  5586                              <1> 	; 24/12/2021
  5587 000021E9 89D7                <1> 	mov	edi, edx	
  5588                              <1> 	; 04/01/2015
  5589                              <1> 	;xor	di,di
  5590                              <1> drst0:
  5591 000021EB B004                <1> 	mov	al, 04h  ; bit 2 - SRST 
  5592                              <1> 	;mov	dx, HF_REG_PORT
  5593 000021ED 668B15[545D0000]    <1> 	mov	dx, [HF_REG_PORT]
  5594 000021F4 EE                  <1> 	out	dx, al			; RESET
  5595                              <1> ;	mov	cx, 10			; DELAY COUNT
  5596                              <1> ;DRD:	dec	cx
  5597                              <1> ;	jnz	short DRD		; WAIT 4.8 MICRO-SEC
  5598                              <1> 	;mov	cx, 2			; wait for 30 micro seconds	
  5599                              <1>         ;mov	ecx, 2 ; 21/02/2015
  5600                              <1> 	; 10/07/2022
  5601 000021F5 29C9                <1> 	sub	ecx, ecx
  5602 000021F7 B102                <1> 	mov	cl, 2
  5603 000021F9 E89BF2FFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  5604                              <1>                                         ; 40 micro seconds)
  5605 000021FE A0[CD620000]        <1> 	mov	al, [CONTROL_BYTE]
  5606 00002203 240F                <1> 	and	al, 0Fh			; SET HEAD OPTION
  5607 00002205 EE                  <1> 	out	dx, al			; TURN RESET OFF
  5608 00002206 E8B2010000          <1> 	call	NOT_BUSY
  5609 0000220B 7514                <1> 	jnz	short DRERR		; TIME OUT ON RESET
  5610 0000220D 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5611 00002214 FEC2                <1> 	inc	dl  ; HF_PORT+1
  5612                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  5613                              <1>         ;mov	cl, 10
  5614                              <1>         ;mov     ecx, 10 ; 21/02/2015
  5615                              <1> 	; 10/07/2022
  5616                              <1> 	;xor	ecx, ecx
  5617 00002216 B10A                <1> 	mov	cl, 10 
  5618                              <1> drst1:
  5619 00002218 EC                  <1> 	in	al, dx			; GET RESET STATUS
  5620 00002219 3C01                <1> 	cmp	al, 1
  5621                              <1> 	; 04/01/2015
  5622 0000221B 740C                <1> 	jz	short drst2
  5623                              <1> 	;jnz	short DRERR		; BAD RESET STATUS
  5624                              <1>         	; Drive/Head Register - bit 4
  5625                              <1> 	;loop	drst1
  5626                              <1> 	; 10/07/2022
  5627 0000221D FEC9                <1> 	dec	cl
  5628 0000221F 75F7                <1> 	jnz	short drst1
  5629                              <1> DRERR:	
  5630 00002221 C605[CB620000]05    <1> 	mov	byte [DISK_STATUS1], BAD_RESET ; CARD FAILED
  5631 00002228 C3                  <1> 	retn
  5632                              <1> drst2:
  5633                              <1> 	; 14/02/2015
  5634                              <1> 	;mov	dx, di
  5635                              <1> 	; 24/12/2021
  5636 00002229 89FA                <1> 	mov	edx, edi
  5637                              <1> ;drst3:
  5638                              <1> ;	; 05/01/2015
  5639                              <1> ;	shl 	di, 1
  5640                              <1> ;	; 04/01/2015
  5641                              <1> ;	mov	ax, [di+hd_cports]
  5642                              <1> ;	cmp	ax, [HF_REG_PORT]
  5643                              <1> ;	je	short drst4
  5644                              <1> ;	mov	[HF_REG_PORT], ax
  5645                              <1> ;	; 03/01/2015
  5646                              <1> ;	mov	ax, [di+hd_ports]
  5647                              <1> ;       mov     [HF_PORT], ax
  5648                              <1> ;	; 05/01/2014
  5649                              <1> ;	shr	di, 1
  5650                              <1> ;	; 04/01/2015
  5651                              <1> ;	jmp	short drst0	; reset other controller
  5652                              <1> ;drst4:
  5653                              <1> ;	; 05/01/2015
  5654                              <1> ;	shr	di, 1
  5655                              <1> ;	mov	al, [di+hd_dregs]
  5656                              <1> ;	and	al, 10h ; bit 4 only
  5657                              <1> ;	shr	al, 4 ; bit 4  -> bit 0
  5658                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  5659                              <1> 	;
  5660 0000222B A0[565D0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  5661 00002230 A801                <1> 	test	al, 1
  5662                              <1> 	;jnz	short drst6
  5663 00002232 7516                <1>         jnz     short drst4
  5664 00002234 8065FDEF            <1> 	and	byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0
  5665                              <1> ;drst5:
  5666                              <1> drst3:
  5667 00002238 E813000000          <1> 	call	INIT_DRV		; SET MAX HEADS
  5668                              <1> 	;mov	dx, di
  5669 0000223D E8A3000000          <1> 	call	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  5670                              <1> 	; 04/01/2014
  5671                              <1> ;	inc	di
  5672                              <1> ;	mov	dx, di
  5673                              <1> ;	cmp	dl, [HF_NUM]
  5674                              <1> ;	jb	short drst3
  5675                              <1> ;DRE:
  5676 00002242 C605[CB620000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; IGNORE ANY SET UP ERRORS
  5677 00002249 C3                  <1> 	retn
  5678                              <1> ;drst6:
  5679                              <1> drst4:		; Drive/Head Register - bit 4
  5680 0000224A 804DFD10            <1> 	or	byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1     
  5681                              <1>         ;jmp    short drst5
  5682 0000224E EBE8                <1>         jmp     short drst3
  5683                              <1> 
  5684                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5685                              <1> 
  5686                              <1> ;----------------------------------------
  5687                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  5688                              <1> ;----------------------------------------
  5689                              <1> 	; 03/01/2015
  5690                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  5691                              <1> 	; logical sector per logical track
  5692                              <1> 	; and logical heads - 1 would be set but
  5693                              <1> 	; it is seen as it will be good
  5694                              <1> 	; if physical parameters will be set here
  5695                              <1> 	; because, number of heads <= 16.
  5696                              <1> 	; (logical heads usually more than 16)
  5697                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  5698                              <1> 	;	== INT 13h physical parameters
  5699                              <1> 
  5700                              <1> ;INIT_DRV:
  5701                              <1> ;	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5702                              <1> ;	call	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  5703                              <1> ;	mov	al, [es:bx+2]		; GET NUMBER OF HEADS
  5704                              <1> ;	dec	al			; CONVERT TO 0-INDEX
  5705                              <1> ;	mov	ah, [CMD_BLOCK+5] 	; GET SDH REGISTER
  5706                              <1> ;	and	ah, 0F0h 		; CHANGE HEAD NUMBER
  5707                              <1> ;	or	ah, al			; TO MAX HEAD
  5708                              <1> ;	mov	[CMD_BLOCK+5], ah
  5709                              <1> ;	mov	al, [es:bx+14]		; MAX SECTOR NUMBER
  5710                              <1> ;	mov	[CMD_BLOCK+1], al
  5711                              <1> ;	sub	ax, ax
  5712                              <1> ;	mov	[CMD_BLOCK+3], al 	; ZERO FLAGS
  5713                              <1> ;	call	COMMAND 		; TELL CONTROLLER
  5714                              <1> ;	jnz	short INIT_EXIT		; CONTROLLER BUSY ERROR
  5715                              <1> ;	call	NOT_BUSY		; WAIT FOR IT TO BE DONE
  5716                              <1> ;	jnz	short INIT_EXIT		; TIME OUT
  5717                              <1> ;	call	CHECK_STATUS
  5718                              <1> ;INIT_EXIT:
  5719                              <1> ;	retn
  5720                              <1> 
  5721                              <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5722                              <1> 
  5723                              <1> ; 04/01/2015
  5724                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  5725                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  5726                              <1> INIT_DRV:
  5727                              <1> 	;xor	ah, ah
  5728 00002250 31C0                <1> 	xor	eax, eax ; 21/02/2015
  5729 00002252 B00B                <1> 	mov	al, 11 ; Physical heads from translated HDPT
  5730 00002254 3825[E0620000]      <1>         cmp     [LBAMode], ah   ; 0
  5731 0000225A 7702                <1> 	ja	short idrv0
  5732 0000225C B002                <1> 	mov	al, 2  ; Physical heads from standard HDPT
  5733                              <1> idrv0:
  5734                              <1> 	; DL = drive number (0 based)
  5735 0000225E E80D020000          <1> 	call	GET_VEC
  5736                              <1> 	;push	bx
  5737 00002263 53                  <1> 	push	ebx ; 21/02/2015
  5738                              <1> 	;add	bx, ax
  5739 00002264 01C3                <1> 	add	ebx, eax
  5740                              <1> 	;; 05/01/2015
  5741 00002266 8A25[565D0000]      <1> 	mov	ah, [hf_m_s] ; drive number (0= master, 1= slave)
  5742                              <1> 	;;and 	ah, 1 
  5743 0000226C C0E404              <1> 	shl	ah, 4
  5744 0000226F 80CCA0              <1> 	or	ah, 0A0h  ; Drive/Head register - 10100000b (A0h)	
  5745                              <1> 	;mov	al, [es:bx]
  5746 00002272 8A03                <1> 	mov	al, [ebx] ; 21/02/2015
  5747 00002274 FEC8                <1> 	dec	al	 ; last head number 
  5748                              <1> 	;and	al, 0Fh
  5749 00002276 08E0                <1> 	or	al, ah	 ; lower 4 bits for head number
  5750                              <1> 	;
  5751 00002278 C645FE91            <1> 	mov	byte [CMD_BLOCK+6], SET_PARM_CMD
  5752 0000227C 8845FD              <1> 	mov	[CMD_BLOCK+5], al
  5753                              <1> 	;pop	bx
  5754 0000227F 5B                  <1> 	pop	ebx
  5755 00002280 29C0                <1> 	sub	eax, eax ; 21/02/2015
  5756 00002282 B004                <1> 	mov	al, 4 ; Physical sec per track from translated HDPT
  5757 00002284 803D[E0620000]00    <1> 	cmp	byte [LBAMode], 0
  5758 0000228B 7702                <1> 	ja	short idrv1
  5759 0000228D B00E                <1> 	mov	al, 14 ; Physical sec per track from standard HDPT
  5760                              <1> idrv1:
  5761                              <1> 	;xor	ah, ah
  5762                              <1> 	;add	bx, ax
  5763 0000228F 01C3                <1> 	add	ebx, eax ; 21/02/2015
  5764                              <1> 	;mov	al, [es:bx]
  5765                              <1> 			; sector number
  5766 00002291 8A03                <1> 	mov	al, [ebx]
  5767 00002293 8845F9              <1> 	mov	[CMD_BLOCK+1], al
  5768 00002296 28C0                <1> 	sub	al, al
  5769 00002298 8845FB              <1> 	mov	[CMD_BLOCK+3], al ; ZERO FLAGS
  5770 0000229B E87B000000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  5771 000022A0 751E                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  5772 000022A2 E816010000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  5773 000022A7 7517                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  5774                              <1> 	;call	CHECK_STATUS
  5775                              <1> 	;jmp	short CHECK_STATUS
  5776                              <1> ;INIT_EXIT:
  5777                              <1> 	;retn
  5778                              <1> 
  5779                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5780                              <1> 
  5781                              <1> ;----------------------------------------
  5782                              <1> ;	CHECK FIXED DISK STATUS 	:
  5783                              <1> ;----------------------------------------
  5784                              <1> CHECK_STATUS:
  5785 000022A9 E861010000          <1> 	call	CHECK_ST		; CHECK THE STATUS BYTE
  5786                              <1> 	;jnz	short CHECK_S1		; AN ERROR WAS FOUND
  5787                              <1> 	; 10/07/2022
  5788 000022AE 7510                <1> 	jnz	short CHECK_S2
  5789 000022B0 A801                <1> 	test	al, ST_ERROR		; WERE THERE ANY OTHER ERRORS
  5790 000022B2 7405                <1> 	jz	short CHECK_S1		; NO ERROR REPORTED
  5791 000022B4 E894010000          <1> 	call	CHECK_ER		; ERROR REPORTED
  5792                              <1> CHECK_S1:
  5793 000022B9 803D[CB620000]00    <1> 	cmp	byte [DISK_STATUS1], 0 	; SET STATUS FOR CALLER
  5794                              <1> CHECK_S2:
  5795                              <1> INIT_EXIT:	; 10/07/2022
  5796 000022C0 C3                  <1> 	retn
  5797                              <1> 
  5798                              <1> ;----------------------------------------
  5799                              <1> ;	TEST DISK READY      (AH = 10H) :
  5800                              <1> ;----------------------------------------
  5801                              <1> 
  5802                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  5803 000022C1 E8F7000000          <1> 	call	NOT_BUSY
  5804 000022C6 751C                <1> 	jnz	short TR_EX
  5805 000022C8 8A45FD              <1> 	mov	al, [CMD_BLOCK+5] 	; SELECT DRIVE
  5806 000022CB 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5807 000022D2 80C206              <1> 	add	dl,6
  5808 000022D5 EE                  <1> 	out	dx, al
  5809 000022D6 E834010000          <1> 	call	CHECK_ST		; CHECK STATUS ONLY
  5810 000022DB 7507                <1> 	jnz	short TR_EX
  5811 000022DD C605[CB620000]00    <1> 	mov	byte [DISK_STATUS1], 0 	; WIPE OUT DATA CORRECTED ERROR
  5812                              <1> TR_EX:	
  5813 000022E4 C3                  <1> 	retn
  5814                              <1> 
  5815                              <1> ;----------------------------------------
  5816                              <1> ;	RECALIBRATE	     (AH = 11H) :
  5817                              <1> ;----------------------------------------
  5818                              <1> 
  5819                              <1> HDISK_RECAL:
  5820 000022E5 C645FE10            <1>         mov	byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16
  5821 000022E9 E82D000000          <1> 	call	COMMAND 		; START THE OPERATION
  5822 000022EE 7523                <1> 	jnz	short RECAL_EXIT	; ERROR
  5823 000022F0 E898000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION
  5824 000022F5 7407                <1> 	jz	short RECAL_X 		; TIME OUT ONE OK ?
  5825 000022F7 E891000000          <1> 	call	_WAIT			; WAIT FOR COMPLETION LONGER
  5826 000022FC 7515                <1> 	jnz	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  5827                              <1> RECAL_X:
  5828 000022FE E8A6FFFFFF          <1> 	call	CHECK_STATUS
  5829 00002303 803D[CB620000]40    <1> 	cmp	byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE
  5830 0000230A 7507                <1> 	jne	short RECAL_EXIT	; IS OK
  5831 0000230C C605[CB620000]00    <1> 	mov	byte [DISK_STATUS1], 0
  5832                              <1> RECAL_EXIT:
  5833 00002313 803D[CB620000]00    <1>         cmp	byte [DISK_STATUS1], 0
  5834 0000231A C3                  <1> 	retn
  5835                              <1> 
  5836                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5837                              <1> 
  5838                              <1> ;--------------------------------------------------------
  5839                              <1> ; COMMAND						:
  5840                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  5841                              <1> ; OUTPUT						:
  5842                              <1> ;	BL = STATUS					:
  5843                              <1> ;	BH = ERROR REGISTER				:
  5844                              <1> ;--------------------------------------------------------
  5845                              <1> 
  5846                              <1> COMMAND:
  5847                              <1> 	;push	ebx ; 10/07/2022	; WAIT FOR SEEK COMPLETE AND READY
  5848                              <1> 	;;mov	ecx, DELAY_2		; SET INITIAL DELAY BEFORE TEST
  5849                              <1> COMMAND1:
  5850                              <1> 	;;push	ecx			; SAVE LOOP COUNT
  5851 0000231B E8A1FFFFFF          <1> 	call	TST_RDY 		; CHECK DRIVE READY
  5852                              <1> 	;;pop	ecx
  5853                              <1> 	;pop	ebx ; 10/07/2022
  5854 00002320 7418                <1> 	jz	short COMMAND2		; DRIVE IS READY
  5855 00002322 803D[CB620000]80    <1>         cmp	byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  5856                              <1> 	;jz	short CMD_TIMEOUT
  5857                              <1> 	;;loop	COMMAND1		; KEEP TRYING FOR A WHILE
  5858                              <1> 	;jmp	short COMMAND4		; ITS NOT GOING TO GET READY
  5859 00002329 7507                <1> 	jne	short COMMAND4
  5860                              <1> CMD_TIMEOUT:
  5861 0000232B C605[CB620000]20    <1> 	mov	byte [DISK_STATUS1], BAD_CNTLR
  5862                              <1> COMMAND4:
  5863                              <1> 	;;pop	ebx ; 10/07/2022
  5864 00002332 803D[CB620000]00    <1>         cmp	byte [DISK_STATUS1], 0	; SET CONDITION CODE FOR CALLER
  5865 00002339 C3                  <1> 	retn
  5866                              <1> COMMAND2:
  5867                              <1> 	;;pop	ebx ; 10/07/2022
  5868                              <1> 	;push	edi ; 10/07/2022
  5869 0000233A C605[C6620000]00    <1> 	mov	byte [HF_INT_FLAG], 0	; RESET INTERRUPT FLAG
  5870 00002341 FA                  <1> 	cli				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  5871 00002342 E4A1                <1> 	in	al, INTB01		; TURN ON SECOND INTERRUPT CHIP
  5872                              <1> 	;and	al, 0BFh
  5873 00002344 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  5874                              <1> 	;JMP	$+2
  5875                              <1> 	IODELAY
  2190 00002346 EB00                <2>  jmp short $+2
  2191 00002348 EB00                <2>  jmp short $+2
  5876 0000234A E6A1                <1> 	out	INTB01, al
  5877 0000234C E421                <1> 	in	al, INTA01		; LET INTERRUPTS PASS THRU TO
  5878 0000234E 24FB                <1> 	and	al, 0FBh 		; SECOND CHIP
  5879                              <1> 	;JMP	$+2
  5880                              <1> 	IODELAY
  2190 00002350 EB00                <2>  jmp short $+2
  2191 00002352 EB00                <2>  jmp short $+2
  5881 00002354 E621                <1> 	out	INTA01, al
  5882 00002356 FB                  <1> 	sti
  5883                              <1> 	;xor	edi, edi		; INDEX THE COMMAND TABLE
  5884                              <1> 	; 10/07/2022
  5885 00002357 31C9                <1> 	xor	ecx, ecx
  5886                              <1> 	;mov	dx, HF_PORT+1		; DISK ADDRESS
  5887 00002359 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5888 00002360 FEC2                <1> 	inc	dl
  5889 00002362 F605[CD620000]C0    <1> 	test	byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION
  5890 00002369 7411                <1> 	jz	short COMMAND3
  5891 0000236B 8A45FE              <1> 	mov	al, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  5892 0000236E 24F0                <1> 	and	al, 0F0h 		; GET RID OF MODIFIERS
  5893 00002370 3C20                <1> 	cmp	al, 20h			; 20H-40H IS READ, WRITE, VERIFY
  5894 00002372 7208                <1> 	jb	short COMMAND3
  5895 00002374 3C40                <1> 	cmp	al, 40h
  5896 00002376 7704                <1> 	ja	short COMMAND3
  5897 00002378 804DFE01            <1> 	or	byte [CMD_BLOCK+6], NO_RETRIES 
  5898                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  5899                              <1> COMMAND3:
  5900                              <1> 	;mov	al, [CMD_BLOCK+edi]	; GET THE COMMAND STRING BYTE
  5901                              <1> 	; 10/07/2022
  5902 0000237C 8A440DF8            <1> 	mov	al, [CMD_BLOCK+ecx]
  5903 00002380 EE                  <1> 	out	dx, al			; GIVE IT TO CONTROLLER
  5904                              <1> 	IODELAY
  2190 00002381 EB00                <2>  jmp short $+2
  2191 00002383 EB00                <2>  jmp short $+2
  5905                              <1> 	;inc	edi			; NEXT BYTE IN COMMAND BLOCK
  5906                              <1> 	; 10/07/2022
  5907 00002385 41                  <1> 	inc	ecx
  5908                              <1> 	;inc	dx			; NEXT DISK ADAPTER REGISTER
  5909 00002386 42                  <1> 	inc	edx   ; 10/07/2022	
  5910                              <1> 	;cmp	di, 7 ; 01/01/2015	; ALL DONE?
  5911                              <1> 	;jne	short COMMAND3		; NO--GO DO NEXT ONE
  5912 00002387 80F907              <1> 	cmp	cl, 7 ; 10/07/2022
  5913 0000238A 72F0                <1> 	jb	short COMMAND3
  5914                              <1> 	;pop	edi ; 10/07/2022
  5915 0000238C C3                  <1> 	retn				; ZERO FLAG IS SET
  5916                              <1> 
  5917                              <1> ;CMD_TIMEOUT:
  5918                              <1> ;	mov	byte [DISK_STATUS1], BAD_CNTLR
  5919                              <1> ;COMMAND4:
  5920                              <1> ;	pop	ebx
  5921                              <1> ;	cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5922                              <1> ;	retn
  5923                              <1> 
  5924                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5925                              <1> 
  5926                              <1> ;----------------------------------------
  5927                              <1> ;	WAIT FOR INTERRUPT		:
  5928                              <1> ;----------------------------------------
  5929                              <1> ;WAIT:
  5930                              <1> _WAIT:
  5931 0000238D FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5932                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5933                              <1> 	;clc
  5934                              <1> 	;mov	ax, 9000h		; DEVICE WAIT INTERRUPT
  5935                              <1> 	;int	15h
  5936                              <1> 	;jc	short WT2		; DEVICE TIMED OUT
  5937                              <1> 	;mov	bl, DELAY_1		; SET DELAY COUNT
  5938                              <1> 
  5939                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  5940                              <1> 	;; 21/02/2015
  5941                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  5942                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  5943 0000238E B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  5944                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  5945                              <1> ;-----	WAIT LOOP
  5946                              <1> 
  5947                              <1> WT1:	
  5948                              <1> 	;test	byte [HF_INT_FLAG], 80h	; TEST FOR INTERRUPT
  5949 00002393 F605[C6620000]C0    <1> 	test 	byte [HF_INT_FLAG], 0C0h
  5950                              <1> 	;loopz	WT1
  5951 0000239A 7512                <1> 	jnz	short WT3		; INTERRUPT--LETS GO
  5952                              <1> 	;dec	bl
  5953                              <1> 	;jnz	short WT1		; KEEP TRYING FOR A WHILE
  5954                              <1> 
  5955                              <1> WT1_hi:
  5956 0000239C E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  5957 0000239E A810                <1> 	test	al, 10h			; transition on memory
  5958 000023A0 75FA                <1> 	jnz	short WT1_hi		; refresh.
  5959                              <1> WT1_lo:
  5960 000023A2 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  5961 000023A4 A810                <1> 	test	al, 10h			
  5962 000023A6 74FA                <1> 	jz	short WT1_lo
  5963 000023A8 E2E9                <1> 	loop	WT1
  5964                              <1> 	;;or	bl, bl
  5965                              <1> 	;;jz	short WT2	
  5966                              <1> 	;;dec	bl
  5967                              <1> 	;;jmp	short WT1
  5968                              <1> 	;dec	bl
  5969                              <1> 	;jnz	short WT1	
  5970                              <1> WT2:	
  5971                              <1> 	; 10/07/2022
  5972                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  5973 000023AA B080                <1> 	mov	al, TIME_OUT
  5974 000023AC EB07                <1> 	jmp	short WT4
  5975                              <1> WT3:
  5976                              <1> 	;mov	byte [DISK_STATUS1], 0
  5977                              <1> 	;mov	byte [HF_INT_FLAG], 0
  5978 000023AE 28C0                <1> 	sub	al, al ; 0
  5979 000023B0 A2[C6620000]        <1> 	mov	byte [HF_INT_FLAG], al
  5980                              <1> WT4:
  5981                              <1> NB2:	
  5982 000023B5 A2[CB620000]        <1> 	mov	byte [DISK_STATUS1], al
  5983                              <1> 
  5984                              <1> 	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  5985 000023BA 20C0                <1> 	and	al, al
  5986                              <1> 	; zf = 0 -> time out, zf = 1 -> ok
  5987 000023BC C3                  <1> 	retn
  5988                              <1> 
  5989                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  5990                              <1> 
  5991                              <1> ;----------------------------------------
  5992                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  5993                              <1> ;----------------------------------------
  5994                              <1> NOT_BUSY:
  5995 000023BD FB                  <1> 	sti				; MAKE SURE INTERRUPTS ARE ON
  5996                              <1> 	;push	ebx
  5997                              <1> 	;sub	cx, cx			; SET INITIAL DELAY BEFORE TEST
  5998 000023BE 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  5999 000023C5 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6000                              <1> 	;mov	bl, DELAY_1
  6001                              <1> 					; wait for 10 seconds
  6002                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6003                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6004                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6005 000023C8 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6006                              <1> 	;
  6007                              <1> 	;;mov	byte [wait_count], 0    ; Reset wait counter
  6008                              <1> NB1:	
  6009 000023CD EC                  <1> 	in	al, dx			; CHECK STATUS
  6010                              <1> 	;test	al, ST_BUSY
  6011 000023CE 2480                <1> 	and	al, ST_BUSY
  6012                              <1> 	;loopnz NB1
  6013 000023D0 74E3                <1> 	jz	short NB2 ; al = 0	; NOT BUSY--LETS GO
  6014                              <1> 	;dec	bl			
  6015                              <1> 	;jnz	short NB1		; KEEP TRYING FOR A WHILE
  6016                              <1> 
  6017                              <1> NB1_hi: 
  6018 000023D2 E461                <1> 	in	al, SYS1		; wait for hi to lo
  6019 000023D4 A810                <1> 	test	al, 010h		; transition on memory
  6020 000023D6 75FA                <1> 	jnz	short NB1_hi		; refresh.
  6021                              <1> NB1_lo: 
  6022 000023D8 E461                <1> 	in	al, SYS1
  6023 000023DA A810                <1> 	test	al, 010h
  6024 000023DC 74FA                <1> 	jz	short NB1_lo
  6025 000023DE E2ED                <1> 	loop	NB1
  6026                              <1> 	;dec	bl
  6027                              <1> 	;jnz	short NB1
  6028                              <1> 	;
  6029                              <1> 	;;cmp	byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6030                              <1> 	;;jb	short NB1
  6031                              <1> 	;
  6032                              <1> 	;mov	byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR
  6033                              <1> 	;jmp	short NB3
  6034 000023E0 B080                <1> 	mov	al, TIME_OUT
  6035                              <1> ;NB2:	
  6036 000023E2 EBD1                <1> 	jmp	short NB2 ; 10/07/2022
  6037                              <1> 
  6038                              <1> ;	;mov	byte [DISK_STATUS1], 0
  6039                              <1> ;;NB3:	
  6040                              <1> ;	;pop	ebx
  6041                              <1> ;	mov	[DISK_STATUS1], al	;;; will be set after return
  6042                              <1> ;	;cmp	byte [DISK_STATUS1], 0 	; SET CONDITION CODE FOR CALLER
  6043                              <1> ;	or	al, al			; (zf = 0 --> timeout)
  6044                              <1> ;	retn
  6045                              <1> 
  6046                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6047                              <1> 
  6048                              <1> ;----------------------------------------
  6049                              <1> ;	WAIT FOR DATA REQUEST		:
  6050                              <1> ;----------------------------------------
  6051                              <1> WAIT_DRQ:
  6052                              <1> 	;mov	cx, DELAY_3
  6053                              <1> 	;mov	dx, HF_PORT+7
  6054 000023E4 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  6055 000023EB 80C207              <1> 	add	dl, 7
  6056                              <1> 	;;mov	bl, WAIT_HDU_DRQ_HI	; 0
  6057                              <1> 	;mov	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  6058                              <1> 					; (but it is written as 2000
  6059                              <1> 					; micro seconds in ATORGS.ASM file
  6060                              <1> 					; of Award Bios - 1999, D1A0622)
  6061 000023EE B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6062                              <1> WQ_1:
  6063 000023F3 EC                  <1> 	in	al, dx			; GET STATUS
  6064 000023F4 A808                <1> 	test	al, ST_DRQ		; WAIT FOR DRQ
  6065 000023F6 7516                <1> 	jnz	short WQ_OK
  6066                              <1> 	;loop	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6067                              <1> WQ_hi:	
  6068 000023F8 E461                <1> 	in	al, SYS1		; wait for hi to lo
  6069 000023FA A810                <1> 	test	al, 010h		; transition on memory
  6070 000023FC 75FA                <1> 	jnz	short WQ_hi		; refresh.
  6071                              <1> WQ_lo:  
  6072 000023FE E461                <1> 	in	al, SYS1
  6073 00002400 A810                <1> 	test	al, 010h
  6074 00002402 74FA                <1> 	jz	short WQ_lo
  6075 00002404 E2ED                <1> 	loop	WQ_1
  6076                              <1> 
  6077 00002406 C605[CB620000]80    <1> 	mov	byte [DISK_STATUS1], TIME_OUT ; ERROR
  6078 0000240D F9                  <1> 	stc
  6079                              <1> WQ_OK:
  6080 0000240E C3                  <1> 	retn
  6081                              <1> ;WQ_OK:
  6082                              <1> 	;clc
  6083                              <1> 	;retn
  6084                              <1> 
  6085                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6086                              <1> 
  6087                              <1> ;----------------------------------------
  6088                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  6089                              <1> ;----------------------------------------
  6090                              <1> CHECK_ST:
  6091                              <1> 	;mov	dx, HF_PORT+7		; GET THE STATUS
  6092 0000240F 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]
  6093 00002416 80C207              <1> 	add	dl, 7
  6094 00002419 EC                  <1> 	in	al, dx
  6095 0000241A A2[C5620000]        <1> 	mov	[HF_STATUS], al
  6096                              <1> 	;mov	ah, 0
  6097 0000241F 28E4                <1> 	sub	ah, ah ; 0
  6098 00002421 A880                <1> 	test	al, ST_BUSY		; IF STILL BUSY
  6099 00002423 751A                <1> 	jnz	short CKST_EXIT		; REPORT OK
  6100 00002425 B4CC                <1> 	mov	ah, WRITE_FAULT
  6101 00002427 A820                <1> 	test 	al, ST_WRT_FLT		; CHECK FOR WRITE FAULT
  6102 00002429 7514                <1> 	jnz	short CKST_EXIT
  6103 0000242B B4AA                <1> 	mov	ah, NOT_RDY
  6104 0000242D A840                <1> 	test	al, ST_READY		; CHECK FOR NOT READY
  6105 0000242F 740E                <1> 	jz	short CKST_EXIT
  6106 00002431 B440                <1> 	mov	ah, BAD_SEEK
  6107 00002433 A810                <1> 	test	al, ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  6108 00002435 7408                <1> 	jz	short CKST_EXIT
  6109 00002437 B411                <1> 	mov	ah, DATA_CORRECTED
  6110 00002439 A804                <1> 	test	al, ST_CORRCTD		; CHECK FOR CORRECTED ECC
  6111 0000243B 7502                <1> 	jnz	short CKST_EXIT
  6112                              <1> 	;mov	ah, 0
  6113 0000243D 30E4                <1> 	xor	ah, ah ; 0
  6114                              <1> CKST_EXIT:
  6115 0000243F 8825[CB620000]      <1> 	mov	[DISK_STATUS1], ah	; SET ERROR FLAG
  6116 00002445 80FC11              <1> 	cmp	ah, DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  6117 00002448 7402                <1> 	je	short CKST_EX1
  6118                              <1> 	;cmp	ah, 0
  6119 0000244A 20E4                <1> 	and	ah, ah
  6120                              <1> CKST_EX1:
  6121 0000244C C3                  <1> 	retn
  6122                              <1> 
  6123                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6124                              <1> 
  6125                              <1> ;----------------------------------------
  6126                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  6127                              <1> ;----------------------------------------
  6128                              <1> CHECK_ER:
  6129                              <1> 	;mov	dx, HF_PORT+1		; GET THE ERROR REGISTER
  6130 0000244D 668B15[525D0000]    <1> 	mov	dx, [HF_PORT]		;
  6131 00002454 FEC2                <1> 	inc	dl
  6132 00002456 EC                  <1> 	in	al, dx
  6133                              <1> 	; 10/07/2022
  6134                              <1> 	;mov	[HF_ERROR], al
  6135                              <1> 	;push	ebx	; 21/02/2015
  6136 00002457 29C9                <1> 	sub	ecx, ecx
  6137                              <1> 	;mov	ecx, 8			; TEST ALL 8 BITS
  6138 00002459 B108                <1> 	mov	cl, 8
  6139                              <1> CK1:	
  6140 0000245B D0E0                <1> 	shl	al, 1			; MOVE NEXT ERROR BIT TO CARRY
  6141 0000245D 7202                <1> 	jc	short CK2		; FOUND THE ERROR
  6142 0000245F E2FA                <1> 	loop	CK1			; KEEP TRYING
  6143                              <1> CK2:
  6144                              <1> 	;mov	ebx, ERR_TBL		; COMPUTE ADDRESS OF
  6145                              <1> 	;add	ebx, ecx		; ERROR CODE
  6146 00002461 81C1[485D0000]      <1> 	add	ecx, ERR_TBL ; 10/07/2022	
  6147                              <1> 
  6148                              <1> 	;;;mov	ah, byte [cs:bx]	; GET ERROR CODE
  6149                              <1> 	;;mov	ah, [bx]
  6150                              <1> 	;mov	ah, [ebx] ; 21/02/2015
  6151 00002467 8A21                <1> 	mov	ah, [ecx]	
  6152                              <1> CKEX:
  6153 00002469 8825[CB620000]      <1> 	mov	[DISK_STATUS1], ah	; SAVE ERROR CODE
  6154                              <1> 	; 10/07/2022
  6155                              <1> 	;pop	ebx
  6156                              <1> 	;;cmp	ah, 0
  6157                              <1> 	;and	ah, ah
  6158 0000246F C3                  <1> 	retn
  6159                              <1> 
  6160                              <1> ;--------------------------------------------------------
  6161                              <1> ; CHECK_DMA						:
  6162                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  6163                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  6164                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  6165                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  6166                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  6167                              <1> ;  -ERROR OTHERWISE					:
  6168                              <1> ;--------------------------------------------------------
  6169                              <1> 
  6170                              <1> 	; 11/07/2022
  6171                              <1> 	; (not needed for hard disks and 32 bit OS)
  6172                              <1> 	;
  6173                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6174                              <1> ;CHECK_DMA:
  6175                              <1> ;	;;push	ax			; SAVE REGISTERS
  6176                              <1> ;	;; 24/12/2021
  6177                              <1> ;	;;push	eax
  6178                              <1> ;	;mov	ax, 8000h		; AH = MAX # SECTORS
  6179                              <1> ;					; AL = MAX OFFSET
  6180                              <1> ;	; 10/07/2022
  6181                              <1> ;	;test	byte [CMD_BLOCK+6], ECC_MODE
  6182                              <1> ;	;jz	short CKD1
  6183                              <1> ;	;mov	ax, 7F04h		; ECC IS 4 MORE BYTES
  6184                              <1> ;CKD1:	
  6185                              <1> ;	;cmp	ah, [CMD_BLOCK+1]	; NUMBER OF SECTORS
  6186                              <1> ;	;ja	short CKDOK		; IT WILL FIT
  6187                              <1> ;	;jb	short CKDERR		; TOO MANY
  6188                              <1> ;	
  6189                              <1> ;	cmp	byte [CMD_BLOCK+1], 80h
  6190                              <1> ;	jb	short CKDOK
  6191                              <1> ;	ja	short CKDERR
  6192                              <1> ;	;cmp	al, bl			; CHECK OFFSET ON MAX SECTORS
  6193                              <1> ;	;jb	short CKDERR		; ERROR
  6194                              <1> ;CKD2:
  6195                              <1> ;	or	bl, bl
  6196                              <1> ;	jz	short CKDR
  6197                              <1> ;	
  6198                              <1> ;;CKDOK:	
  6199                              <1> ;	;clc				; CLEAR CARRY
  6200                              <1> ;	;;pop	ax
  6201                              <1> ;	;; 24/12/2021
  6202                              <1> ;	;pop	eax
  6203                              <1> ;	;retn				; NORMAL RETURN
  6204                              <1> ;CKDERR: 
  6205                              <1> ;	stc				; INDICATE ERROR
  6206                              <1> ;	mov	byte [DISK_STATUS1], DMA_BOUNDARY
  6207                              <1> ;	;;pop	ax
  6208                              <1> ;	;; 24/12/2021
  6209                              <1> ;	;pop	eax	
  6210                              <1> ;	retn
  6211                              <1> ;
  6212                              <1> ;	; 10/07/2022
  6213                              <1> ;CKDOK:
  6214                              <1> ;	clc
  6215                              <1> ;CKDR:
  6216                              <1> ;	retn
  6217                              <1> 
  6218                              <1> ;----------------------------------------
  6219                              <1> ;	SET UP EBX-> DISK PARMS	        :
  6220                              <1> ;----------------------------------------
  6221                              <1> 					
  6222                              <1> ; INPUT -> DL = 0 based drive number
  6223                              <1> ; OUTPUT -> EBX = disk parameter table address
  6224                              <1> 
  6225                              <1> 	; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  6226                              <1> 
  6227                              <1> GET_VEC:
  6228                              <1> 	;sub	ax, ax			; GET DISK PARAMETER ADDRESS
  6229                              <1> 	;mov	es, ax
  6230                              <1> 	;test	dl, 1
  6231                              <1> 	;jz	short GV_0
  6232                              <1> ;	les	bx, [HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  6233                              <1> ;	jmp	short GV_EXIT
  6234                              <1> ;GV_0:
  6235                              <1> ;	les 	bx,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  6236                              <1> ;
  6237 00002470 31DB                <1> 	xor	ebx, ebx
  6238 00002472 88D3                <1> 	mov	bl, dl
  6239                              <1> 	;02/01/2015
  6240                              <1> 	;xor	bh, bh
  6241                              <1> 	;shl	bl, 1			; port address offset
  6242                              <1> 	;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  6243                              <1> 	;shl	bl, 1			; dpt pointer offset
  6244 00002474 C0E302              <1> 	shl	bl, 2
  6245                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  6246 00002477 81C3[D0620000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  6247                              <1> 	;push	word [bx+2]		; dpt segment
  6248                              <1> 	;pop	es
  6249                              <1> 	;mov	bx, [bx]		; dpt offset
  6250 0000247D 8B1B                <1> 	mov	ebx, [ebx]		
  6251                              <1> ;GV_EXIT:
  6252 0000247F C3                  <1> 	retn
  6253                              <1> 
  6254                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6255                              <1> hdc1_int: ; 21/02/2015
  6256                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  6257                              <1> ;								:
  6258                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6259                              <1> ;								:
  6260                              <1> ;----------------------------------------------------------------
  6261                              <1> 
  6262                              <1> ; 22/12/2014
  6263                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  6264                              <1> ;	 '11/15/85'
  6265                              <1> ; AWARD BIOS 1999 (D1A0622) 
  6266                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  6267                              <1> 
  6268                              <1> ;int_76h:
  6269                              <1> HD_INT:
  6270                              <1> 	;push	ax
  6271                              <1> 	; 24/12/2021
  6272 00002480 50                  <1> 	push	eax
  6273 00002481 1E                  <1> 	push	ds
  6274                              <1> 	;CALL	DDS
  6275                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6276 00002482 66B81000            <1> 	mov	ax, KDATA
  6277 00002486 8ED8                <1> 	mov 	ds, ax
  6278                              <1> 	;
  6279                              <1> 	;;MOV	@HF_INT_FLAG, 0FFH	; ALL DONE
  6280                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  6281 00002488 C605[C6620000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  6282                              <1> 	;
  6283                              <1> 	;push	dx
  6284                              <1> 	; 24/12/2021
  6285 0000248F 52                  <1> 	push	edx
  6286 00002490 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  6287                              <1> 					; Clear Controller
  6288                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  6289 00002494 EC                  <1> 	in	al, dx			;
  6290                              <1> 	;pop	dx
  6291                              <1> 	; 24/12/2021
  6292 00002495 5A                  <1> 	pop	edx
  6293                              <1> 	NEWIODELAY
  2195 00002496 E6EB                <2>  out 0EBh,al
  6294                              <1> 	;
  6295 00002498 B020                <1> 	mov	al, EOI			; NON-SPECIFIC END OF INTERRUPT
  6296 0000249A E6A0                <1> 	out	INTB00, al		; FOR CONTROLLER #2
  6297                              <1> 	;JMP	$+2			; WAIT
  6298                              <1> 	NEWIODELAY
  2195 0000249C E6EB                <2>  out 0EBh,al
  6299 0000249E E620                <1> 	out	INTA00, al		; FOR CONTROLLER #1
  6300 000024A0 1F                  <1> 	pop	ds
  6301                              <1> 	;sti				; RE-ENABLE INTERRUPTS
  6302                              <1> 	;mov	ax, 9100h		; DEVICE POST
  6303                              <1> 	;int	15h			; INTERRUPT
  6304                              <1> irq15_iret: ; 25/02/2015
  6305                              <1> 	;pop	ax
  6306                              <1> 	; 24/12/2021
  6307 000024A1 58                  <1> 	pop	eax
  6308 000024A2 CF                  <1> 	iretd				; RETURN FROM INTERRUPT
  6309                              <1> 
  6310                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  6311                              <1> hdc2_int: ; 21/02/2015
  6312                              <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) ----------------------
  6313                              <1> ;								:
  6314                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  6315                              <1> ;								:
  6316                              <1> ;----------------------------------------------------------------
  6317                              <1> 
  6318                              <1> ;int_77h:
  6319                              <1> HD1_INT:
  6320                              <1> 	;push	ax
  6321                              <1> 	; 24/12/2021
  6322 000024A3 50                  <1> 	push	eax
  6323                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  6324                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  6325 000024A4 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  6326 000024A6 E6A0                <1> 	out	0A0h, al
  6327 000024A8 EB00                <1>         jmp short $+2
  6328 000024AA EB00                <1> 	jmp short $+2
  6329 000024AC E4A0                <1> 	in	al, 0A0h
  6330 000024AE 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  6331 000024B0 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  6332                              <1> 	;
  6333 000024B2 1E                  <1> 	push	ds
  6334                              <1> 	;CALL	DDS
  6335                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  6336 000024B3 66B81000            <1> 	mov	ax, KDATA
  6337 000024B7 8ED8                <1> 	mov 	ds, ax
  6338                              <1> 	;
  6339                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  6340                              <1>         ;or	byte [CS:HF_INT_FLAG], 0C0h 
  6341 000024B9 800D[C6620000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  6342                              <1> 	;
  6343                              <1> 	;push	dx
  6344                              <1> 	; 24/12/2021
  6345 000024C0 52                  <1> 	push	edx
  6346 000024C1 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  6347                              <1> 					; Clear Controller (Award BIOS 1999)
  6348 000024C5 EBCD                <1> 	jmp	short Clear_IRQ1415
  6349                              <1> 
  6350                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  6351                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  6352                              <1> 
  6353                              <1> ;////////////////////////////////////////////////////////////////////
  6354                              <1> ;; END OF DISK I/O SYTEM ///
  2110                                  %include 'memory.inc'  ; 09/03/2015
  2111                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2112                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.6) - MEMORY.INC
  2113                              <1> ; Last Modification: 17/07/2022
  2114                              <1> ;
  2115                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2116                              <1> 
  2117                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2118                              <1> 
  2119                              <1> ;;04/11/2014 (unix386.s)	
  2120                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2121                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2122                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2123                              <1> ;;
  2124                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2125                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2126                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2127                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2128                              <1> 
  2129                              <1> ; 27/04/2015
  2130                              <1> ; 09/03/2015
  2131                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2132                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2133                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2134                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2135                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2136                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2137                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2138                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2139                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2140                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2141                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2142                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2143                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2144                              <1> SWP_DISK_READ_ERR 	   equ 40
  2145                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2146                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2147                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2148                              <1> SWP_DISK_WRITE_ERR         equ 44
  2149                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2150                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2151                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2152                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2153                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2154                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2155                              <1> 					; (Indicates that the page is not allocated
  2156                              <1> 					; for the process, it is a shared or system
  2157                              <1>                                         ; page, it must not be deallocated!)
  2158                              <1> ; 14/12/2020
  2159                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2160                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2161                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2162                              <1> 				; (Out of memory allocation table)	
  2163                              <1> ;
  2164                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2165                              <1> ;;
  2166                              <1> ;; 10/10/2014
  2167                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2168                              <1> ;;
  2169                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2170                              <1> ;;	(virtual address = physical address)
  2171                              <1> ;; KERNEL PAGE TABLES:
  2172                              <1> ;;	Kernel page directory and all page tables are
  2173                              <1> ;;	on memory as initialized, as equal to physical memory
  2174                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2175                              <1> ;;
  2176                              <1> ;;	what for: User pages may be swapped out, when accessing
  2177                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2178                              <1> ;;	kernel would have to swap it in! But it is also may be
  2179                              <1> ;;	in use by a user process. (In system/kernel mode
  2180                              <1> ;;	kernel can access all memory pages even if they are
  2181                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2182                              <1> ;;	cause conflicts.) 
  2183                              <1> ;;	
  2184                              <1> ;;	As result of these conditions,
  2185                              <1> ;;	all kernel pages must be initialized as equal to 
  2186                              <1> ;;	physical layout for preventing page faults. 
  2187                              <1> ;;	Also, calling "allocate page" procedure after
  2188                              <1> ;;	a page fault can cause another page fault (double fault)
  2189                              <1> ;;	if all kernel page tables would not be initialized.
  2190                              <1> ;;
  2191                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2192                              <1> ;;	memory allocation table. (double word aligned)
  2193                              <1> ;;
  2194                              <1> ;;	[next_page] = first/next free space to be searched
  2195                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2196                              <1> ;;
  2197                              <1> ;;	[last_page] = End of memory (users space), as offset
  2198                              <1> ;;	to memory allocation table. (double word aligned)
  2199                              <1> ;;
  2200                              <1> ;; USER PAGE TABLES:
  2201                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2202                              <1> ;;		'ready only' marked copies of the 
  2203                              <1> ;;		parent process's page table entries (for
  2204                              <1> ;;		same physical memory).
  2205                              <1> ;;		(A page will be copied to a new page after
  2206                              <1> ;;		 if it causes R/W page fault.)
  2207                              <1> ;;
  2208                              <1> ;;	Every user process has own (different)
  2209                              <1> ;;	page directory and page tables.	
  2210                              <1> ;;
  2211                              <1> ;;	Code starts at virtual address 0, always.
  2212                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2213                              <1> ;;	(Programs can be written/developed as simple
  2214                              <1> ;;	 flat memory programs.)
  2215                              <1> ;;
  2216                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2217                              <1> ;;	Memory page will be allocated by kernel only 
  2218                              <1> ;;		(in kernel/system mode only).
  2219                              <1> ;;	* After a
  2220                              <1> ;;	  - 'not present' page fault
  2221                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2222                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2223                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2224                              <1> ;;	  request by running process.
  2225                              <1> ;;	* While creating a process, allocating a new buffer,
  2226                              <1> ;;	  new page tables etc.
  2227                              <1> ;;
  2228                              <1> ;;	At first,
  2229                              <1> ;;	- 'allocate page' procedure will be called;
  2230                              <1> ;,	   if it will return with a valid (>0) physical address
  2231                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2232                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2233                              <1> ;;	- 'allocate page' will be called for allocating page
  2234                              <1> ;;	   directory, page table and running space (data/code).
  2235                              <1> ;;	- every successful 'allocate page' call will decrease
  2236                              <1> ;;	  'free_pages' count (pointer).
  2237                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2238                              <1> ;;	  if 'free_pages' points to a ZERO.
  2239                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2240                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2241                              <1> ;;	  error except errors caused by attribute conflicts.
  2242                              <1> ;;	 (swapper functions)	 
  2243                              <1> ;;					
  2244                              <1> ;;	At second,
  2245                              <1> ;;	- page directory entry will be updated then page table
  2246                              <1> ;;	  entry will be updated.		
  2247                              <1> ;;
  2248                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2249                              <1> ;;	- M.A.T. has a size according to available memory as
  2250                              <1> ;;	  follows:
  2251                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2252                              <1> ;;		  - a bit with value of 0 means allocated page
  2253                              <1> ;;		  - a bit with value of 1 means a free page
  2254                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2255                              <1> ;;	  depending on M.A.T.
  2256                              <1> ;;		(NOTE: Free page count will not be checked
  2257                              <1> ;;		again -on M.A.T.- after initialization. 
  2258                              <1> ;;		Kernel will trust on initial count.)
  2259                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2260                              <1> ;;	  and it will be increased by deallocation procedures.
  2261                              <1> ;;	
  2262                              <1> ;;	- Available memory will be calculated during
  2263                              <1> ;;	  the kernel's initialization stage (in real mode).
  2264                              <1> ;;	  Memory allocation table and kernel page tables 
  2265                              <1> ;;	  will be formatted/sized as result of available
  2266                              <1> ;;	  memory calculation before paging is enabled.
  2267                              <1> ;;
  2268                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2269                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2270                              <1> ;;	- Memory allocation for kernel page directory size 
  2271                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2272                              <1> ;;	  for page tables)
  2273                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2274                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2275                              <1> ;;	- User (available) space will be started 
  2276                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2277                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2278                              <1> ;;	  memory allocation table and kernel's page directory
  2279                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2280                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2281                              <1> ;; 	  for buffers.
  2282                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2283                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2284                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2285                              <1> ;;
  2286                              <1> ;; For 1GB Available Memory:
  2287                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2288                              <1> ;;	- Memory allocation for kernel page directory size 
  2289                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2290                              <1> ;;	  for page tables)
  2291                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2292                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2293                              <1> ;;	- User (available) space will be started 
  2294                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2295                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2296                              <1> ;;	  memory allocation table and kernel's page directory
  2297                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2298                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2299                              <1> ;; 	  for buffers.
  2300                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2301                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2302                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2303                              <1> ;;
  2304                              <1> ;;
  2305                              <1> 
  2306                              <1> ;;************************************************************************************
  2307                              <1> ;; 
  2308                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2309                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2310                              <1> 
  2311                              <1> ;; Main factor: "sys fork" system call 
  2312                              <1> ;;	
  2313                              <1> ;; 		FORK
  2314                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2315                              <1> ;;  writable pages ---->|
  2316                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2317                              <1> ;; 
  2318                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2319                              <1> ;; 
  2320                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2321                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2322                              <1> ;;       -while R/W bit is 0-. 
  2323                              <1> ;; 
  2324                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2325                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2326                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2327                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2328                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2329                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2330                              <1> ;; 
  2331                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2332                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2333                              <1> ;;   Parent's PTE attributes are not changed.
  2334                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2335                              <1> ;;    destroy/mix previous fork result).
  2336                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2337                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2338                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2339                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2340                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2341                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2342                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2343                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2344                              <1> ;; 
  2345                              <1> ;; !? WHAT FOR (duplication after duplication):
  2346                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2347                              <1> ;; program/executable code continues from specified location as child process, 
  2348                              <1> ;; returns back previous code location as parent process, every child after 
  2349                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2350                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2351                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2352                              <1> ;; was copied to child's process segment (all of code and data) according to
  2353                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2354                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2355                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2356                              <1> ;; (complete running image of parent process) to the child process; 
  2357                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2358                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2359                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2360                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2361                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2362                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2363                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2364                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2365                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2366                              <1> ;; for sharing same read only pages between parent and child processes.
  2367                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2368                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2369                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2370                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2371                              <1> ;; -deallocation problem-.
  2372                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2373                              <1> ;; 
  2374                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2375                              <1> ;; # Page fault handler will do those:
  2376                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2377                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2378                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2379                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2380                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2381                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2382                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2383                              <1> ;;     to child process.)	
  2384                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2385                              <1> ;; # Page fault handler will do those:
  2386                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2387                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2388                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2389                              <1> ;;     address or not. 
  2390                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2391                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2392                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2393                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2394                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2395                              <1> ;; 
  2396                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2397                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2398                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2399                              <1> ;;       duplication method details, it is not possible multiple child processes
  2400                              <1> ;;       were using same page with duplicated PTEs.
  2401                              <1> ;; 
  2402                              <1> ;;************************************************************************************   
  2403                              <1> 
  2404                              <1> ;; 08/10/2014
  2405                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2406                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2407                              <1> 
  2408                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2409                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2410                              <1> ;; (25/08/2014, Revision: 5057) file 
  2411                              <1> ;; by KolibriOS Team (2004-2012)
  2412                              <1> 
  2413                              <1> allocate_page:
  2414                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2415                              <1> 	; 01/07/2015
  2416                              <1> 	; 05/05/2015
  2417                              <1> 	; 30/04/2015
  2418                              <1> 	; 16/10/2014
  2419                              <1> 	; 08/10/2014
  2420                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2421                              <1> 	;
  2422                              <1> 	; INPUT -> none
  2423                              <1> 	;
  2424                              <1> 	; OUTPUT ->
  2425                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2426                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2427                              <1> 	;
  2428                              <1> 	;	CF = 1 and EAX = 0 
  2429                              <1> 	; 		   if there is not a free page to be allocated	
  2430                              <1> 	;
  2431                              <1> 	; Modified Registers -> none (except EAX)
  2432                              <1> 	;
  2433 000024C7 A1[40620000]        <1> 	mov	eax, [free_pages]
  2434 000024CC 21C0                <1> 	and	eax, eax
  2435 000024CE 7438                <1> 	jz	short out_of_memory
  2436                              <1> 	;
  2437 000024D0 53                  <1> 	push	ebx
  2438 000024D1 51                  <1> 	push	ecx
  2439                              <1> 	;
  2440 000024D2 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2441 000024D7 89D9                <1> 	mov	ecx, ebx
  2442                              <1>  				     ; NOTE: 32 (first_page) is initial
  2443                              <1> 				     ; value of [next_page].
  2444                              <1> 				     ; It points to the first available
  2445                              <1> 				     ; page block for users (ring 3) ...	
  2446                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2447                              <1> 				     ; (at the of the first 4 MB)		
  2448 000024D9 031D[44620000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2449                              <1> 				 ; next_free_page >> 5
  2450 000024DF 030D[48620000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2451                              <1> 				 ; (total_pages - 1) >> 5
  2452                              <1> al_p_scan:
  2453 000024E5 39CB                <1> 	cmp	ebx, ecx
  2454 000024E7 770A                <1> 	ja	short al_p_notfound
  2455                              <1> 	;
  2456                              <1> 	; 01/07/2015
  2457                              <1> 	; AMD64 Architecture Programmers Manual
  2458                              <1> 	; Volume 3:
  2459                              <1> 	; General-Purpose and System Instructions
  2460                              <1> 	;
  2461                              <1> 	; BSF - Bit Scan Forward
  2462                              <1> 	;
  2463                              <1> 	;   Searches the value in a register or a memory location
  2464                              <1> 	;   (second operand) for the least-significant set bit. 
  2465                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2466                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2467                              <1> 	;   register (first operand). If the second operand contains 0, 
  2468                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2469                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2470                              <1> 	;   of the searched value
  2471                              <1> 	;
  2472 000024E9 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2473                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2474                              <1> 			   ; loads the destination with an index to
  2475                              <1> 			   ; first set bit. (0 -> 31) 
  2476                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2477 000024EC 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2478                              <1> 			 ;
  2479                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2480                              <1> 			 ;	  with value of 1 means 
  2481                              <1> 			 ;	  the corresponding page is free 
  2482                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2483 000024EE 83C304              <1> 	add	ebx, 4
  2484                              <1> 			 ; We return back for searching next page block
  2485                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2486                              <1> 			 ;	 we always will find at least 1 free page here.
  2487 000024F1 EBF2                <1>         jmp     short al_p_scan
  2488                              <1> 	;
  2489                              <1> al_p_notfound:
  2490 000024F3 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2491 000024F9 890D[44620000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2492                              <1> 				 ; (deallocate_page procedure will change it)
  2493 000024FF 31C0                <1> 	xor	eax, eax
  2494 00002501 A3[40620000]        <1> 	mov	[free_pages], eax ; 0
  2495 00002506 59                  <1> 	pop	ecx
  2496 00002507 5B                  <1> 	pop	ebx
  2497                              <1> 	;
  2498                              <1> ; 24/12/2021
  2499                              <1> ; ('swap_out' procedure call is disabled)
  2500                              <1> 
  2501                              <1> out_of_memory:
  2502                              <1> ;	call	swap_out
  2503                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2504                              <1> ;	;
  2505                              <1> ;	sub 	eax, eax ; 0
  2506 00002508 F9                  <1> 	stc
  2507 00002509 C3                  <1> 	retn
  2508                              <1> 
  2509                              <1> al_p_found:
  2510 0000250A 89D9                <1> 	mov	ecx, ebx
  2511 0000250C 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2512 00002512 890D[44620000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2513                              <1> 				 ; address/offset (to the next)
  2514 00002518 FF0D[40620000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2515                              <1> 	;
  2516 0000251E 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2517                              <1> 				 ; is copied into the Carry Flag and then cleared
  2518                              <1> 				 ; in the destination.
  2519                              <1> 				 ;
  2520                              <1> 				 ; Reset the bit which is corresponding to the 
  2521                              <1> 				 ; (just) allocated page.
  2522                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2523 00002521 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2524 00002524 01C8                <1> 	add	eax, ecx	 ; = page number
  2525 00002526 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2526                              <1> 	; EAX = physical address of memory page
  2527                              <1> 	;
  2528                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2529                              <1> 	;       according to this EAX value...
  2530 00002529 59                  <1> 	pop	ecx
  2531 0000252A 5B                  <1> 	pop	ebx
  2532                              <1> al_p_ok:
  2533 0000252B C3                  <1> 	retn
  2534                              <1> 
  2535                              <1> make_page_dir:
  2536                              <1> 	; 18/04/2015
  2537                              <1> 	; 12/04/2015
  2538                              <1> 	; 23/10/2014
  2539                              <1> 	; 16/10/2014
  2540                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2541                              <1> 	;
  2542                              <1> 	; INPUT ->
  2543                              <1> 	;	none
  2544                              <1> 	; OUTPUT ->
  2545                              <1> 	;	(EAX = 0)
  2546                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2547                              <1> 	;	cf = 0 ->
  2548                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2549                              <1> 	;		  process/user.
  2550                              <1> 	;
  2551                              <1> 	; Modified Registers -> EAX
  2552                              <1> 	;
  2553 0000252C E896FFFFFF          <1> 	call	allocate_page
  2554 00002531 7216                <1> 	jc	short mkpd_error
  2555                              <1> 	;
  2556 00002533 A3[55660000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2557                              <1> 				  ; (Physical address)
  2558                              <1> clear_page:
  2559                              <1> 	; 18/04/2015
  2560                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2561                              <1> 	;
  2562                              <1> 	; INPUT ->
  2563                              <1> 	;	EAX = physical address of the page
  2564                              <1> 	; OUTPUT ->
  2565                              <1> 	;	all bytes of the page will be cleared
  2566                              <1> 	;
  2567                              <1> 	; Modified Registers -> none
  2568                              <1> 	;
  2569 00002538 57                  <1> 	push	edi
  2570 00002539 51                  <1> 	push	ecx
  2571 0000253A 50                  <1> 	push	eax
  2572 0000253B B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2573 00002540 89C7                <1> 	mov	edi, eax
  2574 00002542 31C0                <1> 	xor	eax, eax
  2575 00002544 F3AB                <1> 	rep	stosd
  2576 00002546 58                  <1> 	pop	eax
  2577 00002547 59                  <1> 	pop	ecx
  2578 00002548 5F                  <1> 	pop	edi
  2579                              <1> mkpd_error:
  2580                              <1> mkpt_error:
  2581 00002549 C3                  <1> 	retn
  2582                              <1> 
  2583                              <1> make_page_table:
  2584                              <1> 	; 23/06/2015
  2585                              <1> 	; 18/04/2015
  2586                              <1> 	; 12/04/2015
  2587                              <1> 	; 16/10/2014
  2588                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2589                              <1> 	;
  2590                              <1> 	; INPUT ->
  2591                              <1> 	;	EBX = virtual (linear) address
  2592                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2593                              <1> 	;	      (higher 20 bits must be ZERO)
  2594                              <1> 	;	      (bit 0 must be 1)	 
  2595                              <1> 	;	u.pgdir = page directory (physical) address
  2596                              <1> 	; OUTPUT ->
  2597                              <1> 	;	EDX = Page directory entry address
  2598                              <1> 	;	EAX = Page table address
  2599                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2600                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2601                              <1> 	;
  2602                              <1> 	; Modified Registers -> EAX, EDX
  2603                              <1> 	;
  2604 0000254A E878FFFFFF          <1> 	call	allocate_page
  2605 0000254F 72F8                <1> 	jc	short mkpt_error
  2606 00002551 E811000000          <1> 	call	set_pde	
  2607 00002556 EBE0                <1> 	jmp	short clear_page
  2608                              <1> 
  2609                              <1> make_page:
  2610                              <1> 	; 24/07/2015
  2611                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2612                              <1> 	;
  2613                              <1> 	; INPUT ->
  2614                              <1> 	;	EBX = virtual (linear) address
  2615                              <1> 	;	ECX = page attributes (lower 12 bits)
  2616                              <1> 	;	      (higher 20 bits must be ZERO)
  2617                              <1> 	;	      (bit 0 must be 1)	 
  2618                              <1> 	;	u.pgdir = page directory (physical) address
  2619                              <1> 	; OUTPUT ->
  2620                              <1> 	;	EBX = Virtual address
  2621                              <1> 	;	(EDX = PTE value)
  2622                              <1> 	;	EAX = Physical address
  2623                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2624                              <1> 	;
  2625                              <1> 	; Modified Registers -> EAX, EDX
  2626                              <1> 	;
  2627 00002558 E86AFFFFFF          <1> 	call	allocate_page
  2628 0000255D 7207                <1> 	jc	short mkp_err
  2629 0000255F E821000000          <1> 	call	set_pte	
  2630 00002564 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2631                              <1> mkp_err:
  2632 00002566 C3                  <1> 	retn
  2633                              <1> 
  2634                              <1> set_pde:	; Set page directory entry (PDE)
  2635                              <1> 	; 20/07/2015
  2636                              <1> 	; 18/04/2015
  2637                              <1> 	; 12/04/2015
  2638                              <1> 	; 23/10/2014
  2639                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2640                              <1> 	;
  2641                              <1> 	; INPUT ->
  2642                              <1> 	;	EAX = physical address
  2643                              <1> 	;	      (use present value if EAX = 0)
  2644                              <1> 	;	EBX = virtual (linear) address
  2645                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2646                              <1> 	;	      (higher 20 bits must be ZERO)
  2647                              <1> 	;	      (bit 0 must be 1)	 
  2648                              <1> 	;	u.pgdir = page directory (physical) address
  2649                              <1> 	; OUTPUT ->
  2650                              <1> 	;	EDX = PDE address
  2651                              <1> 	;	EAX = page table address (physical)
  2652                              <1> 	;	;(CF=1 -> Invalid page address)
  2653                              <1> 	;
  2654                              <1> 	; Modified Registers -> EDX
  2655                              <1> 	;
  2656 00002567 89DA                <1> 	mov	edx, ebx
  2657 00002569 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2658 0000256C C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2659 0000256F 0315[55660000]      <1> 	add	edx, [u.pgdir]
  2660                              <1> 	;
  2661 00002575 21C0                <1> 	and	eax, eax
  2662 00002577 7506                <1> 	jnz	short spde_1
  2663                              <1> 	;
  2664 00002579 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2665                              <1> 	;test	al, 1
  2666                              <1> 	;jz	short spde_2
  2667 0000257B 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2668                              <1> spde_1:
  2669                              <1> 	;and	cx, 0FFFh
  2670 0000257F 8902                <1> 	mov	[edx], eax
  2671 00002581 66090A              <1> 	or	[edx], cx
  2672 00002584 C3                  <1> 	retn
  2673                              <1> ;spde_2: ; error
  2674                              <1> ;	stc
  2675                              <1> ;	retn
  2676                              <1> 
  2677                              <1> set_pte:	; Set page table entry (PTE)
  2678                              <1> 	; 24/07/2015
  2679                              <1> 	; 20/07/2015
  2680                              <1> 	; 23/06/2015
  2681                              <1> 	; 18/04/2015
  2682                              <1> 	; 12/04/2015
  2683                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2684                              <1> 	;
  2685                              <1> 	; INPUT ->
  2686                              <1> 	;	EAX = physical page address
  2687                              <1> 	;	      (use present value if EAX = 0)
  2688                              <1> 	;	EBX = virtual (linear) address
  2689                              <1> 	;	ECX = page attributes (lower 12 bits)
  2690                              <1> 	;	      (higher 20 bits must be ZERO)
  2691                              <1> 	;	      (bit 0 must be 1)	 
  2692                              <1> 	;	u.pgdir = page directory (physical) address
  2693                              <1> 	; OUTPUT ->
  2694                              <1> 	;	EAX = physical page address
  2695                              <1> 	;	(EDX = PTE value)
  2696                              <1> 	;	EBX = virtual address
  2697                              <1> 	;
  2698                              <1> 	;	CF = 1 -> error
  2699                              <1> 	;
  2700                              <1> 	; Modified Registers -> EAX, EDX
  2701                              <1> 	;
  2702 00002585 50                  <1> 	push	eax
  2703 00002586 A1[55660000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2704 0000258B E837000000          <1> 	call 	get_pde
  2705                              <1> 		; EDX = PDE address
  2706                              <1> 		; EAX = PDE value
  2707 00002590 5A                  <1> 	pop	edx ; physical page address
  2708 00002591 722A                <1> 	jc	short spte_err ; PDE not present
  2709                              <1> 	;
  2710 00002593 53                  <1> 	push	ebx ; 24/07/2015
  2711 00002594 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2712                              <1> 			    ; EDX = PT address (physical)	
  2713 00002598 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2714 0000259B 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2715                              <1> 			 ; clear higher 10 bits (PD bits)
  2716 000025A1 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2717 000025A4 01C3                <1> 	add	ebx, eax
  2718                              <1> 	;
  2719 000025A6 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2720 000025A8 A801                <1> 	test	al, 1
  2721 000025AA 740C                <1> 	jz	short spte_0
  2722 000025AC 09D2                <1> 	or	edx, edx
  2723 000025AE 750F                <1> 	jnz	short spte_1
  2724 000025B0 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2725 000025B4 89C2                <1> 	mov	edx, eax
  2726 000025B6 EB09                <1> 	jmp	short spte_2	
  2727                              <1> spte_0:
  2728                              <1> 	; If this PTE contains a swap (disk) address,
  2729                              <1> 	; it can be updated by using 'swap_in' procedure
  2730                              <1> 	; only!
  2731 000025B8 21C0                <1> 	and	eax, eax
  2732 000025BA 7403                <1> 	jz	short spte_1
  2733                              <1> 	; 24/07/2015
  2734                              <1> 	; swapped page ! (on disk)
  2735 000025BC 5B                  <1> 	pop	ebx
  2736                              <1> spte_err:
  2737 000025BD F9                  <1> 	stc
  2738 000025BE C3                  <1> 	retn
  2739                              <1> spte_1: 
  2740 000025BF 89D0                <1> 	mov	eax, edx
  2741                              <1> spte_2:
  2742 000025C1 09CA                <1> 	or	edx, ecx
  2743                              <1> 	; 23/06/2015
  2744 000025C3 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2745                              <1> 	; 24/07/2015
  2746 000025C5 5B                  <1> 	pop	ebx
  2747 000025C6 C3                  <1> 	retn
  2748                              <1> 
  2749                              <1> get_pde:	; Get present value of the relevant PDE
  2750                              <1> 	; 20/07/2015
  2751                              <1> 	; 18/04/2015
  2752                              <1> 	; 12/04/2015
  2753                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2754                              <1> 	;
  2755                              <1> 	; INPUT ->
  2756                              <1> 	;	EBX = virtual (linear) address
  2757                              <1> 	;	EAX = page directory (physical) address
  2758                              <1> 	; OUTPUT ->
  2759                              <1> 	;	EDX = Page directory entry address
  2760                              <1> 	;	EAX = Page directory entry value
  2761                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2762                              <1> 	; Modified Registers -> EDX, EAX
  2763                              <1> 	;
  2764 000025C7 89DA                <1> 	mov	edx, ebx
  2765 000025C9 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2766 000025CC C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2767 000025CF 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2768 000025D1 8B02                <1> 	mov	eax, [edx]
  2769 000025D3 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2770 000025D5 751F                <1> 	jnz	short gpte_retn
  2771 000025D7 F9                  <1> 	stc
  2772                              <1> gpde_retn:	
  2773 000025D8 C3                  <1> 	retn
  2774                              <1> 
  2775                              <1> get_pte:
  2776                              <1> 		; Get present value of the relevant PTE
  2777                              <1> 	; 29/07/2015
  2778                              <1> 	; 20/07/2015
  2779                              <1> 	; 18/04/2015
  2780                              <1> 	; 12/04/2015
  2781                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2782                              <1> 	;
  2783                              <1> 	; INPUT ->
  2784                              <1> 	;	EBX = virtual (linear) address
  2785                              <1> 	;	EAX = page directory (physical) address
  2786                              <1> 	; OUTPUT ->
  2787                              <1> 	;	EDX = Page table entry address (if CF=0)
  2788                              <1> 	;	      Page directory entry address (if CF=1)
  2789                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2790                              <1> 	;	EAX = Page table entry value (page address)
  2791                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2792                              <1> 	; Modified Registers -> EAX, EDX
  2793                              <1> 	;
  2794 000025D9 E8E9FFFFFF          <1> 	call 	get_pde
  2795 000025DE 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2796                              <1> 	;jnc	short gpte_1
  2797                              <1> 	;retn
  2798                              <1> ;gpte_1:
  2799 000025E0 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2800 000025E4 89DA                <1> 	mov	edx, ebx
  2801 000025E6 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2802 000025E9 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2803                              <1> 			 ; clear higher 10 bits (PD bits)
  2804 000025EF C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2805 000025F2 01C2                <1> 	add	edx, eax
  2806 000025F4 8B02                <1> 	mov	eax, [edx]
  2807                              <1> gpte_retn:
  2808 000025F6 C3                  <1> 	retn
  2809                              <1> 
  2810                              <1> deallocate_page_dir:
  2811                              <1> 	; 15/09/2015
  2812                              <1> 	; 05/08/2015
  2813                              <1> 	; 30/04/2015
  2814                              <1> 	; 28/04/2015
  2815                              <1> 	; 17/10/2014
  2816                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2817                              <1> 	;
  2818                              <1> 	; INPUT ->
  2819                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2820                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2821                              <1> 	; OUTPUT ->
  2822                              <1> 	;	All of page tables in the page directory
  2823                              <1> 	;	and page dir's itself will be deallocated
  2824                              <1> 	;	except 'read only' duplicated pages (will be converted
  2825                              <1> 	;	to writable pages).
  2826                              <1> 	;
  2827                              <1> 	; Modified Registers -> EAX
  2828                              <1> 	;
  2829                              <1> 	;
  2830 000025F7 56                  <1> 	push	esi
  2831 000025F8 51                  <1> 	push	ecx
  2832 000025F9 50                  <1> 	push	eax
  2833 000025FA 89C6                <1> 	mov	esi, eax 
  2834 000025FC 31C9                <1> 	xor	ecx, ecx
  2835                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2836                              <1> 	; it must not be deallocated
  2837 000025FE 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2838                              <1> dapd_0:
  2839 00002600 AD                  <1> 	lodsd
  2840 00002601 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2841 00002603 7409                <1> 	jz	short dapd_1	
  2842 00002605 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2843 00002609 E812000000          <1> 	call	deallocate_page_table			
  2844                              <1> dapd_1:
  2845 0000260E 41                  <1> 	inc	ecx ; page directory entry index
  2846 0000260F 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2847 00002615 72E9                <1> 	jb	short dapd_0
  2848                              <1> dapd_2:
  2849 00002617 58                  <1> 	pop	eax
  2850 00002618 E870000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2851 0000261D 59                  <1> 	pop	ecx
  2852 0000261E 5E                  <1> 	pop	esi
  2853 0000261F C3                  <1> 	retn
  2854                              <1> 
  2855                              <1> deallocate_page_table:
  2856                              <1> 	; 17/07/2022
  2857                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2858                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2859                              <1> 	; 19/09/2015
  2860                              <1> 	; 15/09/2015
  2861                              <1> 	; 05/08/2015
  2862                              <1> 	; 30/04/2015
  2863                              <1> 	; 28/04/2015
  2864                              <1> 	; 24/10/2014
  2865                              <1> 	; 23/10/2014
  2866                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2867                              <1> 	;
  2868                              <1> 	; INPUT ->
  2869                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2870                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2871                              <1> 	;	(ECX = page directory entry index)
  2872                              <1> 	; OUTPUT ->
  2873                              <1> 	;	All of pages in the page table and page table's itself
  2874                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2875                              <1> 	;	(will be converted to writable pages).
  2876                              <1> 	;
  2877                              <1> 	; Modified Registers -> EAX
  2878                              <1> 	;
  2879 00002620 56                  <1> 	push	esi
  2880 00002621 57                  <1> 	push	edi
  2881 00002622 52                  <1> 	push	edx
  2882 00002623 50                  <1> 	push	eax ; *
  2883 00002624 89C6                <1> 	mov	esi, eax 
  2884 00002626 31FF                <1> 	xor	edi, edi ; 0
  2885                              <1> dapt_0:
  2886 00002628 AD                  <1> 	lodsd
  2887 00002629 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2888 0000262B 7453                <1> 	jz	short dapt_1
  2889                              <1> 	;
  2890 0000262D A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2891                              <1> 				  ; (must be 1)
  2892 0000262F 753D                <1> 	jnz	short dapt_3
  2893                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2894 00002631 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2895                              <1> 				   ; as child's page ?
  2896 00002635 7442                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2897                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2898                              <1> 	; ECX = page directory entry index (0-1023)
  2899 00002637 53                  <1> 	push	ebx
  2900 00002638 51                  <1> 	push	ecx
  2901                              <1> 	;shl	cx, 2 ; *4 
  2902                              <1> 	; 17/07/2022
  2903 00002639 C1E102              <1> 	shl	ecx, 2
  2904 0000263C 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2905 0000263E 8B0B                <1> 	mov	ecx, [ebx]
  2906 00002640 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2907 00002643 7427                <1> 	jz	short dapt_2	; parent process does not use this page
  2908 00002645 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2909                              <1> 	; EDI = page table entry index (0-1023)
  2910 0000264A 89FA                <1> 	mov	edx, edi 
  2911                              <1> 	;shl	dx, 2 ; *4
  2912                              <1> 	; 17/07/2022
  2913 0000264C C1E202              <1> 	shl	edx, 2
  2914 0000264F 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2915 00002651 8B1A                <1> 	mov	ebx, [edx]
  2916 00002653 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2917 00002656 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2918 00002658 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2919 0000265C 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2920 00002661 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2921 00002663 7507                <1> 	jne	short dapt_2	; not same page
  2922                              <1> 				; deallocate the child's page
  2923 00002665 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2924 00002668 59                  <1> 	pop	ecx
  2925 00002669 5B                  <1> 	pop	ebx
  2926 0000266A EB0D                <1> 	jmp	short dapt_4
  2927                              <1> 
  2928                              <1> ; 24/12/2021
  2929                              <1> ; ('dapt_1' is disabled)
  2930                              <1> ;
  2931                              <1> ;dapt_1:
  2932                              <1> ;	or	eax, eax	; swapped page ?
  2933                              <1> ;	jz	short dapt_5	; no
  2934                              <1> ;				; yes
  2935                              <1> ;	shr	eax, 1
  2936                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2937                              <1> ;				  ; on the swap disk (or in file)
  2938                              <1> ;	jmp	short dapt_5
  2939                              <1> dapt_2:
  2940 0000266C 59                  <1> 	pop	ecx
  2941 0000266D 5B                  <1> 	pop	ebx
  2942                              <1> dapt_3:	
  2943                              <1> 	; 12/07/2016
  2944 0000266E 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2945 00002672 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2946                              <1> 	;
  2947                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2948 00002674 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2949                              <1> dapt_4:
  2950 00002679 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2951                              <1> dapt_1:	; 24/12/2021
  2952                              <1> dapt_5:
  2953 00002680 47                  <1> 	inc	edi ; page table entry index
  2954 00002681 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2955 00002687 729F                <1> 	jb	short dapt_0
  2956                              <1> 	;
  2957 00002689 58                  <1> 	pop	eax ; *
  2958 0000268A 5A                  <1> 	pop	edx
  2959 0000268B 5F                  <1> 	pop	edi	
  2960 0000268C 5E                  <1> 	pop	esi
  2961                              <1> 	;
  2962                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2963                              <1> 	;retn
  2964                              <1> 
  2965                              <1> deallocate_page:
  2966                              <1> 	; 15/09/2015
  2967                              <1> 	; 28/04/2015
  2968                              <1> 	; 10/03/2015
  2969                              <1> 	; 17/10/2014
  2970                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2971                              <1> 	;
  2972                              <1> 	; INPUT -> 
  2973                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2974                              <1> 	; OUTPUT ->
  2975                              <1> 	;	[free_pages] is increased
  2976                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2977                              <1> 	;	CF = 1 if the page is already deallocated
  2978                              <1> 	; 	       (or not allocated) before.  
  2979                              <1> 	;
  2980                              <1> 	; Modified Registers -> EAX
  2981                              <1> 	;
  2982 0000268D 53                  <1> 	push	ebx
  2983 0000268E 52                  <1> 	push	edx
  2984                              <1> 	;
  2985 0000268F C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2986                              <1> 				     ; 12 bits right
  2987                              <1> 				     ; to get page number
  2988 00002692 89C2                <1> 	mov	edx, eax
  2989                              <1> 	; 15/09/2015
  2990 00002694 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2991                              <1> 				     ; (1 allocation bit = 1 page)
  2992                              <1> 				     ; (1 allocation bytes = 8 pages)
  2993 00002697 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2994                              <1> 				     ; (to get 32 bit position)			
  2995                              <1> 	;
  2996 0000269A BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2997 0000269F 01D3                <1> 	add	ebx, edx
  2998 000026A1 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2999                              <1> 				     ; (allocation bit position)	 
  3000 000026A4 3B15[44620000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  3001                              <1> 				     ; than the address in 'next_page' ?
  3002                              <1> 				     ; (next/first free page value)		
  3003 000026AA 7306                <1> 	jnb	short dap_1	     ; no	
  3004 000026AC 8915[44620000]      <1> 	mov	[next_page], edx     ; yes
  3005                              <1> dap_1:
  3006 000026B2 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  3007                              <1> 				     ; set relevant bit to 1.
  3008                              <1> 				     ; set CF to the previous bit value	
  3009                              <1> 	;cmc			     ; complement carry flag	
  3010                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  3011                              <1> 				     ; if the page is already deallocated
  3012                              <1> 				     ; before.	
  3013 000026B5 FF05[40620000]      <1>         inc     dword [free_pages]
  3014                              <1> dap_2:
  3015 000026BB 5A                  <1> 	pop	edx
  3016 000026BC 5B                  <1> 	pop	ebx
  3017 000026BD C3                  <1> 	retn
  3018                              <1> 
  3019                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3020                              <1> ;;                                                              ;;
  3021                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  3022                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  3023                              <1> ;;                                                              ;;
  3024                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3025                              <1> 
  3026                              <1> ;;$Revision: 5057 $
  3027                              <1> 
  3028                              <1> 
  3029                              <1> ;;align 4
  3030                              <1> ;;proc alloc_page
  3031                              <1> 
  3032                              <1> ;;        pushfd
  3033                              <1> ;;        cli
  3034                              <1> ;;        push    ebx
  3035                              <1> ;;;//-
  3036                              <1> ;;        cmp     [pg_data.pages_free], 1
  3037                              <1> ;;        jle     .out_of_memory
  3038                              <1> ;;;//-
  3039                              <1> ;;
  3040                              <1> ;;        mov     ebx, [page_start]
  3041                              <1> ;;        mov     ecx, [page_end]
  3042                              <1> ;;.l1:
  3043                              <1> ;;        bsf     eax, [ebx];
  3044                              <1> ;;        jnz     .found
  3045                              <1> ;;        add     ebx, 4
  3046                              <1> ;;        cmp     ebx, ecx
  3047                              <1> ;;        jb      .l1
  3048                              <1> ;;        pop     ebx
  3049                              <1> ;;        popfd
  3050                              <1> ;;        xor     eax, eax
  3051                              <1> ;;        ret
  3052                              <1> ;;.found:
  3053                              <1> ;;;//-
  3054                              <1> ;;        dec     [pg_data.pages_free]
  3055                              <1> ;;        jz      .out_of_memory
  3056                              <1> ;;;//-
  3057                              <1> ;;        btr     [ebx], eax
  3058                              <1> ;;        mov     [page_start], ebx
  3059                              <1> ;;        sub     ebx, sys_pgmap
  3060                              <1> ;;        lea     eax, [eax+ebx*8]
  3061                              <1> ;;        shl     eax, 12
  3062                              <1> ;;;//-       dec [pg_data.pages_free]
  3063                              <1> ;;        pop     ebx
  3064                              <1> ;;        popfd
  3065                              <1> ;;        ret
  3066                              <1> ;;;//-
  3067                              <1> ;;.out_of_memory:
  3068                              <1> ;;        mov     [pg_data.pages_free], 1
  3069                              <1> ;;        xor     eax, eax
  3070                              <1> ;;        pop     ebx
  3071                              <1> ;;        popfd
  3072                              <1> ;;        ret
  3073                              <1> ;;;//-
  3074                              <1> ;;endp
  3075                              <1> 
  3076                              <1> duplicate_page_dir:
  3077                              <1> 	; 21/09/2015
  3078                              <1> 	; 31/08/2015
  3079                              <1> 	; 20/07/2015
  3080                              <1> 	; 28/04/2015
  3081                              <1> 	; 27/04/2015
  3082                              <1> 	; 18/04/2015
  3083                              <1> 	; 12/04/2015
  3084                              <1> 	; 18/10/2014
  3085                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3086                              <1> 	;
  3087                              <1> 	; INPUT -> 
  3088                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3089                              <1> 	;		    page directory.
  3090                              <1> 	; OUTPUT ->
  3091                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3092                              <1> 	;	       page directory.
  3093                              <1> 	;	(New page directory with new page table entries.)
  3094                              <1> 	;	(New page tables with read only copies of the parent's
  3095                              <1> 	;	pages.)
  3096                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3097                              <1> 	;
  3098                              <1> 	; Modified Registers -> none (except EAX)
  3099                              <1> 	;
  3100 000026BE E804FEFFFF          <1> 	call	allocate_page
  3101 000026C3 723E                <1> 	jc	short dpd_err
  3102                              <1> 	;
  3103 000026C5 55                  <1> 	push	ebp ; 20/07/2015
  3104 000026C6 56                  <1> 	push	esi
  3105 000026C7 57                  <1> 	push	edi
  3106 000026C8 53                  <1> 	push	ebx
  3107 000026C9 51                  <1> 	push	ecx
  3108 000026CA 8B35[55660000]      <1> 	mov	esi, [u.pgdir]
  3109 000026D0 89C7                <1> 	mov	edi, eax
  3110 000026D2 50                  <1> 	push	eax ; save child's page directory address
  3111                              <1> 	; 31/08/2015
  3112                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3113                              <1> 	; (use same system space for all user page tables) 
  3114 000026D3 A5                  <1> 	movsd
  3115 000026D4 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3116 000026D9 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3117                              <1> dpd_0:	
  3118 000026DE AD                  <1> 	lodsd
  3119                              <1> 	;or	eax, eax
  3120                              <1>         ;jnz     short dpd_1
  3121 000026DF A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3122 000026E1 7508                <1> 	jnz	short dpd_1
  3123                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3124 000026E3 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3125 000026E9 EB0F                <1> 	jmp	short dpd_2
  3126                              <1> dpd_1:	
  3127 000026EB 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3128 000026EF 89C3                <1> 	mov	ebx, eax
  3129                              <1> 	; EBX = Parent's page table address
  3130 000026F1 E81F000000          <1> 	call	duplicate_page_table
  3131 000026F6 720C                <1> 	jc	short dpd_p_err
  3132                              <1> 	; EAX = Child's page table address
  3133 000026F8 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3134                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3135                              <1> 			 ; (present, writable, user)
  3136                              <1> dpd_2:
  3137 000026FA AB                  <1> 	stosd
  3138 000026FB E2E1                <1> 	loop	dpd_0
  3139                              <1> 	;
  3140 000026FD 58                  <1> 	pop	eax  ; restore child's page directory address
  3141                              <1> dpd_3:
  3142 000026FE 59                  <1> 	pop	ecx
  3143 000026FF 5B                  <1> 	pop	ebx
  3144 00002700 5F                  <1> 	pop	edi
  3145 00002701 5E                  <1> 	pop	esi
  3146 00002702 5D                  <1> 	pop	ebp ; 20/07/2015
  3147                              <1> dpd_err:
  3148 00002703 C3                  <1> 	retn
  3149                              <1> dpd_p_err:
  3150                              <1> 	; release the allocated pages missing (recover free space)
  3151 00002704 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3152 00002705 8B1D[55660000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3153 0000270B E8E7FEFFFF          <1> 	call 	deallocate_page_dir
  3154 00002710 29C0                <1> 	sub	eax, eax ; 0
  3155 00002712 F9                  <1> 	stc
  3156 00002713 EBE9                <1> 	jmp	short dpd_3	
  3157                              <1> 
  3158                              <1> duplicate_page_table:
  3159                              <1> 	; 31/12/2021
  3160                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3161                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3162                              <1> 	; 21/09/2015
  3163                              <1> 	; 20/07/2015
  3164                              <1> 	; 05/05/2015
  3165                              <1> 	; 28/04/2015
  3166                              <1> 	; 27/04/2015
  3167                              <1> 	; 18/04/2015
  3168                              <1> 	; 18/10/2014
  3169                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3170                              <1> 	;
  3171                              <1> 	; INPUT -> 
  3172                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3173                              <1> 	;       20/02/2017		 
  3174                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3175                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3176                              <1> 	; OUTPUT ->
  3177                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3178                              <1> 	;	      (with 'read only' attribute of page table entries)
  3179                              <1> 	;	20/02/2017
  3180                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3181                              <1> 	;	
  3182                              <1> 	;	CF = 1 -> error 
  3183                              <1> 	;
  3184                              <1> 	; Modified Registers -> EBP (except EAX)
  3185                              <1> 	;
  3186 00002715 E8ADFDFFFF          <1> 	call	allocate_page
  3187 0000271A 725B                <1> 	jc	short dpt_err
  3188                              <1> 	;
  3189 0000271C 50                  <1> 	push	eax ; *
  3190 0000271D 56                  <1> 	push	esi
  3191 0000271E 57                  <1> 	push	edi
  3192 0000271F 52                  <1> 	push	edx
  3193 00002720 51                  <1> 	push	ecx
  3194                              <1> 	;
  3195 00002721 89DE                <1> 	mov	esi, ebx
  3196 00002723 89C7                <1> 	mov	edi, eax
  3197 00002725 89C2                <1> 	mov	edx, eax
  3198 00002727 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3199                              <1> dpt_0:
  3200 0000272D AD                  <1> 	lodsd
  3201 0000272E 21C0                <1> 	and	eax, eax
  3202 00002730 7435                <1> 	jz	short dpt_3
  3203 00002732 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3204                              <1> 	; 24/12/2021
  3205 00002734 7503                <1> 	jnz	short dpt_1
  3206                              <1> 	;jz	short dpt_p_err
  3207                              <1> 	; 31/12/2021
  3208 00002736 F9                  <1> 	stc
  3209 00002737 EB39                <1> 	jmp	short dpt_p_err
  3210                              <1> 
  3211                              <1> ; 24/12/2021
  3212                              <1> ; ('reload_page' procedure call is disabled)
  3213                              <1> ;
  3214                              <1> ;	; 20/07/2015
  3215                              <1> ;	; ebp = virtual (linear) address of the memory page
  3216                              <1> ;	call	reload_page ; 28/04/2015
  3217                              <1> ;	jc	short dpt_p_err
  3218                              <1> dpt_1:
  3219                              <1> 	; 21/09/2015
  3220 00002739 89C1                <1> 	mov	ecx, eax
  3221 0000273B 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3222 0000273F F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3223 00002742 751A                <1> 	jnz	short dpt_2
  3224                              <1> 	; Read only (parent) page
  3225                              <1> 	; 	- there is a third process which uses this page -
  3226                              <1> 	; Allocate a new page for the child process
  3227 00002744 E87EFDFFFF          <1> 	call	allocate_page
  3228 00002749 7227                <1> 	jc	short dpt_p_err
  3229 0000274B 57                  <1> 	push	edi
  3230 0000274C 56                  <1> 	push	esi
  3231 0000274D 89CE                <1> 	mov	esi, ecx
  3232 0000274F 89C7                <1> 	mov	edi, eax
  3233 00002751 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3234 00002756 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3235 00002758 5E                  <1> 	pop	esi
  3236 00002759 5F                  <1> 	pop	edi
  3237                              <1> 	;
  3238                              <1> 
  3239                              <1> ; 24/12/2021
  3240                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3241                              <1> ; 
  3242                              <1> ;	push	ebx
  3243                              <1> ;	push	eax
  3244                              <1> ;	; 20/07/2015
  3245                              <1> ;	mov	ebx, ebp
  3246                              <1> ;	; ebx = virtual (linear) address of the memory page
  3247                              <1> ;	call	add_to_swap_queue
  3248                              <1> ;	pop	eax
  3249                              <1> ;	pop	ebx
  3250                              <1> 
  3251                              <1> 	; 21/09/2015
  3252 0000275A 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3253                              <1> 		; user + writable + present page
  3254 0000275C EB09                <1> 	jmp	short dpt_3
  3255                              <1> dpt_2:
  3256                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3257 0000275E 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3258                              <1> 		    ; (read only page!)
  3259 00002760 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3260 00002763 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3261                              <1> dpt_3:
  3262 00002767 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3263                              <1> 	;
  3264 00002768 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3265                              <1> 	;
  3266 0000276E 39D7                <1> 	cmp	edi, edx
  3267 00002770 72BB                <1> 	jb	short dpt_0
  3268                              <1> dpt_p_err:
  3269 00002772 59                  <1> 	pop	ecx
  3270 00002773 5A                  <1> 	pop	edx
  3271 00002774 5F                  <1> 	pop	edi
  3272 00002775 5E                  <1> 	pop	esi
  3273 00002776 58                  <1> 	pop	eax ; *
  3274                              <1> dpt_err:
  3275 00002777 C3                  <1> 	retn
  3276                              <1> 
  3277                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3278                              <1> 	; 31/12/2021
  3279                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3280                              <1> 	; 21/09/2015
  3281                              <1> 	; 19/09/2015
  3282                              <1> 	; 17/09/2015
  3283                              <1> 	; 28/08/2015
  3284                              <1> 	; 20/07/2015
  3285                              <1> 	; 28/06/2015
  3286                              <1> 	; 03/05/2015
  3287                              <1> 	; 30/04/2015
  3288                              <1> 	; 18/04/2015
  3289                              <1> 	; 12/04/2015
  3290                              <1> 	; 30/10/2014
  3291                              <1> 	; 11/09/2014
  3292                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3293                              <1> 	;
  3294                              <1> 	; Note: This is not an interrupt/exception handler.
  3295                              <1> 	;	This is a 'page fault remedy' subroutine 
  3296                              <1> 	;	which will be called by standard/uniform
  3297                              <1> 	;	exception handler.
  3298                              <1> 	;
  3299                              <1> 	; INPUT -> 
  3300                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3301                              <1> 	;
  3302                              <1> 	;	cr2 = the virtual (linear) address 
  3303                              <1> 	;	      which has caused to page fault (19/09/2015)
  3304                              <1> 	;
  3305                              <1> 	; OUTPUT ->
  3306                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3307                              <1> 	;	EAX = 0 -> no error
  3308                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3309                              <1> 	;
  3310                              <1> 	; Modified Registers -> none (except EAX)
  3311                              <1> 	;	
  3312                              <1>         ;
  3313                              <1>         ; ERROR CODE:
  3314                              <1> 	;	 31  .....	4   3	2   1	0
  3315                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3316                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3317                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3318                              <1> 	;
  3319                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3320                              <1>     	;		a page-protection violation. When not set,
  3321                              <1> 	;		it was caused by a non-present page.
  3322                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3323                              <1> 	;		a page write. When not set, it was caused
  3324                              <1> 	;		by a page read.
  3325                              <1> 	; U : USER    -	When set, the page fault was caused 
  3326                              <1> 	;		while CPL = 3. 
  3327                              <1> 	;		This does not necessarily mean that
  3328                              <1> 	;		the page fault was a privilege violation.
  3329                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3330                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3331                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3332                              <1> 	;     FETCH	an instruction fetch
  3333                              <1> 	;
  3334                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3335                              <1> 	;  31               22                  12 11                    0
  3336                              <1> 	; +-------------------+-------------------+-----------------------+
  3337                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3338                              <1>        	; +-------------------+-------------------+-----------------------+
  3339                              <1> 	;
  3340                              <1> 
  3341                              <1> 	;; CR3 REGISTER (Control Register 3)
  3342                              <1> 	;  31                                   12             5 4 3 2   0
  3343                              <1> 	; +---------------------------------------+-------------+---+-----+
  3344                              <1>       	; |                                       |  		|P|P|     |
  3345                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3346                              <1>       	; |                                       | 		|D|T|     |
  3347                              <1>    	; +---------------------------------------+-------------+---+-----+
  3348                              <1> 	;
  3349                              <1> 	;	PWT    - WRITE THROUGH
  3350                              <1> 	;	PCD    - CACHE DISABLE		
  3351                              <1> 	;
  3352                              <1> 	;
  3353                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3354                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3355                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3356                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3357                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3358                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3359                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3360                              <1> 	;
  3361                              <1>         ;       P      - PRESENT
  3362                              <1>         ;       R/W    - READ/WRITE
  3363                              <1>         ;       U/S    - USER/SUPERVISOR
  3364                              <1> 	;	PWT    - WRITE THROUGH
  3365                              <1> 	;	PCD    - CACHE DISABLE	
  3366                              <1> 	;	A      - ACCESSED	
  3367                              <1>         ;       D      - DIRTY (IGNORED)
  3368                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3369                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3370                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3371                              <1> 	;
  3372                              <1> 	;
  3373                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3374                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3375                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3376                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3377                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3378                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3379                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3380                              <1> 	;
  3381                              <1>         ;       P      - PRESENT
  3382                              <1>         ;       R/W    - READ/WRITE
  3383                              <1>         ;       U/S    - USER/SUPERVISOR
  3384                              <1> 	;	PWT    - WRITE THROUGH
  3385                              <1> 	;	PCD    - CACHE DISABLE	
  3386                              <1> 	;	A      - ACCESSED	
  3387                              <1>         ;       D      - DIRTY
  3388                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3389                              <1> 	;	G      - GLOBAL	 
  3390                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3391                              <1> 	;
  3392                              <1> 	;
  3393                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3394                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3395                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3396                              <1>       	; |                                       |     | | | | | | |U|R| |
  3397                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3398                              <1>       	; |                                       |     | | | | | | |S|W| |
  3399                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3400                              <1> 	;
  3401                              <1>         ;       P      - PRESENT
  3402                              <1>         ;       R/W    - READ/WRITE
  3403                              <1>         ;       U/S    - USER/SUPERVISOR
  3404                              <1>         ;       D      - DIRTY
  3405                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3406                              <1> 	;
  3407                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3408                              <1> 	;
  3409                              <1> 	;
  3410                              <1> 	;; Invalid Page Table Entry
  3411                              <1> 	; 31                                                           1 0
  3412                              <1>       	; +-------------------------------------------------------------+-+
  3413                              <1>       	; |                                                             | |
  3414                              <1>       	; |                          AVAILABLE                          |0|
  3415                              <1>       	; |                                                             | |
  3416                              <1>       	; +-------------------------------------------------------------+-+
  3417                              <1> 	;
  3418                              <1> 
  3419 00002778 53                  <1> 	push	ebx
  3420 00002779 52                  <1> 	push	edx
  3421 0000277A 51                  <1> 	push	ecx
  3422                              <1> 	;
  3423                              <1> 	; 21/09/2015 (debugging)
  3424 0000277B FF05[65660000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3425 00002781 FF05[EC620000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3426                              <1> 	; 28/06/2015
  3427                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3428 00002787 8A15[E4620000]      <1> 	mov	dl, [error_code]
  3429                              <1> 	;
  3430 0000278D F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3431                              <1> 			; sign
  3432 00002790 7425                <1> 	jz	short pfh_alloc_np
  3433                              <1> 	; 
  3434                              <1> 	; If it is not a 'write on read only page' type page fault
  3435                              <1> 	; major page fault error with minor reason must be returned without 
  3436                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3437                              <1> 	; after return here!
  3438                              <1> 	; Page fault will be remedied, by copying page contents
  3439                              <1> 	; to newly allocated page with write permission;
  3440                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3441                              <1> 	; used for working with minimum possible memory usage. 
  3442                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3443                              <1> 	; process with 'read only' flag. If the child process attempts to
  3444                              <1> 	; write on these read only pages, page fault will be directed here
  3445                              <1> 	; for allocating a new page with same data/content. 
  3446                              <1> 	;
  3447                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3448                              <1> 	; will not force to separate CODE and DATA space 
  3449                              <1> 	; in a process/program... 
  3450                              <1> 	; CODE segment/section may contain DATA!
  3451                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3452                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3453                              <1> 	;	
  3454 00002792 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3455                              <1> 			; sign
  3456 00002795 7418                <1>         jz      pfh_p_err
  3457                              <1> 	; 31/08/2015
  3458 00002797 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3459                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3460 0000279A 7413                <1>         jz	short pfh_pv_err
  3461                              <1> 	;
  3462                              <1> 	; make a new page and copy the parent's page content
  3463                              <1> 	; as the child's new page content
  3464                              <1> 	;
  3465 0000279C 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3466                              <1> 			 ; which has caused to page fault
  3467 0000279F E87C000000          <1> 	call 	copy_page
  3468 000027A4 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3469                              <1> 	;
  3470 000027A6 EB72                <1>         jmp     pfh_cpp_ok
  3471                              <1> 
  3472                              <1> 	; 31/12/2021 (short jump)
  3473                              <1> pfh_im_err:
  3474 000027A8 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3475                              <1> 			; Major (Primary) Error: Page Fault
  3476                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3477 000027AD EB6D                <1> 	jmp	short pfh_err_retn
  3478                              <1> 
  3479                              <1> 	; 31/12/2021
  3480                              <1> pfh_p_err: ; 09/03/2015
  3481                              <1> pfh_pv_err:
  3482                              <1> 	; Page fault was caused by a protection-violation
  3483 000027AF B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3484                              <1> 			; Major (Primary) Error: Page Fault
  3485                              <1> 			; Minor (Secondary) Error: Protection violation !
  3486 000027B4 F9                  <1> 	stc
  3487 000027B5 EB65                <1> 	jmp	short pfh_err_retn
  3488                              <1> 	
  3489                              <1> pfh_alloc_np:
  3490 000027B7 E80BFDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3491 000027BC 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3492                              <1> pfh_chk_cpl:
  3493                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3494                              <1> 		; (Lower 12 bits are ZERO, because 
  3495                              <1> 		;	the address is on a page boundary)
  3496 000027BE 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3497 000027C1 7505                <1> 	jnz	short pfh_um
  3498                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3499 000027C3 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3500                              <1> 			 ; of the current/active page directory
  3501                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3502                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3503 000027C6 EB06                <1> 	jmp	short pfh_get_pde
  3504                              <1> 	;
  3505                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3506 000027C8 8B1D[55660000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3507                              <1> 			; Physical address of the USER's page directory
  3508                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3509                              <1> pfh_get_pde:
  3510 000027CE 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3511 000027D1 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3512                              <1> 			 ; which has been caused to page fault
  3513                              <1> 			 ;
  3514 000027D4 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3515 000027D7 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3516                              <1> 	;
  3517 000027DA 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3518 000027DC 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3519 000027DE F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3520 000027E1 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3521                              <1> 			  	  ; set/validate page directory entry
  3522 000027E3 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3523 000027E8 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3524 000027EA 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3525 000027EC EB16                <1> 	jmp	short pfh_get_pte
  3526                              <1> pfh_set_pde:
  3527                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3528                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3529                              <1> 	;
  3530 000027EE 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3531 000027F0 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3532 000027F2 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3533 000027F4 89C3                <1> 	mov	ebx, eax
  3534 000027F6 E8CCFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3535 000027FB 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3536                              <1> pfh_spde_1:
  3537                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3538 000027FD 89C1                <1> 	mov	ecx, eax
  3539 000027FF E834FDFFFF          <1> 	call	clear_page ; Clear page content
  3540                              <1> pfh_get_pte:
  3541 00002804 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3542                              <1> 			 ; which has been caused to page fault
  3543 00002807 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3544 00002809 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3545                              <1> 			 ; higher 20 bits of the page fault address 
  3546 0000280C 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3547 00002811 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3548 00002814 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3549                              <1> ; 24/12/2021
  3550                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3551                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3552                              <1> ; 24/12/2021
  3553                              <1> ; ('swap_in' procedure call has been disabled)
  3554                              <1> ;
  3555                              <1> ;	and	eax, eax
  3556                              <1> ;	jz	short pfh_gpte_1
  3557                              <1> ;	; 20/07/2015
  3558                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3559                              <1> ;	push	ebp ; 20/07/2015
  3560                              <1> ;	mov	ebp, cr2
  3561                              <1> ;		; ECX = physical address of the page table entry
  3562                              <1> ;		; EBX = Memory page address (physical!)
  3563                              <1> ;		; EAX = Swap disk (offset) address
  3564                              <1> ;		; EBP = virtual address (page fault address)
  3565                              <1> ;	call	swap_in
  3566                              <1> ;	pop	ebp
  3567                              <1> ;	jc      short pfh_err_retn
  3568                              <1> ;	xchg	ecx, ebx
  3569                              <1> ;		; EBX = physical address of the page table entry
  3570                              <1> ;		; ECX = new page
  3571                              <1> pfh_gpte_1:
  3572 00002816 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3573 00002818 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3574                              <1> pfh_cpp_ok:
  3575                              <1> ; 24/12/2021
  3576                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3577                              <1> ;
  3578                              <1> ;	; 20/07/2015
  3579                              <1> ;	mov	ebx, cr2
  3580                              <1> ;	call 	add_to_swap_queue
  3581                              <1> 	;
  3582                              <1> 	; The new PTE (which contains the new page) will be added to 
  3583                              <1> 	; the swap queue, here. 
  3584                              <1> 	; (Later, if memory will become insufficient, 
  3585                              <1> 	; one page will be swapped out which is at the head of 
  3586                              <1> 	; the swap queue by using FIFO and access check methods.)
  3587                              <1> 	;
  3588 0000281A 31C0                <1> 	xor	eax, eax  ; 0
  3589                              <1> 	;
  3590                              <1> pfh_err_retn:
  3591 0000281C 59                  <1> 	pop	ecx
  3592 0000281D 5A                  <1> 	pop	edx
  3593 0000281E 5B                  <1> 	pop	ebx
  3594 0000281F C3                  <1> 	retn 
  3595                              <1> 	
  3596                              <1> copy_page:
  3597                              <1> 	; 17/07/2022
  3598                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3599                              <1> 	; 16/04/2021
  3600                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3601                              <1> 	; 22/09/2015
  3602                              <1> 	; 21/09/2015
  3603                              <1> 	; 19/09/2015
  3604                              <1> 	; 07/09/2015
  3605                              <1> 	; 31/08/2015
  3606                              <1> 	; 20/07/2015
  3607                              <1> 	; 05/05/2015
  3608                              <1> 	; 03/05/2015
  3609                              <1> 	; 18/04/2015
  3610                              <1> 	; 12/04/2015
  3611                              <1> 	; 30/10/2014
  3612                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3613                              <1> 	;
  3614                              <1> 	; INPUT -> 
  3615                              <1> 	;	EBX = Virtual (linear) address of source page
  3616                              <1> 	;	     (Page fault address)
  3617                              <1> 	; OUTPUT ->
  3618                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3619                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3620                              <1> 	;	EAX = 0 (CF = 1) 
  3621                              <1> 	;		if there is not a free page to be allocated
  3622                              <1> 	;	(page content of the source page will be copied
  3623                              <1> 	;	onto the target/new page) 	
  3624                              <1> 	;
  3625                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3626                              <1> 	;
  3627                              <1> 
  3628                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3629                              <1> 	; INPUT: 
  3630                              <1> 	;	EBX = Virtual (linear) address of source page
  3631                              <1> 	;	     (Page fault address)
  3632                              <1> 	; OUTPUT:
  3633                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3634                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3635                              <1> 	;	EAX = 0 (CF = 1) 
  3636                              <1> 	;		if there is not a free page to be allocated
  3637                              <1> 	;	(page content of the source page will be copied
  3638                              <1> 	;	onto the target/new page) 	
  3639                              <1> 	;
  3640                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3641                              <1> 	
  3642 00002820 56                  <1> 	push	esi ; *
  3643 00002821 57                  <1> 	push	edi ; **
  3644                              <1> 	; 16/04/2021
  3645                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3646                              <1> 	;push	ebx ; ***
  3647                              <1> 	;push	ecx ; ****
  3648 00002822 31F6                <1> 	xor 	esi, esi
  3649 00002824 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3650 00002827 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3651 00002829 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3652 0000282C 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3653 0000282F 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3654 00002831 031D[55660000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3655 00002837 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3656 00002839 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3657 0000283D 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3658 0000283F 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3659                              <1> 	;shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3660                              <1> 	; 17/07/2022
  3661 00002845 C1E302              <1> 	shl	ebx, 2
  3662 00002848 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3663                              <1> 	; 07/09/2015
  3664 0000284A 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3665                              <1> 				     ; read only page as a child process?)	
  3666 0000284F 7509                <1> 	jnz	short cpp_0 ; yes
  3667 00002851 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3668 00002853 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3669 00002858 EB31                <1> 	jmp	short cpp_1
  3670                              <1> cpp_0:
  3671 0000285A 89FE                <1> 	mov	esi, edi
  3672 0000285C 0335[59660000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3673 00002862 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3674 00002864 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3675 00002868 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3676 0000286A 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3677                              <1> 	;shl	si, 2	   ; shift 2 bits left to get PTE offset
  3678                              <1> 	; 17/07/2022
  3679 00002870 C1E602              <1> 	shl	esi, 2
  3680 00002873 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3681 00002875 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3682                              <1> 	; 21/09/2015
  3683 00002877 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3684 00002879 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3685                              <1> 	;
  3686 0000287D F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3687 00002880 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3688                              <1> 	;
  3689 00002882 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3690 00002887 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3691 00002889 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3692                              <1> 			    ; Convert child's page to writable page
  3693                              <1> cpp_1:
  3694 0000288B E837FCFFFF          <1> 	call	allocate_page
  3695 00002890 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3696 00002892 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3697 00002894 7405                <1> 	jz	short cpp_2
  3698                              <1> 		; Convert read only page to writable page 
  3699                              <1> 		;(for the parent of the current process)
  3700                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3701                              <1> 	; 22/09/2015
  3702 00002896 890E                <1> 	mov	[esi], ecx
  3703 00002898 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3704                              <1> 				 ; 1+2+4 = 7
  3705                              <1> cpp_2:
  3706 0000289B 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3707                              <1> 	; 07/09/2015
  3708 0000289D 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3709 0000289F B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3710 000028A4 F3A5                <1> 	rep	movsd ; 31/08/2015
  3711                              <1> cpp_3:		
  3712 000028A6 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3713 000028A8 8903                <1> 	mov	[ebx], eax ; Update PTE
  3714 000028AA 28C0                <1> 	sub	al, al ; clear attributes
  3715                              <1> cpp_4:
  3716                              <1> 	; 16/04/2021
  3717                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3718                              <1> 	;pop	ecx ; ****
  3719                              <1> 	;pop	ebx ; ***
  3720 000028AC 5F                  <1> 	pop	edi ; **
  3721 000028AD 5E                  <1> 	pop	esi ; *
  3722 000028AE C3                  <1> 	retn
  3723                              <1> 
  3724                              <1> ;; 28/04/2015
  3725                              <1> ;; 24/10/2014
  3726                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3727                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3728                              <1> ;;
  3729                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3730                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3731                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3732                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3733                              <1> ;;
  3734                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3735                              <1> ;;
  3736                              <1> ;; Method:
  3737                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3738                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3739                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3740                              <1> ;;	When a new page is being allocated, swap queue is updated
  3741                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3742                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3743                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3744                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3745                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3746                              <1> ;;	offset value becomes it's previous offset value - 4.
  3747                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3748                              <1> ;;	the queue/list is not shifted.
  3749                              <1> ;;	After the queue/list shift, newly allocated page is added
  3750                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3751                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3752                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3753                              <1> ;;	
  3754                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3755                              <1> ;;	the first non-accessed, writable page in the list, 
  3756                              <1> ;;	from the head to the tail. The list is shifted to left 
  3757                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3758                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3759                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3760                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3761                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3762                              <1> ;;	procedure will be failed)...
  3763                              <1> ;;
  3764                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3765                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3766                              <1> ;;	(PTE) will be added to the tail of the queue after
  3767                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3768                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3769                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3770                              <1> ;;
  3771                              <1> ;;
  3772                              <1> ;;	
  3773                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3774                              <1> ;;
  3775                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3776                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3777                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3778                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3779                              <1> ;;
  3780                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3781                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3782                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3783                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3784                              <1> ;; 		 (entire swap space must be accessed by using
  3785                              <1> ;;		 31 bit offset address) 
  3786                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3787                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3788                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3789                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3790                              <1> ;;
  3791                              <1> ;; 					
  3792                              <1> ;; Method:
  3793                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3794                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3795                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3796                              <1> ;;	Swapping out is performed by using swap page queue.
  3797                              <1> ;;
  3798                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3799                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3800                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3801                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3802                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3803                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3804                              <1> ;;	calculated by adding offset value to the swap partition's 
  3805                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3806                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3807                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3808                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3809                              <1> ;;	is in a partitioned virtual hard disk.) 
  3810                              <1> ;;
  3811                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3812                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3813                              <1> ;;
  3814                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3815                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3816                              <1> ;;
  3817                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3818                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3819                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3820                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3821                              <1> ;;	it means relevant (respective) block is in use, and, 
  3822                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3823                              <1> ;;      swap disk/file block is free.
  3824                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3825                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3826                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3827                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3828                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3829                              <1> ;;	------------------------------------------------------------
  3830                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3831                              <1> ;;	------------------------------------------------------------
  3832                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3833                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3834                              <1> ;;
  3835                              <1> ;;	..............................................................
  3836                              <1> ;;
  3837                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3838                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3839                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3840                              <1> ;;	position with value of 1 on the table is converted to swap
  3841                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3842                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3843                              <1> ;;	number of physical swap disk or virtual swap disk)
  3844                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3845                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3846                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3847                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3848                              <1> ;;	If disk write procedure returns with error or free count of 
  3849                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3850                              <1> ;;	'insufficient memory error' (cf=1). 
  3851                              <1> ;;
  3852                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3853                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3854                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3855                              <1> ;;	free blocks after a disk write error. It will return to 
  3856                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3857                              <1> ;;
  3858                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3859                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3860                              <1> ;;	address (cf=0). 
  3861                              <1> ;;
  3862                              <1> ;;	..............................................................
  3863                              <1> ;;
  3864                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3865                              <1> ;;	file sectors at specified memory page. Then page allocation
  3866                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3867                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3868                              <1> ;;	to do, except to terminate the process which is the owner of
  3869                              <1> ;;	the swapped page.
  3870                              <1> ;;
  3871                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3872                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3873                              <1> ;;	updates [swpd_first] pointer if it is required.
  3874                              <1> ;;
  3875                              <1> ;;	..............................................................	 
  3876                              <1> ;;
  3877                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3878                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3879                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3880                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3881                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3882                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3883                              <1> ;;
  3884                              <1> 
  3885                              <1> ; 24/12/2021
  3886                              <1> ; ('swap_in' procedure call is disabled)
  3887                              <1> 
  3888                              <1> ;swap_in:
  3889                              <1> 	; 31/08/2015
  3890                              <1> 	; 20/07/2015
  3891                              <1> 	; 28/04/2015
  3892                              <1> 	; 18/04/2015
  3893                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3894                              <1> 	;
  3895                              <1> 	; INPUT -> 
  3896                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3897                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3898                              <1> 	;	EAX = Offset Address for the swapped page on the
  3899                              <1> 	;	      swap disk or in the swap file.
  3900                              <1> 	;
  3901                              <1> 	; OUTPUT ->
  3902                              <1> 	;	EAX = 0 if loading at memory has been successful
  3903                              <1> 	;
  3904                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3905                              <1> 	;		  or sector not present or drive not ready
  3906                              <1> 	;	     EAX = Error code
  3907                              <1> 	;	     [u.error] = EAX 
  3908                              <1> 	;		       = The last error code for the process
  3909                              <1> 	;		         (will be reset after returning to user)	  
  3910                              <1> 	;
  3911                              <1> 	; Modified Registers -> EAX
  3912                              <1> 	;
  3913                              <1> 
  3914                              <1> ;       cmp     dword [swp_drv], 0
  3915                              <1> ;	jna	short swpin_dnp_err
  3916                              <1> ;
  3917                              <1> ;	cmp	eax, [swpd_size]
  3918                              <1> ;	jnb	short swpin_snp_err
  3919                              <1> ;
  3920                              <1> ;	push	esi
  3921                              <1> ;	push	ebx
  3922                              <1> ;	push	ecx
  3923                              <1> ;	mov	esi, [swp_drv]	
  3924                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3925                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3926                              <1> ;		; size different than 512 bytes, logical disk sector
  3927                              <1> ;		; size is 512 bytes and disk reading procedure
  3928                              <1> ;		; will be performed for reading 4096 bytes
  3929                              <1> ;		; (2*2048, 8*512). 
  3930                              <1> ;	; ESI = Logical disk description table address
  3931                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3932                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3933                              <1> ;	; ECX = Sector count ; 8 sectors
  3934                              <1> ;	push	eax
  3935                              <1> ;	call	logical_disk_read
  3936                              <1> ;	pop	eax
  3937                              <1> ;	jnc	short swpin_read_ok
  3938                              <1> ;	;
  3939                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3940                              <1> ;	mov	[u.error], eax
  3941                              <1> ;	jmp	short swpin_retn
  3942                              <1> ;	;
  3943                              <1> ;swpin_read_ok:
  3944                              <1> ;	; EAX = Offset address (logical sector number)
  3945                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3946                              <1> ;	;
  3947                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3948                              <1> ;	; 20/07/2015
  3949                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3950                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3951                              <1> ;	mov	bl, [u.uno] ; current process number
  3952                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3953                              <1> ;	call	swap_queue_shift
  3954                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3955                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3956                              <1> ;	; zf = 1
  3957                              <1> ;swpin_retn:
  3958                              <1> ;	pop	ecx
  3959                              <1> ;	pop	ebx
  3960                              <1> ;	pop	esi
  3961                              <1> ;	retn
  3962                              <1> ;
  3963                              <1> ;swpin_dnp_err:
  3964                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3965                              <1> ;swpin_err_retn:
  3966                              <1> ;	mov	[u.error], eax
  3967                              <1> ;	stc
  3968                              <1> ;	retn
  3969                              <1> ;
  3970                              <1> ;swpin_snp_err:
  3971                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3972                              <1> ;	jmp	short swpin_err_retn
  3973                              <1> 
  3974                              <1> ; 24/12/2021
  3975                              <1> ; ('swap_out' procedure call is disabled)
  3976                              <1> 
  3977                              <1> ;swap_out:
  3978                              <1> 	; 10/06/2016
  3979                              <1> 	; 07/06/2016
  3980                              <1>         ; 23/05/2016
  3981                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3982                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3983                              <1> 	;
  3984                              <1> 	; INPUT -> 
  3985                              <1> 	;	none
  3986                              <1> 	;
  3987                              <1> 	; OUTPUT ->
  3988                              <1> 	;	EAX = Physical page address (which is swapped out
  3989                              <1> 	;	      for allocating a new page)
  3990                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3991                              <1> 	;		  or sector not present or drive not ready
  3992                              <1> 	;	     EAX = Error code
  3993                              <1> 	;	     [u.error] = EAX 
  3994                              <1> 	;		       = The last error code for the process
  3995                              <1> 	;		         (will be reset after returning to user)	  
  3996                              <1> 	;
  3997                              <1> 	; Modified Registers -> none (except EAX)
  3998                              <1> 	;
  3999                              <1> 
  4000                              <1> ;	cmp 	word [swpq_count], 1
  4001                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  4002                              <1> ;
  4003                              <1> ;       ;cmp    dword [swp_drv], 1
  4004                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  4005                              <1> ;
  4006                              <1> ;       cmp     dword [swpd_free], 1
  4007                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  4008                              <1> ;
  4009                              <1> ;	push	ebx ; *
  4010                              <1> ;swpout_1:
  4011                              <1> ;	; 10/06/2016
  4012                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  4013                              <1> ;	call	swap_queue_shift
  4014                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  4015                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  4016                              <1> ;				       ; pointer in the swap queue
  4017                              <1> ;	; EAX = PTE value of the page
  4018                              <1> ;	; EBX = PTE address of the page
  4019                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4020                              <1> ;	;
  4021                              <1> ;	; 07/06/2016
  4022                              <1> ;	; 19/05/2016
  4023                              <1> ;	; check this page is in timer events or not
  4024                              <1> ;	
  4025                              <1> ;swpout_timer_page_0:
  4026                              <1> ;	push	edx ; **
  4027                              <1> ;
  4028                              <1> ;	; 07/06/2016
  4029                              <1> ;	cmp	byte [timer_events], 0 
  4030                              <1> ;	jna	short swpout_2
  4031                              <1> ;	;
  4032                              <1> ;	mov	dl, [timer_events]
  4033                              <1> ;
  4034                              <1> ;	push	ecx ; ***
  4035                              <1> ;	push	ebx ; ****
  4036                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4037                              <1> ;			       ; structures 
  4038                              <1> ;swpout_timer_page_1:
  4039                              <1> ;	mov	cl, [ebx]
  4040                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4041                              <1> ;	jz	short swpout_timer_page_3
  4042                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4043                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4044                              <1> ;				; of the response byte address, to
  4045                              <1> ;				; get beginning of the page address)
  4046                              <1> ;	cmp	eax, ecx
  4047                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4048                              <1> ;	
  4049                              <1> ;	; !same page!
  4050                              <1> ;	;
  4051                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4052                              <1> ;	; This page will be used by the kernel to put timer event
  4053                              <1> ;	; response (signal return) byte at the requested address;
  4054                              <1> ;	; in order to prevent a possible wrong write (while
  4055                              <1> ;	; this page is swapped out) on physical memory,
  4056                              <1> ;	; we must protect this page against to be swapped out!
  4057                              <1> ;	;
  4058                              <1> ;	pop	ebx ; ****
  4059                              <1> ;	pop	ecx ; ***
  4060                              <1> ;	pop	edx ; **
  4061                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4062                              <1> ; 
  4063                              <1> ;swpout_timer_page_2:
  4064                              <1> ;	; 07/06/2016
  4065                              <1> ;	dec	dl
  4066                              <1> ;	jz	short swpout_timer_page_4
  4067                              <1> ;swpout_timer_page_3:
  4068                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4069                              <1> ;	;jnb	short swpout_timer_page_4
  4070                              <1> ;	add	ebx, 16
  4071                              <1> ;	jmp	short swpout_timer_page_1	
  4072                              <1> ;
  4073                              <1> ;swpout_timer_page_4:
  4074                              <1> ;	pop	ebx ; ****
  4075                              <1> ;	pop	ecx ; ***
  4076                              <1> ;swpout_2:
  4077                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4078                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4079                              <1> ;	;
  4080                              <1> ;	call	link_swap_block
  4081                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4082                              <1> ;				       ; because [swpd_free] value
  4083                              <1> ;				       ; was checked at the beginging. 	
  4084                              <1> ;	pop	edx ; **
  4085                              <1> ;	pop	ebx ; *
  4086                              <1> ;	jmp	short swpout_nfspc_err 
  4087                              <1> ;swpout_3:
  4088                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4089                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4090                              <1> ;	;	
  4091                              <1> ;	push	esi ; **
  4092                              <1> ;	push	ecx ; ***
  4093                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4094                              <1> ;	mov	esi, [swp_drv]	
  4095                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4096                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4097                              <1> ;		; size different than 512 bytes, logical disk sector
  4098                              <1> ;		; size is 512 bytes and disk writing procedure
  4099                              <1> ;		; will be performed for writing 4096 bytes
  4100                              <1> ;		; (2*2048, 8*512). 
  4101                              <1> ;	; ESI = Logical disk description table address
  4102                              <1> ;	; EBX = Buffer (Page) address
  4103                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4104                              <1> ;	; ECX = Sector count ; 8 sectors
  4105                              <1> ;	; edx = PTE address
  4106                              <1> ;	call	logical_disk_write
  4107                              <1> ;	; edx = PTE address
  4108                              <1> ;	pop	ecx ; sector address	
  4109                              <1> ;	jnc	short swpout_write_ok
  4110                              <1> ;	;
  4111                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4112                              <1> ;swpout_dw_err:
  4113                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4114                              <1> ;	mov	[u.error], eax
  4115                              <1> ;	jmp	short swpout_retn
  4116                              <1> ;	;
  4117                              <1> ;swpout_write_ok:
  4118                              <1> ;	; EBX = Buffer (page) address
  4119                              <1> ;	; EDX = Page Table Entry address
  4120                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4121                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4122                              <1> ;	mov 	[edx], ecx 
  4123                              <1> ;		; bit 0 = 0 (swapped page)
  4124                              <1> ;	mov	eax, ebx
  4125                              <1> ;swpout_retn:
  4126                              <1> ;	pop	ecx ; ***
  4127                              <1> ;	pop	esi ; **
  4128                              <1> ;	pop	ebx ; *
  4129                              <1> ;	retn
  4130                              <1> ;
  4131                              <1> ;;swpout_dnp_err:
  4132                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4133                              <1> ;;	jmp	short swpout_err_retn
  4134                              <1> ;swpout_nfspc_err:
  4135                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4136                              <1> ;swpout_err_retn:
  4137                              <1> ;	mov	[u.error], eax
  4138                              <1> ;	;stc
  4139                              <1> ;	retn
  4140                              <1> ;swpout_npts_err:
  4141                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4142                              <1> ;	pop	ebx
  4143                              <1> ;	jmp	short swpout_err_retn
  4144                              <1> ;swpout_im_err:
  4145                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4146                              <1> ;	jmp	short swpout_err_retn
  4147                              <1> 
  4148                              <1> ; 24/12/2021
  4149                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4150                              <1> 
  4151                              <1> ;swap_queue_shift:
  4152                              <1> 	; 26/03/2017
  4153                              <1> 	; 10/06/2016
  4154                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4155                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4156                              <1> 	;
  4157                              <1> 	; INPUT ->
  4158                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4159                              <1> 	;	      and process number combination (bit 0 to 11)
  4160                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4161                              <1> 	;	
  4162                              <1> 	; OUTPUT ->
  4163                              <1> 	;	If EBX input > 0 
  4164                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4165                              <1> 	; 	   from the tail to the head, up to entry offset
  4166                              <1> 	; 	   which points to EBX input value or nothing
  4167                              <1> 	;	   to do if EBX value is not found on the queue.
  4168                              <1> 	;	   (The entry -with EBX value- will be removed
  4169                              <1> 	;	   from the queue if it is found.)
  4170                              <1> 	;
  4171                              <1> 	;	   EAX = 0		
  4172                              <1> 	;
  4173                              <1> 	;	If EBX input = 0
  4174                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4175                              <1> 	; 	   from the tail to the head, if the PTE address
  4176                              <1> 	;	   which is pointed in head of the queue is marked
  4177                              <1> 	;	   as "accessed" or it is marked as "non present".
  4178                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4179                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4180                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4181                              <1> 	;	   -without dropping pointer of the PTE from 
  4182                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4183                              <1> 	;	   Pointer in the head will be moved into the tail,
  4184                              <1> 	;	   other PTEs will be shifted on head direction.)
  4185                              <1> 	;
  4186                              <1> 	;	   Swap queue will be shifted up to the first
  4187                              <1> 	;	   'present' or 'non accessed' page will be found
  4188                              <1> 	;	   (as pointed) on the queue head (then it will be
  4189                              <1>         ;          removed/dropped from the queue).
  4190                              <1> 	;
  4191                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4192                              <1> 	;		 (it's pointer -virtual address-) dropped
  4193                              <1> 	;		 (removed) from swap queue.
  4194                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4195                              <1> 	;	         which is (it's pointer -virtual address-)
  4196                              <1> 	;		 dropped (removed) from swap queue.
  4197                              <1> 	;
  4198                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4199                              <1> 	;
  4200                              <1> 	; Modified Registers -> EAX, EBX
  4201                              <1> 	;
  4202                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4203                              <1> ;	and	ax, ax
  4204                              <1> ;	jz	short swpqs_retn
  4205                              <1> ;	push	edi
  4206                              <1> ;	push	esi
  4207                              <1> ;	push	ecx
  4208                              <1> ;	mov	esi, swap_queue
  4209                              <1> ;	mov	ecx, eax
  4210                              <1> ;	or	ebx, ebx
  4211                              <1> ;	jz	short swpqs_7
  4212                              <1> ;swpqs_1:
  4213                              <1> ;	lodsd
  4214                              <1> ;	cmp	eax, ebx
  4215                              <1> ;	je	short swpqs_2
  4216                              <1> ;	loop	swpqs_1
  4217                              <1> ;	; 10/06/2016
  4218                              <1> ;	sub	eax, eax 
  4219                              <1> ;	jmp	short swpqs_6
  4220                              <1> ;swpqs_2:
  4221                              <1> ;	mov	edi, esi
  4222                              <1> ;	sub 	edi, 4
  4223                              <1> ;swpqs_3:
  4224                              <1> ;	dec	word [swpq_count]
  4225                              <1> ;	jz	short swpqs_5
  4226                              <1> ;swpqs_4:
  4227                              <1> ;	dec 	ecx
  4228                              <1> ;	rep	movsd	; shift up (to the head)
  4229                              <1> ;swpqs_5:
  4230                              <1> ;	xor	eax, eax
  4231                              <1> ;	mov	[edi], eax
  4232                              <1> ;swpqs_6:
  4233                              <1> ;	pop	ecx
  4234                              <1> ;	pop	esi
  4235                              <1> ;	pop	edi
  4236                              <1> ;swpqs_retn:
  4237                              <1> ;	retn		
  4238                              <1> ;swpqs_7:
  4239                              <1> ;	mov	edi, esi ; head
  4240                              <1> ;	lodsd
  4241                              <1> ;	; 20/07/2015
  4242                              <1> ;	mov	ebx, eax
  4243                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4244                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4245                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4246                              <1> ;		      ; ax = process number (1 to 4095)
  4247                              <1> ;	cmp	al, [u.uno]
  4248                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4249                              <1> ;	jne	short swpqs_8
  4250                              <1> ;	mov	eax, [u.pgdir]
  4251                              <1> ;	jmp	short swpqs_9
  4252                              <1> ;swpqs_8:
  4253                              <1> ;	; 09/06/2016
  4254                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4255                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4256                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4257                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4258                              <1> ;
  4259                              <1> ;	;shl	ax, 2
  4260                              <1> ;	shl	al, 2
  4261                              <1> ;	mov 	eax, [eax+p.upage-4]
  4262                              <1> ;	or	eax, eax
  4263                              <1> ;	jz	short swpqs_3 ; invalid upage
  4264                              <1> ;	add	eax, u.pgdir - user
  4265                              <1> ;			 ; u.pgdir value for the process
  4266                              <1> ;			 ; is in [eax]
  4267                              <1> ;	mov	eax, [eax]
  4268                              <1> ;	and	eax, eax
  4269                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4270                              <1> ;swpqs_9:
  4271                              <1> ;	push	edx
  4272                              <1> ;	; eax = page directory
  4273                              <1> ;	; ebx = virtual address
  4274                              <1> ;	call	get_pte
  4275                              <1> ;	mov	ebx, edx	; PTE address
  4276                              <1> ;	pop	edx
  4277                              <1> ;	; 10/06/2016
  4278                              <1> ;	jc	short swpqs_13 ; empty PDE
  4279                              <1> ;	; EAX = PTE value
  4280                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4281                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4282                              <1> ;			        ; from the queue (head)
  4283                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4284                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4285                              <1> ;			        ; from the queue (head) 	
  4286                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4287                              <1> ;	;jnz	short swpqs_11  ; present
  4288                              <1> ;			        ; accessed page
  4289                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4290                              <1> ;	jc	short swpqs_11  ; accessed page
  4291                              <1> ;
  4292                              <1> ;	dec	ecx
  4293                              <1> ;	mov	[swpq_count], cx
  4294                              <1> ;       jz      short swpqs_10
  4295                              <1> ;		; esi = head + 4
  4296                              <1> ;		; edi = head
  4297                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4298                              <1> ;swpqs_10:
  4299                              <1> ;	mov	[edi], ecx ; 0
  4300                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4301                              <1> ;
  4302                              <1> ;swpqs_11:
  4303                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4304                              <1> ;	; Rotation (head -> tail)
  4305                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4306                              <1> ;	jz	short swpqs_10
  4307                              <1> ;		; esi = head + 4
  4308                              <1> ;		; edi = head
  4309                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4310                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4311                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4312                              <1> ;
  4313                              <1> ;	mov	cx, [swpq_count]
  4314                              <1> ;
  4315                              <1> ;swpqs_12:
  4316                              <1> ;	mov	esi, swap_queue ; head
  4317                              <1> ;       jmp     swpqs_7
  4318                              <1> ;
  4319                              <1> ;swpqs_13:
  4320                              <1> ;	dec	ecx
  4321                              <1> ;	mov	[swpq_count], cx
  4322                              <1> ;       jz      swpqs_5
  4323                              <1> ;	jmp	short swpqs_12
  4324                              <1> 
  4325                              <1> ; 24/12/2021
  4326                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4327                              <1> 
  4328                              <1> ;add_to_swap_queue:
  4329                              <1> 	; 20/02/2017
  4330                              <1> 	; 20/07/2015
  4331                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4332                              <1> 	;
  4333                              <1> 	; Adds new page to swap queue
  4334                              <1> 	; (page directories and page tables must not be added
  4335                              <1> 	; to swap queue)	
  4336                              <1> 	;
  4337                              <1> 	; INPUT ->
  4338                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4339                              <1> 	;	[u.uno]
  4340                              <1> 	;	20/02/2017
  4341                              <1> 	;	(Linear address = CORE + user's virtual address)
  4342                              <1> 	;
  4343                              <1> 	; OUTPUT ->
  4344                              <1> 	;	EAX = [swpq_count]
  4345                              <1> 	;	      (after the PTE has been added)
  4346                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4347                              <1> 	;	      the PTE could not be added.
  4348                              <1> 	;
  4349                              <1> 	; Modified Registers -> EAX
  4350                              <1> 	;
  4351                              <1> ;	push	ebx
  4352                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4353                              <1> ;	mov	bl, [u.uno] ; current process number
  4354                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4355                              <1> ;				 ; it is already on the queue
  4356                              <1> ;		; then add it to the tail of the queue
  4357                              <1> ;	movzx	eax, word [swpq_count]
  4358                              <1> ;	cmp	ax, 1024
  4359                              <1> ;	jb	short atsq_1
  4360                              <1> ;	sub	ax, ax
  4361                              <1> ;	pop	ebx
  4362                              <1> ;	retn
  4363                              <1> ;atsq_1:
  4364                              <1> ;	push	esi
  4365                              <1> ;	mov	esi, swap_queue
  4366                              <1> ;	and	ax, ax
  4367                              <1> ;	jz	short atsq_2
  4368                              <1> ;	shl	ax, 2	; convert to offset
  4369                              <1> ;	add	esi, eax
  4370                              <1> ;	shr	ax, 2
  4371                              <1> ;atsq_2:
  4372                              <1> ;	inc	ax
  4373                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4374                              <1> ;	mov	[swpq_count], ax
  4375                              <1> ;	pop	esi
  4376                              <1> ;	pop	ebx
  4377                              <1> ;	retn
  4378                              <1> 
  4379                              <1> ; 24/12/2021
  4380                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4381                              <1> 
  4382                              <1> ;unlink_swap_block:
  4383                              <1> 	; 15/09/2015
  4384                              <1> 	; 30/04/2015
  4385                              <1> 	; 18/04/2015
  4386                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4387                              <1> 	;
  4388                              <1> 	; INPUT -> 
  4389                              <1> 	;	EAX = swap disk/file offset address
  4390                              <1> 	;	      (bit 1 to bit 31)
  4391                              <1> 	; OUTPUT ->
  4392                              <1> 	;	[swpd_free] is increased
  4393                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4394                              <1> 	;
  4395                              <1> 	; Modified Registers -> EAX
  4396                              <1> 	;
  4397                              <1> ;	push	ebx
  4398                              <1> ;	push	edx
  4399                              <1> ;	;
  4400                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4401                              <1> ;				     ; 3 bits right
  4402                              <1> ;				     ; to get swap block/page number
  4403                              <1> ;	mov	edx, eax
  4404                              <1> ;	; 15/09/2015
  4405                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4406                              <1> ;				     ; (1 allocation bit = 1 page)
  4407                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4408                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4409                              <1> ;				     ; (to get 32 bit position)			
  4410                              <1> ;	;
  4411                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4412                              <1> ;	add	ebx, edx
  4413                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4414                              <1> ;				     ; (allocation bit position)	 
  4415                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4416                              <1> ;				     ; than the address in 'swpd_next' ?
  4417                              <1> ;				     ; (next/first free block value)		
  4418                              <1> ;	jnb	short uswpbl_1	     ; no	
  4419                              <1> ;	mov	[swpd_next], eax     ; yes	
  4420                              <1> ;uswpbl_1:
  4421                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4422                              <1> ;				     ; set relevant bit to 1.
  4423                              <1> ;				     ; set CF to the previous bit value	
  4424                              <1> ;	cmc			     ; complement carry flag	
  4425                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4426                              <1> ;				     ; if the block is already deallocated
  4427                              <1> ;				     ; before.	
  4428                              <1> ;       inc     dword [swpd_free]
  4429                              <1> ;uswpbl_2:
  4430                              <1> ;	pop	edx
  4431                              <1> ;	pop	ebx
  4432                              <1> ;	retn
  4433                              <1> 
  4434                              <1> ; 24/12/2021
  4435                              <1> ; ('link_swap_block' procedure call is disabled)
  4436                              <1> 
  4437                              <1> ;link_swap_block:
  4438                              <1> 	; 01/07/2015
  4439                              <1> 	; 18/04/2015
  4440                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4441                              <1> 	;
  4442                              <1> 	; INPUT -> none
  4443                              <1> 	;
  4444                              <1> 	; OUTPUT ->
  4445                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4446                              <1> 	;	      in sectors (corresponding 
  4447                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4448                              <1> 	;
  4449                              <1> 	;	CF = 1 and EAX = 0 
  4450                              <1> 	; 		   if there is not a free block to be allocated	
  4451                              <1> 	;
  4452                              <1> 	; Modified Registers -> none (except EAX)
  4453                              <1> 	;
  4454                              <1> 
  4455                              <1> ;	;mov	eax, [swpd_free]
  4456                              <1> ;	;and	eax, eax
  4457                              <1> ;	;jz	short out_of_swpspc
  4458                              <1> ;	;
  4459                              <1> ;	push	ebx
  4460                              <1> ;	push	ecx
  4461                              <1> ;	;
  4462                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4463                              <1> ;	mov	ecx, ebx
  4464                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4465                              <1> ;				 ; next_free_swap_block >> 5
  4466                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4467                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4468                              <1> ;lswbl_scan:
  4469                              <1> ;	cmp	ebx, ecx
  4470                              <1> ;	ja	short lswbl_notfound
  4471                              <1> ;	;
  4472                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4473                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4474                              <1> ;			   ; loads the destination with an index to
  4475                              <1> ;			   ; first set bit. (0 -> 31) 
  4476                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4477                              <1> ;	; 01/07/2015
  4478                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4479                              <1> ;			 ;
  4480                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4481                              <1> ;			 ;	  with value of 1 means 
  4482                              <1> ;			 ;	  the corresponding page is free 
  4483                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4484                              <1> ;	add	ebx, 4
  4485                              <1> ;			 ; We return back for searching next page block
  4486                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4487                              <1> ;			 ;	 we always will find at least 1 free block here.
  4488                              <1> ;	jmp    	short lswbl_scan
  4489                              <1> ;	;
  4490                              <1> ;lswbl_notfound:	
  4491                              <1> ;	sub	ecx, swap_alloc_table
  4492                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4493                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4494                              <1> ;	xor	eax, eax
  4495                              <1> ;	mov	[swpd_free], eax
  4496                              <1> ;	stc
  4497                              <1> ;lswbl_ok:
  4498                              <1> ;	pop	ecx
  4499                              <1> ;	pop	ebx
  4500                              <1> ;	retn
  4501                              <1> ;	;
  4502                              <1> ;;out_of_swpspc:
  4503                              <1> ;;	stc
  4504                              <1> ;;	retn
  4505                              <1> ;
  4506                              <1> ;lswbl_found:
  4507                              <1> ;	mov	ecx, ebx
  4508                              <1> ;	sub	ecx, swap_alloc_table
  4509                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4510                              <1> ;				 ; address/offset (to the next)
  4511                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4512                              <1> ;	;
  4513                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4514                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4515                              <1> ;				 ; in the destination.
  4516                              <1> ;				 ;
  4517                              <1> ;				 ; Reset the bit which is corresponding to the 
  4518                              <1> ;				 ; (just) allocated block.
  4519                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4520                              <1> ;	add	eax, ecx	 ; = block number
  4521                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4522                              <1> ;				 ; 1 block =  8 sectors
  4523                              <1> ;	;
  4524                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4525                              <1> ;	;
  4526                              <1> ;	; NOTE: The relevant page table entry will be updated
  4527                              <1> ;	;       according to this EAX value...
  4528                              <1> ;	;
  4529                              <1> ;	jmp	short lswbl_ok
  4530                              <1> 
  4531                              <1> ; 24/12/2021
  4532                              <1> ; ('logical_disk_read' procedure call is disabled)
  4533                              <1> 
  4534                              <1> ;logical_disk_read:
  4535                              <1> 	; 20/07/2015
  4536                              <1> 	; 09/03/2015 (temporary code here)
  4537                              <1> 	;
  4538                              <1> 	; INPUT ->
  4539                              <1> 	; 	ESI = Logical disk description table address
  4540                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4541                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4542                              <1> 	; 	ECX = Sector count
  4543                              <1> 	;
  4544                              <1> 	;
  4545                              <1> ;	retn
  4546                              <1> 
  4547                              <1> ; 24/12/2021
  4548                              <1> ; ('logical_disk_write' procedure call is disabled)
  4549                              <1> 
  4550                              <1> ;logical_disk_write:
  4551                              <1> 	; 20/07/2015
  4552                              <1> 	; 09/03/2015 (temporary code here)
  4553                              <1> 	;
  4554                              <1> 	; INPUT ->
  4555                              <1> 	; 	ESI = Logical disk description table address
  4556                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4557                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4558                              <1> 	; 	ECX = Sector count
  4559                              <1> 	;
  4560                              <1> ;	retn
  4561                              <1> 
  4562                              <1> get_physical_addr:
  4563                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4564                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4565                              <1> 	; 18/10/2015
  4566                              <1> 	; 29/07/2015
  4567                              <1> 	; 20/07/2015
  4568                              <1> 	; 04/06/2015
  4569                              <1> 	; 20/05/2015
  4570                              <1> 	; 28/04/2015
  4571                              <1> 	; 18/04/2015
  4572                              <1> 	; Get physical address
  4573                              <1> 	;     (allocates a new page for user if it is not present)
  4574                              <1> 	;	
  4575                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4576                              <1> 	; (buffer) address to physical address (of the buffer).)
  4577                              <1> 	; ('sys write', 'sys read' system calls...)
  4578                              <1> 	;
  4579                              <1> 	; INPUT ->
  4580                              <1> 	;	EBX = virtual address
  4581                              <1> 	;	u.pgdir = page directory (physical) address
  4582                              <1> 	;
  4583                              <1> 	; OUTPUT ->
  4584                              <1> 	;	EAX = physical address 
  4585                              <1> 	;	EBX = linear address	
  4586                              <1> 	;	EDX = physical address of the page frame
  4587                              <1> 	;	      (with attribute bits)
  4588                              <1> 	;	ECX = byte count within the page frame
  4589                              <1> 	;
  4590                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4591                              <1> 	;
  4592                              <1> 
  4593                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4594 000028AF A1[55660000]        <1> 	mov	eax, [u.pgdir]
  4595                              <1> 
  4596                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4597                              <1> 	
  4598 000028B4 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4599                              <1> 	;
  4600                              <1> 	;mov	eax, [u.pgdir]
  4601 000028BA E81AFDFFFF          <1> 	call	get_pte
  4602                              <1> 		; EDX = Page table entry address (if CF=0)
  4603                              <1> 	        ;       Page directory entry address (if CF=1)
  4604                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4605                              <1> 		; EAX = Page table entry value (page address)
  4606                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4607 000028BF 731C                <1> 	jnc	short gpa_1
  4608                              <1> 	;
  4609 000028C1 E801FCFFFF          <1> 	call	allocate_page
  4610 000028C6 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4611                              <1> gpa_0:
  4612 000028C8 E86BFCFFFF          <1> 	call 	clear_page
  4613                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4614 000028CD 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4615                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4616                              <1> 			   ; (user, writable, present page)	
  4617 000028CF 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4618 000028D1 A1[55660000]        <1> 	mov	eax, [u.pgdir]	
  4619 000028D6 E8FEFCFFFF          <1> 	call	get_pte
  4620 000028DB 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4621                              <1> gpa_1:
  4622                              <1> 	; EAX = PTE value, EDX = PTE address
  4623 000028DD A801                <1> 	test 	al, PTE_A_PRESENT
  4624 000028DF 750A                <1> 	jnz	short gpa_3
  4625 000028E1 09C0                <1> 	or	eax, eax
  4626 000028E3 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4627                              <1> 
  4628                              <1> ; 24/12/2021
  4629                              <1> ; ('reload_page' procedure call is disabled)
  4630 000028E5 EB2C                <1> 	jmp	short gpa_im_err
  4631                              <1> 
  4632                              <1> 	; 20/07/2015
  4633                              <1> ;	push	ebp
  4634                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4635                              <1> ;	; reload swapped page
  4636                              <1> ;	call	reload_page ; 28/04/2015
  4637                              <1> ;	pop	ebp
  4638                              <1> ;	jc	short gpa_retn
  4639                              <1> gpa_2:
  4640                              <1> ; 24/12/2021
  4641                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4642                              <1> 
  4643                              <1> 	; 20/07/2015
  4644                              <1> 	; 20/05/2015
  4645                              <1> 	; add this page to swap queue
  4646                              <1> ;	push	eax 
  4647                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4648                              <1> ;	call 	add_to_swap_queue
  4649                              <1> ;	pop	eax
  4650                              <1> 		; PTE address in EDX
  4651                              <1> 		; virtual address in EBX
  4652                              <1> 	; EAX = memory page address
  4653 000028E7 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4654                              <1> 				  ; present flag, bit 0 = 1
  4655                              <1> 				  ; user flag, bit 2 = 1	
  4656                              <1> 				  ; writable flag, bit 1 = 1
  4657 000028E9 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4658                              <1> gpa_3:
  4659                              <1> 	; 18/10/2015
  4660 000028EB 89D9                <1> 	mov	ecx, ebx
  4661 000028ED 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4662 000028F3 89C2                <1> 	mov 	edx, eax
  4663 000028F5 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4664 000028F9 01C8                <1> 	add	eax, ecx
  4665 000028FB F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4666 000028FD 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4667 00002903 F8                  <1> 	clc
  4668                              <1> gpa_retn:
  4669 00002904 C3                  <1> 	retn	
  4670                              <1> gpa_4:	
  4671 00002905 E8BDFBFFFF          <1> 	call	allocate_page
  4672 0000290A 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4673 0000290C E827FCFFFF          <1> 	call	clear_page
  4674 00002911 EBD4                <1> 	jmp	short gpa_2
  4675                              <1> 
  4676                              <1> gpa_im_err:	
  4677 00002913 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4678                              <1> 				  ; Major error = 0 (No protection fault)	
  4679 00002918 C3                  <1> 	retn
  4680                              <1> 
  4681                              <1> ; 24/12/2021
  4682                              <1> ; ('reload_page' procedure call is disabled)
  4683                              <1> 
  4684                              <1> ;reload_page:
  4685                              <1> 	; 20/07/2015
  4686                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4687                              <1> 	;
  4688                              <1> 	; Reload (Restore) swapped page at memory
  4689                              <1> 	;
  4690                              <1> 	; INPUT -> 
  4691                              <1> 	;	EBP = Virtual (linear) memory address
  4692                              <1> 	;	EAX = PTE value (swap disk sector address)
  4693                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4694                              <1> 	; OUTPUT ->
  4695                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4696                              <1> 	;
  4697                              <1> 	;	CF = 1 and EAX = error code
  4698                              <1> 	;
  4699                              <1> 	; Modified Registers -> none (except EAX)
  4700                              <1> 	;
  4701                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4702                              <1> ;	push	ebx      ;
  4703                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4704                              <1> ;	call	allocate_page
  4705                              <1> ;	jc	short rlp_im_err
  4706                              <1> ;	xchg 	eax, ebx	
  4707                              <1> ;	; EBX = Physical memory (page) address
  4708                              <1> ;	; EAX = Swap disk (offset) address
  4709                              <1> ;	; EBP = Virtual (linear) memory address
  4710                              <1> ;	call	swap_in
  4711                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4712                              <1> ;	mov	eax, ebx	
  4713                              <1> ;rlp_retn:
  4714                              <1> ;	pop	ebx
  4715                              <1> ;	retn
  4716                              <1> ;	
  4717                              <1> ;rlp_im_err:	
  4718                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4719                              <1> ;				  ; Major error = 0 (No protection fault)	
  4720                              <1> ;	jmp	short rlp_retn
  4721                              <1> ;
  4722                              <1> ;rlp_swp_err:
  4723                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4724                              <1> ;	jmp	short rlp_retn
  4725                              <1> 
  4726                              <1> copy_page_dir:
  4727                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4728                              <1> 	; 19/09/2015
  4729                              <1> 	; temporary - 07/09/2015
  4730                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4731                              <1> 	;
  4732                              <1> 	; INPUT -> 
  4733                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4734                              <1> 	;		    page directory.
  4735                              <1> 	; OUTPUT ->
  4736                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4737                              <1> 	;	       page directory.
  4738                              <1> 	;	(New page directory with new page table entries.)
  4739                              <1> 	;	(New page tables with read only copies of the parent's
  4740                              <1> 	;	pages.)
  4741                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4742                              <1> 	;
  4743                              <1> 	; Modified Registers -> none (except EAX)
  4744                              <1> 	;
  4745 00002919 E8A9FBFFFF          <1> 	call	allocate_page
  4746 0000291E 723E                <1> 	jc	short cpd_err
  4747                              <1> 	;
  4748 00002920 55                  <1> 	push	ebp ; 20/07/2015
  4749 00002921 56                  <1> 	push	esi
  4750 00002922 57                  <1> 	push	edi
  4751 00002923 53                  <1> 	push	ebx
  4752 00002924 51                  <1> 	push	ecx
  4753 00002925 8B35[55660000]      <1> 	mov	esi, [u.pgdir]
  4754 0000292B 89C7                <1> 	mov	edi, eax
  4755 0000292D 50                  <1> 	push	eax ; save child's page directory address
  4756                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4757                              <1> 	; (use same system space for all user page tables) 
  4758 0000292E A5                  <1> 	movsd
  4759 0000292F BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4760 00002934 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4761                              <1> cpd_0:	
  4762 00002939 AD                  <1> 	lodsd
  4763                              <1> 	;or	eax, eax
  4764                              <1>         ;jnz	short cpd_1
  4765 0000293A A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4766 0000293C 7508                <1> 	jnz	short cpd_1
  4767                              <1>  	; (virtual address at the end of the page table)	
  4768 0000293E 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4769 00002944 EB0F                <1> 	jmp	short cpd_2
  4770                              <1> cpd_1:	
  4771 00002946 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4772 0000294A 89C3                <1> 	mov	ebx, eax
  4773                              <1> 	; EBX = Parent's page table address
  4774 0000294C E81F000000          <1> 	call	copy_page_table
  4775 00002951 720C                <1> 	jc	short cpd_p_err
  4776                              <1> 	; EAX = Child's page table address
  4777 00002953 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4778                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4779                              <1> 			 ; (present, writable, user)
  4780                              <1> cpd_2:
  4781 00002955 AB                  <1> 	stosd
  4782 00002956 E2E1                <1> 	loop	cpd_0
  4783                              <1> 	;
  4784 00002958 58                  <1> 	pop	eax  ; restore child's page directory address
  4785                              <1> cpd_3:
  4786 00002959 59                  <1> 	pop	ecx
  4787 0000295A 5B                  <1> 	pop	ebx
  4788 0000295B 5F                  <1> 	pop	edi
  4789 0000295C 5E                  <1> 	pop	esi
  4790 0000295D 5D                  <1> 	pop	ebp
  4791                              <1> cpd_err:
  4792 0000295E C3                  <1> 	retn
  4793                              <1> cpd_p_err:
  4794                              <1> 	; release the allocated pages missing (recover free space)
  4795 0000295F 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4796 00002960 8B1D[55660000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4797 00002966 E88CFCFFFF          <1> 	call 	deallocate_page_dir
  4798 0000296B 29C0                <1> 	sub	eax, eax ; 0
  4799 0000296D F9                  <1> 	stc
  4800 0000296E EBE9                <1> 	jmp	short cpd_3	
  4801                              <1> 
  4802                              <1> copy_page_table:
  4803                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4804                              <1> 	; 19/09/2015
  4805                              <1> 	; temporary - 07/09/2015
  4806                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4807                              <1> 	;
  4808                              <1> 	; INPUT -> 
  4809                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4810                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4811                              <1> 	; OUTPUT ->
  4812                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4813                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4814                              <1> 	;	CF = 1 -> error 
  4815                              <1> 	;
  4816                              <1> 	; Modified Registers -> EBP (except EAX)
  4817                              <1> 	;
  4818 00002970 E852FBFFFF          <1> 	call	allocate_page
  4819 00002975 7244                <1> 	jc	short cpt_err
  4820                              <1> 	;
  4821 00002977 50                  <1> 	push	eax ; *
  4822                              <1> 	;push 	ebx
  4823 00002978 56                  <1> 	push	esi
  4824 00002979 57                  <1> 	push	edi
  4825 0000297A 52                  <1> 	push	edx
  4826 0000297B 51                  <1> 	push	ecx
  4827                              <1> 	;
  4828 0000297C 89DE                <1> 	mov	esi, ebx
  4829 0000297E 89C7                <1> 	mov	edi, eax
  4830 00002980 89C2                <1> 	mov	edx, eax
  4831 00002982 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4832                              <1> cpt_0:
  4833 00002988 AD                  <1> 	lodsd
  4834 00002989 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4835                              <1> 	;jnz	short cpt_1 (*)
  4836                              <1> 	; 24/12/2021
  4837                              <1> 	;and	eax, eax (*)
  4838 0000298B 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4839                              <1> 	
  4840                              <1> ; 24/12/2021
  4841                              <1> ; ('reload_page' procedure call is disabled)
  4842                              <1> ;
  4843                              <1> ;	; ebp = virtual (linear) address of the memory page
  4844                              <1> ;	call	reload_page ; 28/04/2015
  4845                              <1> ;	jc	short cpt_p_err
  4846                              <1> cpt_1:
  4847 0000298D 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4848 00002991 89C1                <1> 	mov	ecx, eax
  4849                              <1> 	; Allocate a new page for the child process
  4850 00002993 E82FFBFFFF          <1> 	call	allocate_page
  4851 00002998 721C                <1> 	jc	short cpt_p_err
  4852 0000299A 57                  <1> 	push	edi
  4853 0000299B 56                  <1> 	push	esi
  4854 0000299C 89CE                <1> 	mov	esi, ecx
  4855 0000299E 89C7                <1> 	mov	edi, eax
  4856 000029A0 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4857 000029A5 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4858 000029A7 5E                  <1> 	pop	esi
  4859 000029A8 5F                  <1> 	pop	edi
  4860                              <1> 	; 
  4861                              <1> ; 24/12/2021
  4862                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4863                              <1> ;
  4864                              <1> ;	push	ebx
  4865                              <1> ;	push	eax
  4866                              <1> ;	mov	ebx, ebp
  4867                              <1> ;	; ebx = virtual address of the memory page
  4868                              <1> ;	call	add_to_swap_queue
  4869                              <1> ;	pop	eax
  4870                              <1> ;	pop	ebx
  4871                              <1> 	;
  4872                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4873 000029A9 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4874                              <1> cpt_2:
  4875 000029AB AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4876                              <1> 	;
  4877 000029AC 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4878                              <1> 	;
  4879 000029B2 39D7                <1> 	cmp	edi, edx
  4880 000029B4 72D2                <1> 	jb	short cpt_0
  4881                              <1> cpt_p_err:
  4882 000029B6 59                  <1> 	pop	ecx
  4883 000029B7 5A                  <1> 	pop	edx
  4884 000029B8 5F                  <1> 	pop	edi
  4885 000029B9 5E                  <1> 	pop	esi
  4886                              <1> 	;pop	ebx
  4887 000029BA 58                  <1> 	pop	eax ; *
  4888                              <1> cpt_err:
  4889 000029BB C3                  <1> 	retn
  4890                              <1> 
  4891                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4892                              <1> 
  4893                              <1> ;; Data:
  4894                              <1> 
  4895                              <1> ; 09/03/2015
  4896                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4897                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4898                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4899                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4900                              <1> ;swpd_next:  dd 0 ; next free page block
  4901                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2111                                  %include 'sysdefs.inc' ; 09/03/2015
  2112                              <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.6) - SYSDEFS.INC
  2113                              <1> ; Last Modification: 15/07/2022
  2114                              <1> ;
  2115                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2116                              <1> ; (Modified from 
  2117                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2118                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2119                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2120                              <1> ; ----------------------------------------------------------------------------
  2121                              <1> ;
  2122                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2123                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2124                              <1> ; <Bell Laboratories (17/3/1972)>
  2125                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2126                              <1> ;
  2127                              <1> ; ****************************************************************************
  2128                              <1> 
  2129                              <1> nproc 	equ	16  ; number of processes
  2130                              <1> nfiles 	equ	50
  2131                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2132                              <1> ;nbuf	equ	6   ; number of buffers (04/02/2016)
  2133                              <1> nbuf	equ	8   ; 15/07/2022 
  2134                              <1> 
  2135                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2136                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2137                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2138                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2139                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2140                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2141                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2142                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2143                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2144                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2145                              <1> 	; '/core' dump file size = 32768 bytes
  2146                              <1>  
  2147                              <1> ; 08/03/2014 
  2148                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2149                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feature only !
  2150                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2151                              <1> 
  2152                              <1> ; 30/08/2013
  2153                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2154                              <1> 
  2155                              <1> ; 05/02/2014
  2156                              <1> ; process status
  2157                              <1> ;SFREE 	equ 0
  2158                              <1> ;SRUN	equ 1
  2159                              <1> ;SWAIT	equ 2
  2160                              <1> ;SZOMB	equ 3
  2161                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2162                              <1> 
  2163                              <1> ; 09/03/2015
  2164                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2165                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2166                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2167                              <1> 
  2168                              <1> ; 17/09/2015
  2169                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2170                              <1> 
  2171                              <1> ; 21/09/2015 (36) 
  2172                              <1> ; 01/07/2015 (35)
  2173                              <1> ; 14/07/2013 (0-34)
  2174                              <1> ; UNIX v1 system calls
  2175                              <1> _rele 	equ 0
  2176                              <1> _exit 	equ 1
  2177                              <1> _fork 	equ 2
  2178                              <1> _read 	equ 3
  2179                              <1> _write	equ 4
  2180                              <1> _open	equ 5
  2181                              <1> _close 	equ 6
  2182                              <1> _wait 	equ 7
  2183                              <1> _creat 	equ 8
  2184                              <1> _link 	equ 9
  2185                              <1> _unlink	equ 10
  2186                              <1> _exec	equ 11
  2187                              <1> _chdir	equ 12
  2188                              <1> _time 	equ 13
  2189                              <1> _mkdir 	equ 14
  2190                              <1> _chmod	equ 15
  2191                              <1> _chown	equ 16
  2192                              <1> _break	equ 17
  2193                              <1> _stat	equ 18
  2194                              <1> _seek	equ 19
  2195                              <1> _tell 	equ 20
  2196                              <1> _mount	equ 21
  2197                              <1> _umount	equ 22
  2198                              <1> _setuid	equ 23
  2199                              <1> _getuid	equ 24
  2200                              <1> _stime	equ 25
  2201                              <1> _quit	equ 26	
  2202                              <1> _intr	equ 27
  2203                              <1> _fstat	equ 28
  2204                              <1> _emt 	equ 29
  2205                              <1> _mdate 	equ 30
  2206                              <1> _stty 	equ 31
  2207                              <1> _gtty	equ 32
  2208                              <1> _ilgins	equ 33
  2209                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2210                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2211                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2212                              <1> 
  2213                              <1> %macro sys 1-4
  2214                              <1>     ; 13/04/2015
  2215                              <1>     ; Retro UNIX 386 v1 system call.		
  2216                              <1>     mov eax, %1
  2217                              <1>     %if %0 >= 2   
  2218                              <1>         mov ebx, %2
  2219                              <1>         %if %0 >= 3    
  2220                              <1>             mov ecx, %3
  2221                              <1>             %if %0 = 4
  2222                              <1>                mov edx, %4   
  2223                              <1>             %endif
  2224                              <1>         %endif
  2225                              <1>     %endif
  2226                              <1>     int 30h	   
  2227                              <1> %endmacro
  2228                              <1> 
  2229                              <1> ; 13/05/2015 - ERROR CODES
  2230                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2231                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2232                              <1> ; 14/05/2015
  2233                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2234                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2235                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2236                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2237                              <1> ; 16/05/2015		
  2238                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2239                              <1> ; 18/05/2015
  2240                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2241                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2242                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2243                              <1> ; 07/06/2015
  2244                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2245                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2246                              <1> ; 09/06/2015
  2247                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2248                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2249                              <1> ; 16/06/2015
  2250                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2251                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2252                              <1> ; 22/06/2015
  2253                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2254                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2255                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2256                              <1> ; 23/06/2015
  2257                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2258                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2259                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2260                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2261                              <1> ; 27/06/2015
  2262                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2263                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2264                              <1> ; 29/06/2015
  2265                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2266                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2267                              <1> ; 08/02/2022 
  2268                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2269                              <1> ; 10/10/2016
  2270                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2271                              <1> ; 18/05/2016
  2272                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2273                              <1> ; 15/10/2016
  2274                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2275                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2276                              <1> ; 16/10/2016
  2277                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2278                              <1> ; 08/02/2022
  2279                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2280                              <1> 
  2281                              <1> ; 13/06/2022
  2282                              <1> ; printer errors
  2283                              <1> ERR_PRN_NOT_RDY	   equ 15 ; 'device not ready !' error
  2284                              <1> ERR_PRN_TIMEOUT	   equ 25 ; 'time out !' error
  2285                              <1> ERR_PRN_PAPER	   equ 31 ; 'out of paper !' error
  2286                              <1> ERR_PRN_IO	   equ 32 ; 'io error !' error
  2287                              <1> ERR_PRN_BUSY	   equ 34 ; 'busy !' error
  2288                              <1> 
  2289                              <1> ; 26/08/2015
  2290                              <1> ; 24/07/2015
  2291                              <1> ; 24/06/2015
  2292                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2293                              <1> ; 01/07/2015
  2294                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2295                              <1> ; 24/12/2021
  2296                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2112                                  %include 'u0.s'        ; 15/03/2015
  2113                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS0.INC
  2114                              <1> ; Last Modification: 17/07/2022
  2115                              <1> ; ----------------------------------------------------------------------------
  2116                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2117                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2118                              <1> ;
  2119                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2120                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2121                              <1> ; <Bell Laboratories (17/3/1972)>
  2122                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2123                              <1> ;
  2124                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2125                              <1> ;
  2126                              <1> ; ****************************************************************************
  2127                              <1> 
  2128                              <1> sys_init:
  2129                              <1> 	; 26/02/2022
  2130                              <1> 	; 08/01/2022
  2131                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2132                              <1> 	; 18/10/2015
  2133                              <1> 	; 28/08/2015
  2134                              <1> 	; 24/08/2015
  2135                              <1> 	; 14/08/2015
  2136                              <1> 	; 24/07/2015 
  2137                              <1> 	; 02/07/2015
  2138                              <1> 	; 01/07/2015
  2139                              <1> 	; 23/06/2015
  2140                              <1> 	; 15/04/2015
  2141                              <1> 	; 13/03/2015
  2142                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2143                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2144                              <1> 	;
  2145                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2146                              <1> 	;
  2147                              <1> 	; 14/02/2014
  2148                              <1> 	; 14/07/2013
  2149                              <1> 	;;mov	ax, 41
  2150                              <1> 	; 24/12/2021
  2151                              <1> 	;xor	eax, eax
  2152                              <1> 	;mov	al, 41
  2153                              <1> 	;mov	[rootdir], ax
  2154                              <1> 	;mov	[u.cdir], ax
  2155                              <1> 	;;and	al, 1 ; 15/04/2015
  2156                              <1> 	;inc	al  ; ax = 1
  2157 000029BC B001                <1> 	mov	al, 1
  2158 000029BE A2[4B660000]        <1> 	mov	[u.uno], al
  2159                              <1> 	;mov	[mpid], ax
  2160                              <1> 	;mov	[p.pid], ax
  2161 000029C3 A2[EA650000]        <1> 	mov	[mpid], al
  2162 000029C8 A2[14630000]        <1> 	mov	[p.pid], al	
  2163 000029CD A2[74630000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2164                              <1> 	; 24/12/2021
  2165 000029D2 B029                <1> 	mov	al, 41
  2166                              <1> 	;mov	[rootdir], ax
  2167                              <1> 	;mov	[u.cdir], ax
  2168 000029D4 A2[EC650000]        <1> 	mov	[rootdir], al
  2169 000029D9 A2[00660000]        <1> 	mov	[u.cdir], al
  2170                              <1> 	;
  2171 000029DE B004                <1> 	mov	al, time_count ; 30/08/2013
  2172 000029E0 A2[3E660000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2173                              <1> 	; 02/07/2015
  2174 000029E5 A1[38620000]        <1> 	mov	eax, [k_page_dir]
  2175                              <1> 	;sub	eax, eax
  2176 000029EA A3[55660000]        <1> 	mov	[u.pgdir], eax ; reset
  2177                              <1> 	; 18/10/2015
  2178                              <1> 	;mov	[u.ppgdir], eax ; 0
  2179                              <1> 	; 26/02/2022
  2180                              <1>  	;call	epoch
  2181                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2182                              <1> 	; 17/07/2013
  2183 000029EF E881060000          <1> 	call 	bf_init ; buffer initialization
  2184                              <1> 	; 26/02/2022
  2185                              <1> 	; (save sysinit time on sb0)
  2186 000029F4 E829030000          <1> 	call	epoch
  2187 000029F9 A3[58780000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2188                              <1> 	; 23/06/2015
  2189 000029FE E8C4FAFFFF          <1> 	call	allocate_page
  2190                              <1> 	;;jc	error
  2191                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2192                              <1> 	; 24/12/2021
  2193 00002A03 7305                <1> 	jnc	short sysinit_1
  2194 00002A05 E989000000          <1> 	jmp	panic
  2195                              <1> sysinit_1:
  2196 00002A0A A3[4C660000]        <1> 	mov	[u.upage], eax ; user structure page	
  2197 00002A0F A3[84630000]        <1> 	mov	[p.upage], eax
  2198                              <1> 	;
  2199 00002A14 E81FFBFFFF          <1> 	call	clear_page
  2200                              <1> 	;
  2201                              <1> 	; 14/08/2015
  2202 00002A19 FA                  <1> 	cli
  2203                              <1> 	; 14/03/2015
  2204                              <1> 	; 17/01/2014
  2205 00002A1A E8D0010000          <1> 	call	sp_init ; serial port initialization
  2206                              <1> 	; 14/08/2015
  2207 00002A1F FB                  <1> 	sti
  2208                              <1> 	;
  2209                              <1> 	; 30/06/2015
  2210                              <1> 	;mov	esi, kernel_init_ok_msg
  2211                              <1> 	;call 	print_msg
  2212                              <1> 	;
  2213 00002A20 30DB                <1> 	xor	bl, bl ; video page 0
  2214                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2215 00002A22 E8410F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2216 00002A27 FEC3                <1> 	inc	bl
  2217 00002A29 80FB08              <1> 	cmp	bl, 8
  2218 00002A2C 72F4                <1> 	jb	short vp_clr_nxt
  2219                              <1> 	;
  2220                              <1> 	; 24/07/2015
  2221                              <1> 	;push    KDATA
  2222                              <1>         ;push    esp
  2223                              <1> 	;mov	[tss.esp0], esp
  2224                              <1>         ;mov     word [tss.ss0], KDATA
  2225                              <1> 	;
  2226                              <1> 	; 08/01/2022
  2227                              <1> 	; 24/08/2015
  2228                              <1> 	;; temporary (01/07/2015)
  2229                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2230                              <1> 			       ; it is not needed here !
  2231                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2232 00002A2E FE0D[F3650000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2233                              <1> 			      ; 0 = executing a system call
  2234                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2235                              <1> 	;
  2236                              <1> 	;;; 06/08/2015
  2237                              <1> 	;;;call	getch ; wait for a key stroke
  2238                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2239                              <1> ;;sys_init_msg_wait:
  2240                              <1> ;;	push 	ecx
  2241                              <1> ;;	mov	al, 1
  2242                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2243                              <1> ;;	call	getc_n
  2244                              <1> ;;	pop	ecx
  2245                              <1> ;;	jnz	short sys_init_msg_ok
  2246                              <1> ;;	loop	sys_init_msg_wait
  2247                              <1> 	;
  2248                              <1> ;;sys_init_msg_ok:
  2249                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2250 00002A34 6A10                <1> 	push	KDATA ; ss
  2251 00002A36 54                  <1> 	push	esp
  2252 00002A37 9C                  <1> 	pushfd
  2253 00002A38 6A08                <1> 	push	KCODE ; cs
  2254 00002A3A 68[672A0000]        <1> 	push	init_exec ; eip
  2255 00002A3F 8925[F4650000]      <1> 	mov	[u.sp], esp
  2256 00002A45 1E                  <1> 	push	ds
  2257 00002A46 06                  <1> 	push	es
  2258 00002A47 0FA0                <1> 	push	fs
  2259 00002A49 0FA8                <1> 	push	gs	
  2260 00002A4B 60                  <1> 	pushad
  2261 00002A4C 8925[F8650000]      <1> 	mov	[u.usp], esp
  2262 00002A52 E8AD1B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2263                              <1> 		      ; and interrupt return components (for IRET)
  2264 00002A57 61                  <1> 	popad
  2265 00002A58 6658                <1> 	pop	ax ; gs
  2266 00002A5A 6658                <1> 	pop	ax ; fs
  2267 00002A5C 6658                <1> 	pop	ax ; es
  2268 00002A5E 6658                <1> 	pop	ax ; ds	
  2269 00002A60 58                  <1> 	pop	eax ; eip (init_exec)
  2270 00002A61 6658                <1> 	pop	ax ; cs (KCODE)
  2271 00002A63 58                  <1> 	pop	eax ; E-FLAGS
  2272 00002A64 58                  <1> 	pop	eax ; esp
  2273 00002A65 6658                <1> 	pop	ax ; ss (KDATA)
  2274                              <1> 	;
  2275                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2276                              <1> 	;xor	eax, eax ; 0
  2277                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2278                              <1> 	;
  2279                              <1> 	; 02/07/2015
  2280                              <1> 	; [u.pgdir ] = [k_page_dir]
  2281                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2282                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2283                              <1> init_exec:
  2284                              <1> 	; 13/03/2013
  2285                              <1> 	; 24/07/2013
  2286 00002A67 BB[892A0000]        <1> 	mov	ebx, init_file
  2287 00002A6C B9[812A0000]        <1> 	mov	ecx, init_argp
  2288                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2289                              <1> 	; ECX contains address of argument list pointer
  2290                              <1> 	;
  2291                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2292                              <1> 			      ; 0 = executing a system call
  2293                              <1> 	sys	_exec  ; execute file
  2214                              <2> 
  2215                              <2> 
  2216 00002A71 B80B000000          <2>  mov eax, %1
  2217                              <2>  %if %0 >= 2
  2218                              <2>  mov ebx, %2
  2219                              <2>  %if %0 >= 3
  2220                              <2>  mov ecx, %3
  2221                              <2>  %if %0 = 4
  2222                              <2>  mov edx, %4
  2223                              <2>  %endif
  2224                              <2>  %endif
  2225                              <2>  %endif
  2226 00002A76 CD30                <2>  int 30h
  2294 00002A78 7319                <1> 	jnc	short panic
  2295                              <1> 	;
  2296 00002A7A BE[505F0000]        <1> 	mov	esi, etc_init_err_msg
  2297                              <1> 	; 08/01/2022
  2298                              <1> 	;call 	print_msg
  2299 00002A7F EB17                <1> 	jmp	short key_to_reboot
  2300                              <1> 
  2301                              <1> ;align 4
  2302                              <1> init_argp:
  2303 00002A81 [892A0000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2304                              <1> init_file:
  2305                              <1> 	; 24/08/2015
  2306 00002A89 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2306 00002A92 00                  <1>
  2307                              <1> panic:
  2308                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2309                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2310 00002A93 BE[355F0000]        <1> 	mov 	esi, panic_msg
  2311                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2312 00002A98 E819000000          <1> 	call 	print_msg
  2313                              <1> ;key_to_reboot:
  2314                              <1> 	; 15/11/2015
  2315 00002A9D E8D82B0000          <1> 	call 	getch 
  2316                              <1> 		; wait for a character from the current tty
  2317                              <1> 	;
  2318 00002AA2 B00A                <1> 	mov	al, 0Ah
  2319 00002AA4 8A1D[66620000]      <1> 	mov	bl, [ptty] ; [active_page]
  2320 00002AAA B407                <1> 	mov	ah, 07h ; Black background, 
  2321                              <1> 			; light gray forecolor
  2322 00002AAC E8F1E8FFFF          <1> 	call 	write_tty
  2323 00002AB1 E990E5FFFF          <1> 	jmp	cpu_reset 
  2324                              <1> 
  2325                              <1> print_msg:
  2326                              <1> 	; 01/07/2015
  2327                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2328                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2329                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2330                              <1> 	;
  2331                              <1> 	;
  2332 00002AB6 AC                  <1> 	lodsb
  2333                              <1> pmsg1:
  2334 00002AB7 56                  <1> 	push 	esi
  2335 00002AB8 0FB61D[66620000]    <1> 	movzx	ebx, byte [ptty]
  2336 00002ABF B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2337 00002AC1 E8DCE8FFFF          <1> 	call 	write_tty
  2338 00002AC6 5E                  <1> 	pop	esi
  2339 00002AC7 AC                  <1> 	lodsb
  2340 00002AC8 20C0                <1> 	and 	al, al
  2341 00002ACA 75EB                <1> 	jnz 	short pmsg1
  2342 00002ACC C3                  <1> 	retn
  2343                              <1> 	
  2344                              <1> ctrlbrk:
  2345                              <1> 	; 04/02/2022
  2346                              <1> 	; 01/02/2022
  2347                              <1> 	; 12/11/2015
  2348                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2349                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2350                              <1> 	;
  2351                              <1> 	; INT 1Bh (control+break) handler
  2352                              <1> 	;
  2353                              <1>       	; Retro Unix 8086 v1 feature only!
  2354                              <1>       	;
  2355 00002ACD 66833D[40660000]00  <1> 	cmp 	word [u.intr], 0
  2356 00002AD5 764B                <1> 	jna 	short cbrk4
  2357                              <1> cbrk0:
  2358                              <1> 	; 12/11/2015
  2359                              <1> 	; 06/12/2013
  2360 00002AD7 66833D[42660000]00  <1> 	cmp 	word [u.quit], 0
  2361 00002ADF 7441                <1> 	jz	short cbrk4
  2362                              <1> 	;
  2363                              <1> 	; 20/09/2013	
  2364                              <1> 	;push 	ax
  2365                              <1> 	; 01/02/2022
  2366 00002AE1 50                  <1> 	push	eax
  2367                              <1> 
  2368                              <1> 	; 04/02/2022
  2369                              <1> 	; (repetitive ctrl+brk check) 
  2370 00002AE2 66A1[42660000]      <1> 	mov	ax, [u.quit]
  2371 00002AE8 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2372 00002AEA 7435                <1> 	jz	short cbrk3
  2373                              <1> 
  2374                              <1> 	; 20/09/2013
  2375 00002AEC A0[66620000]        <1> 	mov	al, [ptty]
  2376                              <1> 	;
  2377                              <1> 	; 12/11/2015
  2378                              <1> 	;
  2379                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2380                              <1> 	; or ctrl+break from console (pseudo) tty
  2381                              <1> 	; (!redirection!)
  2382                              <1> 	;
  2383 00002AF1 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2384 00002AF3 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2385                              <1> 	;	
  2386                              <1> 	; Serial port interrupt handler sets [ptty]
  2387                              <1> 	; to the port's tty number (as temporary).
  2388                              <1> 	;
  2389                              <1> 	; If active process is using a stdin or 
  2390                              <1> 	; stdout redirection (by the shell),
  2391                              <1>         ; console tty keyboard must be available
  2392                              <1> 	; to terminate running process,
  2393                              <1> 	; in order to prevent a deadlock. 
  2394                              <1> 	;
  2395 00002AF5 52                  <1> 	push	edx
  2396 00002AF6 0FB615[4B660000]    <1> 	movzx	edx, byte [u.uno]
  2397 00002AFD 3A82[53630000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2398 00002B03 5A                  <1> 	pop	edx
  2399 00002B04 7412                <1> 	je	short cbrk2
  2400                              <1> cbrk1:
  2401 00002B06 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2402                              <1> 	; 06/12/2013
  2403 00002B08 3A05[2C660000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2404 00002B0E 7408                <1> 	je	short cbrk2	
  2405 00002B10 3A05[2D660000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2406 00002B16 7509                <1> 	jne	short cbrk3	
  2407                              <1> cbrk2:
  2408                              <1> 	;; 06/12/2013
  2409                              <1> 	;mov	ax, [u.quit]
  2410                              <1> 	;and	ax, ax
  2411                              <1> 	;jz	short cbrk3
  2412                              <1> 	;
  2413                              <1> 	;xor	ax, ax ; 0
  2414                              <1> 	;dec	ax
  2415                              <1> 	; 01/02/2022
  2416 00002B18 31C0                <1> 	xor	eax, eax ; 0
  2417 00002B1A 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2418                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2419 00002B1B 66A3[42660000]      <1> 	mov	[u.quit], ax
  2420                              <1> cbrk3:
  2421                              <1> 	;pop	ax
  2422                              <1> 	; 01/02/2022
  2423 00002B21 58                  <1> 	pop	eax
  2424                              <1> cbrk4:
  2425 00002B22 C3                  <1> 	retn
  2426                              <1> 
  2427                              <1> com2_int:
  2428                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2429                              <1> 	; 07/11/2015 
  2430                              <1> 	; 24/10/2015
  2431                              <1> 	; 23/10/2015
  2432                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2433                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2434                              <1> 	; < serial port 2 interrupt handler >
  2435                              <1> 	;
  2436 00002B23 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2437                              <1> 	;;push	eax
  2438                              <1> 	; 08/01/2022
  2439 00002B26 29C0                <1> 	sub	eax, eax
  2440 00002B28 B009                <1> 	mov	al, 9
  2441                              <1> 	;mov	ax, 9
  2442 00002B2A EB07                <1> 	jmp	short comm_int
  2443                              <1> com1_int:
  2444                              <1> 	; 07/11/2015
  2445                              <1> 	; 24/10/2015
  2446 00002B2C 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2447                              <1> 	; 23/10/2015
  2448                              <1> 	;push	eax
  2449                              <1> 	; 08/01/2022
  2450 00002B2F 29C0                <1> 	sub	eax, eax
  2451 00002B31 B008                <1> 	mov	al, 8
  2452                              <1> 	;mov	ax, 8
  2453                              <1> comm_int:
  2454                              <1> 	; 08/01/2022
  2455                              <1> 	; 20/11/2015
  2456                              <1> 	; 18/11/2015
  2457                              <1> 	; 17/11/2015
  2458                              <1> 	; 16/11/2015
  2459                              <1> 	; 09/11/2015
  2460                              <1> 	; 08/11/2015
  2461                              <1> 	; 07/11/2015
  2462                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2463                              <1> 	; 01/11/2015
  2464                              <1> 	; 26/10/2015
  2465                              <1> 	; 23/10/2015
  2466 00002B33 53                  <1> 	push	ebx
  2467 00002B34 56                  <1> 	push	esi
  2468 00002B35 57                  <1> 	push	edi
  2469 00002B36 1E                  <1> 	push 	ds
  2470 00002B37 06                  <1> 	push 	es
  2471                              <1> 	; 18/11/2015
  2472 00002B38 0F20DB              <1> 	mov	ebx, cr3
  2473 00002B3B 53                  <1> 	push	ebx ; ****
  2474                              <1> 	;
  2475 00002B3C 51                  <1> 	push	ecx ; ***
  2476 00002B3D 52                  <1> 	push	edx ; **
  2477                              <1> 	;
  2478 00002B3E BB10000000          <1> 	mov	ebx, KDATA
  2479 00002B43 8EDB                <1> 	mov	ds, bx
  2480 00002B45 8EC3                <1> 	mov	es, bx
  2481                              <1> 	;
  2482 00002B47 8B0D[38620000]      <1> 	mov	ecx, [k_page_dir]
  2483 00002B4D 0F22D9              <1> 	mov	cr3, ecx
  2484                              <1> 	; 20/11/2015
  2485                              <1> 	; Interrupt identification register
  2486 00002B50 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2487                              <1> 	;
  2488 00002B54 3C08                <1> 	cmp 	al, 8 
  2489 00002B56 7702                <1> 	ja 	short com_i0
  2490                              <1> 	;
  2491                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2492                              <1> 	; 20/11/2015
  2493                              <1> 	; 17/11/2015
  2494                              <1> 	; 16/11/2015
  2495                              <1> 	; 15/11/2015
  2496                              <1> 	; 24/10/2015
  2497                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2498                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2499                              <1> 	; < serial port 1 interrupt handler >
  2500                              <1> 	;
  2501 00002B58 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2502                              <1> com_i0:
  2503                              <1> 	;push	eax ; *
  2504                              <1> 	; 07/11/2015
  2505 00002B5A A2[A6620000]        <1> 	mov 	byte [ccomport], al
  2506                              <1> 	; 09/11/2015
  2507                              <1> 	;movzx	ebx, ax ; 8 or 9
  2508                              <1> 	; 08/01/2022
  2509 00002B5F 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2510                              <1> 	; 17/11/2015
  2511                              <1>  	; reset request for response status
  2512 00002B61 88A3[9C620000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2513                              <1> 	;
  2514                              <1> 	; 20/11/2015
  2515 00002B67 EC                  <1> 	in	al, dx		; read interrupt id. register
  2516 00002B68 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2517 00002B6A 2404                <1> 	and	al, 4		; received data available?	
  2518 00002B6C 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2519                              <1> 	;
  2520                              <1> 	; 20/11/2015
  2521 00002B6E 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2522 00002B71 EC                  <1> 	in	al, dx     	; read character
  2523                              <1> 	;JMP	$+2	   	; I/O DELAY
  2524                              <1> 	; 08/11/2015
  2525                              <1> 	; 07/11/2015
  2526 00002B72 89DE                <1> 	mov	esi, ebx 
  2527 00002B74 89DF                <1> 	mov	edi, ebx
  2528 00002B76 81C6[A0620000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2529 00002B7C 81C7[A2620000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2530 00002B82 8806                <1> 	mov	[esi], al ; received char (current char)
  2531                              <1> 	; query
  2532 00002B84 20C0                <1> 	and	al, al
  2533 00002B86 7527                <1> 	jnz	short com_i2
  2534                              <1>    	; response
  2535                              <1> 	; 17/11/2015
  2536                              <1> 	; set request for response status
  2537 00002B88 FE83[9C620000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2538                              <1> 	;
  2539 00002B8E 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2540 00002B92 EC                  <1> 	in	al, dx	   	; read line status register 
  2541 00002B93 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2542 00002B95 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2543 00002B97 7445                <1> 	jz	short com_eoi 	; no
  2544 00002B99 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2545 00002B9B 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2546 00002B9F EE                  <1> 	out	dx, al	   	; send on serial port
  2547                              <1> 	; 17/11/2015
  2548 00002BA0 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2549 00002BA3 7502                <1> 	jne 	short com_i1    ; no
  2550 00002BA5 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2551                              <1> com_i1:
  2552                              <1> 	; 17/11/2015
  2553                              <1> 	; reset request for response status (again)
  2554 00002BA7 FE8B[9C620000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2555 00002BAD EB2F                <1> 	jmp	short com_eoi
  2556                              <1> com_i2:	
  2557                              <1> 	; 08/11/2015
  2558 00002BAF 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2559 00002BB1 7417                <1> 	je	short com_i3	; (check for response signal)
  2560                              <1> 	; 07/11/2015
  2561 00002BB3 3C04                <1> 	cmp	al, 04h	; EOT
  2562 00002BB5 751C                <1> 	jne	short com_i4	
  2563                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2564                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2565                              <1> 	; 08/11/2015
  2566                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2567 00002BB7 861D[66620000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2568 00002BBD E80BFFFFFF          <1> 	call 	ctrlbrk
  2569 00002BC2 861D[66620000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2570                              <1> 	;mov	al, 04h ; EOT
  2571                              <1> 	; 08/11/2015
  2572 00002BC8 EB09                <1> 	jmp	short com_i4	
  2573                              <1> com_i3:
  2574                              <1> 	; 08/11/2015
  2575                              <1> 	; If 0FFh has been received just after a query
  2576                              <1> 	; (schar, ZERO), it is a response signal.
  2577                              <1> 	; 17/11/2015
  2578 00002BCA 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2579 00002BCD 7704                <1> 	ja	short com_i4 ; no
  2580                              <1> 	; reset query status (schar)
  2581 00002BCF 8807                <1> 	mov	[edi], al ; 0FFh
  2582 00002BD1 FEC0                <1> 	inc	al ; 0
  2583                              <1> com_i4:
  2584                              <1> 	; 27/07/2014
  2585                              <1> 	; 09/07/2014
  2586 00002BD3 D0E3                <1> 	shl	bl, 1	
  2587 00002BD5 81C3[68620000]      <1> 	add	ebx, ttychr
  2588                              <1> 	; 23/07/2014 (always overwrite)
  2589                              <1> 	;;cmp	word [ebx], 0
  2590                              <1> 	;;ja	short com_eoi
  2591                              <1> 	;
  2592 00002BDB 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2593                              <1> 			    ; scan code = 0
  2594                              <1> com_eoi:
  2595                              <1> 	;mov	al, 20h
  2596                              <1> 	;out	20h, al	   ; end of interrupt
  2597                              <1> 	;
  2598                              <1> 	; 07/11/2015
  2599                              <1>       	;pop	eax ; *
  2600 00002BDE A0[A6620000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2601                              <1> 	; al = tty number (8 or 9)
  2602 00002BE3 E8F61A0000          <1>         call	wakeup
  2603                              <1> com_iret:
  2604                              <1> 	; 23/10/2015
  2605 00002BE8 5A                  <1> 	pop	edx ; **
  2606 00002BE9 59                  <1> 	pop	ecx ; ***
  2607                              <1> 	; 18/11/2015
  2608                              <1> 	;pop	eax ; ****
  2609                              <1> 	;mov	cr3, eax
  2610                              <1> 	;jmp	iiret
  2611 00002BEA E995DDFFFF          <1> 	jmp	iiretp
  2612                              <1> 
  2613                              <1> ;iiretp: ; 01/09/2015
  2614                              <1> ;	; 28/08/2015
  2615                              <1> ;	pop	eax ; (*) page directory
  2616                              <1> ;	mov	cr3, eax
  2617                              <1> ;iiret:
  2618                              <1> ;	; 22/08/2014
  2619                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2620                              <1> ;	out	20h, al	; 8259 PORT
  2621                              <1> ;	;
  2622                              <1> ;	pop	es
  2623                              <1> ;	pop	ds
  2624                              <1> ;	pop	edi
  2625                              <1> ;	pop	esi
  2626                              <1> ;	pop	ebx ; 29/08/2014
  2627                              <1> ;	pop 	eax
  2628                              <1> ;	iretd
  2629                              <1> 
  2630                              <1> sp_init:
  2631                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2632                              <1> 	; 07/11/2015
  2633                              <1> 	; 29/10/2015
  2634                              <1> 	; 26/10/2015
  2635                              <1> 	; 23/10/2015
  2636                              <1> 	; 29/06/2015
  2637                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2638                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2639                              <1> 	; Initialization of Serial Port Communication Parameters
  2640                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2641                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2642                              <1> 	;
  2643                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2644                              <1> 	;
  2645                              <1> 	; INPUT:  (29/06/2015)
  2646                              <1> 	;	AL = 0 for COM1
  2647                              <1> 	;	     1 for COM2
  2648                              <1> 	;	AH = Communication parameters	
  2649                              <1> 	;
  2650                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2651                              <1> 	;	Bit	4	3	2	1	0
  2652                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2653                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2654                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2655                              <1> 	;		11 = even
  2656                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2657                              <1> 	;		Retro UNIX 386 v1 feature only !
  2658                              <1> 	;	Bit	7    6    5  | Baud rate
  2659                              <1> 	;		------------------------
  2660                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2661                              <1> 	;		0    0    1  | 9600 (12)
  2662                              <1> 	;		0    1    0  | 19200 (6) 
  2663                              <1> 	;		0    1	  1  | 38400 (3) 
  2664                              <1> 	;		1    0	  0  | 14400 (8)
  2665                              <1> 	;		1    0	  1  | 28800 (4)
  2666                              <1> 	;		1    1    0  | 57600 (2)
  2667                              <1> 	;		1    1    1  | 115200 (1) 	
  2668                              <1> 	
  2669                              <1> 	; References:	
  2670                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2671                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2672                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2673                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2674                              <1> 	;
  2675                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2676                              <1> 	;
  2677 00002BEF BB[A2620000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2678 00002BF4 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2679                              <1> 	; 29/10/2015
  2680 00002BF8 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2681 00002BFC E84F000000          <1> 	call	sp_i3	; call A4	
  2682 00002C01 A880                <1> 	test	al, 80h
  2683 00002C03 740E                <1> 	jz	short sp_i0 ; OK..
  2684                              <1> 		; Error !
  2685                              <1> 	;mov	dx, 3F8h
  2686 00002C05 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2687                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2688                              <1> 	; 08/01/2022
  2689 00002C08 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2690 00002C0A E841000000          <1> 	call	sp_i3	; call A4	
  2691 00002C0F A880                <1> 	test	al, 80h
  2692 00002C11 7508                <1> 	jnz	short sp_i1
  2693                              <1> sp_i0:
  2694                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2695                              <1>         ; (INT 14h initialization code disables interrupts.)
  2696                              <1> 	;
  2697 00002C13 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2698 00002C16 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2699                              <1> sp_i1:
  2700 00002C1B 43                  <1> 	inc	ebx
  2701 00002C1C 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2702                              <1> 	; 29/10/2015
  2703                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2704                              <1> 	; 08/01/2022
  2705 00002C20 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2706 00002C22 E829000000          <1> 	call	sp_i3	; call A4	
  2707 00002C27 A880                <1> 	test	al, 80h
  2708 00002C29 740E                <1> 	jz	short sp_i2 ; OK..
  2709                              <1> 		; Error !
  2710                              <1> 	;mov	dx, 2F8h
  2711 00002C2B 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2712                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2713                              <1> 	; 08/01/2022
  2714 00002C2E B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2715 00002C30 E81B000000          <1> 	call	sp_i3	; call A4	
  2716 00002C35 A880                <1> 	test	al, 80h
  2717 00002C37 7516                <1> 	jnz	short sp_i7
  2718                              <1> sp_i2:
  2719 00002C39 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2720                              <1> sp_i6:
  2721                              <1> 	;; COM2 - enabling IRQ 3
  2722                              <1> 	; 08/01/2022
  2723 00002C3C B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2724                              <1> 	; 07/11/2015
  2725                              <1> 	; 26/10/2015
  2726                              <1> 	;pushf
  2727                              <1> 	;cli
  2728                              <1> 	;;
  2729                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2730                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2731                              <1> 	;in	al, dx 	   		; read register
  2732                              <1> 	;JMP	$+2	   		; I/O DELAY
  2733                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2734                              <1> 	;out	dx, al     		; write back to register
  2735                              <1> 	;JMP	$+2	   		; I/O DELAY
  2736                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2737                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2738                              <1> 	;in	al, dx     		; read register
  2739                              <1> 	;JMP	$+2	   		; I/O DELAY
  2740                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2741                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2742                              <1> 	;out	dx, al 	   		; write back to register
  2743                              <1> 	;JMP	$+2        		; I/O DELAY
  2744                              <1> 	;in	al, 21h    		; read interrupt mask register
  2745                              <1> 	;JMP	$+2	   		; I/O DELAY
  2746                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2747                              <1> 	;out	21h, al    		; write back to register
  2748                              <1> 	;
  2749                              <1> 	; 08/01/2022
  2750 00002C3E 9C                  <1> 	pushf
  2751 00002C3F E8AA000000          <1> 	call	sp_i8
  2752                              <1> 	; 23/10/2015
  2753 00002C44 B8[232B0000]        <1> 	mov 	eax, com2_int
  2754 00002C49 A3[D4300000]        <1> 	mov	[com2_irq3], eax
  2755                              <1> 	; 26/10/2015
  2756 00002C4E 9D                  <1> 	popf	
  2757                              <1> sp_i7:
  2758 00002C4F C3                  <1> 	retn
  2759                              <1> 
  2760                              <1> sp_i3:
  2761                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2762                              <1> 	; 28/10/2015
  2763 00002C50 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2764 00002C52 B000                <1> 	mov	al, 0
  2765 00002C54 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2766 00002C55 EB00                <1> 	JMP	$+2			; I/O DELAY
  2767 00002C57 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2768 00002C5A B080                <1> 	mov	al, 80h			
  2769 00002C5C EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2770                              <1> 	;-----	SET BAUD RATE DIVISOR
  2771                              <1> 	; 26/10/2015
  2772 00002C5D 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2773                              <1> 					; of the divisor value
  2774 00002C60 88C8                <1> 	mov	al, cl	; 1
  2775 00002C62 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2776                              <1> 					; 2 = 57600 baud
  2777                              <1> 					; 3 = 38400 baud
  2778                              <1> 					; 6 = 19200 baud
  2779                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2780 00002C63 EB00                <1> 	JMP	$+2			; I/O DELAY
  2781 00002C65 28C0                <1> 	sub	al, al
  2782 00002C67 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2783                              <1> 					; of the divisor value
  2784 00002C69 EE                  <1> 	out	dx, al ; 0
  2785 00002C6A EB00                <1> 	JMP	$+2			; I/O DELAY
  2786                              <1> 	;	
  2787 00002C6C 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2788                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2789 00002C6E 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2790 00002C71 EE                  <1> 	out	dx, al			
  2791 00002C72 EB00                <1> 	JMP	$+2			; I/O DELAY
  2792                              <1> 	; 29/10/2015
  2793 00002C74 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2794 00002C76 30C0                <1> 	xor	al, al			; 0
  2795 00002C78 EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2796 00002C79 EB00                <1> 	JMP	$+2	
  2797                              <1> sp_i4:
  2798                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2799                              <1> 	; 29/06/2015 (line status after modem status)
  2800 00002C7B 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2801                              <1> sp_i4s:
  2802 00002C7E EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2803 00002C7F EB00                <1> 	JMP	$+2			; I/O DELAY
  2804 00002C81 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2805 00002C83 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2806                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2807 00002C85 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2808                              <1> 	; AL = Line status, AH = Modem status
  2809 00002C86 C3                  <1> 	retn
  2810                              <1> 
  2811                              <1> sp_status:
  2812                              <1> 	; 29/06/2015
  2813                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2814                              <1> 	; Get serial port status
  2815 00002C87 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2816 00002C8B 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2817                              <1> 					; dx = 2FEh for COM2
  2818 00002C8D EBEF                <1> 	jmp	short sp_i4s
  2819                              <1> 
  2820                              <1> sp_setp: ; Set serial port communication parameters
  2821                              <1> 	; 08/01/2022
  2822                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2823                              <1> 	; 07/11/2015
  2824                              <1> 	; 29/10/2015
  2825                              <1> 	; 29/06/2015
  2826                              <1> 	; Retro UNIX 386 v1 feature only !	
  2827                              <1> 	;
  2828                              <1> 	; INPUT:
  2829                              <1> 	;	AL = 0 for COM1
  2830                              <1> 	;	     1 for COM2
  2831                              <1> 	;	AH = Communication parameters (*)
  2832                              <1> 	; OUTPUT:
  2833                              <1> 	;	CL = Line status
  2834                              <1> 	;	CH = Modem status
  2835                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2836                              <1> 	;		 'invalid parameter !' 
  2837                              <1> 	;		 	 or
  2838                              <1> 	;		 'device not ready !' error
  2839                              <1> 	;	
  2840                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2841                              <1> 	;	Bit	4	3	2	1	0
  2842                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2843                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2844                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2845                              <1> 	;		11 = even
  2846                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2847                              <1> 	;		Retro UNIX 386 v1 feature only !
  2848                              <1> 	;	Bit	7    6    5  | Baud rate
  2849                              <1> 	;		------------------------
  2850                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2851                              <1> 	;		0    0    1  | 9600 (12)
  2852                              <1> 	;		0    1    0  | 19200 (6) 
  2853                              <1> 	;		0    1	  1  | 38400 (3) 
  2854                              <1> 	;		1    0	  0  | 14400 (8)
  2855                              <1> 	;		1    0	  1  | 28800 (4)
  2856                              <1> 	;		1    1    0  | 57600 (2)
  2857                              <1> 	;		1    1    1  | 115200 (1) 
  2858                              <1> 	;
  2859                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2860                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2861                              <1> 	;
  2862                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2863                              <1> 	;
  2864 00002C8F 66BAF803            <1> 	mov	dx, 3F8h
  2865 00002C93 BB[A2620000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2866 00002C98 3C01                <1> 	cmp	al, 1
  2867 00002C9A 7770                <1> 	ja 	short sp_invp_err
  2868 00002C9C 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2869 00002C9E FECE                <1> 	dec	dh ; 2F8h
  2870 00002CA0 43                  <1> 	inc	ebx ; COM2 control byte offset
  2871                              <1> sp_setp1:
  2872                              <1> 	; 29/10/2015
  2873 00002CA1 8823                <1> 	mov	[ebx], ah
  2874 00002CA3 0FB6CC              <1> 	movzx 	ecx, ah
  2875 00002CA6 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2876 00002CA9 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2877 00002CAC 8A81[1B2D0000]      <1> 	mov	al, [ecx+b_div_tbl]
  2878 00002CB2 6689C1              <1> 	mov	cx, ax
  2879 00002CB5 E896FFFFFF          <1> 	call	sp_i3
  2880 00002CBA 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2881 00002CBD A880                <1> 	test	al, 80h
  2882 00002CBF 740F                <1> 	jz	short sp_setp2
  2883 00002CC1 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2884                              <1> stp_dnr_err:
  2885 00002CC4 C705[51660000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2885 00002CCC 0000                <1>
  2886                              <1> 	; CL = Line status, CH = Modem status
  2887 00002CCE F9                  <1> 	stc
  2888 00002CCF C3                  <1> 	retn
  2889                              <1> sp_setp2:
  2890 00002CD0 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2891                              <1>         ;jna	sp_i6
  2892                              <1> 		      ; COM1 (3F?h)
  2893                              <1> 	; 24/12/2021
  2894 00002CD3 7705                <1> 	ja	short sp_i5
  2895 00002CD5 E962FFFFFF          <1> 	jmp	sp_i6
  2896                              <1> sp_i5: 
  2897                              <1> 	; 08/01/2022
  2898 00002CDA B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2899                              <1> 	; 07/11/2015
  2900                              <1> 	; 26/10/2015
  2901                              <1> 	; 29/06/2015
  2902                              <1> 	;
  2903                              <1> 	;; COM1 - enabling IRQ 4
  2904                              <1> 	;pushf
  2905                              <1> 	;cli
  2906                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2907                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2908                              <1> 	;in	al, dx 	   		; read register
  2909                              <1> 	;JMP	$+2			; I/O DELAY
  2910                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2911                              <1> 	;out	dx, al     		; write back to register
  2912                              <1> 	;JMP	$+2			; I/O DELAY
  2913                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2914                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2915                              <1> 	;in	al, dx     		; read register
  2916                              <1> 	;JMP	$+2			; I/O DELAY
  2917                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2918                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2919                              <1> 	;out	dx, al 	   		; write back to register
  2920                              <1> 	;JMP	$+2        		; I/O DELAY
  2921                              <1> 	;in	al, 21h    		; read interrupt mask register
  2922                              <1> 	;JMP	$+2			; I/O DELAY
  2923                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2924                              <1> 	;out	21h, al    		; write back to register
  2925                              <1> 	;
  2926                              <1> 	; 08/01/2022
  2927 00002CDC 9C                  <1> 	pushf
  2928 00002CDD E80C000000          <1> 	call	sp_i8
  2929                              <1> 	; 23/10/2015
  2930 00002CE2 B8[2C2B0000]        <1> 	mov 	eax, com1_int
  2931 00002CE7 A3[D0300000]        <1> 	mov	[com1_irq4], eax
  2932                              <1> 	; 26/10/2015
  2933 00002CEC 9D                  <1> 	popf
  2934 00002CED C3                  <1> 	retn
  2935                              <1> 
  2936                              <1> sp_i8:
  2937                              <1> 	; 08/01/2022
  2938                              <1> 	;pushf
  2939 00002CEE FA                  <1> 	cli
  2940                              <1> 	;
  2941                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2942 00002CEF B2FC                <1> 	mov	dl, 0FCh
  2943 00002CF1 EC                  <1> 	in	al, dx 	   		; read register
  2944 00002CF2 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2945 00002CF4 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2946 00002CF6 EE                  <1> 	out	dx, al     		; write back to register
  2947 00002CF7 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2948                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2949 00002CF9 B2F9                <1> 	mov	dl, 0F9h
  2950 00002CFB EC                  <1> 	in	al, dx     		; read register
  2951 00002CFC EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2952                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2953 00002CFE 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2954 00002D00 EE                  <1> 	out	dx, al 	   		; write back to register
  2955 00002D01 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2956 00002D03 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2957 00002D05 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2958                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2959 00002D07 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2960 00002D09 E621                <1> 	out	21h, al    		; write back to register
  2961                              <1> 	;
  2962                              <1> 	;popf	
  2963 00002D0B C3                  <1> 	retn
  2964                              <1> 
  2965                              <1> sp_invp_err:
  2966 00002D0C C705[51660000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2966 00002D14 0000                <1>
  2967 00002D16 31C9                <1> 	xor	ecx, ecx
  2968 00002D18 49                  <1> 	dec	ecx ; 0FFFFh
  2969 00002D19 F9                  <1> 	stc
  2970 00002D1A C3                  <1> 	retn
  2971                              <1> 
  2972                              <1> ; 29/10/2015
  2973                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2974 00002D1B 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2975                              <1> 
  2976                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2977                              <1> epoch:
  2978                              <1> 	; 17/07/2022
  2979                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2980                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2981                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2982                              <1> 	; 'epoch' procedure prototype: 
  2983                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2984                              <1> 	; 14/11/2012
  2985                              <1> 	; unixboot.asm (boot file configuration)
  2986                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2987                              <1> 	; 21/7/2012
  2988                              <1> 	; 15/7/2012
  2989                              <1> 	; 14/7/2012		
  2990                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2991                              <1> 	; compute current date and time as UNIX Epoch/Time
  2992                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2993                              <1> 	;
  2994                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2995                              <1> 	;
  2996 00002D22 E818010000          <1> 	call 	get_rtc_time		; Return Current Time
  2997 00002D27 86E9                <1>         xchg 	ch,cl
  2998 00002D29 66890D[A85F0000]    <1>         mov 	[hour], cx
  2999 00002D30 86F2                <1>         xchg 	dh,dl
  3000 00002D32 668915[AA5F0000]    <1>         mov 	[second], dx
  3001                              <1> 	;
  3002 00002D39 E832010000          <1>         call 	get_rtc_date		; Return Current Date
  3003 00002D3E 86E9                <1>         xchg 	ch,cl
  3004 00002D40 66890D[A45F0000]    <1>         mov 	[year], cx
  3005 00002D47 86F2                <1>         xchg 	dh,dl
  3006 00002D49 668915[A65F0000]    <1>         mov 	[month], dx
  3007                              <1> 	;
  3008 00002D50 66B93030            <1> 	mov 	cx, 3030h
  3009                              <1> 	;
  3010 00002D54 A0[A85F0000]        <1> 	mov 	al, [hour] ; Hour
  3011                              <1>         	; AL <= BCD number)
  3012 00002D59 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3013                              <1> 					; AH = AL / 10h
  3014                              <1> 					; AL = AL MOD 10h
  3015 00002D5B D50A                <1>         aad 	; AX= AH*10+AL
  3016 00002D5D A2[A85F0000]        <1> 	mov 	[hour], al
  3017 00002D62 A0[A95F0000]        <1> 	mov 	al, [hour+1] ; Minute
  3018                              <1>         	; AL <= BCD number)
  3019 00002D67 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3020                              <1> 					; AH = AL / 10h
  3021                              <1> 					; AL = AL MOD 10h
  3022 00002D69 D50A                <1>         aad 	; AX= AH*10+AL
  3023 00002D6B A2[A95F0000]        <1> 	mov 	[minute], al
  3024 00002D70 A0[AA5F0000]        <1> 	mov 	al, [second] ; Second
  3025                              <1>         	; AL <= BCD number)
  3026 00002D75 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3027                              <1> 					; AH = AL / 10h
  3028                              <1> 					; AL = AL MOD 10h
  3029 00002D77 D50A                <1>         aad 	; AX= AH*10+AL
  3030 00002D79 A2[AA5F0000]        <1> 	mov 	[second], al
  3031 00002D7E 66A1[A45F0000]      <1> 	mov 	ax, [year] ; Year (century)
  3032                              <1>  	;push 	ax
  3033                              <1> 	; 08/01/2022
  3034 00002D84 50                  <1> 	push	eax
  3035                              <1> 	   	; AL <= BCD number)
  3036 00002D85 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3037                              <1> 					; AH = AL / 10h
  3038                              <1> 					; AL = AL MOD 10h
  3039 00002D87 D50A                <1>         aad 	; AX= AH*10+AL
  3040 00002D89 B464                <1> 	mov 	ah, 100
  3041 00002D8B F6E4                <1> 	mul 	ah
  3042 00002D8D 66A3[A45F0000]      <1> 	mov 	[year], ax
  3043                              <1> 	;pop	ax
  3044                              <1> 	; 08/01/2022
  3045 00002D93 58                  <1> 	pop	eax
  3046 00002D94 88E0                <1> 	mov	al, ah
  3047                              <1>         	; AL <= BCD number)
  3048 00002D96 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3049                              <1> 					; AH = AL / 10h
  3050                              <1> 					; AL = AL MOD 10h
  3051 00002D98 D50A                <1>         aad 	; AX= AH*10+AL
  3052 00002D9A 660105[A45F0000]    <1> 	add 	[year], ax
  3053 00002DA1 A0[A65F0000]        <1> 	mov 	al, [month] ; Month
  3054                              <1>            	; AL <= BCD number)
  3055 00002DA6 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3056                              <1> 					; AH = AL / 10h
  3057                              <1> 					; AL = AL MOD 10h
  3058 00002DA8 D50A                <1>         aad 	; AX= AH*10+AL
  3059 00002DAA A2[A65F0000]        <1> 	mov 	[month], al	
  3060 00002DAF A0[A75F0000]        <1>         mov     al, [month+1]      	; Day
  3061                              <1>            	; AL <= BCD number)
  3062 00002DB4 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3063                              <1> 					; AH = AL / 10h
  3064                              <1> 					; AL = AL MOD 10h
  3065 00002DB6 D50A                <1>         aad 	; AX= AH*10+AL
  3066 00002DB8 A2[A75F0000]        <1>         mov     [day], al
  3067                              <1> 	
  3068                              <1> convert_to_epoch:
  3069                              <1> 	; 17/07/2022
  3070                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3071                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3072                              <1> 	;
  3073                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3074                              <1> 	;
  3075                              <1> 	; Derived from DALLAS Semiconductor
  3076                              <1> 	; Application Note 31 (DS1602/DS1603)
  3077                              <1> 	; 6 May 1998
  3078 00002DBD 29C0                <1> 	sub 	eax, eax
  3079 00002DBF 66A1[A45F0000]      <1> 	mov 	ax, [year]
  3080 00002DC5 662DB207            <1> 	sub 	ax, 1970
  3081 00002DC9 BA6D010000          <1> 	mov 	edx, 365
  3082 00002DCE F7E2                <1> 	mul 	edx
  3083 00002DD0 31DB                <1> 	xor 	ebx, ebx
  3084 00002DD2 8A1D[A65F0000]      <1> 	mov 	bl, [month]
  3085 00002DD8 FECB                <1> 	dec 	bl
  3086 00002DDA D0E3                <1> 	shl 	bl, 1
  3087                              <1> 	;sub	edx, edx
  3088 00002DDC 668B93[AC5F0000]    <1> 	mov 	dx, [EBX+DMonth]
  3089 00002DE3 8A1D[A75F0000]      <1>         mov     bl, [day]
  3090 00002DE9 FECB                <1> 	dec 	bl
  3091 00002DEB 01D0                <1> 	add 	eax, edx
  3092 00002DED 01D8                <1> 	add 	eax, ebx
  3093                              <1> 			; EAX = days since 1/1/1970
  3094 00002DEF 668B15[A45F0000]    <1> 	mov 	dx, [year]
  3095 00002DF6 6681EAB107          <1> 	sub 	dx, 1969
  3096                              <1> 	;shr 	dx, 1
  3097                              <1> 	;shr 	dx, 1		
  3098                              <1> 	; 17/07/2022
  3099 00002DFB C1EA02              <1> 	shr	edx, 2
  3100                              <1> 		; (year-1969)/4
  3101 00002DFE 01D0                <1> 	add 	eax, edx
  3102                              <1> 			; + leap days since 1/1/1970
  3103 00002E00 803D[A65F0000]02    <1> 	cmp 	byte [month], 2	; if past february
  3104 00002E07 7610                <1> 	jna 	short cte1
  3105 00002E09 668B15[A45F0000]    <1> 	mov 	dx, [year]
  3106 00002E10 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3107 00002E14 7503                <1> 	jnz 	short cte1		
  3108                              <1> 			; and if leap year
  3109 00002E16 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3110                              <1> cte1: 			; compute seconds since 1/1/1970
  3111 00002E19 BA18000000          <1> 	mov 	edx, 24
  3112 00002E1E F7E2                <1> 	mul	edx
  3113 00002E20 8A15[A85F0000]      <1> 	mov 	dl, [hour]
  3114 00002E26 01D0                <1> 	add 	eax, edx
  3115                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3116                              <1> 	;mov	ebx, 60
  3117 00002E28 B33C                <1> 	mov	bl, 60
  3118 00002E2A F7E3                <1> 	mul	ebx
  3119 00002E2C 8A15[A95F0000]      <1> 	mov 	dl, [minute]
  3120 00002E32 01D0                <1> 	add 	eax, edx
  3121                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3122                              <1> 	;mov 	ebx, 60
  3123 00002E34 F7E3                <1> 	mul	ebx
  3124 00002E36 8A15[AA5F0000]      <1> 	mov 	dl, [second]
  3125 00002E3C 01D0                <1> 	add 	eax, edx
  3126                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3127 00002E3E C3                  <1> 	retn
  3128                              <1> 
  3129                              <1> get_rtc_time:
  3130                              <1> 	; 15/03/2015
  3131                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3132                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3133                              <1> 	; INT 1Ah
  3134                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3135                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3136                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3137                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3138                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3139                              <1> 	;								
  3140                              <1> RTC_20: 				; GET RTC TIME
  3141 00002E3F FA                  <1> 	cli
  3142 00002E40 E8DBDCFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3143 00002E45 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3144                              <1> 
  3145 00002E47 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3146 00002E49 E8BCDCFFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3147 00002E4E 88C6                <1> 	MOV	DH, AL			; SAVE
  3148 00002E50 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3149 00002E52 E8B3DCFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3150 00002E57 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3151 00002E59 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3152 00002E5B B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3153 00002E5D E8A8DCFFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3154 00002E62 88C1                <1> 	MOV	CL, AL			; SAVE
  3155 00002E64 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3156 00002E66 E89FDCFFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3157 00002E6B 88C5                <1> 	MOV	CH, AL			; SAVE
  3158 00002E6D F8                  <1> 	CLC				; SET CY= 0
  3159                              <1> RTC_29:
  3160 00002E6E FB                  <1> 	sti
  3161 00002E6F C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3162                              <1> 
  3163                              <1> get_rtc_date:
  3164                              <1> 	; 15/03/2015
  3165                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3166                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3167                              <1> 	; INT 1Ah
  3168                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3169                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3170                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3171                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3172                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3173                              <1> 	;
  3174                              <1> RTC_40: 				; GET RTC DATE
  3175 00002E70 FA                  <1> 	cli
  3176 00002E71 E8AADCFFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3177 00002E76 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3178                              <1> 
  3179 00002E78 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3180 00002E7A E88BDCFFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3181 00002E7F 88C2                <1> 	MOV	DL, AL			; SAVE
  3182 00002E81 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3183 00002E83 E882DCFFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3184 00002E88 88C6                <1> 	MOV	DH, AL			; SAVE
  3185 00002E8A B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3186 00002E8C E879DCFFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3187 00002E91 88C1                <1> 	MOV	CL, AL			; SAVE
  3188 00002E93 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3189 00002E95 E870DCFFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3190 00002E9A 88C5                <1> 	MOV	CH, AL			; SAVE
  3191 00002E9C F8                  <1> 	CLC				; SET CY=0
  3192                              <1> RTC_49:
  3193 00002E9D FB                  <1> 	sti
  3194 00002E9E C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3195                              <1> 
  3196                              <1> set_date_time:
  3197                              <1> convert_from_epoch:
  3198                              <1> 	; 02/06/2022
  3199                              <1> 	; 01/06/2022 (BugFix)
  3200                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3201                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3202                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3203                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3204                              <1> 	;
  3205                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3206                              <1> 	;
  3207                              <1> 	; Derived from DALLAS Semiconductor
  3208                              <1> 	; Application Note 31 (DS1602/DS1603)
  3209                              <1> 	; 6 May 1998
  3210                              <1> 	;
  3211                              <1> 	; INPUT:
  3212                              <1> 	; EAX = Unix (Epoch) Time
  3213                              <1> 	;
  3214 00002E9F 31D2                <1> 	xor 	edx, edx
  3215                              <1> 	; 02/06/2022
  3216 00002EA1 31C9                <1> 	xor	ecx, ecx
  3217 00002EA3 31DB                <1> 	xor	ebx, ebx
  3218                              <1> 	;mov 	ecx, 60
  3219 00002EA5 B13C                <1> 	mov	cl, 60
  3220 00002EA7 F7F1                <1> 	div	ecx
  3221                              <1> 	;mov 	[imin], eax  ; whole minutes
  3222                              <1> 			     ; since 1/1/1970
  3223                              <1> 	;mov 	[second], dx ; leftover seconds
  3224 00002EA9 8815[AA5F0000]      <1> 	mov	[second], dl ; 02/06/2022
  3225 00002EAF 29D2                <1> 	sub 	edx, edx
  3226 00002EB1 F7F1                <1> 	div	ecx
  3227                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3228                              <1> 	;		     ; since 1/1/1970
  3229                              <1> 	;mov 	[minute], dx ; leftover minutes
  3230 00002EB3 8815[A95F0000]      <1> 	mov	[minute], dl ; 02/06/2022
  3231 00002EB9 31D2                <1> 	xor	edx, edx
  3232                              <1> 	;mov 	cx, 24
  3233 00002EBB B118                <1> 	mov 	cl, 24
  3234 00002EBD F7F1                <1> 	div	ecx
  3235                              <1> 	;mov 	[iday], ax   ; whole days
  3236                              <1> 			     ; since 1/1/1970
  3237                              <1> 	;mov 	[hour], dx   ; leftover hours
  3238 00002EBF 8815[A85F0000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3239                              <1> 
  3240 00002EC5 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3241                              <1> 			     ; 1/1/1968 	
  3242                              <1> 	;mov 	[iday], ax
  3243 00002ECA 50                  <1> 	push 	eax
  3244 00002ECB 29D2                <1> 	sub	edx, edx
  3245 00002ECD B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3246 00002ED2 F7F1                <1> 	div	ecx
  3247 00002ED4 59                  <1> 	pop 	ecx
  3248                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3249                              <1> 	;push	dx
  3250                              <1> 	; 01/06/2022
  3251 00002ED5 52                  <1> 	push 	edx
  3252                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3253 00002ED6 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3254 00002EDA F5                  <1> 	cmc		     ; add this quadyr's leap day
  3255 00002EDB 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3256                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3257                              <1> 	;mov 	cx, [iday]
  3258 00002EDE 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3259 00002EDF 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3260 00002EE1 B96D010000          <1> 	mov 	ecx, 365
  3261 00002EE6 31D2                <1> 	xor	edx, edx
  3262                              <1> 	; EAX = iday-lday, EDX = 0
  3263 00002EE8 F7F1                <1> 	div	ecx
  3264                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3265                              <1> 	;jday = iday - (iyrs*365) - lday
  3266                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3267                              <1> 	;add	eax, 1968
  3268 00002EEA 6605B007            <1> 	add 	ax, 1968     ; compute year
  3269 00002EEE 66A3[A45F0000]      <1> 	mov 	[year], ax
  3270                              <1> 	;mov 	cx, dx
  3271                              <1> 	; 02/06/2022
  3272 00002EF4 89D1                <1> 	mov	ecx, edx
  3273                              <1> 	;mov 	dx, [qday]
  3274                              <1> 	;pop	dx
  3275                              <1> 	; 01/06/2022
  3276 00002EF6 5A                  <1> 	pop 	edx
  3277 00002EF7 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3278 00002EFC 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3279 00002EFE 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3280 00002F02 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3281 00002F03 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3282                              <1> cfe1:			
  3283                              <1> 	;mov 	[jday], cx
  3284                              <1> 	;mov 	bx, 12       ; estimate month
  3285                              <1> 	;sub	ebx, ebx
  3286                              <1> 	; 02/06/2022
  3287 00002F07 B30C                <1> 	mov	bl, 12
  3288 00002F09 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3289 00002F0D 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3290                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3291                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3292                              <1> 	; 02/06/2022
  3293 00002F11 39D1                <1> 	cmp	ecx, edx 	 		
  3294 00002F13 7319                <1> 	jnb 	short cfe3
  3295                              <1> 	;dec 	bx           ; month = month - 1
  3296 00002F15 FECB                <1> 	dec	bl			
  3297                              <1> 	;shl 	bx, 1
  3298 00002F17 D0E3                <1> 	shl	bl, 1
  3299 00002F19 668B93[AC5F0000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3300                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3301                              <1> 	; 02/06/2022
  3302 00002F20 D0EB                <1> 	shr	bl, 1
  3303 00002F22 80FB01              <1> 	cmp	bl, 1
  3304                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3305 00002F25 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3306 00002F27 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3307 00002F29 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3308                              <1> 	;inc 	dx           ; mday = mday + 1
  3309 00002F2B 42                  <1> 	inc	edx
  3310 00002F2C EBE3                <1> 	jmp 	short cfe2
  3311                              <1> cfe3:
  3312                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3313                              <1> 	; 02/06/2022
  3314 00002F2E FEC3                <1> 	inc	bl
  3315                              <1> 	;mov 	[month], bx
  3316 00002F30 881D[A65F0000]      <1> 	mov	[month], bl
  3317                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1	
  3318 00002F36 29D1                <1> 	sub	ecx, edx
  3319                              <1> 	;inc 	cx 			  
  3320 00002F38 FEC1                <1> 	inc	cl
  3321                              <1> 	;mov 	[day], cx
  3322 00002F3A 880D[A75F0000]      <1> 	mov	[day], cl    ; 02/06/2022
  3323                              <1> 	
  3324                              <1> 	; eax, ebx, ecx, edx is changed at return
  3325                              <1> 	; output ->
  3326                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3327                              <1> 
  3328                              <1> 	; 01/06/2022 (BugFix)	
  3329                              <1> _set_date:
  3330 00002F40 66A1[A45F0000]      <1> 	mov	ax, [year]
  3331 00002F46 B520                <1> 	mov	ch, 20h ; century (bcd)
  3332 00002F48 662DD007            <1> 	sub	ax, 2000
  3333 00002F4C 7306                <1> 	jnc	short set_date
  3334 00002F4E B519                <1> 	mov	ch, 19h ; century (bcd) 
  3335 00002F50 6683C064            <1> 	add	ax, 100	
  3336                              <1> 	; 01/06/2022
  3337                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3338                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3339                              <1> set_date:
  3340                              <1>         ;mov	al, [year+1]
  3341                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3342                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3343                              <1> 	;		     ; AL = AH * 10h + AL
  3344                              <1> 	;mov 	ch, al ; century (BCD)
  3345                              <1> 	;mov 	al, [year]
  3346                              <1> 	; al = year (0-99) ; 01/06/2022
  3347 00002F54 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3348 00002F56 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3349                              <1> 			     ; AL = AH * 10h + AL
  3350 00002F58 88C1                <1> 	mov 	cl, al ; year (BCD)
  3351 00002F5A A0[A65F0000]        <1>         mov 	al, [month]
  3352 00002F5F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3353 00002F61 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3354                              <1> 			     ; AL = AH * 10h + AL
  3355 00002F63 88C6                <1> 	mov 	dh, al ; month (BCD)
  3356 00002F65 A0[A75F0000]        <1> 	mov 	al, [day]
  3357 00002F6A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3358 00002F6C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3359                              <1> 			     ; AL = AH * 10h + AL
  3360                              <1> 	; 01/06/2022 (BugFix)
  3361 00002F6E 88C2                <1> 	mov 	dl, al ; day (BCD)
  3362                              <1> 
  3363                              <1> 	; Set real-time clock date
  3364 00002F70 E879000000          <1> 	call	set_rtc_date
  3365                              <1> set_time:
  3366                              <1>         ; Read real-time clock time 
  3367                              <1> 	; (get day light saving time bit status)
  3368 00002F75 FA                  <1>  	cli
  3369 00002F76 E8A5DBFFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3370                              <1> 	; cf = 1 -> al = 0
  3371 00002F7B 7207                <1>         jc      short stime1
  3372 00002F7D B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3373 00002F7F E886DBFFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3374                              <1> stime1:
  3375 00002F84 FB                  <1> 	sti
  3376 00002F85 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3377 00002F87 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3378                              <1> 	; DL = 1 or 0 (day light saving time)
  3379                              <1> 	;	
  3380 00002F89 A0[A85F0000]        <1> 	mov 	al, [hour]
  3381 00002F8E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3382 00002F90 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3383                              <1> 			     ; AL = AH * 10h + AL
  3384 00002F92 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3385 00002F94 A0[A95F0000]        <1>         mov     al, [minute]
  3386 00002F99 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3387 00002F9B D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3388                              <1> 			     ; AL = AH * 10h + AL
  3389 00002F9D 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3390 00002F9F A0[AA5F0000]        <1>         mov     al, [second]
  3391 00002FA4 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3392 00002FA6 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3393                              <1> 			     ; AL = AH * 10h + AL
  3394 00002FA8 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3395                              <1> 
  3396                              <1> 	; Set real-time clock time
  3397                              <1>  	; call	set_rtc_time
  3398                              <1> set_rtc_time:
  3399                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3400                              <1> 	; 15/03/2015
  3401                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3402                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3403                              <1> 	; INT 1Ah
  3404                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3405                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3406                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3407                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3408                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3409                              <1> 	;								:
  3410                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3411                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3412                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3413                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3414                              <1> 	;
  3415                              <1> RTC_30: 				; SET RTC TIME
  3416 00002FAA FA                  <1> 	cli
  3417 00002FAB E870DBFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3418 00002FB0 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3419 00002FB2 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3420                              <1> RTC_35:
  3421 00002FB7 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3422 00002FB9 B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3423 00002FBB E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3424 00002FC0 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3425 00002FC2 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3426 00002FC4 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3427 00002FC9 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3428 00002FCB B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3429 00002FCD E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3430                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3431 00002FD2 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3432 00002FD6 E82FDBFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3433 00002FDB 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3434 00002FDD 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3435 00002FDF 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3436 00002FE2 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3437 00002FE4 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3438 00002FE6 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3439 00002FEB F8                  <1> 	CLC				; SET CY= 0
  3440 00002FEC FB                  <1> 	sti
  3441 00002FED C3                  <1> 	RETn				; RETURN WITH CY= 0
  3442                              <1> 
  3443                              <1> set_rtc_date:
  3444                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3445                              <1> 	; 15/03/2015
  3446                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3447                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3448                              <1> 	; INT 1Ah
  3449                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3450                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3451                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3452                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3453                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3454                              <1> 	;
  3455                              <1> RTC_50: 				; SET RTC DATE
  3456 00002FEE FA                  <1> 	cli
  3457 00002FEF E82CDBFFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3458 00002FF4 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3459 00002FF6 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3460                              <1> RTC_55:
  3461 00002FFB 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3462 00002FFF E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3463 00003004 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3464 00003006 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3465 00003008 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3466 0000300D 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3467 0000300F B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3468 00003011 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3469 00003016 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3470 00003018 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3471 0000301A E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3472 0000301F 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3473 00003021 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3474 00003023 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3475                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3476 00003028 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3477 0000302C E8D9DAFFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3478 00003031 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3479 00003033 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3480 00003035 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3481 0000303A F8                  <1> 	CLC				; SET CY= 0
  3482 0000303B FB                  <1> 	sti
  3483 0000303C C3                  <1> 	RETn				; RETURN CY=0
  3484                              <1> 
  3485                              <1> 	; 15/03/2015
  3486                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3487 0000303D B426                <1> 	mov	ah, 26h
  3488 0000303F B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3489 00003041 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3490 00003046 B482                <1> 	mov	ah, 82h
  3491 00003048 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3492 0000304A E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3493 0000304F B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3494 00003051 E8B4DAFFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3495 00003056 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3496                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3497                              <1> 	;RETn
  3498                              <1> 	; 12/01/2022
  3499 00003058 E9ADDAFFFF          <1> 	jmp	CMOS_READ
  3500                              <1> 
  3501                              <1> 	; 15/03/2015
  3502                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3503                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3504 0000305D 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3505                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3506 0000305E D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3507 00003060 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3508 00003061 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3509 00003063 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3510 00003064 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3511 00003066 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3512 00003068 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3513 0000306A B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3514 0000306C D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3515 0000306E E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3516 00003070 90                  <1> 	nop			; I/O DELAY
  3517 00003071 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3518                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3519 00003073 9D                  <1> 	popf	
  3520 00003074 C3                  <1> 	RETn
  3521                              <1> 
  3522                              <1> bf_init:
  3523                              <1> 	; 14/08/2015
  3524                              <1> 	; 02/07/2015
  3525                              <1> 	; 01/07/2015
  3526                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3527                              <1> 	; Buffer (pointer) initialization !
  3528                              <1> 	; 
  3529                              <1> 	; 17/07/2013 - 24/07/2013
  3530                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3531                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3532                              <1> 	;
  3533 00003075 BF[B8650000]        <1> 	mov	edi, bufp 
  3534 0000307A B8[C4760000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3535 0000307F 29D2                <1> 	sub	edx, edx
  3536 00003081 FECA                <1> 	dec	dl
  3537 00003083 31C9                <1> 	xor	ecx, ecx
  3538 00003085 49                  <1> 	dec	ecx
  3539                              <1> bi0:
  3540 00003086 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3541 0000308B AB                  <1> 	stosd
  3542 0000308C 89C6                <1> 	mov	esi, eax
  3543 0000308E 8916                <1> 	mov	[esi], edx ; 000000FFh
  3544                              <1> 			   ; Not a valid device sign
  3545 00003090 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3546                              <1> 		      ; Not a valid block number sign 	 	
  3547 00003093 3D[84660000]        <1> 	cmp	eax, buffer
  3548 00003098 77EC                <1> 	ja	short bi0
  3549 0000309A B8[C4760000]        <1> 	mov	eax, sb0
  3550 0000309F AB                  <1> 	stosd
  3551 000030A0 B8[CC780000]        <1> 	mov	eax, sb1
  3552 000030A5 AB                  <1> 	stosd
  3553 000030A6 89C6                <1> 	mov	esi, eax ; offset sb1
  3554 000030A8 8916                <1> 	mov	[esi], edx ; 000000FFh
  3555                              <1> 			   ; Not a valid device sign
  3556 000030AA 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3557                              <1> 		      ; Not a valid block number sign 	 
  3558                              <1> 	; 14/08/2015
  3559                              <1> 	;call 	rdev_init
  3560                              <1> 	;retn
  3561                              <1> 
  3562                              <1> rdev_init: ; root device, super block buffer initialization
  3563                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3564                              <1> 	; 14/08/2015
  3565                              <1> 	; Retro UNIX 386 v1 feature only !
  3566                              <1> 	;
  3567                              <1> 	; NOTE: Disk partitions (file systems), logical
  3568                              <1> 	; drive initialization, partition's start sector etc.
  3569                              <1> 	; will be coded here, later in 'ldrv_init'	
  3570                              <1> 
  3571 000030AD 0FB605[585D0000]    <1> 	movzx	eax, byte [boot_drv]
  3572                              <1> rdi_0:
  3573 000030B4 3C80                <1> 	cmp	al, 80h
  3574 000030B6 7202                <1> 	jb	short rdi_1
  3575 000030B8 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3576                              <1> rdi_1:
  3577 000030BA A2[E4650000]        <1> 	mov	[rdev], al
  3578 000030BF BB[C4760000]        <1>         mov	ebx, sb0 ; super block buffer
  3579 000030C4 8903                <1> 	mov 	[ebx], eax
  3580 000030C6 B001                <1> 	mov	al, 1 ; eax = 1
  3581 000030C8 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3582                              <1> 	;call 	diskio
  3583                              <1> 	;retn
  3584                              <1> 	; 24/12/2021
  3585 000030CB E923250000          <1> 	jmp	diskio
  3586                              <1> 
  3587                              <1> ; 23/10/2015
  3588                              <1> com1_irq4:
  3589 000030D0 [D8300000]          <1> 	dd	dummy_retn
  3590                              <1> com2_irq3:
  3591 000030D4 [D8300000]          <1> 	dd	dummy_retn
  3592                              <1> 
  3593                              <1> dummy_retn:
  3594 000030D8 C3                  <1> 	retn
  2113                                  %include 'u1.s'        ; 10/05/2015
  2114                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS1.INC
  2115                              <1> ; Last Modification: 17/07/2022
  2116                              <1> ; ----------------------------------------------------------------------------
  2117                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2118                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2119                              <1> ;
  2120                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2121                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2122                              <1> ; <Bell Laboratories (17/3/1972)>
  2123                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2124                              <1> ;
  2125                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2126                              <1> ;
  2127                              <1> ; ****************************************************************************
  2128                              <1> 
  2129                              <1> unkni: ; / used for all system calls
  2130                              <1> sysent: ; < enter to system call >
  2131                              <1> 	; 08/01/2022
  2132                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2133                              <1> 	; 19/10/2015
  2134                              <1> 	; 21/09/2015
  2135                              <1> 	; 01/07/2015
  2136                              <1> 	; 19/05/2015
  2137                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2138                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2139                              <1> 	;
  2140                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2141                              <1> 	; The trap type is determined and an indirect jump is made to 
  2142                              <1> 	; the appropriate system call handler. If there is a trap inside
  2143                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2144                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2145                              <1> 	; instructor is decoded to get the the system code part (see
  2146                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2147                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2148                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2149                              <1> 	; is called. If the call is legitimate control passes to the
  2150                              <1> 	; appropriate system routine.
  2151                              <1> 	;
  2152                              <1> 	; Calling sequence:
  2153                              <1> 	;	Through a trap caused by any sys call outside the system.
  2154                              <1> 	; Arguments:
  2155                              <1> 	;	Arguments of particular system call.	
  2156                              <1> 	; ...............................................................
  2157                              <1> 	;	
  2158                              <1> 	; Retro UNIX 8086 v1 modification: 
  2159                              <1> 	;       System call number is in EAX register.
  2160                              <1> 	;
  2161                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2162                              <1> 	;	registers depending of function details.
  2163                              <1>   	;
  2164                              <1> 	; 16/04/2015
  2165 000030D9 368925[F4650000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2166                              <1> 	; save user registers
  2167 000030E0 1E                  <1> 	push	ds
  2168 000030E1 06                  <1> 	push	es
  2169 000030E2 0FA0                <1> 	push	fs
  2170 000030E4 0FA8                <1> 	push	gs
  2171 000030E6 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2172                              <1> 	;
  2173                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2174                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2175                              <1> 	;	for saving/restoring user registers.)
  2176                              <1> 	;
  2177 000030E7 50                  <1> 	push	eax ; 01/07/2015
  2178 000030E8 66B81000            <1> 	mov     ax, KDATA
  2179 000030EC 8ED8                <1>         mov     ds, ax
  2180 000030EE 8EC0                <1>         mov     es, ax
  2181 000030F0 8EE0                <1>         mov     fs, ax
  2182 000030F2 8EE8                <1>         mov     gs, ax
  2183 000030F4 A1[38620000]        <1> 	mov	eax, [k_page_dir]
  2184 000030F9 0F22D8              <1> 	mov	cr3, eax
  2185 000030FC 58                  <1> 	pop	eax ; 01/07/2015
  2186                              <1> 	; 19/10/2015
  2187 000030FD FC                  <1> 	cld
  2188                              <1> 	;
  2189 000030FE FE05[F3650000]      <1> 	inc	byte [sysflg]
  2190                              <1> 		; incb sysflg / indicate a system routine is in progress
  2191 00003104 FB                  <1>         sti 	; 18/01/2014
  2192                              <1> 	;jnz	panic ; 24/05/2013
  2193                              <1> 	; 24/12/2021
  2194 00003105 7405                <1> 	jz	short _1
  2195 00003107 E987F9FFFF          <1> 	jmp	panic
  2196                              <1> 		; beq 1f
  2197                              <1> 		; jmp panic ; / called if trap inside system
  2198                              <1> ;1:
  2199                              <1> _1:	; 24/12/2021
  2200                              <1> 	; 16/04/2015
  2201 0000310C A3[FC650000]        <1> 	mov	[u.r0], eax
  2202 00003111 8925[F8650000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2203                              <1> 	;
  2204                              <1> 		; mov $s.syst+2,clockp
  2205                              <1> 		; mov r0,-(sp) / save user registers 
  2206                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2207                              <1> 			   ; / in u.r0
  2208                              <1> 		; mov r1,-(sp)
  2209                              <1> 		; mov r2,-(sp)
  2210                              <1> 		; mov r3,-(sp)
  2211                              <1> 		; mov r4,-(sp)
  2212                              <1> 		; mov r5,-(sp)
  2213                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2214                              <1> 		             ; / arithmetic unit
  2215                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2216                              <1> 		             ; / extended arithmetic unit
  2217                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2218                              <1> 		             ; / arithmetic unit
  2219                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2220                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2221                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2222                              <1> 		; sub $sys,r0 / get xxx code
  2223 00003117 C1E002              <1> 	shl	eax, 2
  2224                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2225 0000311A 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2226                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2227                              <1> 	;jnb	short badsys
  2228                              <1> 		; bhis badsys / yes, bad system call
  2229                              <1> 	; 08/01/2022
  2230 0000311F 7205                <1> 	jb	short _2
  2231 00003121 E95D010000          <1> 	jmp	badsys
  2232                              <1> _2:
  2233                              <1> 	; 08/01/2022
  2234                              <1> 	;cmc
  2235                              <1> 	;pushf	
  2236                              <1> 	;push	eax
  2237 00003126 8B2D[F4650000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2238                              <1> 	;mov	al, 0FEh ; 11111110b
  2239                              <1> 	;;adc	al, 0 ; al = al + cf
  2240                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2241 0000312C 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2242                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2243                              <1> 				 ; / and clear carry bit
  2244                              <1> 	;pop	ebp ; eax
  2245 00003130 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2246                              <1> 	;popf
  2247                              <1>         ;;jc	badsys
  2248                              <1> 	; 24/12/2021
  2249                              <1> 	;jnc	short _3  ; 08/01/2022
  2250                              <1> 	;jmp	badsys
  2251                              <1> ;_3:
  2252 00003132 A1[FC650000]        <1> 	mov	eax, [u.r0]
  2253                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2254 00003137 FFA5[3D310000]      <1> 	jmp	dword [ebp+syscalls]
  2255                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2256                              <1> 		            ; / to proper system routine.
  2257                              <1> syscalls: ; 1:
  2258                              <1> 	; 21/09/2015
  2259                              <1> 	; 01/07/2015
  2260                              <1> 	; 16/04/2015 (32 bit address modification) 
  2261 0000313D [4D320000]          <1> 	dd sysrele	; / 0
  2262 00003141 [F5320000]          <1> 	dd sysexit 	; / 1
  2263 00003145 [1F340000]          <1> 	dd sysfork 	; / 2
  2264 00003149 [25350000]          <1> 	dd sysread 	; / 3
  2265 0000314D [38350000]          <1> 	dd syswrite 	; / 4
  2266 00003151 [A1350000]          <1> 	dd sysopen 	; / 5
  2267 00003155 [CC360000]          <1> 	dd sysclose 	; / 6
  2268 00003159 [9A330000]          <1> 	dd syswait 	; / 7
  2269 0000315D [49360000]          <1> 	dd syscreat 	; / 8
  2270 00003161 [853A0000]          <1> 	dd syslink 	; / 9
  2271 00003165 [413B0000]          <1> 	dd sysunlink 	; / 10
  2272 00003169 [0B3C0000]          <1> 	dd sysexec 	; / 11
  2273 0000316D [8E420000]          <1> 	dd syschdir 	; / 12
  2274 00003171 [71430000]          <1> 	dd systime 	; / 13
  2275 00003175 [85360000]          <1> 	dd sysmkdir 	; / 14
  2276 00003179 [DE420000]          <1> 	dd syschmod 	; / 15
  2277 0000317D [41430000]          <1> 	dd syschown 	; / 16
  2278 00003181 [A4430000]          <1> 	dd sysbreak 	; / 17
  2279 00003185 [CB3F0000]          <1> 	dd sysstat 	; / 18
  2280 00003189 [74440000]          <1> 	dd sysseek 	; / 19
  2281 0000318D [86440000]          <1> 	dd systell 	; / 20
  2282 00003191 [C44F0000]          <1> 	dd sysmount 	; / 21
  2283 00003195 [AF500000]          <1> 	dd sysumount 	; / 22
  2284 00003199 [02450000]          <1> 	dd syssetuid 	; / 23
  2285 0000319D [33450000]          <1> 	dd sysgetuid 	; / 24
  2286 000031A1 [80430000]          <1> 	dd sysstime 	; / 25
  2287 000031A5 [F6440000]          <1> 	dd sysquit 	; / 26
  2288 000031A9 [EA440000]          <1> 	dd sysintr 	; / 27
  2289 000031AD [A83F0000]          <1> 	dd sysfstat 	; / 28
  2290 000031B1 [E9360000]          <1> 	dd sysemt 	; / 29
  2291 000031B5 [35370000]          <1> 	dd sysmdate 	; / 30
  2292 000031B9 [8F370000]          <1> 	dd sysstty 	; / 31
  2293 000031BD [78390000]          <1> 	dd sysgtty 	; / 32
  2294 000031C1 [30370000]          <1> 	dd sysilgins 	; / 33
  2295 000031C5 [15580000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2296                              <1> 			     ; 11/06/2014
  2297 000031C9 [2C580000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2298                              <1> 			     ; 01/07/2015
  2299 000031CD [04590000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2300                              <1> 			     ; 21/09/2015 - get last error number
  2301                              <1> end_of_syscalls:
  2302                              <1> 
  2303                              <1> error:
  2304                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2305                              <1> 	; 17/09/2015
  2306                              <1> 	; 03/09/2015
  2307                              <1> 	; 01/09/2015
  2308                              <1> 	; 09/06/2015
  2309                              <1> 	; 13/05/2015
  2310                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2311                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2312                              <1> 	;
  2313                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2314                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2315                              <1> 	;
  2316                              <1> 	; INPUTS -> none
  2317                              <1> 	; OUTPUTS ->
  2318                              <1> 	;	processor status - carry (c) bit is set (means error)
  2319                              <1> 	;
  2320                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2321                              <1> 	; 	      Because, jumps to error procedure
  2322                              <1> 	;	      disrupts push-pop nesting balance)
  2323                              <1> 	;
  2324 000031D1 8B2D[F4650000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2325 000031D7 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2326                              <1> 				 ; (system call will return with cf = 1)
  2327                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2328                              <1> 		               ; / users stack
  2329                              <1> 	; 17/09/2015
  2330 000031DB 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2331                              <1> 				 ; for saving/restoring user registers	
  2332                              <1> 	;cmp	ebp, [u.usp]
  2333                              <1> 	;je	short err0	
  2334 000031DE 892D[F8650000]      <1> 	mov	[u.usp], ebp
  2335                              <1> ;err0:
  2336                              <1> 	; 01/09/2015
  2337 000031E4 8B25[F8650000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2338                              <1> 				    ; 10/04/2013
  2339                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2340                              <1> 				    ; related procedures will jump to 'error'
  2341                              <1> 				    ; procedure directly without returning to 
  2342                              <1> 				    ; the caller procedure. So, stack pointer
  2343                              <1>                                     ; must be restored here.)
  2344                              <1> 	; 13/05/2015
  2345                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2346                              <1> 	;	'get last error' system call later. 	
  2347                              <1> 
  2348                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2349 000031EA C605[63660000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2350                              <1> 
  2351                              <1> sysret: ; < return from system call>
  2352                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2353                              <1> 	; 10/09/2015
  2354                              <1> 	; 29/07/2015
  2355                              <1> 	; 25/06/2015
  2356                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2357                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2358                              <1> 	;
  2359                              <1> 	; 'sysret' first checks to see if process is about to be 
  2360                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2361                              <1> 	; If not, following happens:	 
  2362                              <1> 	; 	1) The user's stack pointer is restored.
  2363                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2364                              <1> 	;	   i-node has been modified. If it has, it is written out
  2365                              <1> 	;	   via 'ppoke'.
  2366                              <1> 	;	3) If the super block has been modified, it is written out
  2367                              <1> 	;	   via 'ppoke'.				
  2368                              <1> 	;	4) If the dismountable file system's super block has been
  2369                              <1> 	;	   modified, it is written out to the specified device
  2370                              <1> 	;	   via 'ppoke'.
  2371                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2372                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2373                              <1> 	;	   another user a chance to run.
  2374                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2375                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2376                              <1> 	;
  2377                              <1> 	; Calling sequence:
  2378                              <1> 	;	jump table or 'br sysret'
  2379                              <1> 	; Arguments: 
  2380                              <1> 	;	-	
  2381                              <1> 	; ...............................................................
  2382                              <1> 	;	
  2383                              <1> 	; ((AX=r1 for 'iget' input))
  2384                              <1> 	;	
  2385                              <1> 	;xor	ax, ax ; 04/05/2013
  2386                              <1> 	; 24/12/2021
  2387 000031F1 31C0                <1> 	xor	eax, eax
  2388                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2389 000031F3 FEC0                <1> 	inc	al ; 04/05/2013
  2390 000031F5 3805[4A660000]      <1> 	cmp	[u.bsys], al ; 1
  2391                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2392                              <1> 	;jnb	sysexit ; 04/05/2013
  2393                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2394                              <1> 	; 24/12/2021
  2395 000031FB 720F                <1> 	jb	short _3
  2396 000031FD C705[51660000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2396 00003205 0000                <1>
  2397 00003207 E9E9000000          <1> 	jmp	sysexit
  2398                              <1> _3:
  2399                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2400                              <1> 		; mov u.sp,sp / no point stack to users stack
  2401 0000320C FEC8                <1> 	dec 	al ; mov ax, 0
  2402                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2403 0000320E E8DA160000          <1> 	call	iget
  2404                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2405                              <1> 		            ; / it is written out
  2406                              <1> 	;xor 	ax, ax ; 0
  2407                              <1> 	; 24/12/2021
  2408 00003213 31C0                <1> 	xor	eax, eax
  2409 00003215 3805[F1650000]      <1> 	cmp	[smod], al ; 0
  2410                              <1> 		; tstb	smod / has the super block been modified
  2411 0000321B 7614                <1> 	jna	short sysret1
  2412                              <1> 		; beq	1f / no, 1f
  2413 0000321D A2[F1650000]        <1> 	mov	[smod], al ; 0
  2414                              <1> 		; clrb smod / yes, clear smod
  2415 00003222 BB[C4760000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2416 00003227 66810B0002          <1>    	or	word [ebx], 200h ;;
  2417                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2418                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2419                              <1> 		      	      ; / output
  2420                              <1> 	; AX = 0
  2421 0000322C E826230000          <1> 	call 	poke ; 07/08/2013
  2422                              <1> 	; call	ppoke
  2423                              <1> 	; AX = 0
  2424                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2425                              <1> sysret1: ;1:
  2426 00003231 3805[F2650000]      <1> 	cmp	[mmod], al ; 0
  2427                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2428                              <1> 		           ; / system
  2429 00003237 7614                <1> 	jna	short sysrel0
  2430                              <1> 		; beq 1f / been modified?  no, 1f
  2431 00003239 A2[F2650000]        <1> 	mov	[mmod], al ; 0	
  2432                              <1> 		; clrb	mmod / yes, clear mmod
  2433                              <1>         ;mov    ax, [mntd]
  2434                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2435 0000323E BB[CC780000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2436                              <1>         ;;mov	[ebx], al
  2437                              <1> 	;mov    [sb1], al
  2438                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2439 00003243 66810B0002          <1> 	or	word [ebx], 200h
  2440                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2441                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2442 00003248 E80A230000          <1> 	call	poke ; 07/08/2013
  2443                              <1> 	;call	ppoke 
  2444                              <1> 		; jsr r0,ppoke / write it out to its device
  2445                              <1>         ;xor    al, al ; 26/04/2013       
  2446                              <1> ;1:
  2447                              <1> 		; tstb uquant / is the time quantum 0?
  2448                              <1> 		; bne 1f / no, don't swap it out
  2449                              <1> 
  2450                              <1> sysrele: ; < release >
  2451                              <1> 	; 14/10/2015
  2452                              <1> 	; 01/09/2015
  2453                              <1> 	; 24/07/2015
  2454                              <1> 	; 14/05/2015
  2455                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2456                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2457                              <1> 	;
  2458                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2459                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2460                              <1> 	; turns off the system flag. It then checked to see if there is
  2461                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2462                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2463                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2464                              <1> 	; the user, a rti is made.
  2465                              <1> 	;
  2466                              <1> 	; Calling sequence:
  2467                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2468                              <1> 	; Arguments:
  2469                              <1> 	;	-	
  2470                              <1> 	; ...............................................................
  2471                              <1> 	;	
  2472                              <1> 	; 23/02/2014 (swapret)
  2473                              <1> 	; 22/09/2013
  2474                              <1> sysrel0: ;1:
  2475 0000324D 803D[3E660000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2476                              <1> 		; tstb uquant / is the time quantum 0?
  2477 00003254 7705                <1>         ja      short swapret
  2478                              <1> 		; bne 1f / no, don't swap it out
  2479                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2480 00003256 E828130000          <1> 	call	tswap
  2481                              <1> 		; jsr r0,tswap / yes, swap it out
  2482                              <1> ;
  2483                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2484                              <1> swapret: ;1:
  2485                              <1> 	; 10/09/2015
  2486                              <1> 	; 01/09/2015
  2487                              <1> 	; 14/05/2015
  2488                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2489                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2490                              <1> 	; cli
  2491                              <1> 	; 24/07/2015
  2492                              <1> 	;
  2493                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2494                              <1> 	;; mov	esp, [u.usp]
  2495                              <1> 
  2496                              <1> 	; 22/09/2013
  2497 0000325B E8FA140000          <1> 	call	isintr
  2498                              <1> 	; 20/10/2013
  2499 00003260 7405                <1> 	jz	short sysrel1
  2500 00003262 E877000000          <1> 	call	intract
  2501                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2502                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2503                              <1> 		               ; / action
  2504                              <1> sysrel1:
  2505 00003267 FA                  <1> 	cli ; 14/10/2015
  2506 00003268 FE0D[F3650000]      <1> 	dec	byte [sysflg]
  2507                              <1> 		; decb sysflg / turn system flag off
  2508 0000326E A1[55660000]        <1> 	mov     eax, [u.pgdir]
  2509 00003273 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2510                              <1> 			  ; (others are different than kernel page tables) 
  2511                              <1> 	; 10/09/2015
  2512 00003276 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2513                              <1> 		; mov (sp)+,sc / restore user registers
  2514                              <1> 		; mov (sp)+,mq
  2515                              <1> 		; mov (sp)+,ac
  2516                              <1> 		; mov (sp)+,r5
  2517                              <1> 		; mov (sp)+,r4
  2518                              <1> 		; mov (sp)+,r3
  2519                              <1> 		; mov (sp)+,r2
  2520                              <1> 	;
  2521 00003277 A1[FC650000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2522 0000327C 0FA9                <1> 	pop	gs
  2523 0000327E 0FA1                <1> 	pop	fs
  2524 00003280 07                  <1> 	pop	es
  2525 00003281 1F                  <1> 	pop	ds
  2526 00003282 CF                  <1> 	iretd	
  2527                              <1> 		; rti / no, return from interrupt
  2528                              <1> 
  2529                              <1> badsys:
  2530                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2531                              <1> 	; (Major Modification: 'core' dumping procedure in
  2532                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2533                              <1> 	;	has been changed to print 'Invalid System Call !'
  2534                              <1> 	;	message on the user's console tty.)
  2535                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2536                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2537                              <1> 	; (EAX = Function number)  
  2538                              <1> 	;
  2539 00003283 FE05[4A660000]      <1> 	inc	byte [u.bsys]
  2540                              <1> 	;
  2541 00003289 8B1D[F4650000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2542 0000328F 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2543 00003291 E83AE4FFFF          <1> 	call	dwordtohex
  2544 00003296 8915[985F0000]      <1> 	mov	[bsys_msg_eip], edx
  2545 0000329C A3[9C5F0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2546 000032A1 A1[FC650000]        <1> 	mov	eax, [u.r0]
  2547 000032A6 E825E4FFFF          <1> 	call	dwordtohex
  2548 000032AB 8915[885F0000]      <1> 	mov	[bsys_msg_eax], edx
  2549 000032B1 A3[8C5F0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2550                              <1> 	; 24/12/2021
  2551                              <1> 	;xor	eax, eax
  2552                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2553                              <1> 	;mov	ebx, [u.fofp]
  2554                              <1> 	;mov	[ebx], eax
  2555                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2556                              <1> 	;inc	eax
  2557                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2558                              <1> 		; writei
  2559                              <1> 		; INPUTS ->
  2560                              <1> 		;    r1 - inode number
  2561                              <1> 		;    u.count - byte count to be written
  2562                              <1> 		;    u.base - points to user buffer
  2563                              <1> 		;    u.fofp - points to word with current file offset
  2564                              <1> 		; OUTPUTS ->
  2565                              <1> 		;    u.count - cleared
  2566                              <1> 		;    u.nread - accumulates total bytes passed back	
  2567                              <1> 		;
  2568                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2569                              <1> 	;call	writei
  2570                              <1> 	;;mov	eax, 1
  2571                              <1> 	;jmp	sysexit
  2572                              <1> 
  2573                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2574 000032B6 BE[695F0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2575 000032BB 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2576 000032C2 8A83[53630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2577 000032C8 C605[67620000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2578 000032CF A2[50660000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2579 000032D4 E810260000          <1> 	call	print_cmsg
  2580                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2581 000032D9 E9F3FEFFFF          <1> 	jmp	error
  2582                              <1> 
  2583                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2584                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2585                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2586                              <1> 		; br 1f / error
  2587                              <1> 		; neg r1 / negate the i-number to open the core image file
  2588                              <1> 		       ; / for writing
  2589                              <1> 		; jsr r0,iopen / open the core image file
  2590                              <1> 		; jsr r0,itrunc / free all associated blocks
  2591                              <1> 		; br 2f
  2592                              <1> ;1:
  2593                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2594                              <1> 		; jsr r0,maknod / make an i-node
  2595                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2596                              <1> ;2:
  2597                              <1> 		; mov $core,u.base / move address core to u.base
  2598                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2599                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2600                              <1> 		; clr u.off / clear user offset
  2601                              <1> 		; jsr r0,writei / write out the core image to the user
  2602                              <1> 		; mov $user,u.base / pt. u.base to user
  2603                              <1> 		; mov $64.,u.count / u.count = 64
  2604                              <1> 		; jsr r0,writei / write out all the user parameters
  2605                              <1> 		; neg r1 / make i-number positive
  2606                              <1> 		; jsr r0,iclose / close the core image file
  2607                              <1> 		; br sysexit /
  2608                              <1> ;3:
  2609                              <1> 		; <core\0\0>
  2610                              <1> 
  2611                              <1> intract: ; / interrupt action
  2612                              <1> 	; 14/10/2015
  2613                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2614                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2615                              <1> 	;
  2616                              <1> 	; Retro UNIX 8086 v1 modification !
  2617                              <1> 	; (Process/task switching and quit routine by using
  2618                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2619                              <1> 	;
  2620                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2621                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2622                              <1> 	;		'intract' will jump to 'sysexit'.
  2623                              <1> 	;	    Intract will return to the caller 
  2624                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2625                              <1> 	; 14/10/2015
  2626 000032DE FB                  <1> 	sti
  2627                              <1> 	; 07/12/2013	
  2628 000032DF 66FF05[42660000]    <1> 	inc 	word [u.quit]
  2629 000032E6 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2630 000032E8 66FF0D[42660000]    <1> 	dec	word [u.quit]
  2631                              <1> 	; 16/04/2015
  2632 000032EF C3                  <1> 	retn
  2633                              <1> intrct0:	
  2634 000032F0 58                  <1> 	pop	eax ; call intract -> retn
  2635                              <1> 	;
  2636 000032F1 31C0                <1> 	xor 	eax, eax
  2637 000032F3 FEC0                <1> 	inc	al  ; mov ax, 1
  2638                              <1> ;;;
  2639                              <1> 	; UNIX v1 original 'intract' routine... 
  2640                              <1> 	; / interrupt action
  2641                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2642                              <1> 		; bne 1f / no, 1f
  2643                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2644                              <1> 	; 1: / now in user area
  2645                              <1> 		; mov r1,-(sp) / save r1
  2646                              <1> 		; mov u.ttyp,r1 
  2647                              <1> 			; / pointer to tty buffer in control-to r1
  2648                              <1> 		; cmpb 6(r1),$177
  2649                              <1> 			; / is the interrupt char equal to "del"
  2650                              <1> 		; beq 1f / yes, 1f
  2651                              <1> 		; clrb 6(r1) 
  2652                              <1> 		        ; / no, clear the byte 
  2653                              <1> 			; / (must be a quit character)
  2654                              <1> 		; mov (sp)+,r1 / restore r1
  2655                              <1> 		; clr u.quit / clear quit flag
  2656                              <1> 		; bis $20,2(sp) 
  2657                              <1> 		    	; / set trace for quit (sets t bit of 
  2658                              <1> 			; / ps-trace trap)
  2659                              <1> 		; rti   ;  / return from interrupt
  2660                              <1> 	; 1: / interrupt char = del
  2661                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2662                              <1> 			   ; / in the buffer
  2663                              <1> 		; mov (sp)+,r1 / restore r1
  2664                              <1> 		; cmp u.intr,$core / should control be 
  2665                              <1> 				; / transferred to loc core?
  2666                              <1> 		; blo 1f
  2667                              <1> 		; jmp *u.intr / user to do rti yes, 
  2668                              <1> 				; / transfer to loc core
  2669                              <1> 	; 1:
  2670                              <1> 		; sys 1 / exit
  2671                              <1> 
  2672                              <1> sysexit: ; <terminate process>
  2673                              <1> 	; 17/07/2022
  2674                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2675                              <1> 	; 01/09/2015
  2676                              <1> 	; 31/08/2015
  2677                              <1> 	; 14/05/2015
  2678                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2679                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2680                              <1> 	;
  2681                              <1> 	; 'sysexit' terminates a process. First each file that
  2682                              <1> 	; the process has opened is closed by 'flose'. The process
  2683                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2684                              <1> 	; searched to find children of the dying process. If any of
  2685                              <1> 	; children are zombies (died by not waited for), they are
  2686                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2687                              <1> 	; dying process's parent. When the parent is found, it is
  2688                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2689                              <1> 	; one of these, the dying process just dies. If it is waiting
  2690                              <1> 	; for a child process to die, it notified that it doesn't 
  2691                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2692                              <1> 	; (waiting to active). It is awakened and put on runq by
  2693                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2694                              <1> 	; it will never be run again but stays around until a 'wait'
  2695                              <1> 	; is completed by it's parent process. If the parent is not
  2696                              <1> 	; found, process just dies. This means 'swap' is called with
  2697                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2698                              <1> 	; to write out the process and 'rswap' reads the new process
  2699                              <1> 	; over the one that dies..i.e., the dying process is 
  2700                              <1> 	; overwritten and destroyed.	
  2701                              <1>  	;
  2702                              <1> 	; Calling sequence:
  2703                              <1> 	;	sysexit or conditional branch.
  2704                              <1> 	; Arguments:
  2705                              <1> 	;	-	
  2706                              <1> 	; ...............................................................
  2707                              <1> 	;	
  2708                              <1> 	; Retro UNIX 8086 v1 modification: 
  2709                              <1> 	;       System call number (=1) is in EAX register.
  2710                              <1> 	;
  2711                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2712                              <1> 	;       registers depending of function details.
  2713                              <1> 	;
  2714                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2715                              <1> 	;
  2716                              <1> ; / terminate process
  2717                              <1> 	; AX = 1
  2718                              <1> 	;dec 	ax ; 0
  2719                              <1> 	; 24/12/2021
  2720 000032F5 48                  <1> 	dec	eax ; 0
  2721                              <1> 	;dec 	ax ; 0
  2722 000032F6 66A3[40660000]      <1> 	mov	[u.intr], ax ; 0
  2723                              <1> 		; clr u.intr / clear interrupt control word
  2724                              <1> 		; clr r1 / clear r1
  2725                              <1> 	; AX = 0
  2726                              <1> sysexit_1: ; 1:
  2727                              <1> 	; AX = File descriptor
  2728                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2729                              <1> 		; / Search the whole list
  2730 000032FC E8680D0000          <1> 	call	fclose
  2731                              <1> 		; jsr r0,fclose / close all files the process opened
  2732                              <1> 	;; ignore error return
  2733                              <1> 		; br .+2 / ignore error return
  2734                              <1> 	;inc	ax
  2735 00003301 FEC0                <1> 	inc	al
  2736                              <1> 		; inc r1 / increment file descriptor
  2737                              <1> 	;cmp	ax, 10
  2738 00003303 3C0A                <1> 	cmp	al, 10
  2739                              <1> 		; cmp r1,$10. / end of u.fp list?
  2740 00003305 72F5                <1> 	jb	short sysexit_1
  2741                              <1> 		; blt 1b / no, go back
  2742 00003307 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2743                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2744 0000330E 88A3[73630000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2745                              <1> 		; clrb p.stat-1(r1) / free the process
  2746                              <1> 	;shl	bx, 1
  2747 00003314 D0E3                <1> 	shl	bl, 1
  2748                              <1> 		; asl r1 / use r1 for index into the below tables
  2749 00003316 668B8B[12630000]    <1> 	mov	cx, [ebx+p.pid-2]
  2750                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2751 0000331D 668B93[32630000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2752                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2753                              <1> 	; xor 	bx, bx ; 0
  2754 00003324 30DB                <1> 	xor	bl, bl ; 0
  2755                              <1> 		; clr r2
  2756 00003326 31F6                <1> 	xor	esi, esi ; 0
  2757                              <1> 		; clr r5 / initialize reg
  2758                              <1> sysexit_2: ; 1:
  2759                              <1> 	        ; / find children of this dying process, 
  2760                              <1> 		; / if they are zombies, free them
  2761                              <1> 	;add	bx, 2
  2762 00003328 80C302              <1> 	add	bl, 2
  2763                              <1> 		; add $2,r2 / search parent process table 
  2764                              <1> 		          ; / for dying process's name
  2765 0000332B 66398B[32630000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2766                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2767 00003332 7513                <1> 	jne	short sysexit_4
  2768                              <1> 		; bne 3f / no
  2769                              <1> 	;shr	bx, 1
  2770 00003334 D0EB                <1> 	shr	bl, 1
  2771                              <1> 		; asr r2 / yes, it is a parent
  2772 00003336 80BB[73630000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2773                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2774                              <1> 				     ; / dying process a zombie
  2775 0000333D 7506                <1> 	jne	short sysexit_3 
  2776                              <1> 		; bne 2f / no
  2777 0000333F 88A3[73630000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2778                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2779                              <1> sysexit_3: ; 2:
  2780                              <1> 	;shr	bx, 1
  2781 00003345 D0E3                <1> 	shl	bl, 1
  2782                              <1> 		; asl r2
  2783                              <1> sysexit_4: ; 3:
  2784                              <1> 		; / search the process name table 
  2785                              <1> 		; / for the dying process's parent
  2786 00003347 663993[12630000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2787                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2788 0000334E 7502                <1> 	jne	short sysexit_5
  2789                              <1> 		; bne 3f / no
  2790 00003350 89DE                <1> 	mov	esi, ebx
  2791                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2792                              <1> 		          ; / process # x2) in r5
  2793                              <1> sysexit_5: ; 3:
  2794                              <1> 	;cmp	bx, nproc + nproc
  2795 00003352 80FB20              <1> 	cmp	bl, nproc + nproc
  2796                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2797 00003355 72D1                <1> 	jb	short sysexit_2
  2798                              <1> 		; blt 1b / no, go back
  2799                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2800 00003357 21F6                <1> 	and	esi, esi ; r5=r1
  2801 00003359 7430                <1> 	jz	short sysexit_6
  2802                              <1> 		; beq 2f / no parent has been found. 
  2803                              <1> 		       ; / The process just dies
  2804                              <1> 	;shr	si, 1
  2805                              <1> 	; 17/07/2022
  2806 0000335B D1EE                <1> 	shr	esi, 1
  2807                              <1> 		; asr r1 / set up index to p.stat
  2808 0000335D 8A86[73630000]      <1> 	mov	al, [esi+p.stat-1]
  2809                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2810 00003363 20C0                <1> 	and	al, al
  2811 00003365 7424                <1> 	jz	short sysexit_6
  2812                              <1> 		; beq 2f / if its been freed, 2f
  2813 00003367 3C03                <1> 	cmp	al, 3
  2814                              <1> 		; cmp r2,$3 / is parent a zombie?
  2815 00003369 7420                <1> 	je	short sysexit_6
  2816                              <1> 		; beq 2f / yes, 2f
  2817                              <1> 	; BH = 0
  2818 0000336B 8A1D[4B660000]      <1> 	mov	bl, [u.uno]
  2819                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2820 00003371 C683[73630000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2821                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2822                              <1> 	; 05/02/2014
  2823 00003378 3C01                <1> 	cmp	al, 1 ; SRUN
  2824 0000337A 740F                <1> 	je	short sysexit_6
  2825                              <1> 	;cmp	al, 2
  2826                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2827                              <1> 			  ; / this child to die
  2828                              <1> 	;jne	short sysexit_6	
  2829                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2830                              <1> 	; 05/02/2014
  2831                              <1> 	; p.stat = 2 --> waiting
  2832                              <1> 	; p.stat = 4 --> sleeping
  2833 0000337C C686[73630000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2834                              <1> 	;dec	byte [esi+p.stat-1]
  2835                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2836 00003383 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2837                              <1> 	; 
  2838                              <1> 	;mov	ebx, runq + 4
  2839                              <1> 		; mov $runq+4,r2 / on the runq
  2840 00003386 E8CF120000          <1> 	call	putlu
  2841                              <1> 		; jsr r0, putlu
  2842                              <1> sysexit_6: ; 2:
  2843                              <1> 	; 31/08/2015
  2844                              <1> 		; / the process dies
  2845 0000338B C605[4B660000]00    <1> 	mov	byte [u.uno], 0
  2846                              <1> 		; clrb u.uno / put zero as the process number, 
  2847                              <1> 	           ; / so "swap" will
  2848 00003392 E8F6110000          <1> 	call	swap
  2849                              <1> 		; jsr r0,swap / overwrite process with another process
  2850                              <1> hlt_sys:
  2851                              <1> 	;sti ; 18/01/2014
  2852                              <1> hlts0:
  2853 00003397 F4                  <1> 	hlt
  2854 00003398 EBFD                <1> 	jmp	short hlts0
  2855                              <1> 		; 0 / and thereby kill it; halt?
  2856                              <1> 
  2857                              <1> 
  2858                              <1> syswait: ; < wait for a processs to die >
  2859                              <1> 	; 09/02/2022
  2860                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2861                              <1> 	; 17/09/2015
  2862                              <1> 	; 02/09/2015
  2863                              <1> 	; 01/09/2015
  2864                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2865                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2866                              <1> 	;
  2867                              <1> 	; 'syswait' waits for a process die. 
  2868                              <1> 	; It works in following way:
  2869                              <1> 	;    1) From the parent process number, the parent's 
  2870                              <1> 	; 	process name is found. The p.ppid table of parent
  2871                              <1> 	;	names is then searched for this process name.
  2872                              <1> 	;	If a match occurs, r2 contains child's process
  2873                              <1> 	;	number. The child status is checked to see if it is
  2874                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2875                              <1> 	;	If it is, the child process is freed and it's name
  2876                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2877                              <1> 	;	If the child is not a zombie, nothing happens and
  2878                              <1> 	;	the search goes on through the p.ppid table until
  2879                              <1> 	;	all processes are checked or a zombie is found.
  2880                              <1> 	;    2) If no zombies are found, a check is made to see if
  2881                              <1> 	;	there are any children at all. If there are none,
  2882                              <1> 	;	an error return is made. If there are, the parent's
  2883                              <1> 	;	status is set to 2 (waiting for child to die),
  2884                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2885                              <1> 	;	is made to wait on the next process.
  2886                              <1> 	;
  2887                              <1> 	; Calling sequence:
  2888                              <1> 	;	?
  2889                              <1> 	; Arguments:
  2890                              <1> 	;	-
  2891                              <1> 	; Inputs: - 
  2892                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2893                              <1> 	; ...............................................................
  2894                              <1> 	;				
  2895                              <1> 	
  2896                              <1> ; / wait for a process to die
  2897                              <1> 
  2898                              <1> syswait_0:
  2899 0000339A 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2900                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2901 000033A1 D0E3                <1> 	shl	bl, 1
  2902                              <1> 	;shl	bx, 1
  2903                              <1> 		; asl r1 / x2 to get index into p.pid table
  2904 000033A3 668B83[12630000]    <1> 	mov	ax, [ebx+p.pid-2]
  2905                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2906 000033AA 31F6                <1> 	xor	esi, esi
  2907                              <1> 		; clr r2
  2908 000033AC 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2909                              <1> 	;xor 	cl, cl
  2910                              <1> 		; clr r3 / initialize reg 3
  2911                              <1> syswait_1: ; 1:
  2912                              <1> 	; 09/02/2022
  2913 000033AE 46                  <1> 	inc	esi
  2914 000033AF 46                  <1> 	inc	esi
  2915                              <1> 	;add	si, 2
  2916                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2917                              <1> 			  ; / search table of parent processes 
  2918                              <1> 			  ; / for this process name
  2919 000033B0 663B86[32630000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2920                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2921                              <1> 			            ; / process number
  2922 000033B7 7531                <1> 	jne	short syswait_3
  2923                              <1> 		;bne 3f / branch if no match of parent process name
  2924                              <1> 	;inc	cx
  2925 000033B9 FEC1                <1> 	inc	cl
  2926                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2927                              <1> 	; 09/02/2022
  2928 000033BB D1EE                <1> 	shr	esi, 1
  2929                              <1> 	;shr	si, 1
  2930                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2931                              <1> 	; The possible states ('p.stat' values) of a process are:
  2932                              <1> 	;	0 = free or unused
  2933                              <1> 	;	1 = active
  2934                              <1> 	;	2 = waiting for a child process to die
  2935                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2936 000033BD 80BE[73630000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2937                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2938 000033C4 7522                <1> 	jne	short syswait_2
  2939                              <1> 		; bne 2f / no, skip it
  2940 000033C6 88BE[73630000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2941                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2942                              <1> 	; 09/02/2022
  2943 000033CC D1E6                <1> 	shl	esi, 1
  2944                              <1> 	;shl	si, 1
  2945                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2946 000033CE 0FB786[12630000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2947 000033D5 A3[FC650000]        <1> 	mov	[u.r0], eax
  2948                              <1> 		; mov p.pid-2(r2),*u.r0 
  2949                              <1> 			      ; / put childs process name in (u.r0)
  2950                              <1> 	;
  2951                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2952                              <1> 	;
  2953                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2954                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2955                              <1> 	; system call loop from the application/program if it calls
  2956                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2957                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2958                              <1> 	;
  2959                              <1> 	; Note: syswait will return with error if there is not a
  2960                              <1> 	;       zombie or running process to wait.	
  2961                              <1> 	;
  2962                              <1> 	;sub	ax, ax
  2963                              <1> 	; 08/01/2022
  2964 000033DA 29C0                <1> 	sub	eax, eax
  2965 000033DC 668986[32630000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2966 000033E3 E90BFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2967                              <1> 	;
  2968                              <1> 	;jmp	sysret
  2969                              <1> 		; br sysret1 / return cause child is dead
  2970                              <1> syswait_2: ; 2:
  2971                              <1> 	; 09/02/2022
  2972 000033E8 D1E6                <1> 	shl	esi, 1
  2973                              <1> 	;shl	si, 1
  2974                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2975                              <1> syswait_3: ; 3:
  2976 000033EA 6683FE20            <1> 	cmp	si, nproc+nproc
  2977                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2978 000033EE 72BE                <1> 	jb	short syswait_1
  2979                              <1> 		; blt 1b / no, continue search
  2980                              <1> 	;and	cx, cx
  2981 000033F0 20C9                <1> 	and	cl, cl
  2982                              <1> 		; tst r3 / one gets here if there are no children 
  2983                              <1> 		       ; / or children that are still active
  2984                              <1> 	; 30/10/2013
  2985 000033F2 7515                <1> 	jnz	short syswait_4
  2986                              <1> 	;jz	error
  2987                              <1> 		; beq error1 / there are no children, error
  2988 000033F4 890D[FC650000]      <1> 	mov	[u.r0], ecx ; 0
  2989                              <1> 	; 09/02/2022
  2990 000033FA C705[51660000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2990 00003402 0000                <1>
  2991                              <1> 			; miscellaneous/other errors
  2992 00003404 E9C8FDFFFF          <1> 	jmp	error
  2993                              <1> syswait_4:
  2994 00003409 8A1D[4B660000]      <1> 	mov	bl, [u.uno]
  2995                              <1> 		; movb u.uno,r1 / there are children so put 
  2996                              <1> 			      ; / parent process number in r1
  2997 0000340F FE83[73630000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2998                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2999                              <1> 				  ; / other children to die
  3000                              <1> 	; 04/11/2013
  3001 00003415 E873110000          <1> 	call	swap
  3002                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  3003 0000341A E97BFFFFFF          <1> 	jmp	syswait_0
  3004                              <1> 		; br syswait / wait on next process
  3005                              <1> 
  3006                              <1> sysfork: ; < create a new process >
  3007                              <1> 	; 26/02/2022
  3008                              <1> 	; 25/02/2022
  3009                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  3010                              <1> 	; 18/09/2015
  3011                              <1> 	; 04/09/2015
  3012                              <1> 	; 02/09/2015
  3013                              <1> 	; 01/09/2015
  3014                              <1> 	; 28/08/2015
  3015                              <1> 	; 14/05/2015
  3016                              <1> 	; 10/05/2015
  3017                              <1> 	; 09/05/2015
  3018                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  3019                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3020                              <1> 	;
  3021                              <1> 	; 'sysfork' creates a new process. This process is referred
  3022                              <1> 	; to as the child process. This new process core image is
  3023                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3024                              <1> 	; distinction is the return location and the fact that (u.r0)
  3025                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3026                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3027                              <1> 	; 'sysfork' works in the following manner: 	
  3028                              <1> 	;    1) The process status table (p.stat) is searched to find
  3029                              <1> 	;	a process number that is unused. If none are found
  3030                              <1> 	;	an error occurs.
  3031                              <1> 	;    2) when one is found, it becomes the child process number
  3032                              <1> 	;	and it's status (p.stat) is set to active.
  3033                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3034                              <1> 	;	character in that tty buffer is cleared.
  3035                              <1> 	;    4) The child process is put on the lowest priority run 
  3036                              <1> 	;	queue via 'putlu'.
  3037                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3038                              <1> 	;	it is a unique number) and is put in the child's unique
  3039                              <1> 	;	identifier; process id (p.pid).
  3040                              <1> 	;    6) The process name of the parent is then obtained and
  3041                              <1> 	;	placed in the unique identifier of the parent process
  3042                              <1> 	;	name is then put in 'u.r0'.	
  3043                              <1> 	;    7) The child process is then written out on disk by
  3044                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3045                              <1> 	;	and the child is born. (The child process is written 
  3046                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3047                              <1> 	;	number.)
  3048                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3049                              <1> 	;    9) The child process name is put in 'u.r0'.
  3050                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3051                              <1> 	;	create the return address for the parent process.
  3052                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3053                              <1> 	;	the parent has opened. For each file the parent has
  3054                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3055                              <1> 	;	to indicate that the child process also has opened
  3056                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3057                              <1> 	;
  3058                              <1> 	; Calling sequence:
  3059                              <1> 	;	from shell ?
  3060                              <1> 	; Arguments:
  3061                              <1> 	;	-
  3062                              <1> 	; Inputs: -
  3063                              <1> 	; Outputs: *u.r0 - child process name
  3064                              <1> 	; ...............................................................
  3065                              <1> 	;	
  3066                              <1> 	; Retro UNIX 8086 v1 modification: 
  3067                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3068                              <1> 	;	= process id of child a parent process returns
  3069                              <1> 	;	= process id of parent when a child process returns
  3070                              <1> 	;
  3071                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3072                              <1> 	;	in following manner: (with an example: c library, fork)
  3073                              <1> 	;	
  3074                              <1> 	;	1:
  3075                              <1> 	;		sys	fork
  3076                              <1> 	;			br 1f  / child process returns here
  3077                              <1> 	;		bes	2f     / parent process returns here
  3078                              <1> 	;		/ pid of new process in r0
  3079                              <1> 	;		rts	pc
  3080                              <1> 	;	2: / parent process condionally branches here
  3081                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3082                              <1> 	;		rts	pc
  3083                              <1> 	;
  3084                              <1> 	;	1: / child process brances here
  3085                              <1> 	;		clr	r0   / pid = 0 in child process
  3086                              <1> 	;		rts	pc
  3087                              <1> 	;
  3088                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3089                              <1> 	;		// pid = fork();
  3090                              <1> 	;		//
  3091                              <1> 	;		// pid == 0 in child process; 
  3092                              <1> 	;		// pid == -1 means error return
  3093                              <1> 	;		// in child, 
  3094                              <1> 	;		//	parents id is in par_uid if needed
  3095                              <1> 	;		
  3096                              <1> 	;		_fork:
  3097                              <1> 	;			mov	$.fork,eax
  3098                              <1> 	;			int	$0x30
  3099                              <1> 	;			jmp	1f
  3100                              <1> 	;			jnc	2f
  3101                              <1> 	;			jmp	cerror
  3102                              <1> 	;		1:
  3103                              <1> 	;			mov	eax,_par_uid
  3104                              <1> 	;			xor	eax,eax
  3105                              <1> 	;		2:
  3106                              <1> 	;			ret
  3107                              <1> 	;
  3108                              <1> 	;	In Retro UNIX 8086 v1,
  3109                              <1> 	;	'sysfork' returns in following manner:
  3110                              <1> 	;	
  3111                              <1> 	;		mov	ax, sys_fork
  3112                              <1> 	;		mov	bx, offset @f ; routine for child
  3113                              <1> 	;		int	20h
  3114                              <1> 	;		jc	error
  3115                              <1> 	;		
  3116                              <1> 	;	; Routine for parent process here (just after 'jc')
  3117                              <1> 	;		mov	word ptr [pid_of_child], ax
  3118                              <1> 	;		jmp	next_routine_for_parent	
  3119                              <1> 	;
  3120                              <1> 	;	@@: ; routine for child process here				
  3121                              <1> 	;		....	
  3122                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3123                              <1> 	;	       for child process by using BX input.
  3124                              <1> 	;	      (at first, parent process will return then 
  3125                              <1> 	;	      child process will return -after swapped in-
  3126                              <1> 	;	      'syswait' is needed in parent process
  3127                              <1> 	;	      if return from child process will be waited for.)
  3128                              <1> 	;	  				
  3129                              <1> 	
  3130                              <1> ; / create a new process
  3131                              <1> 	; EBX = return address for child process 
  3132                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3133 0000341F 31F6                <1> 	xor 	esi, esi
  3134                              <1> 		; clr r1
  3135                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3136 00003421 46                  <1> 	inc	esi
  3137                              <1> 		; inc r1
  3138 00003422 80BE[73630000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3139                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3140 00003429 760B                <1> 	jna	short sysfork_2	
  3141                              <1> 		; beq 1f / it's unused so branch
  3142 0000342B 6683FE10            <1> 	cmp	si, nproc
  3143                              <1> 		; cmp r1,$nproc / all processes checked
  3144 0000342F 72F0                <1> 	jb	short sysfork_1
  3145                              <1> 		; blt 1b / no, branch back
  3146                              <1> 	;
  3147                              <1> 	; Retro UNIX 8086 v1. modification:
  3148                              <1> 	;	Parent process returns from 'sysfork' to address 
  3149                              <1> 	;	which is just after 'sysfork' system call in parent
  3150                              <1> 	;	process. Child process returns to address which is put
  3151                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3152                              <1> 	;
  3153                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3154                              <1> 		             ; / to old process return
  3155                              <1> 		; br error1 / no room for a new process
  3156                              <1> sysfork_0:
  3157 00003431 E99BFDFFFF          <1> 	jmp	error
  3158                              <1> sysfork_2: ; 1:
  3159 00003436 E88CF0FFFF          <1> 	call	allocate_page
  3160                              <1> 	;jc	error
  3161                              <1> 	; 08/01/2022
  3162 0000343B 72F4                <1> 	jc	short sysfork_0
  3163                              <1> 
  3164 0000343D 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3165                              <1> 	; Retro UNIX 386 v1 modification!
  3166 0000343E E87BF2FFFF          <1> 	call	duplicate_page_dir
  3167                              <1> 		; EAX = New page directory 
  3168 00003443 7308                <1> 	jnc	short sysfork_3
  3169 00003445 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3170 00003446 E842F2FFFF          <1> 	call 	deallocate_page
  3171                              <1> 	;jmp	error
  3172                              <1> 	; 08/01/2022
  3173 0000344B EBE4                <1> 	jmp	short sysfork_0 ; error
  3174                              <1> sysfork_3:
  3175                              <1> 	; Retro UNIX 386 v1 modification !
  3176 0000344D 56                  <1> 	push	esi
  3177 0000344E E8B1110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3178                              <1> 		      ; and interrupt return components (for IRET)
  3179 00003453 8705[55660000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3180 00003459 A3[59660000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3181 0000345E 5E                  <1> 	pop	esi
  3182 0000345F 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3183                              <1> 		; [u.usp] = esp
  3184 00003460 89F7                <1> 	mov	edi, esi
  3185                              <1> 	;shl	di, 2
  3186                              <1> 	; 08/01/2022
  3187 00003462 C1E702              <1> 	shl	edi, 2
  3188 00003465 8987[80630000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3189 0000346B A3[4C660000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3190                              <1> 	; 28/08/2015
  3191 00003470 0FB605[4B660000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3192                              <1> 		; movb u.uno,-(sp) / save parent process number
  3193 00003477 89C7                <1> 	mov	edi, eax
  3194 00003479 50                  <1>         push	eax ; ** 
  3195 0000347A 8A87[53630000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3196                              <1> 		; 18/09/2015
  3197 00003480 8886[53630000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3198                              <1> 	; 26/02/2022 (p.waitc is not used)
  3199                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3200                              <1> 	; 25/02/2022 (BugFix)
  3201                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3202                              <1> 	;			   ; ah - reset child's wait channel	
  3203 00003486 89F0                <1> 	mov	eax, esi
  3204 00003488 A2[4B660000]        <1> 	mov	[u.uno], al ; child process number
  3205                              <1> 		;movb r1,u.uno / set child process number to r1
  3206 0000348D FE86[73630000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3207                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3208                              <1> 				; / process to active status
  3209                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3210                              <1> 			      ; / control tty buffer in r2
  3211                              <1>                 ; beq 2f / branch, if no such tty assigned
  3212                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3213                              <1> 	; 2:
  3214 00003493 53                  <1> 	push	ebx  ; * return address for the child process
  3215                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3216                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3217                              <1> 		; mov $runq+4,r2
  3218 00003494 E8C1110000          <1> 	call	putlu 
  3219                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3220                              <1> 			   ; / run queue
  3221                              <1> 	; 08/01/2022
  3222 00003499 D1E6                <1> 	shl	esi, 1
  3223                              <1> 	;shl	si, 1
  3224                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3225                              <1> 		       ; / into p.pid table
  3226 0000349B 66FF05[EA650000]    <1> 	inc	word [mpid]
  3227                              <1> 		; inc mpid / increment m.pid; get a new process name
  3228 000034A2 66A1[EA650000]      <1> 	mov	ax, [mpid]
  3229 000034A8 668986[12630000]    <1> 	mov	[esi+p.pid-2], ax
  3230                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3231                              <1> 				    ; / in child process' name slot
  3232 000034AF 5A                  <1> 	pop	edx  ; * return address for the child process
  3233                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3234 000034B0 5B                  <1>   	pop	ebx  ; **
  3235                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3236                              <1> 		; movb (sp),r2 / put parent process number in r2
  3237                              <1> 	; 08/01/2022
  3238 000034B1 D1E3                <1> 	shl	ebx, 1
  3239                              <1> 	;shl 	bx, 1
  3240                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3241                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3242 000034B3 668B83[12630000]    <1> 	mov	ax, [ebx+p.pid-2]
  3243                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3244                              <1> 				   ; / process
  3245 000034BA 668986[32630000]    <1> 	mov	[esi+p.ppid-2], ax
  3246                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3247                              <1> 			  ; / in parent process slot for child
  3248 000034C1 A3[FC650000]        <1> 	mov	[u.r0], eax	
  3249                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3250                              <1> 			     ; / at location where r0 was saved
  3251 000034C6 8B2D[F4650000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3252 000034CC 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3253                              <1> 			   ; * return address for the child process
  3254                              <1> 		; mov $sysret1,-(sp) /
  3255                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3256                              <1> 			      ; / user is swapped out
  3257                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3258                              <1> 	; 04/09/2015 - 01/09/2015
  3259                              <1> 	; [u.usp] = esp
  3260 000034CF 68[F1310000]        <1> 	push	sysret ; ***
  3261 000034D4 8925[F8650000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3262                              <1> 			     ; (for child process)	
  3263 000034DA 31C0                <1> 	xor 	eax, eax
  3264 000034DC 66A3[2C660000]      <1> 	mov 	[u.ttyp], ax ; 0
  3265                              <1> 	;
  3266 000034E2 E81D110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3267                              <1> 		;jsr r0,wswap / put child process out on drum
  3268                              <1> 		;jsr r0,unpack / unpack user stack
  3269                              <1> 		;mov u.usp,sp / restore user stack pointer
  3270                              <1> 		; tst (sp)+ / bump stack pointer
  3271                              <1> 	; Retro UNIX 386 v1 modification !
  3272 000034E7 58                  <1> 	pop	eax ; ***
  3273                              <1> 	; 08/01/2022
  3274 000034E8 D1E3                <1> 	shl	ebx, 1
  3275                              <1> 	;shl 	bx, 1
  3276 000034EA 8B83[80630000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3277 000034F0 E838110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3278                              <1> 		      ; registers and return address (for IRET)
  3279                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3280 000034F5 0FB705[EA650000]    <1>         movzx   eax, word [mpid]
  3281 000034FC A3[FC650000]        <1> 	mov	[u.r0], eax
  3282                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3283                              <1> 			       ; / where r0 was saved
  3284                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3285                              <1> 			          ; / process return
  3286                              <1> 	;xor	ebx, ebx
  3287 00003501 31F6                <1> 	xor     esi, esi
  3288                              <1> 		;clr r1
  3289                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3290                              <1> 	      ; / opened by the parent process
  3291                              <1> 	; 01/09/2015
  3292                              <1> 	;xor	bh, bh
  3293                              <1> 	;mov 	bl, [esi+u.fp]
  3294 00003503 8A86[02660000]      <1> 	mov 	al, [esi+u.fp]
  3295                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3296                              <1>         ;or	bl, bl
  3297 00003509 08C0                <1> 	or	al, al
  3298 0000350B 740C                <1> 	jz	short sysfork_5	
  3299                              <1> 		; beq 2f / file has not been opened by parent, 
  3300                              <1> 		       ; / so branch
  3301 0000350D B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3302 0000350F F6E4                <1> 	mul	ah
  3303                              <1> 	;;movzx	ebx, ax
  3304                              <1> 	;mov	bx, ax
  3305 00003511 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3306                              <1> 	;shl	bx, 3
  3307                              <1> 		; asl r2 / multiply by 8
  3308                              <1>        		; asl r2 / to get index into fsp table
  3309                              <1>        		; asl r2
  3310 00003513 FE83[C2630000]      <1>   	inc     byte [ebx+fsp-2]
  3311                              <1> 		; incb fsp-2(r2) / increment number of processes
  3312                              <1> 			     ; / using file, because child will now be
  3313                              <1> 			     ; / using this file
  3314                              <1> sysfork_5: ; 2:
  3315 00003519 46                  <1>         inc     esi
  3316                              <1> 		; inc r1 / get next open file
  3317 0000351A 6683FE0A            <1>         cmp     si, 10
  3318                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3319                              <1> 			  ; / can be opened
  3320 0000351E 72E3                <1> 	jb	short sysfork_4	
  3321                              <1> 		; blt 1b / check next entry
  3322 00003520 E9CCFCFFFF          <1> 	jmp	sysret
  3323                              <1> 		; br sysret1
  3324                              <1> 
  3325                              <1> sysread: ; < read from file >
  3326                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3327                              <1> 	; 13/05/2015
  3328                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3329                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3330                              <1> 	;
  3331                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3332                              <1> 	; characters to be read. If finds the file from the file
  3333                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3334                              <1> 	; is returned from a successful open call (sysopen).
  3335                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3336                              <1> 	; is read into core via 'readi'.
  3337                              <1> 	;
  3338                              <1> 	; Calling sequence:
  3339                              <1> 	;	sysread; buffer; nchars
  3340                              <1> 	; Arguments:
  3341                              <1> 	;	buffer - location of contiguous bytes where 
  3342                              <1> 	;		 input will be placed.
  3343                              <1> 	;	nchars - number of bytes or characters to be read.
  3344                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3345                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3346                              <1> 	; ...............................................................
  3347                              <1> 	;				
  3348                              <1> 	; Retro UNIX 8086 v1 modification: 
  3349                              <1> 	;       'sysread' system call has three arguments; so,
  3350                              <1> 	;	* 1st argument, file descriptor is in BX register
  3351                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3352                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3353                              <1> 	;
  3354                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3355                              <1> 	;	to the user with number of bytes read. 
  3356                              <1> 	;
  3357 00003525 E840000000          <1> 	call	rw1
  3358                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3359                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3360                              <1>        	; 24/12/2021
  3361 0000352A 7239                <1> 	jc	short sysread_err
  3362 0000352C F6C480              <1> 	test	ah, 80h
  3363                              <1> 		; tst r1 / negative i-number?
  3364 0000352F 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3365                              <1> 	;jnz	error
  3366                              <1> 		; ble error1 / yes, error 1 to read
  3367                              <1> 			   ; / it should be positive
  3368 00003531 E88B150000          <1> 	call	readi
  3369                              <1> 		; jsr r0,readi / read data into core
  3370 00003536 EB14                <1> 	jmp	short rw0
  3371                              <1> 		; br 1f
  3372                              <1> 
  3373                              <1> syswrite: ; < write to file >
  3374                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3375                              <1> 	; 13/05/2015
  3376                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3377                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3378                              <1> 	;
  3379                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3380                              <1> 	; and the number of characters to write. If finds the file
  3381                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3382                              <1> 	; descriptor is returned from a successful open or create call
  3383                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3384                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3385                              <1> 	;
  3386                              <1> 	; Calling sequence:
  3387                              <1> 	;	syswrite; buffer; nchars
  3388                              <1> 	; Arguments:
  3389                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3390                              <1> 	;	nchars - number of characters to be written.
  3391                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3392                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3393                              <1> 	; ...............................................................
  3394                              <1> 	;				
  3395                              <1> 	; Retro UNIX 8086 v1 modification: 
  3396                              <1> 	;       'syswrite' system call has three arguments; so,
  3397                              <1> 	;	* 1st argument, file descriptor is in BX register
  3398                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3399                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3400                              <1> 	;
  3401                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3402                              <1> 	;	to the user with number of bytes written. 
  3403                              <1> 	;
  3404 00003538 E82D000000          <1> 	call	rw1
  3405                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3406                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3407                              <1>        	; 24/12/2021
  3408 0000353D 7226                <1> 	jc	short syswrite_err
  3409 0000353F F6C480              <1>         test	ah, 80h
  3410                              <1> 		; tst r1 / positive i-number ?
  3411 00003542 7417                <1>         jz	short rw3 ; 13/05/2015
  3412                              <1> 	;jz	error
  3413                              <1> 		; bge error1 / yes, error 1 
  3414                              <1> 			   ; / negative i-number means write
  3415 00003544 66F7D8              <1>         neg	ax
  3416                              <1> 		; neg r1 / make it positive
  3417 00003547 E867170000          <1> 	call	writei
  3418                              <1>         	; jsr r0,writei / write data
  3419                              <1> rw0: ; 1:
  3420 0000354C A1[24660000]        <1>         mov	eax, [u.nread]
  3421 00003551 A3[FC650000]        <1> 	mov	[u.r0], eax
  3422                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3423                              <1> 				  ; / into (u.r0)
  3424 00003556 E996FCFFFF          <1> 	jmp	sysret
  3425                              <1>         	; br sysret1
  3426                              <1> 
  3427                              <1> rw3: 
  3428                              <1> 	; 13/05/2015
  3429 0000355B C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3429 00003563 0000                <1>
  3430                              <1> 	;stc
  3431                              <1> 	;retn
  3432                              <1> 	; 24/12/2021 (BugFix)
  3433                              <1> sysread_err:
  3434                              <1> syswrite_err:
  3435 00003565 E967FCFFFF          <1> 	jmp	error
  3436                              <1> 
  3437                              <1> rw1:	
  3438                              <1> 	; 14/05/2015
  3439                              <1> 	; 13/05/2015
  3440                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3441                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3442                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3443                              <1> 	;
  3444                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3445                              <1> 				;(in the user's virtual memory space)
  3446                              <1> 	;mov	[u.count], edx 
  3447                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3448                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3449                              <1> 	;;mov	eax, ebx ; file descriptor
  3450                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3451                              <1> 		             ; / (index to u.fp table) in r1
  3452                              <1> 	; 13/05/2015
  3453 0000356A C705[FC650000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3453 00003572 0000                <1>
  3454                              <1> 	;
  3455                              <1> 	;; call	getf
  3456                              <1>         ; eBX = File descriptor
  3457 00003574 E8330B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3458                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3459                              <1> 	; AX = I-number of the file ; negative i-number means write
  3460                              <1> 	; 13/05/2015
  3461 00003579 6683F801            <1> 	cmp 	ax, 1
  3462 0000357D 7217                <1> 	jb	short rw2
  3463                              <1> 	;
  3464 0000357F 890D[1C660000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3465                              <1> 				;(in the user's virtual memory space)
  3466 00003585 8915[20660000]      <1> 	mov	[u.count], edx 
  3467                              <1> 	; 14/05/2015
  3468 0000358B C705[51660000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3468 00003593 0000                <1>
  3469 00003595 C3                  <1> 	retn
  3470                              <1>         	; rts r0
  3471                              <1> rw2:
  3472                              <1> 	; 13/05/2015
  3473 00003596 C705[51660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3473 0000359E 0000                <1>
  3474 000035A0 C3                  <1> 	retn
  3475                              <1> 
  3476                              <1> sysopen: ;<open file>
  3477                              <1> 	; 09/01/2022
  3478                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3479                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3480                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3481                              <1> 	;
  3482                              <1> 	; 'sysopen' opens a file in following manner:
  3483                              <1> 	;    1) The second argument in a sysopen says whether to
  3484                              <1> 	;	open the file ro read (0) or write (>0).
  3485                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3486                              <1> 	;    3) The file is opened by 'iopen'.
  3487                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3488                              <1> 	;	and the user's open file list - u.fp.
  3489                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3490                              <1> 	;	b) An entry for the file is created in the fsp table.
  3491                              <1> 	;	c) The number of this entry is put on u.fp list.
  3492                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3493                              <1> 	;	   to by u.r0.
  3494                              <1> 	;
  3495                              <1> 	; Calling sequence:
  3496                              <1> 	;	sysopen; name; mode
  3497                              <1> 	; Arguments:
  3498                              <1> 	;	name - file name or path name
  3499                              <1> 	;	mode - 0 to open for reading
  3500                              <1> 	;	       1 to open for writing
  3501                              <1> 	; Inputs: (arguments)
  3502                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3503                              <1> 	;		  is put into r0's location on the stack.	
  3504                              <1> 	; ...............................................................
  3505                              <1> 	;				
  3506                              <1> 	; Retro UNIX 8086 v1 modification: 
  3507                              <1> 	;       'sysopen' system call has two arguments; so,
  3508                              <1> 	;	* 1st argument, name is pointed to by BX register
  3509                              <1> 	;	* 2nd argument, mode is in CX register
  3510                              <1> 	;
  3511                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3512                              <1> 	;	to the user with the file descriptor/number 
  3513                              <1> 	;	(index to u.fp list).
  3514                              <1> 	;
  3515                              <1> 	;call	arg2
  3516                              <1> 	; * name - 'u.namep' points to address of file/path name
  3517                              <1> 	;          in the user's program segment ('u.segmnt')
  3518                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3519                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3520                              <1> 	;          which is on top of stack.
  3521                              <1> 	;
  3522                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3523                              <1> 	;
  3524                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3525                              <1> 
  3526 000035A1 891D[14660000]      <1> 	mov	[u.namep], ebx
  3527                              <1> 	; 24/12/2021 (cx -> ecx)
  3528 000035A7 51                  <1> 	push	ecx ; * 
  3529 000035A8 E8300B0000          <1> 	call	namei
  3530                              <1> 		; jsr r0,namei / i-number of file in r1
  3531                              <1>      	;and	ax, ax
  3532                              <1> 	;jz	error ; File not found
  3533 000035AD 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3534                              <1> 	;jc	error ; 27/05/2013
  3535                              <1> 		; br  error2 / file not found
  3536                              <1>    	; 24/12/2021
  3537                              <1> 	;pop	edx ; * ; mode
  3538                              <1> 	;push	edx ; *
  3539 000035AF 8B1424              <1> 	mov	edx, [esp] ; *
  3540                              <1> 	; edx = open mode (0 or 1)
  3541                              <1> 	;or	dx, dx
  3542 000035B2 08D2                <1> 	or	dl, dl
  3543                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3544                              <1> 		         ; / 0 means, open for read)
  3545 000035B4 7403                <1> 	jz	short sysopen_0
  3546                              <1> 		; beq 1f / yes, leave i-number positive
  3547                              <1> syscreat_0: ; 27/12/2015
  3548 000035B6 66F7D8              <1> 	neg	ax
  3549                              <1>         	; neg r1 / open for writing so make i-number negative
  3550                              <1> sysopen_0: ;1:
  3551 000035B9 E8931B0000          <1> 	call	iopen
  3552                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3553 000035BE 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3554                              <1> 	;and	dx, dx
  3555 000035BF 20D2                <1> 	and	dl, dl
  3556                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3557 000035C1 7403                <1> 	jz	short sysopen_2
  3558                              <1>         	; beq op1 / is open for read op1
  3559                              <1> sysopen_1: ;op0:
  3560 000035C3 66F7D8              <1> 	neg	ax
  3561                              <1>         	; neg r1 
  3562                              <1> 	;; NOTE: iopen always make i-number positive.
  3563                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3564                              <1> sysopen_2: ;op1:
  3565 000035C6 31F6                <1>         xor     esi, esi
  3566                              <1>         	; clr r2 / clear registers
  3567 000035C8 31DB                <1>         xor     ebx, ebx
  3568                              <1> 		; clr r3
  3569                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3570 000035CA 389E[02660000]      <1>         cmp     [esi+u.fp], bl ; 0
  3571                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3572 000035D0 7625                <1>         jna      short sysopen_4
  3573                              <1> 		; beq 1f / if byte in list is 0 branch
  3574 000035D2 46                  <1>         inc     esi
  3575                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3576 000035D3 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3577                              <1> 		; cmp r2,$10. / reached end of list?
  3578 000035D7 72F1                <1> 	jb	short sysopen_3
  3579                              <1> 		; blt 1b / no, go back
  3580                              <1> toomanyf:
  3581                              <1> 	; 14/05/2015
  3582 000035D9 C705[51660000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3582 000035E1 0000                <1>
  3583 000035E3 E9E9FBFFFF          <1> 	jmp	error
  3584                              <1>         	; br error2 / yes, error (no files open)
  3585                              <1> fnotfound: 
  3586                              <1> 	; 14/05/2015
  3587 000035E8 C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3587 000035F0 0000                <1>
  3588 000035F2 E9DAFBFFFF          <1> 	jmp	error
  3589                              <1> 
  3590                              <1> sysopen_4: ; 1:
  3591 000035F7 6683BB[C4630000]00  <1>         cmp     word [ebx+fsp], 0
  3592                              <1> 		; tst fsp(r3) / scan fsp entries
  3593 000035FF 760D                <1>         jna     short sysopen_5
  3594                              <1> 		; beq 1f / if 0 branch
  3595                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3596 00003601 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3597                              <1> 		; add $8.,r3 / add 8 to r3 
  3598                              <1> 			; / to bump it to next entry mfsp table
  3599 00003605 6681FBF401          <1>         cmp     bx, nfiles*10
  3600                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3601 0000360A 72EB                <1> 	jb	short sysopen_4
  3602                              <1>        		; blt 1b / no, back
  3603                              <1> 	;jmp	error
  3604                              <1>         ;	; br error2 / yes, error
  3605                              <1> 	; 24/12/2021
  3606 0000360C EBCB                <1> 	jmp	short toomanyf
  3607                              <1> 
  3608                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3609 0000360E 668983[C4630000]    <1>         mov     [ebx+fsp], ax
  3610                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3611                              <1> 			; / into next available entry in fsp table,
  3612                              <1> 	; 09/01/2022
  3613                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3614                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3615                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3616                              <1> 	;xor	edi, edi
  3617                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3618                              <1> 	;	; clr fsp+4(r3)
  3619                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3620                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3621 00003615 31C0                <1> 	xor	eax, eax
  3622 00003617 8983[C8630000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3623 0000361D 668983[CC630000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3624                              <1> 
  3625 00003624 A0[E3650000]        <1> 	mov	al, [cdev]
  3626 00003629 668983[C6630000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3627                              <1> 
  3628 00003630 89D8                <1>   	mov	eax, ebx
  3629 00003632 B30A                <1> 	mov	bl, 10
  3630 00003634 F6F3                <1> 	div	bl 
  3631                              <1> 		; asr r3
  3632                              <1> 		; asr r3 / divide by 8 
  3633                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3634 00003636 FEC0                <1> 	inc	al
  3635                              <1>         	; inc r3 / add 1 to get fsp entry number
  3636 00003638 8886[02660000]      <1>         mov     [esi+u.fp], al
  3637                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3638                              <1> 			; / next available slot in u.fp list
  3639 0000363E 8935[FC650000]      <1>         mov     [u.r0], esi
  3640                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3641                              <1> 			     ; / into r0 loc on stack
  3642 00003644 E9A8FBFFFF          <1>         jmp	sysret
  3643                              <1> 		; br sysret2
  3644                              <1> 
  3645                              <1> 	;
  3646                              <1> 	; 'fsp' table (10 bytes/entry)
  3647                              <1> 	; bit 15				   bit 0
  3648                              <1> 	; ---|-------------------------------------------
  3649                              <1> 	; r/w|		i-number of open file
  3650                              <1> 	; ---|-------------------------------------------
  3651                              <1> 	;		   device number
  3652                              <1> 	; -----------------------------------------------
  3653                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3654                              <1> 	; -----------------------------------------------
  3655                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3656                              <1> 	; ----------------------|------------------------
  3657                              <1> 	;  flag that says file 	| number of processes
  3658                              <1> 	;   has been deleted	| that have file open 
  3659                              <1> 	; ----------------------|------------------------
  3660                              <1> 	;
  3661                              <1> 
  3662                              <1> syscreat: ; < create file >
  3663                              <1> 	; 24/12/2021
  3664                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3665                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3666                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3667                              <1> 	;
  3668                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3669                              <1> 	; u.namep points to name of the file and mode is put
  3670                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3671                              <1> 	; If the file aready exists, it's mode and owner remain 
  3672                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3673                              <1> 	; did not exist, an i-node is created with the new mode via
  3674                              <1> 	; 'maknod' whether or not the file already existed, it is
  3675                              <1> 	; open for writing. The fsp table is then searched for a free
  3676                              <1> 	; entry. When a free entry is found, proper data is placed
  3677                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3678                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3679                              <1> 	; is put in the user's r0. 			
  3680                              <1> 	;
  3681                              <1> 	; Calling sequence:
  3682                              <1> 	;	syscreate; name; mode
  3683                              <1> 	; Arguments:
  3684                              <1> 	;	name - name of the file to be created
  3685                              <1> 	;	mode - mode of the file to be created
  3686                              <1> 	; Inputs: (arguments)
  3687                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3688                              <1> 	;		   (the file descriptor of new file)
  3689                              <1> 	; ...............................................................
  3690                              <1> 	;				
  3691                              <1> 	; Retro UNIX 8086 v1 modification: 
  3692                              <1> 	;       'syscreate' system call has two arguments; so,
  3693                              <1> 	;	* 1st argument, name is pointed to by BX register
  3694                              <1> 	;	* 2nd argument, mode is in CX register
  3695                              <1> 	;
  3696                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3697                              <1> 	;	to the user with the file descriptor/number 
  3698                              <1> 	;	(index to u.fp list).
  3699                              <1> 	;
  3700                              <1> 	;call	arg2
  3701                              <1> 	; * name - 'u.namep' points to address of file/path name
  3702                              <1> 	;          in the user's program segment ('u.segmnt')
  3703                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3704                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3705                              <1> 	;          which is on top of stack.
  3706                              <1> 	;
  3707                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3708                              <1> 			    ; / on stack
  3709 00003649 891D[14660000]      <1> 	mov	[u.namep], ebx ; file name address
  3710                              <1> 	;push	cx ; mode
  3711                              <1> 	; 24/12/2021
  3712 0000364F 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3713 00003650 E8880A0000          <1> 	call 	namei        	
  3714                              <1> 		; jsr r0,namei / get the i-number
  3715                              <1>         ;and	ax, ax
  3716                              <1> 	;jz	short syscreat_2	       	
  3717 00003655 721B                <1> 	jc	short syscreat_2
  3718                              <1> 		; br  2f / if file doesn't exist 2f
  3719                              <1> 	; 27/12/2015
  3720 00003657 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3721                              <1>         ;jb	syscreat_0 ; yes
  3722                              <1> 	; 24/12/2021
  3723 0000365B 7305                <1> 	jnb	short syscreat_1
  3724 0000365D E954FFFFFF          <1> 	jmp	syscreat_0
  3725                              <1> syscreat_1:
  3726 00003662 66F7D8              <1> 	neg 	ax
  3727                              <1>         	; neg r1 / if file already exists make i-number 
  3728                              <1> 		       ; / negative (open for writing)
  3729 00003665 E8E71A0000          <1> 	call	iopen
  3730                              <1>         	; jsr r0,iopen /
  3731 0000366A E8AA130000          <1> 	call	itrunc
  3732                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3733                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3734                              <1> 	; 04/12/2021
  3735 0000366F 59                  <1> 	pop	ecx
  3736                              <1> 	; 08/01/2022
  3737 00003670 EB0E                <1> 	jmp	short syscreat_3
  3738                              <1>         ;jmp	sysopen_1
  3739                              <1>         	; br op0
  3740                              <1> syscreat_2: ; 2: / file doesn't exist
  3741                              <1> 	;pop	ax
  3742                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3743                              <1> 	; 24/12/2021
  3744 00003672 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3745 00003673 30E4                <1> 	xor	ah, ah	
  3746                              <1>         	; bic $!377,r1 / clear upper byte
  3747 00003675 E86F0D0000          <1> 	call 	maknod
  3748                              <1>         	; jsr r0,maknod / make an i-node for this file
  3749 0000367A 66A1[2E660000]      <1> 	mov	ax, [u.dirbuf]
  3750                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3751                              <1> 			        ; / for this new file in r1
  3752                              <1> syscreat_3:
  3753 00003680 E93EFFFFFF          <1>         jmp     sysopen_1
  3754                              <1>         	; br op0 / open the file
  3755                              <1> 
  3756                              <1> sysmkdir: ; < make directory >
  3757                              <1> 	; 26/02/2022
  3758                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3759                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3760                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3761                              <1> 	;
  3762                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3763                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3764                              <1> 	; The special entries '.' and '..' are not present.
  3765                              <1> 	; Errors are indicated if the directory already exists or		
  3766                              <1> 	; user is not the super user. 
  3767                              <1> 	;
  3768                              <1> 	; Calling sequence:
  3769                              <1> 	;	sysmkdir; name; mode
  3770                              <1> 	; Arguments:
  3771                              <1> 	;	name - points to the name of the directory
  3772                              <1> 	;	mode - mode of the directory
  3773                              <1> 	; Inputs: (arguments)
  3774                              <1> 	; Outputs: -
  3775                              <1> 	;    (sets 'directory' flag to 1; 
  3776                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3777                              <1> 	; ...............................................................
  3778                              <1> 	;				
  3779                              <1> 	; Retro UNIX 8086 v1 modification: 
  3780                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3781                              <1> 	;	* 1st argument, name is pointed to by BX register
  3782                              <1> 	;	* 2nd argument, mode is in CX register
  3783                              <1> 	;
  3784                              <1> 		
  3785                              <1> ; / make a directory
  3786                              <1> 
  3787                              <1> 	;call	arg2
  3788                              <1> 	; * name - 'u.namep' points to address of file/path name
  3789                              <1> 	;          in the user's program segment ('u.segmnt')
  3790                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3791                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3792                              <1> 	;          which is on top of stack.
  3793                              <1> 
  3794                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3795                              <1> 			    ; / on stack
  3796 00003685 891D[14660000]      <1> 	mov	[u.namep], ebx
  3797                              <1> 	;push	cx ; mode
  3798                              <1> 	; 24/12/2021
  3799 0000368B 51                  <1> 	push	ecx ; cx = mode
  3800 0000368C E84C0A0000          <1> 	call	namei
  3801                              <1>         	; jsr r0,namei / get the i-number
  3802                              <1>         	;     br .+4 / if file not found branch around error
  3803                              <1>         ;xor 	ax, ax
  3804                              <1> 	;jnz	error
  3805 00003691 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3806                              <1> 	;jnc	error	
  3807                              <1> 		; br  error2 / directory already exists (error)
  3808 00003693 803D[48660000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3809                              <1>         	;tstb u.uid / is user the super user
  3810                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3811                              <1> 	;;jna	error
  3812                              <1> 	; 26/02/2022 (BugFix)
  3813 0000369A 7721                <1> 	ja	short dir_access_err
  3814                              <1>         	;bne error2 / no, not allowed
  3815                              <1> 	;pop	ax
  3816                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3817                              <1> 	; 24/12/2021
  3818 0000369C 58                  <1> 	pop	eax  ; ax = mode
  3819 0000369D 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3820                              <1>         	;bic $!317,r1 / all but su and ex
  3821                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3822 000036A1 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3823                              <1>         	;bis $40000,r1 / directory flag
  3824 000036A4 E8400D0000          <1> 	call	maknod
  3825                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3826                              <1> ;sysclose_sysret: ; 26/02/2022
  3827 000036A9 E943FBFFFF          <1> 	jmp	sysret
  3828                              <1>         	;br sysret2 /
  3829                              <1> dir_exists:
  3830                              <1> 	; 14/05/2015
  3831 000036AE C705[51660000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3831 000036B6 0000                <1>
  3832 000036B8 E914FBFFFF          <1> 	jmp	error
  3833                              <1> dir_access_err:
  3834                              <1> 	; 14/05/2015
  3835 000036BD C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3835 000036C5 0000                <1>
  3836 000036C7 E905FBFFFF          <1> 	jmp	error
  3837                              <1> 
  3838                              <1> sysclose: ;<close file>
  3839                              <1> 	; 26/02/2022
  3840                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3841                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3842                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3843                              <1> 	;
  3844                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3845                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3846                              <1> 	; is put in r1 and 'fclose' is called.
  3847                              <1> 	;
  3848                              <1> 	; Calling sequence:
  3849                              <1> 	;	sysclose
  3850                              <1> 	; Arguments:
  3851                              <1> 	;	-  
  3852                              <1> 	; Inputs: *u.r0 - file descriptor
  3853                              <1> 	; Outputs: -
  3854                              <1> 	; ...............................................................
  3855                              <1> 	;				
  3856                              <1> 	; Retro UNIX 8086 v1 modification:
  3857                              <1> 	;	 The user/application program puts file descriptor
  3858                              <1> 	;        in BX register as 'sysclose' system call argument.
  3859                              <1> 	; 	 (argument transfer method 1)
  3860                              <1> 
  3861                              <1> 	; / close the file
  3862                              <1> 	
  3863 000036CC 89D8                <1> 	mov 	eax, ebx
  3864 000036CE E896090000          <1> 	call 	fclose
  3865                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3866                              <1> 		; jsr r0,fclose / close the file
  3867                              <1>                	; br error2 / unknown file descriptor
  3868                              <1> 		; br sysret2
  3869                              <1> 	; 14/05/2015
  3870                              <1> 	;jnc	sysret
  3871                              <1> 	; 04/12/2021
  3872 000036D3 7205                <1> 	jc	short sysclose_err
  3873 000036D5 E917FBFFFF          <1> 	jmp	sysret
  3874                              <1> 	; 26/02/2022
  3875                              <1> 	;jnc	short sysclose_sysret
  3876                              <1> sysclose_err:
  3877 000036DA C705[51660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3877 000036E2 0000                <1>
  3878 000036E4 E9E8FAFFFF          <1> 	jmp	error
  3879                              <1> 
  3880                              <1> sysemt:
  3881                              <1> 	; 26/02/2022
  3882                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3883                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3884                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3885                              <1> 	;
  3886                              <1> 	; Retro UNIX 8086 v1 modification: 
  3887                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3888                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3889                              <1> 	;
  3890                              <1> 	; Retro UNIX 8086 v1 feature only!
  3891                              <1> 	;	Using purpose: Kernel will start without time-out
  3892                              <1> 	;	(internal clock/timer) functionality.
  3893                              <1> 	;	Then etc/init will enable clock/timer for
  3894                              <1> 	;	multi tasking. (Then it will not be disabled again
  3895                              <1> 	;	except hardware reset/restart.)
  3896                              <1> 	;
  3897                              <1> 
  3898 000036E9 803D[48660000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3899                              <1> 	;;ja	error
  3900                              <1> 	;ja	badsys ; 14/05/2015
  3901                              <1> 	; 24/12/2021
  3902 000036F0 7605                <1> 	jna	short emt_0 
  3903 000036F2 E98CFBFFFF          <1> 	jmp	badsys
  3904                              <1> emt_0:
  3905                              <1> 	; 24/12/2021
  3906                              <1> 	;cli
  3907 000036F7 21DB                <1> 	and	ebx, ebx
  3908 000036F9 7429                <1> 	jz	short emt_2
  3909                              <1> 	; Enable multi tasking -time sharing-
  3910 000036FB B8[A2460000]        <1> 	mov	eax, clock
  3911                              <1> 	; 26/02/2022
  3912 00003700 BA[2C0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3913                              <1> emt_1:
  3914 00003705 A3[F1060000]        <1> 	mov	[x_timer], eax
  3915                              <1> 	; 26/02/2022 (Temporary)
  3916 0000370A 8915[F5060000]      <1> 	mov	[x_rtci], edx
  3917 00003710 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3918 00003712 E851020000          <1> 	call	wttyc  ; clear video page
  3919 00003717 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3920 00003719 E84A020000          <1> 	call	wttyc  ; clear video page
  3921                              <1> 	;
  3922 0000371E FB                  <1> 	sti
  3923 0000371F E9CDFAFFFF          <1> 	jmp	sysret
  3924                              <1> emt_2:
  3925                              <1> 	; Disable multi tasking -time sharing-
  3926 00003724 B8[FD060000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3927                              <1> 	; 26/02/2022
  3928 00003729 BA[330A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3929                              <1> 	;
  3930 0000372E EBD5                <1> 	jmp	short emt_1
  3931                              <1> 
  3932                              <1> 	; Original UNIX v1 'sysemt' routine
  3933                              <1> ;sysemt:
  3934                              <1>         ;
  3935                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3936                              <1> 			 ; / in loc 30
  3937                              <1>         ;cmp    30,$core / was the argument a lower address 
  3938                              <1> 			; / than core
  3939                              <1>         ;blo    1f / yes, rtssym
  3940                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3941                              <1> 			; / and less than "ecore"
  3942                              <1>         ;blo    2f / yes, sysret2
  3943                              <1> ;1:
  3944                              <1>         ;mov    $rtssym,30
  3945                              <1> ;2:
  3946                              <1>         ;br     sysret2
  3947                              <1> 
  3948                              <1> sysilgins:
  3949                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3950                              <1> 	; 03/06/2013
  3951                              <1> 	; Retro UNIX 8086 v1 modification: 
  3952                              <1> 	;	not a valid system call ! (not in use)
  3953                              <1> 	;
  3954 00003730 E94EFBFFFF          <1> 	jmp	badsys
  3955                              <1> 	;jmp	error
  3956                              <1> 	;;jmp 	sysret
  3957                              <1> 
  3958                              <1> 	; Original UNIX v1 'sysemt' routine
  3959                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3960                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3961                              <1> 			  ;/ put it in loc 8.,
  3962                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3963                              <1> 		       ; / trap address
  3964                              <1>         ;blo    1f / is the address a user core address?  
  3965                              <1> 		; / yes, go to 2f
  3966                              <1>         ;cmp    10,$ecore
  3967                              <1>         ;blo    2f
  3968                              <1> ;1:
  3969                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3970                              <1> 		    ; / instruction trap address for the system
  3971                              <1> ;2:
  3972                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3973                              <1> 
  3974                              <1> sysmdate: ; < change the modification time of a file >
  3975                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3976                              <1> 	;	(ECX input)
  3977                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3978                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3979                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3980                              <1> 	;
  3981                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3982                              <1> 	; file into core. The user is checked if he is the owner 
  3983                              <1> 	; or super user. If he is neither an error occurs.
  3984                              <1> 	; 'setimod' is then called to set the i-node modification
  3985                              <1> 	; byte and the modification time, but the modification time
  3986                              <1> 	; is overwritten by whatever get put on the stack during
  3987                              <1> 	; a 'systime' system call. This calls are restricted to
  3988                              <1> 	; the super user.		
  3989                              <1> 	;
  3990                              <1> 	; Calling sequence:
  3991                              <1> 	;	sysmdate; name
  3992                              <1> 	; Arguments:
  3993                              <1> 	;	name - points to the name of file
  3994                              <1> 	; Inputs: (arguments)
  3995                              <1> 	; Outputs: -
  3996                              <1> 	; ...............................................................
  3997                              <1> 	;				
  3998                              <1> 	; Retro UNIX 8086 v1 modification: 
  3999                              <1> 	;	 The user/application program puts address 
  4000                              <1> 	;	 of the file name in BX register 
  4001                              <1> 	;	 as 'sysmdate' system call argument.
  4002                              <1> 	;
  4003                              <1> ; / change the modification time of a file
  4004                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4005 00003735 891D[14660000]      <1>         mov	[u.namep], ebx
  4006                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  4007 0000373B 890D[80620000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  4008 00003741 E897090000          <1> 	call	namei
  4009                              <1> 		; jsr r0,namei / get its i-number
  4010                              <1> 	;;jc	error       
  4011                              <1> 	;	; br error2 / no, such file
  4012                              <1> 	;jc	fnotfound ; file not found !
  4013                              <1> 	; 24/12/2021
  4014 00003746 7305                <1> 	jnc	short mdate_0
  4015 00003748 E99BFEFFFF          <1> 	jmp	fnotfound
  4016                              <1> mdate_0:
  4017 0000374D E89B110000          <1> 	call	iget
  4018                              <1> 		; jsr r0,iget / get i-node into core
  4019 00003752 A0[48660000]        <1> 	mov	al, [u.uid]
  4020 00003757 3A05[F7620000]      <1> 	cmp	al, [i.uid]
  4021                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  4022 0000375D 7413                <1> 	je	short mdate_1
  4023                              <1>         	; beq 1f / yes
  4024 0000375F 20C0                <1> 	and	al, al
  4025                              <1> 		; tstb u.uid / no, is user the super user
  4026                              <1> 	;jnz	error
  4027                              <1> 		; bne error2 / no, error
  4028 00003761 740F                <1> 	jz	short mdate_1
  4029 00003763 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4029 0000376B 0000                <1>
  4030                              <1> sysstty_err:	; 04/02/2022
  4031 0000376D E95FFAFFFF          <1> 	jmp	error
  4032                              <1> mdate_1: ;1:
  4033 00003772 E880120000          <1> 	call	setimod
  4034                              <1>         	; jsr r0,setimod / fill in modification data,
  4035                              <1> 		               ; / time etc.
  4036 00003777 BE[80620000]        <1> 	mov	esi, p_time
  4037 0000377C BF[0E630000]        <1> 	mov	edi, i.mtim
  4038 00003781 A5                  <1> 	movsd
  4039                              <1> 		; mov 4(sp),i.mtim / move present time to
  4040                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4041 00003782 E96AFAFFFF          <1>         jmp	sysret
  4042                              <1> 		; br sysret2
  4043                              <1> 
  4044                              <1> 	; 04/02/2022
  4045                              <1> sysstty_err_s:
  4046 00003787 880D[FC650000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4047 0000378D EBDE                <1> 	jmp	short sysstty_err
  4048                              <1> 
  4049                              <1> sysstty: ; < set tty status and mode >
  4050                              <1> 	; 26/02/2022
  4051                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4052                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4053                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4054                              <1> 	; 17/11/2015
  4055                              <1> 	; 12/11/2015
  4056                              <1> 	; 29/10/2015
  4057                              <1> 	; 17/10/2015
  4058                              <1> 	; 13/10/2015
  4059                              <1> 	; 29/06/2015
  4060                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4061                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4062                              <1> 	;
  4063                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4064                              <1> 	; whose file descriptor is in (u.r0).
  4065                              <1> 	;
  4066                              <1> 	; Calling sequence:
  4067                              <1> 	;	sysstty; arg
  4068                              <1> 	; Arguments:
  4069                              <1> 	;	arg - address of 3 consequitive words that contain
  4070                              <1> 	;	      the source of status data	
  4071                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4072                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4073                              <1> 	; ...............................................................
  4074                              <1> 	;	
  4075                              <1> 	; Retro UNIX 8086 v1 modification: 
  4076                              <1> 	;	'sysstty' system call will set the tty
  4077                              <1> 	;	(clear keyboard buffer and set cursor position)
  4078                              <1> 	;	 in following manner:
  4079                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4080                              <1> 	;
  4081                              <1> 	; Inputs:
  4082                              <1> 	;	BX = 0 --> means
  4083                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4084                              <1> 	;	      set cursor position for console tty, only 
  4085                              <1> 	;	      CH will be ignored (char. will not be written)	
  4086                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4087                              <1> 	;	      set console tty for (current) process
  4088                              <1> 	;	      CL = tty number (0 to 9)
  4089                              <1> 	;	      (If CH = 0, character will not be written)			
  4090                              <1> 	;          If CH > 0 (CL < FFh)	
  4091                              <1> 	;             CL = tty number (0 to 9)
  4092                              <1> 	;	      CH = character will be written
  4093                              <1> 	;	        at requested cursor position (in DX)	
  4094                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4095                              <1>   	;		(only tty number 0 to 7) 
  4096                              <1> 	;          DL = communication parameters (for serial ports) 
  4097                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4098                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4099                              <1> 	;			or set cursor position	
  4100                              <1> 	;	   DH = 0FFh -> DL is not valid
  4101                              <1> 	;		do not set serial port parameters 
  4102                              <1> 	;		or do not set cursor position
  4103                              <1> 	;
  4104                              <1> 	;	BX > 0 --> points to name of tty
  4105                              <1> 	;    	   CH > 0 -->
  4106                              <1> 	;		CH = character will be written in current 
  4107                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4108                              <1> 	;	     	or character will be sent to serial port
  4109                              <1> 	;	     	(for tty number 8 or 9)
  4110                              <1> 	;		CL = color of the character if tty number < 8.
  4111                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4112                              <1> 	;		set mode (tty 8 to 9) or 
  4113                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4114                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4115                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4116                              <1> 	;		(DL is not valid)
  4117                              <1> 	;	   DL = communication parameters 
  4118                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4119                              <1> 	;
  4120                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4121                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4122                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4123                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4124                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4125                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4126                              <1> 	;
  4127                              <1> 	; Outputs:
  4128                              <1> 	;	cf = 0 -> OK
  4129                              <1> 	;	     AL = tty number (0 to 9)
  4130                              <1> 	;	     AH = line status if tty number is 8 or 9
  4131                              <1> 	;	     AH = process number (of the caller) 	
  4132                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4133                              <1> 	;	     AH = FFh if the tty is locked 
  4134                              <1> 	;		  (owned by another process)
  4135                              <1> 	;	        = process number (of the caller) 
  4136                              <1> 	;		  (if < FFh and tty number < 8)
  4137                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4138                              <1> 	;	     AH = line status if tty number is 8 or 9
  4139                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4140                              <1> 	;	
  4141                              <1> 
  4142                              <1> 	; 27/06/2015 (32 bit modifications)
  4143                              <1> 	; 14/01/2014
  4144 0000378F 31C0                <1> 	xor 	eax, eax
  4145 00003791 6648                <1> 	dec	ax ; 17/10/2015
  4146 00003793 A3[FC650000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4147                              <1> 	;;;
  4148                              <1> 	; 01/02/2022
  4149 00003798 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4150 0000379A 39C2                <1> 	cmp	edx, eax
  4151                              <1> 	;cmp	dx, ax ; 0FFFFh
  4152 0000379C 7521                <1> 	jne	short sysstty_18
  4153                              <1> 	; clear video page
  4154                              <1> 	; (CH must be 0)
  4155 0000379E 08ED                <1> 	or	ch, ch
  4156 000037A0 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4157 000037A2 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4158 000037A5 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4159 000037A7 20C9                <1> 	and	cl, cl
  4160 000037A9 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4161 000037AB 0FB635[4B660000]    <1> 	movzx	esi, byte [u.uno]
  4162 000037B2 8A8E[53630000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4163 000037B8 80F907              <1> 	cmp	cl, 7
  4164 000037BB 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4165                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4166 000037BD FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4167                              <1> sysstty_18:
  4168 000037BF FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4169                              <1> 	; cl = video page (tty) number		
  4170                              <1> 	;;;
  4171 000037C1 21DB                <1> 	and	ebx, ebx
  4172                              <1> 	;jnz	sysstty_6
  4173                              <1> 	; 01/02/2022
  4174 000037C3 7405                <1> 	jz	short sysstty_19
  4175 000037C5 E9C2000000          <1> 	jmp	sysstty_6
  4176                              <1> sysstty_19:
  4177                              <1> 	; set console tty
  4178                              <1> 	; 29/10/2015
  4179                              <1> 	; 17/01/2014 
  4180 000037CA 80F909              <1> 	cmp	cl, 9
  4181 000037CD 7613                <1> 	jna	short sysstty_0
  4182                              <1> 	; 17/11/2015
  4183 000037CF 80F9FF              <1> 	cmp	cl, 0FFh
  4184 000037D2 7202                <1> 	jb	short sysstty_13
  4185 000037D4 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4186                              <1> sysstty_13:
  4187 000037D6 8A1D[4B660000]      <1> 	mov	bl, [u.uno] ; process number
  4188 000037DC 8A8B[53630000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4189                              <1> sysstty_0:
  4190                              <1> 	; 29/06/2015
  4191                              <1> 	;push	dx
  4192                              <1> 	;push	cx
  4193                              <1> 	; 01/02/2022
  4194 000037E2 52                  <1> 	push	edx
  4195 000037E3 51                  <1> 	push	ecx
  4196 000037E4 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4197 000037E6 88C8                <1> 	mov	al, cl
  4198 000037E8 A2[FC650000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4199 000037ED E8F9190000          <1> 	call	ottyp
  4200                              <1> 	; 01/02/2022
  4201 000037F2 59                  <1> 	pop	ecx
  4202 000037F3 5A                  <1> 	pop	edx
  4203                              <1> 	;pop	cx
  4204                              <1> 	;pop	dx
  4205                              <1> 	;
  4206 000037F4 7220                <1> 	jc	short sysstty_pd_err
  4207                              <1> 	;
  4208                              <1> 	; 26/02/2022 (Bug! BugFix)
  4209                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4210                              <1> 	;
  4211 000037F6 80F908              <1> 	cmp	cl, 8
  4212 000037F9 720C                <1> 	jb	short sysstty_2
  4213                              <1> 	;
  4214 000037FB 80FEFF              <1> 	cmp	dh, 0FFh
  4215 000037FE 7407                <1> 	je	short sysstty_2
  4216                              <1> 		; set communication parameters for serial ports
  4217                              <1> 
  4218                              <1> ; 01/02/2022
  4219                              <1> ;	; 29/10/2015
  4220                              <1> ;	mov	ah, dl ; communication parameters
  4221                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4222                              <1> ;		;			 THRE int + RDA int 
  4223                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4224                              <1> ;		;			 THRE int + RDA int 
  4225                              <1> ;	sub	al, al ; 0
  4226                              <1> ;	; 12/07/2014
  4227                              <1> ;	cmp	cl, 9
  4228                              <1> ;	jb	short sysstty_1
  4229                              <1> ;	inc	al
  4230                              <1> ;sysstty_1:
  4231                              <1> ;	; 01/02/2022
  4232                              <1> ;	push	ecx
  4233                              <1> ;	;push	cx
  4234                              <1> ;	; 29/06/2015	
  4235                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4236                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4237                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4238                              <1> ;	; 01/02/2022
  4239                              <1> ;	pop	ecx	
  4240                              <1> ;	;pop	cx
  4241                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4242                              <1> 
  4243                              <1> 	; 01/02/2022
  4244 00003800 E830010000          <1> 	call	sysstty_scp
  4245 00003805 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4246                              <1> 
  4247                              <1> sysstty_2:
  4248                              <1> 	; 17/01/2014
  4249 00003807 20ED                <1> 	and	ch, ch 	; set cursor position 
  4250                              <1> 			; or comm. parameters ONLY
  4251 00003809 7527                <1> 	jnz	short sysstty_3
  4252                              <1> 	; 01/02/2022
  4253 0000380B 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4254 0000380F 7214                <1> 	jb	short sysstty_20
  4255                              <1> 	; clear screen (video page)
  4256 00003811 E93B010000          <1> 	jmp	sysstty_14
  4257                              <1> 
  4258                              <1> sysstty_pd_err: ; 29/06/2015
  4259                              <1> 	; 'permission denied !' error
  4260 00003816 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4260 0000381E 0000                <1>
  4261 00003820 E9ACF9FFFF          <1> 	jmp	error
  4262                              <1> 
  4263                              <1> sysstty_20:
  4264 00003825 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4265 0000382C 888B[53630000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4266                              <1> sysstty_3:
  4267                              <1> 	; 16/01/2014
  4268 00003832 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4269                              <1> 	; 17/11/2015
  4270 00003834 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4271 00003836 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4272                              <1> 	;jna	sysstty_9
  4273                              <1> 	; 01/02/2022
  4274 00003838 7705                <1> 	ja	short sysstty_12
  4275 0000383A E9C5000000          <1> 	jmp	sysstty_9
  4276                              <1> 
  4277                              <1> sysstty_12:
  4278                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4279                              <1> 	; (Set specified serial port as console tty port)
  4280                              <1> 	; CH = character to be written
  4281                              <1> 	; 15/04/2014
  4282                              <1> 	; CH = 0 --> initialization only
  4283                              <1> 	; AL = character
  4284                              <1> 	; 26/06/2014
  4285 0000383F 880D[50660000]      <1> 	mov	[u.ttyn], cl
  4286                              <1> 	; 12/07/2014
  4287 00003845 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4288                              <1> 	; 02/02/2022
  4289 00003847 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4290 00003849 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4291 0000384B FEC8                <1> 	dec	al  ; 1 -> 0	
  4292                              <1> 	;and	al, al
  4293 0000384D 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4294                              <1>  	; 04/07/2014
  4295 0000384F E8AD1E0000          <1> 	call 	sndc
  4296                              <1> 	; 12/07/2014
  4297 00003854 EB0C                <1> 	jmp	short sysstty_5
  4298                              <1> 
  4299                              <1> sysstty_4:
  4300                              <1> 	; 12/07/2014
  4301                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4302 00003856 88E0                <1> 	mov	al, ah ; 29/06/2015
  4303 00003858 2C08                <1> 	sub	al, 8
  4304                              <1> 	; 27/06/2015
  4305 0000385A E828F4FFFF          <1> 	call	sp_status ; get serial port status
  4306                              <1> 	; AL = Line status, AH = Modem status
  4307                              <1> 	; 12/11/2015
  4308 0000385F 3C80                <1> 	cmp	al, 80h
  4309 00003861 F5                  <1> 	cmc
  4310                              <1> sysstty_5:
  4311 00003862 66A3[FD650000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4312                              <1> 		; EAX bits 16-23 = modem status	
  4313 00003868 9C                  <1> 	pushf
  4314 00003869 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4315 0000386B A0[50660000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4316 00003870 E8991A0000          <1> 	call	cttyp
  4317 00003875 9D                  <1> 	popf
  4318                              <1> 	;jnc	sysret ; time out error 
  4319                              <1> 	; 01/02/2022
  4320 00003876 7205                <1> 	jc	short sysstty_tmout_err
  4321 00003878 E974F9FFFF          <1> 	jmp	sysret
  4322                              <1> 
  4323                              <1> sysstty_tmout_err:
  4324 0000387D C705[51660000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4324 00003885 0000                <1>
  4325 00003887 E945F9FFFF          <1> 	jmp	error
  4326                              <1> 
  4327                              <1> sysstty_6:
  4328                              <1> 	;push	dx
  4329                              <1> 	;push	cx
  4330                              <1> 	; 01/02/2022
  4331 0000388C 52                  <1> 	push	edx
  4332 0000388D 51                  <1> 	push	ecx
  4333 0000388E 891D[14660000]      <1> 	mov	[u.namep], ebx
  4334 00003894 E844080000          <1> 	call	namei
  4335                              <1> 	; 01/02/2022
  4336 00003899 59                  <1> 	pop	ecx
  4337 0000389A 5A                  <1> 	pop	edx
  4338                              <1> 	;pop	cx
  4339                              <1> 	;pop	dx
  4340 0000389B 7258                <1> 	jc	short sysstty_inv_dn
  4341                              <1> 	;
  4342 0000389D 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4343 000038A1 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4344                              <1> 	;
  4345 000038A3 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4346                              <1> 		       ; /dev/COM1, /dev/COM2
  4347 000038A5 7204                <1> 	jb	short sysstty_7
  4348 000038A7 2C0A                <1> 	sub	al, 10
  4349 000038A9 EB11                <1> 	jmp	short sysstty_8
  4350                              <1> 
  4351                              <1> sysstty_7:
  4352 000038AB 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4353 000038AD 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4354 000038AF 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4355 000038B6 8A83[53630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4356                              <1> sysstty_8:
  4357                              <1> 	; 26/02/2022
  4358                              <1> 	; (ebx < 256)	
  4359 000038BC A2[FC650000]        <1> 	mov	[u.r0], al
  4360                              <1> 	; 01/02/2022
  4361                              <1> 	;push	dx
  4362                              <1> 	;push	ax
  4363                              <1> 	;push	cx
  4364 000038C1 52                  <1> 	push	edx
  4365 000038C2 50                  <1> 	push	eax
  4366 000038C3 51                  <1> 	push	ecx	
  4367 000038C4 E822190000          <1> 	call	ottyp
  4368 000038C9 59                  <1> 	pop	ecx
  4369 000038CA 58                  <1> 	pop	eax
  4370 000038CB 5A                  <1> 	pop	edx
  4371                              <1> 	;pop	cx
  4372                              <1> 	;pop	ax
  4373                              <1> 	;pop	dx
  4374                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4375                              <1> 	; 01/02/2022
  4376 000038CC 7305                <1> 	jnc	short sysstty_21
  4377 000038CE E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4378                              <1> sysstty_21:
  4379                              <1> 	; 29/10/2015
  4380 000038D3 86E9                <1> 	xchg 	ch, cl
  4381                              <1> 		; cl = character, ch = color code
  4382 000038D5 86C1                <1> 	xchg	al, cl
  4383                              <1> 		; al = character, cl = tty number
  4384 000038D7 80F907              <1> 	cmp	cl, 7
  4385                              <1> 	;ja	sysstty_12
  4386                              <1> 	; 01/02/2022
  4387 000038DA 7628                <1> 	jna	short sysstty_16
  4388                              <1> ;;
  4389 000038DC 80FEFF              <1> 	cmp	dh, 0FFh
  4390 000038DF 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4391                              <1> 
  4392                              <1> ; 01/02/2022
  4393                              <1> ;	; 29/10/2015
  4394                              <1> ;	mov	ah, dl ; communication parameters
  4395                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4396                              <1> ;		;			 THRE int + RDA int 
  4397                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4398                              <1> ;		;			 THRE int + RDA int 
  4399                              <1> ;	sub	al, al ; 0
  4400                              <1> ;	; 12/07/2014
  4401                              <1> ;	cmp	cl, 9
  4402                              <1> ;	jb	short sysstty_1
  4403                              <1> ;	inc	al
  4404                              <1> ;sysstty_1:
  4405                              <1> ;	; 01/02/2022
  4406                              <1> ;	push	ecx
  4407                              <1> ;	;push	cx
  4408                              <1> ;	; 29/06/2015	
  4409                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4410                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4411                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4412                              <1> ;	; 01/02/2022
  4413                              <1> ;	pop	ecx	
  4414                              <1> ;	;pop	cx
  4415                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4416                              <1> 
  4417                              <1> 	; 02/02/2022
  4418 000038E1 88C5                <1> 	mov	ch, al ; save char
  4419                              <1> 	; 01/02/2022
  4420 000038E3 E84D000000          <1> 	call	sysstty_scp
  4421 000038E8 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4422                              <1> 	; 02/02/2022
  4423 000038EA 88E8                <1> 	mov	al, ch ; restore char
  4424                              <1> sysstty_22:
  4425                              <1> 	; 01/02/2022
  4426 000038EC 08ED                <1> 	or	ch, ch
  4427 000038EE 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4428                              <1> 	; send char to (serial port) terminal
  4429                              <1> 	; al = character
  4430                              <1> 	; cl = tty number (8 or 9)
  4431 000038F0 E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4432                              <1> 
  4433                              <1> sysstty_inv_dn: 
  4434                              <1> 	; 27/06/2015
  4435                              <1> 	; Invalid device name (not a tty) ! error
  4436                              <1> 	; (Device is not a tty or device name not found)
  4437 000038F5 C705[51660000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4437 000038FD 0000                <1>
  4438 000038FF E9CDF8FFFF          <1> 	jmp	error 
  4439                              <1> 
  4440                              <1> sysstty_16:
  4441                              <1> 	; 26/02/2022
  4442                              <1> 	; 16/01/2014
  4443                              <1> 	;xor	bh, bh
  4444                              <1> 	; 02/02/2022
  4445                              <1> sysstty_9: 	; tty 0 to tty 7
  4446                              <1> 	; al = character
  4447                              <1> 	; ch = color/attribute ; 01/02/2022
  4448                              <1> 	;
  4449                              <1> 	; 26/02/2022 (BugFix)
  4450                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4451 00003904 29DB                <1> 	sub	ebx, ebx ; *
  4452 00003906 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4453 00003909 740B                <1> 	je	short sysstty_10
  4454                              <1> 	; 02/02/2022
  4455 0000390B 51                  <1> 	push	ecx
  4456 0000390C 50                  <1> 	push	eax
  4457                              <1> 	;push	cx
  4458                              <1> 	;push	ax	
  4459                              <1> 	;movzx	ebx, cl
  4460 0000390D 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4461 0000390F E898DBFFFF          <1> 	call	set_cpos
  4462                              <1> 	;pop	ax
  4463                              <1> 	;pop	cx
  4464                              <1> 	; 02/02/2022
  4465 00003914 58                  <1> 	pop	eax
  4466 00003915 59                  <1> 	pop	ecx
  4467                              <1> sysstty_10: 
  4468                              <1> 	; 29/10/2015
  4469 00003916 08C0                <1> 	or	al, al ; character
  4470 00003918 740D                <1> 	jz      short sysstty_11 ; al = 0
  4471                              <1> 	; 17/11/2015
  4472 0000391A 3CFF                <1> 	cmp	al, 0FFh
  4473 0000391C 7309                <1> 	jnb	short sysstty_11
  4474                              <1> 		; ch > 0 and ch < FFh
  4475                              <1> 	; write a character at current cursor position
  4476 0000391E 88EC                <1> 	mov	ah, ch ; color/attribute
  4477                              <1> 	; 12/07/2014
  4478                              <1> 	;push	cx
  4479                              <1> 	; 02/02/2022
  4480 00003920 51                  <1> 	push	ecx
  4481 00003921 E86EDCFFFF          <1> 	call	write_c_current
  4482                              <1> 	;pop	cx
  4483                              <1> 	; 02/02/2022
  4484 00003926 59                  <1> 	pop	ecx
  4485                              <1> sysstty_11:
  4486                              <1> 	; 14/01/2014
  4487 00003927 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4488                              <1> 	; 18/01/2014
  4489                              <1> 	;movzx	eax, cl ; 27/06/2015
  4490 00003929 88C8                <1> 	mov	al, cl
  4491 0000392B E8DE190000          <1> 	call	cttyp
  4492 00003930 E9BCF8FFFF          <1> 	jmp	sysret
  4493                              <1> 
  4494                              <1> sysstty_scp:
  4495                              <1> 	; 02/02/2022
  4496                              <1> 	; set communication parameters (for COM1 or COM2)
  4497                              <1> 	; 01/02/2022
  4498                              <1> 	;
  4499                              <1> 	; 29/10/2015
  4500 00003935 88D4                <1> 	mov	ah, dl ; communication parameters
  4501                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4502                              <1> 		;			 THRE int + RDA int 
  4503                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4504                              <1> 		;			 THRE int + RDA int 
  4505 00003937 28C0                <1> 	sub	al, al ; 0
  4506                              <1> 	; 12/07/2014
  4507 00003939 80F909              <1> 	cmp	cl, 9
  4508 0000393C 7202                <1> 	jb	short sysstty_1
  4509 0000393E FEC0                <1> 	inc	al
  4510                              <1> sysstty_1:
  4511                              <1> 	; 02/02/2022
  4512 00003940 52                  <1> 	push	edx
  4513                              <1> 	; 01/02/2022
  4514 00003941 51                  <1> 	push	ecx
  4515                              <1> 	;push	cx
  4516                              <1> 	; 29/06/2015	
  4517 00003942 E848F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4518 00003947 66890D[FD650000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4519                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4520                              <1> 	; 01/02/2022
  4521 0000394E 59                  <1> 	pop	ecx	
  4522                              <1> 	;pop	cx
  4523 0000394F 5A                  <1> 	pop	edx ; 02/02/2022
  4524                              <1> 	; 01/02/2022
  4525                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4526 00003950 C3                  <1> 	retn
  4527                              <1> 
  4528                              <1> sysstty_14:
  4529                              <1> 	; 26/02/2022
  4530                              <1> 	; 02/02/2022
  4531                              <1> 	; ch = 0
  4532                              <1> 	; cl = video page
  4533                              <1> 	;
  4534                              <1> 	; dx = 0FFFFh
  4535                              <1> 	; clear screen (video page)
  4536                              <1> 	;
  4537                              <1> 
  4538                              <1> 	; 02/02/2022
  4539                              <1> 	; clear screen
  4540                              <1> 	;
  4541                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4542                              <1> 	; clear video page
  4543                              <1> 
  4544                              <1> 	; 26/02/2022
  4545 00003951 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4546                              <1> 
  4547                              <1> 	; clear video page
  4548 00003953 E810000000          <1> 	call	wttyc ; 26/02/2022
  4549                              <1> 
  4550                              <1> 	; 26/02/2022
  4551 00003958 88D8                <1> 	mov	al, bl
  4552 0000395A 8A25[4B660000]      <1> 	mov	ah, [u.uno]
  4553 00003960 66A3[FC650000]      <1> 	mov	[u.r0], ax
  4554 00003966 EBBF                <1> 	jmp	short sysstty_11
  4555                              <1> 
  4556                              <1> vp_clr:	; 27/02/2022
  4557                              <1> wttyc:
  4558                              <1> 	; 23/02/2022
  4559                              <1> 	; (clear video page)
  4560                              <1> 	; INPUT:
  4561                              <1> 	;  bl = video page (0 to 7)
  4562                              <1> 	;
  4563                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4564                              <1> 
  4565                              <1> 	;xor	dx, dx ; column 0, row 0
  4566                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4567                              <1> 	;
  4568                              <1> ;	movzx	ebx, cl
  4569                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4570                              <1> 
  4571                              <1> ;	shl 	bl, 1 
  4572                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4573                              <1> ;		; AL = lock value (0 or process number)
  4574                              <1> ;	or	al, al
  4575                              <1> ;	jz	short @f
  4576                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4577                              <1> ;	jne	short sysstty_15
  4578                              <1> ;		; only the owner can clear its video page
  4579                              <1> ;	xor	al, al ; 0
  4580                              <1> ;@@:
  4581                              <1> ;	;mov	bl, cl		
  4582                              <1> ;	shr	bl, 1 
  4583                              <1> 
  4584 00003968 30C0                <1> 	xor	al, al	; 0
  4585 0000396A B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4586                              <1> 
  4587                              <1> 	; scroll_up input:
  4588                              <1> 	;
  4589                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4590                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4591                              <1> 	; ah = attribute to be used on blanked line
  4592                              <1> 	; bl = video page number (0 to 7)
  4593                              <1> 
  4594 0000396C E8C1DBFFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4595                              <1> 
  4596                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4597                              <1> 
  4598                              <1> 	; bl = video page number (0 to 7)
  4599                              <1> 	;xor	dx, dx ; column 0, row 0
  4600                              <1> 	; 02/02/2022
  4601 00003971 31D2                <1> 	xor	edx, edx
  4602                              <1> 	; 26/02/2022
  4603                              <1> 	;call	set_cpos
  4604                              <1> 	;retn
  4605 00003973 E934DBFFFF          <1> 	jmp	set_cpos
  4606                              <1> 
  4607                              <1> 	;mov	al, bl
  4608                              <1> 	;mov	ah, [u.uno]
  4609                              <1> 	;mov	[u.r0], ax
  4610                              <1> 	;jmp	short sysstty_11
  4611                              <1> 
  4612                              <1> ;sysstty_15:
  4613                              <1> ;	; 30/01/2022
  4614                              <1> ;	; permission (denied) error
  4615                              <1> ;	;xor	dl, dl ; sysstty call sign
  4616                              <1> ;	mov	al, cl
  4617                              <1> ;	sub	ah, ah ; 0
  4618                              <1> ;	call	cttyp
  4619                              <1> ;	jmp	error
  4620                              <1> 
  4621                              <1> ; Original UNIX v1 'sysstty' routine:
  4622                              <1> ; gtty:
  4623                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4624                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4625                              <1> 	; 		/ r2 has source
  4626                              <1>         ;mov    r2,-(sp)
  4627                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4628                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4629                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4630                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4631                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4632                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4633                              <1>         ;       br .+4 / list empty, skip branch
  4634                              <1>         ;br     1b / get another character until list is empty
  4635                              <1>         ;mov    0b,r1 / move cc offset to r1
  4636                              <1>         ;inc    r1 / bump it for output clist
  4637                              <1>         ;tstb   cc(r1) / is it 0
  4638                              <1>         ;beq    1f / yes, no characters to output
  4639                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4640                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4641                              <1>         ;br     1b / try to calm it down again
  4642                              <1> ;1:
  4643                              <1>         ;mov    (sp)+,r1
  4644                              <1>         ;mov    (sp)+,r2 / restore registers
  4645                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4646                              <1>         ;beq    1f / if 0, 1f
  4647                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4648                              <1>         ;                   / control status register
  4649                              <1> ;1:
  4650                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4651                              <1>         ;beq    1f / if 0 1f
  4652                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4653                              <1> 	;		    / control status reg
  4654                              <1> ;1:
  4655                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4656                              <1>         ;jmp     sysret2 / return to user
  4657                              <1> 
  4658                              <1> sysgtty: ; < get tty status >
  4659                              <1> 	; 26/02/2022
  4660                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4661                              <1> 	;	    ((32 bit reg push/pop))
  4662                              <1> 	; 23/11/2015
  4663                              <1> 	; 29/10/2015
  4664                              <1> 	; 17/10/2015
  4665                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4666                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4667                              <1> 	;
  4668                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4669                              <1> 	; It stores in the three words addressed by it's argument
  4670                              <1> 	; the status of the typewriter whose file descriptor
  4671                              <1> 	; in (u.r0).
  4672                              <1> 	;
  4673                              <1> 	; Calling sequence:
  4674                              <1> 	;	sysgtty; arg
  4675                              <1> 	; Arguments:
  4676                              <1> 	;	arg - address of 3 words destination of the status
  4677                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4678                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4679                              <1> 	; ...............................................................
  4680                              <1> 	;	
  4681                              <1> 	; Retro UNIX 8086 v1 modification: 
  4682                              <1> 	;	'sysgtty' system call will return status of tty
  4683                              <1> 	;	(keyboard, serial port and video page status)
  4684                              <1> 	;	 in following manner:
  4685                              <1> 	;
  4686                              <1> 	; Inputs:
  4687                              <1> 	;	BX = 0 --> means 
  4688                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4689                              <1> 	;	                 for (current) process
  4690                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4691                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4692                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4693                              <1> 	;	     CH > 0 -->	tty number + 1
  4694                              <1> 	;
  4695                              <1> 	;	BX > 0 --> points to name of tty
  4696                              <1> 	;	     CL = 0 --> return keyboard status
  4697                              <1> 	;	     CL = 1 --> return video page status
  4698                              <1> 	;	     CH = undefined		 
  4699                              <1> 	;
  4700                              <1> 	; Outputs:
  4701                              <1> 	;	cf = 0 ->
  4702                              <1> 	;
  4703                              <1> 	;	     AL = tty number from 0 to 9
  4704                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4705                              <1> 	;	     AH = 0 if the tty is free/unused
  4706                              <1> 	;	     AH = the process number of the caller 
  4707                              <1>  	;	     AH = FFh if the tty is locked by another process
  4708                              <1> 	;
  4709                              <1> 	;	  (if calling is for serial port status)
  4710                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4711                              <1> 	;		  (BH = modem status, BL = Line status)
  4712                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4713                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4714                              <1> 	;
  4715                              <1> 	;	  (if calling is for keyboard status)
  4716                              <1> 	;	     BX = current character in tty/keyboard buffer
  4717                              <1> 	;		  (BH = scan code, BL = ascii code)
  4718                              <1> 	;		  (BX=0 if there is not a waiting character)
  4719                              <1> 	;	     CX  is undefined
  4720                              <1> 	;
  4721                              <1> 	;	  (if calling is for video page status)	
  4722                              <1> 	;	     BX = cursor position on the video page
  4723                              <1> 	;		  if tty number < 8
  4724                              <1> 	;		  (BH = row, BL = column)
  4725                              <1> 	;	     CX = current character (in cursor position)
  4726                              <1> 	;		  on the video page of the tty 
  4727                              <1> 	;		  if tty number < 8
  4728                              <1> 	;		  (CH = color, CL = character)
  4729                              <1> 	;	
  4730                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4731                              <1> 	;
  4732                              <1> 	;	     AH = FFh if the caller is not owner of
  4733                              <1> 	;		  specified tty or console tty
  4734                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4735                              <1> 	;	     BX, CX are undefined if cf = 1
  4736                              <1> 	;
  4737                              <1> 	;	  (If tty number is 8 or 9)
  4738                              <1> 	;	     AL = tty number 
  4739                              <1> 	;	     AH = the process number of the caller 
  4740                              <1> 	;	     BX = serial port status
  4741                              <1> 	;  		 (BH = modem status, BL = Line status)
  4742                              <1> 	;	     CX = 0
  4743                              <1> 	;
  4744                              <1> 		
  4745                              <1> gtty:   ; get (requested) tty number
  4746                              <1> 	; 26/02/2022
  4747                              <1> 	; 17/10/2015
  4748                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4749                              <1> 	; 30/05/2013 - 12/07/2014
  4750                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4751                              <1> 	;
  4752                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4753                              <1> 	;
  4754                              <1> 	; 28/06/2015 (32 bit modifications)
  4755                              <1> 	; 16/01/2014
  4756 00003978 31C0                <1> 	xor 	eax, eax
  4757 0000397A 6648                <1> 	dec	ax ; 17/10/2015
  4758 0000397C A3[FC650000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4759 00003981 80F901              <1> 	cmp	cl, 1
  4760 00003984 760F                <1> 	jna	short sysgtty_0
  4761                              <1> sysgtty_invp:
  4762                              <1> 	; 28/06/2015
  4763 00003986 C705[51660000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4763 0000398E 0000                <1>
  4764 00003990 E93CF8FFFF          <1> 	jmp	error
  4765                              <1> sysgtty_0:	
  4766 00003995 21DB                <1> 	and	ebx, ebx
  4767 00003997 742E                <1> 	jz	short sysgtty_1
  4768                              <1> 	;
  4769 00003999 891D[14660000]      <1> 	mov	[u.namep], ebx
  4770                              <1> 	;push	cx ; 23/11/2015
  4771 0000399F 51                  <1> 	push	ecx ; 24/12/2021
  4772 000039A0 E838070000          <1> 	call	namei
  4773 000039A5 59                  <1> 	pop	ecx
  4774                              <1> 	;pop	cx ; 23/11/2015
  4775 000039A6 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4776                              <1> 	;
  4777 000039A8 6683F801            <1> 	cmp	ax, 1
  4778 000039AC 7622                <1> 	jna	short sysgtty_2
  4779                              <1> 	; 26/02/2022
  4780 000039AE 20E4                <1> 	and	ah, ah
  4781 000039B0 7506                <1> 	jnz	short sysgtty_inv_dn
  4782                              <1> 	;sub	ax, 10
  4783 000039B2 2C0A                <1> 	sub	al, 10
  4784 000039B4 3C09                <1> 	cmp	al, 9
  4785                              <1> 	;cmp	ax, 9
  4786                              <1> 	;ja	short sysgtty_inv_dn
  4787                              <1> 	;mov	ch, al
  4788                              <1> 	;jmp	short sysgtty_4
  4789                              <1> 	; 23/11/2015
  4790 000039B6 7629                <1> 	jna	short sysgtty_4
  4791                              <1> sysgtty_inv_dn: 
  4792                              <1> 	; 28/06/2015
  4793                              <1> 	; Invalid device name (not a tty) ! error
  4794                              <1> 	; (Device is not a tty or device name not found)
  4795 000039B8 C705[51660000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4795 000039C0 0000                <1>
  4796 000039C2 E90AF8FFFF          <1> 	jmp	error 
  4797                              <1> sysgtty_1:
  4798                              <1> 	; 16/01/2014
  4799 000039C7 80FD0A              <1> 	cmp	ch, 10
  4800 000039CA 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4801 000039CC FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4802 000039CE 790F                <1> 	jns	short sysgtty_3 ; not negative
  4803                              <1> 	;
  4804                              <1> sysgtty_2:
  4805                              <1> 	; get tty number of console tty
  4806 000039D0 8A25[4B660000]      <1> 	mov	ah, [u.uno]
  4807                              <1>  	; 28/06/2015
  4808 000039D6 0FB6DC              <1> 	movzx 	ebx, ah
  4809 000039D9 8AAB[53630000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4810                              <1> sysgtty_3:
  4811 000039DF 88E8                <1> 	mov	al, ch
  4812                              <1> sysgtty_4:
  4813 000039E1 A2[FC650000]        <1> 	mov	[u.r0], al
  4814                              <1>  	; 28/06/2015
  4815                              <1> 	;cmp	al, 9
  4816                              <1> 	;ja	short sysgtty_invp
  4817 000039E6 8B2D[F8650000]      <1> 	mov	ebp, [u.usp]
  4818                              <1> 	; 23/11/2015
  4819 000039EC 20C9                <1> 	and	cl, cl
  4820 000039EE 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4821 000039F0 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4822 000039F2 722E                <1> 	jb	short sysgtty_6 ; video page status
  4823                              <1> 	; serial port status
  4824                              <1> 	; 12/07/2014
  4825                              <1> 	;mov	dx, 0
  4826                              <1> 	;je	short sysgtty_5
  4827                              <1> 	;inc	dl
  4828                              <1> ;sysgtty_5:
  4829                              <1> 	; 28/06/2015
  4830 000039F4 2C08                <1> 	sub	al, 8
  4831 000039F6 E88CF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4832                              <1> 	; AL = Line status, AH = Modem status
  4833 000039FB 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4834 000039FF 8A25[4B660000]      <1> 	mov	ah, [u.uno]
  4835 00003A05 8825[FD650000]      <1>         mov     [u.r0+1], ah
  4836                              <1> 	; 24/12/2021
  4837 00003A0B 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4838                              <1> 				; (in ECX)
  4839 00003A11 A880                <1> 	test	al, 80h
  4840 00003A13 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4841 00003A15 A801                <1> 	test	al, 1
  4842                              <1> 	;jz	sysret
  4843 00003A17 7404                <1> 	jz	short sysgtty_10
  4844 00003A19 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4845                              <1> sysgtty_10:
  4846 00003A1D E9CFF7FFFF          <1> 	jmp	sysret
  4847                              <1> sysgtty_6:
  4848 00003A22 A2[50660000]        <1> 	mov	[u.ttyn], al ; tty number
  4849                              <1> 	;movzx	ebx, al
  4850 00003A27 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4851 00003A29 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4852                              <1> 	; 22/04/2014 - 29/06/2015
  4853 00003A2B 81C3[84620000]      <1>         add     ebx, ttyl
  4854 00003A31 8A23                <1>  	mov	ah, [ebx]
  4855 00003A33 3A25[4B660000]      <1> 	cmp	ah, [u.uno]
  4856 00003A39 7404                <1> 	je	short sysgtty_7
  4857 00003A3B 20E4                <1> 	and	ah, ah
  4858                              <1> 	;jz	short sysgtty_7
  4859 00003A3D 7506                <1> 	jnz	short sysgtty_8
  4860                              <1> 	;mov	ah, 0FFh
  4861                              <1> sysgtty_7:
  4862 00003A3F 8825[FD650000]      <1>         mov     [u.r0+1], ah
  4863                              <1> sysgtty_8:
  4864 00003A45 08C9                <1> 	or	cl, cl
  4865 00003A47 7510                <1> 	jnz	short sysgtty_9
  4866 00003A49 B001                <1> 	mov	al, 1  ; test a key is available
  4867 00003A4B E8341C0000          <1> 	call	getc
  4868 00003A50 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4869 00003A54 E998F7FFFF          <1> 	jmp	sysret
  4870                              <1> sysgtty_9:
  4871 00003A59 8A1D[50660000]      <1> 	mov	bl, [u.ttyn]
  4872                              <1> 	; bl = video page number
  4873 00003A5F E8911D0000          <1> 	call 	get_cpos
  4874                              <1> 	; dx = cursor position
  4875 00003A64 66895510            <1> 	mov	[ebp+16], dx ; bx
  4876                              <1> 	;mov	bl, [u.ttyn]
  4877                              <1> 	; bl = video page number
  4878 00003A68 E8991D0000          <1> 	call	read_ac_current
  4879                              <1> 	; ax = character and attribute/color
  4880 00003A6D 66894518            <1> 	mov	[ebp+24], ax ; cx
  4881 00003A71 E97BF7FFFF          <1> 	jmp	sysret
  4882                              <1> sysgtty_dnr_err:
  4883                              <1> 	; 'device not responding !' error	
  4884                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4885 00003A76 C705[51660000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4885 00003A7E 0000                <1>
  4886 00003A80 E94CF7FFFF          <1> 	jmp	error	
  4887                              <1> 
  4888                              <1> ; Original UNIX v1 'sysgtty' routine:
  4889                              <1> ; sysgtty:
  4890                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4891                              <1> 	;	       / r2 has destination
  4892                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4893                              <1> 	;                     / in 1st word of dest
  4894                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4895                              <1> 	;                     / in 2nd word of dest
  4896                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4897                              <1>         ;jmp    sysret2 / return to user
  4898                              <1> 	
  4899                              <1> ; Original UNIX v1 'gtty' routine:
  4900                              <1> ; gtty:
  4901                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4902                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4903                              <1>         ;jsr    r0,getf / get the i-number of the file
  4904                              <1>         ;tst    r1 / is it open for reading
  4905                              <1>         ;bgt    1f / yes
  4906                              <1>         ;neg    r1 / no, i-number is negative, 
  4907                              <1> 	;          / so make it positive
  4908                              <1> ;1:
  4909                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4910                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4911                              <1>         ;bhis   error9 / no, error
  4912                              <1>         ;asl    r1 / 0%2
  4913                              <1>         ;asl    r1 / 0%4 / yes
  4914                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4915                              <1> 	;	       ; / tty block
  4916                              <1>         ;mov    u.off,r2 / put argument in r2
  4917                              <1>         ;rts    r0 / return
  2114                                  %include 'u2.s'        ; 11/05/2015
  2115                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS2.INC
  2116                              <1> ; Last Modification: 15/05/2022
  2117                              <1> ; ----------------------------------------------------------------------------
  2118                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2119                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2120                              <1> ;
  2121                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2122                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2123                              <1> ; <Bell Laboratories (17/3/1972)>
  2124                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2125                              <1> ;
  2126                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2127                              <1> ;
  2128                              <1> ; ****************************************************************************
  2129                              <1> 
  2130                              <1> syslink:
  2131                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2132                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2133                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2134                              <1> 	;
  2135                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2136                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2137                              <1> 	; given to the entry that will go in the current directory.
  2138                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2139                              <1> 	; in the name 2 entry of current directory is the same
  2140                              <1> 	; i-number for the name 1 file.
  2141                              <1> 	;
  2142                              <1> 	; Calling sequence:
  2143                              <1> 	;	syslink; name 1; name 2
  2144                              <1> 	; Arguments:
  2145                              <1> 	;	name 1 - file name to which link will be created.
  2146                              <1> 	;	name 2 - name of entry in current directory that
  2147                              <1> 	;		 links to name 1.
  2148                              <1> 	; Inputs: -
  2149                              <1> 	; Outputs: -
  2150                              <1> 	; ...............................................................
  2151                              <1> 	;	
  2152                              <1> 	; Retro UNIX 8086 v1 modification: 
  2153                              <1> 	;       'syslink' system call has two arguments; so,
  2154                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2155                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2156                              <1> 	;
  2157                              <1> 		; / name1, name2
  2158                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2159 00003A85 891D[14660000]      <1> 	mov	[u.namep], ebx
  2160 00003A8B 51                  <1> 	push	ecx
  2161 00003A8C E84C060000          <1> 	call	namei
  2162                              <1> 		; jsr r0,namei / find the i-number associated with
  2163                              <1> 			     ; / the 1st path name
  2164                              <1>      	;;and	ax, ax
  2165                              <1> 	;;jz	error ; File not found
  2166                              <1> 	;jc	error 
  2167                              <1> 		; br error9 / cannot be found
  2168 00003A91 730F                <1> 	jnc	short syslink0
  2169                              <1> 	;pop 	ecx
  2170                              <1> 	; 'file not found !' error
  2171 00003A93 C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2171 00003A9B 0000                <1>
  2172 00003A9D E92FF7FFFF          <1> 	jmp	error
  2173                              <1> syslink0:
  2174 00003AA2 E8460E0000          <1> 	call	iget
  2175                              <1> 		; jsr r0,iget / get the i-node into core
  2176 00003AA7 8F05[14660000]      <1> 	pop	dword [u.namep] ; ecx
  2177                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2178                              <1> 	; 24/12/2021
  2179 00003AAD 50                  <1> 	push	eax ; *
  2180                              <1> 	;push	ax
  2181                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2182                              <1> 			    ; / (a link to this file is to be created)
  2183                              <1> 	; 24/12/2021
  2184 00003AAE 8A0D[E3650000]      <1> 	mov	cl, [cdev]
  2185 00003AB4 51                  <1> 	push	ecx ; **
  2186                              <1> 	;push	word [cdev]
  2187                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2188 00003AB5 E852000000          <1> 	call	isdir
  2189                              <1> 		; jsr r0,isdir / is it a directory
  2190 00003ABA E81E060000          <1> 	call	namei
  2191                              <1> 		; jsr r0,namei / no, get i-number of name2
  2192                              <1> 	;jnc	error
  2193                              <1> 		; br .+4   / not found 
  2194                              <1> 			 ; / so r1 = i-number of current directory
  2195                              <1> 			 ; / ii = i-number of current directory
  2196                              <1> 		; br error9 / file already exists., error
  2197 00003ABF 720F                <1> 	jc	short syslink1
  2198                              <1> 	; pop eax ; 24/12/2021
  2199                              <1> 	; pop eax
  2200                              <1> 	; 'file exists !' error
  2201 00003AC1 C705[51660000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2201 00003AC9 0000                <1>
  2202 00003ACB E901F7FFFF          <1> 	jmp	error
  2203                              <1> syslink1:
  2204                              <1> 	;pop	cx
  2205                              <1> 	; 24/12/2021
  2206 00003AD0 59                  <1> 	pop	ecx ; **
  2207                              <1> 	;cmp	cx, [cdev]
  2208 00003AD1 3A0D[E3650000]      <1> 	cmp	cl, [cdev]
  2209                              <1> 	;jne	error
  2210                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2211                              <1> 			       ; / end of current directory
  2212                              <1> 	        ; bne error9
  2213 00003AD7 740F                <1> 	je	short syslink2
  2214                              <1> 	; 'not same drive !' error
  2215 00003AD9 C705[51660000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2215 00003AE1 0000                <1>
  2216 00003AE3 E9E9F6FFFF          <1> 	jmp	error
  2217                              <1> syslink2:
  2218                              <1> 	;pop	eax ; 24/12/2021
  2219                              <1> 	;push	eax
  2220                              <1> 	; 24/12/2021
  2221 00003AE8 8B0424              <1> 	mov	eax, [esp] ; *
  2222 00003AEB 66A3[2E660000]      <1> 	mov	[u.dirbuf], ax
  2223                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2224 00003AF1 E89E000000          <1> 	call	mkdir
  2225                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2226                              <1> 		 	     ; / in current directory
  2227                              <1> 	; 24/12/2021
  2228 00003AF6 58                  <1> 	pop	eax ; *
  2229                              <1> 	;pop	ax
  2230                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2231 00003AF7 E8F10D0000          <1> 	call	iget
  2232                              <1> 		; jsr r0,iget / get i-node into core
  2233 00003AFC FE05[F6620000]      <1> 	inc	byte [i.nlks]
  2234                              <1> 		; incb i.nlks / add 1 to its number of links
  2235 00003B02 E8F00E0000          <1> 	call	setimod
  2236                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2237 00003B07 E9E5F6FFFF          <1> 	jmp	sysret
  2238                              <1> 
  2239                              <1> isdir:
  2240                              <1> 	; 03/02/2022
  2241                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2242                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2243                              <1> 	;
  2244                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2245                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2246                              <1> 	;  called by syslink and sysunlink to make sure directories
  2247                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2248                              <1> 	; 'isdir' does not bother checking. The current i-node
  2249                              <1> 	;  is not disturbed.			
  2250                              <1> 	;		
  2251                              <1> 	; INPUTS ->
  2252                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2253                              <1> 	;    u.uid - user id
  2254                              <1> 	; OUTPUTS ->
  2255                              <1> 	;    r1 - contains current i-number upon exit
  2256                              <1> 	;    	 (current i-node back in core) 
  2257                              <1> 	;	
  2258                              <1> 	; ((AX = R1))
  2259                              <1> 	;
  2260                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2261                              <1> 	;
  2262                              <1> 
  2263                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2264                              <1> 	; / there is an error unless super user made the call
  2265                              <1> 	
  2266 00003B0C 803D[48660000]00    <1> 	cmp	byte [u.uid], 0 
  2267                              <1> 		; tstb u.uid / super user
  2268 00003B13 762B                <1> 	jna	short isdir1
  2269                              <1> 		; beq 1f / yes, don't care
  2270 00003B15 66FF35[E0650000]    <1> 	push	word [ii]
  2271                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2272 00003B1C E8CC0D0000          <1> 	call	iget
  2273                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2274                              <1> 	; 03/02/2022
  2275 00003B21 F605[F5620000]40    <1> 	test	byte [i.flgs+1], 40h
  2276                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2277                              <1> 		; bit $40000,i.flgs / is it a directory
  2278                              <1> 	;jnz	error
  2279                              <1> 		; bne error9 / yes, error
  2280 00003B28 740F                <1> 	jz	short isdir0
  2281 00003B2A C705[51660000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2281 00003B32 0000                <1>
  2282                              <1> 				; 'permission denied !' error
  2283                              <1> 	; pop	ax
  2284 00003B34 E998F6FFFF          <1> 	jmp	error	
  2285                              <1> isdir0:	
  2286 00003B39 6658                <1> 	pop	ax
  2287                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2288 00003B3B E8AD0D0000          <1> 	call	iget
  2289                              <1> 		; jsr r0,iget / get it back in
  2290                              <1> isdir1: ; 1:
  2291 00003B40 C3                  <1> 	retn
  2292                              <1> 		; rts r0
  2293                              <1> 
  2294                              <1> sysunlink:
  2295                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2296                              <1> 	; 04/12/2015 (14 byte file names)
  2297                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2298                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2299                              <1> 	;
  2300                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2301                              <1> 	; name from its directory. If this entry was the last link
  2302                              <1> 	; to the file, the contents of the file are freed and the
  2303                              <1> 	; file is destroyed. If, however, the file was open in any
  2304                              <1> 	; process, the actual destruction is delayed until it is 
  2305                              <1> 	; closed, even though the directory entry has disappeared.
  2306                              <1> 	; 
  2307                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2308                              <1> 	; does not exist or that its directory can not be written.
  2309                              <1> 	; Write permission is not required on the file itself.
  2310                              <1> 	; It is also illegal to unlink a directory (except for
  2311                              <1> 	; the superuser).
  2312                              <1> 	;
  2313                              <1> 	; Calling sequence:
  2314                              <1> 	;	sysunlink; name
  2315                              <1> 	; Arguments:
  2316                              <1> 	;	name - name of directory entry to be removed 
  2317                              <1> 	; Inputs: -
  2318                              <1> 	; Outputs: -
  2319                              <1> 	; ...............................................................
  2320                              <1> 	;				
  2321                              <1> 	; Retro UNIX 8086 v1 modification:
  2322                              <1> 	;	 The user/application program puts address of the name
  2323                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2324                              <1> 
  2325                              <1> 	; / name - remove link name
  2326 00003B41 891D[14660000]      <1> 	mov	[u.namep], ebx
  2327                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2328 00003B47 E891050000          <1> 	call	namei
  2329                              <1> 		; jsr r0,namei / find the i-number associated 
  2330                              <1> 			     ; / with the path name
  2331                              <1> 	;jc	error
  2332                              <1> 		; br error9 / not found
  2333 00003B4C 730F                <1> 	jnc	short sysunlink1
  2334                              <1> 	; 'file not found !' error
  2335 00003B4E C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2335 00003B56 0000                <1>
  2336 00003B58 E974F6FFFF          <1> 	jmp	error
  2337                              <1> sysunlink1:
  2338 00003B5D 50                  <1> 	push	eax ; 24/12/2021
  2339                              <1> 	;push	ax
  2340                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2341 00003B5E E8A9FFFFFF          <1> 	call	isdir
  2342                              <1> 		; jsr r0,isdir / is it a directory
  2343                              <1> 	;xor 	ax, ax
  2344                              <1> 	; 24/12/2021
  2345 00003B63 31C0                <1> 	xor	eax, eax
  2346 00003B65 66A3[2E660000]      <1> 	mov	[u.dirbuf], ax ; 0
  2347                              <1> 		; clr u.dirbuf / no, clear the location that will
  2348                              <1> 			   ; / get written into the i-number portion
  2349                              <1> 			 ; / of the entry
  2350 00003B6B 832D[18660000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2351                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2352 00003B72 E868000000          <1> 	call	wdir
  2353                              <1> 		; jsr r0,wdir / free the directory entry
  2354 00003B77 58                  <1> 	pop	eax ; 24/12/2021
  2355                              <1> 	;pop	ax
  2356                              <1> 		; mov (sp)+,r1 / get i-number back
  2357 00003B78 E8700D0000          <1> 	call	iget
  2358                              <1> 		; jsr r0,iget / get i-node
  2359 00003B7D E8750E0000          <1> 	call	setimod
  2360                              <1> 		; jsr r0,setimod / set modified flag
  2361 00003B82 FE0D[F6620000]      <1> 	dec	byte [i.nlks]
  2362                              <1> 		; decb i.nlks / decrement the number of links
  2363                              <1> 	; 24/12/2021
  2364 00003B88 7505                <1> 	jnz	short sysunlink_2
  2365                              <1> 	;jnz	sysret
  2366                              <1> 		; bgt sysret9 / if this was not the last link
  2367                              <1> 			    ; / to file return
  2368                              <1> 	; AX = r1 = i-number
  2369 00003B8A E8B3090000          <1> 	call	anyi
  2370                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2371                              <1> 			 ; / Then free contents of file and destroy it.
  2372                              <1> sysunlink_2:
  2373 00003B8F E95DF6FFFF          <1> 	jmp	sysret
  2374                              <1> 		; br sysret9
  2375                              <1> 
  2376                              <1> mkdir:
  2377                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2378                              <1> 	; 04/12/2015 (14 byte directory names)
  2379                              <1> 	; 12/10/2015
  2380                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2381                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2382                              <1> 	;
  2383                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2384                              <1> 	; by u.namep into the current directory.
  2385                              <1> 	;
  2386                              <1> 	; INPUTS ->
  2387                              <1> 	;    u.namep - points to a file name 
  2388                              <1> 	;	           that is about to be a directory entry.
  2389                              <1> 	;    ii - current directory's i-number.	
  2390                              <1> 	; OUTPUTS ->
  2391                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2392                              <1> 	;    u.off - points to entry to be filled 
  2393                              <1> 	;	     in the current directory		
  2394                              <1> 	;    u.base - points to start of u.dirbuf.
  2395                              <1> 	;    r1 - contains i-number of current directory 
  2396                              <1> 	;	
  2397                              <1> 	; ((AX = R1)) output
  2398                              <1> 	;
  2399                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2400                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2401                              <1> 	;
  2402                              <1> 
  2403                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2404 00003B94 31C0                <1> 	xor 	eax, eax
  2405 00003B96 BF[30660000]        <1> 	mov     edi, u.dirbuf+2
  2406 00003B9B 89FE                <1> 	mov	esi, edi
  2407 00003B9D AB                  <1> 	stosd
  2408 00003B9E AB                  <1> 	stosd
  2409                              <1> 	; 04/12/2015 (14 byte directory names)
  2410 00003B9F AB                  <1> 	stosd
  2411 00003BA0 66AB                <1> 	stosw
  2412                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2413 00003BA2 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2414                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2415                              <1> 	;mov 	ebp, [u.namep]
  2416 00003BA4 E8B3060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2417                              <1> 		; esi = physical address (page start + offset)
  2418                              <1> 		; ecx = byte count in the page (1 - 4096)
  2419                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2420                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2421                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2422                              <1> mkdir_1: ; 1: 
  2423 00003BA9 45                  <1> 	inc	ebp ; 12/10/2015
  2424                              <1> 	;
  2425                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2426                              <1> 	 ; 01/08/2013
  2427 00003BAA AC                  <1> 	lodsb
  2428                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2429 00003BAB 20C0                <1> 	and 	al, al
  2430 00003BAD 7426                <1> 	jz 	short mkdir_3 	  
  2431                              <1> 		; beq 1f / if null, done
  2432 00003BAF 3C2F                <1> 	cmp	al, '/'
  2433                              <1> 		; cmp r1,$'/ / is it a "/"?
  2434 00003BB1 7413                <1> 	je	short mkdir_err
  2435                              <1> 	;je	error
  2436                              <1> 		; beq error9 / yes, error
  2437                              <1> 	; 12/10/2015
  2438                              <1> 	;dec	cx
  2439 00003BB3 49                  <1> 	dec	ecx ; 24/12/2021
  2440 00003BB4 7505                <1> 	jnz	short mkdir_2
  2441                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2442 00003BB6 E8A7060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2443                              <1> 		; esi = physical address (page start + offset)
  2444                              <1> 		; ecx = byte count in the page
  2445                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2446                              <1> mkdir_2:
  2447 00003BBB 81FF[3E660000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2448                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2449                              <1> 				     ; / a char?
  2450 00003BC1 74E6                <1> 	je	short mkdir_1
  2451                              <1> 		; beq 1b / yes, go back
  2452 00003BC3 AA                  <1> 	stosb
  2453                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2454 00003BC4 EBE3                <1> 	jmp 	short mkdir_1
  2455                              <1> 		; br 1b / get next char
  2456                              <1> mkdir_err:
  2457                              <1> 	; 17/06/2015
  2458 00003BC6 C705[51660000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2458 00003BCE 0000                <1>
  2459 00003BD0 E9FCF5FFFF          <1> 	jmp	error
  2460                              <1> 
  2461                              <1> mkdir_3: ; 1:
  2462 00003BD5 A1[10660000]        <1> 	mov	eax, [u.dirp]
  2463 00003BDA A3[18660000]        <1> 	mov	[u.off], eax
  2464                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2465                              <1> 				 ; / slot to u.off
  2466                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2467                              <1> 	; 29/04/2013
  2468 00003BDF C705[1C660000]-     <1>         mov     dword [u.base], u.dirbuf
  2468 00003BE5 [2E660000]          <1>
  2469                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2470 00003BE9 C705[20660000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2470 00003BF1 0000                <1>
  2471                              <1> 		; mov $10.,u.count / u.count = 10
  2472 00003BF3 66A1[E0650000]      <1> 	mov	ax, [ii] 
  2473                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2474 00003BF9 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2475 00003BFB E8C10D0000          <1> 	call 	access
  2476                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2477                              <1> 				 ; / for writing
  2478                              <1> 	; AX = i-number of current directory
  2479                              <1> 	; 01/08/2013
  2480 00003C00 FE05[63660000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2481                              <1> 	;call	writei
  2482                              <1> 	;	; jsr r0,writei / write into directory
  2483                              <1> 	;retn	
  2484                              <1> 	;	; rts r0
  2485                              <1> 	; 24/12/2021
  2486 00003C06 E9A8100000          <1> 	jmp	writei
  2487                              <1> 
  2488                              <1> sysexec:
  2489                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2490                              <1> 	; 03/02/2022
  2491                              <1> 	; 12/01/2022
  2492                              <1> 	; 08/01/2022
  2493                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2494                              <1> 	; 23/10/2015
  2495                              <1> 	; 19/10/2015
  2496                              <1> 	; 10/10/2015, 18/10/2015
  2497                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2498                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2499                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2500                              <1> 	; 24/06/2015, 25/06/2015
  2501                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2502                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2503                              <1> 	;
  2504                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2505                              <1> 	; pointed to by 'name' in the sysexec call. 
  2506                              <1> 	; 'sysexec' performs the following operations:
  2507                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2508                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2509                              <1> 	;    3. sets trap vectors to system routines.
  2510                              <1> 	;    4. loads arguments to be passed to executing file into
  2511                              <1> 	;	highest locations of user's core
  2512                              <1> 	;    5. puts pointers to arguments in locations immediately
  2513                              <1> 	;	following arguments.
  2514                              <1> 	;    6.	saves number of arguments in next location.
  2515                              <1> 	;    7. initializes user's stack area so that all registers
  2516                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2517                              <1> 	;	to core when 'sysret' restores registers 
  2518                              <1> 	;	and does an rti.
  2519                              <1> 	;    8. inializes u.r0 and u.sp
  2520                              <1> 	;    9. zeros user's core down to u.r0
  2521                              <1> 	;   10.	reads executable file from storage device into core
  2522                              <1> 	;	starting at location 'core'.
  2523                              <1> 	;   11.	sets u.break to point to end of user's code with
  2524                              <1> 	;	data area appended.
  2525                              <1> 	;   12.	calls 'sysret' which returns control at location
  2526                              <1> 	;	'core' via 'rti' instruction. 		  		
  2527                              <1> 	;
  2528                              <1> 	; Calling sequence:
  2529                              <1> 	;	sysexec; namep; argp
  2530                              <1> 	; Arguments:
  2531                              <1> 	;	namep - points to pathname of file to be executed
  2532                              <1> 	;	argp  - address of table of argument pointers
  2533                              <1> 	;	argp1... argpn - table of argument pointers
  2534                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2535                              <1> 	; Inputs: (arguments)
  2536                              <1> 	; Outputs: -	
  2537                              <1> 	; ...............................................................
  2538                              <1> 	;
  2539                              <1> 	; Retro UNIX 386 v1 modification: 
  2540                              <1> 	;	User application runs in it's own virtual space 
  2541                              <1> 	;	which is izolated from kernel memory (and other
  2542                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2543                              <1> 	;	privilige mode. Virtual start address is always 0.
  2544                              <1> 	;	User's core memory starts at linear address 400000h
  2545                              <1> 	;	(the end of the 1st 4MB).
  2546                              <1> 	;
  2547                              <1> 	; Retro UNIX 8086 v1 modification: 
  2548                              <1> 	;	user/application segment and system/kernel segment
  2549                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2550                              <1> 	;	are different (user's registers are saved to 
  2551                              <1> 	;	and then restored from system's stack.)
  2552                              <1> 	;
  2553                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2554                              <1> 	;	      arguments which were in these registers;
  2555                              <1> 	;	      but, it returns by putting the 1st argument
  2556                              <1> 	;	      in 'u.namep' and the 2nd argument
  2557                              <1> 	;	      on top of stack. (1st argument is offset of the
  2558                              <1> 	;	      file/path name in the user's program segment.)		 	
  2559                              <1> 	
  2560                              <1> 	;call	arg2
  2561                              <1> 	; * name - 'u.namep' points to address of file/path name
  2562                              <1> 	;          in the user's program segment ('u.segmnt')
  2563                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2564                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2565                              <1> 	;          which is on top of stack.
  2566                              <1> 	;
  2567                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2568                              <1> 
  2569                              <1> 	; 23/06/2015 (32 bit modifications)
  2570                              <1> 
  2571 00003C0B 891D[14660000]      <1> 	mov	[u.namep], ebx ; argument 1
  2572                              <1>         ; 18/10/2015
  2573 00003C11 890D[7C660000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2574 00003C17 E8C1040000          <1> 	call	namei
  2575                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2576                              <1> 			     ; / named in sysexec call in r1
  2577                              <1> 	;jc	error
  2578                              <1> 		; br error9
  2579 00003C1C 731E                <1> 	jnc	short sysexec_0
  2580                              <1> 	;
  2581                              <1> 	; 'file not found !' error
  2582 00003C1E C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2582 00003C26 0000                <1>
  2583 00003C28 E9A4F5FFFF          <1> 	jmp	error 
  2584                              <1> sysexec_not_exf:
  2585                              <1> 	; 'not executable file !' error
  2586 00003C2D C705[51660000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2586 00003C35 0000                <1>
  2587 00003C37 E995F5FFFF          <1> 	jmp	error 
  2588                              <1> sysexec_0:
  2589 00003C3C E8AC0C0000          <1> 	call	iget
  2590                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2591                              <1> 	; 24/12/2021
  2592 00003C41 F605[F4620000]10    <1> 	test	byte [i.flgs], 10h
  2593                              <1> 	;test	word [i.flgs], 10h
  2594                              <1> 	;	; bit $20,i.flgs / is file executable
  2595 00003C48 74E3                <1> 	jz	short sysexec_not_exf
  2596                              <1> 	;jz	error
  2597                              <1> 		; beq error9
  2598                              <1> 	;;
  2599 00003C4A E802150000          <1> 	call	iopen
  2600                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2601                              <1> 			     ; / given in r1 (opens file)
  2602                              <1> 	; AX = i-number of the file
  2603                              <1> 	; 24/12/2021
  2604 00003C4F F605[F4620000]20    <1> 	test	byte [i.flgs], 20h
  2605                              <1> 	;test	word [i.flgs], 20h
  2606                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2607 00003C56 7415                <1> 	jz	short sysexec_1
  2608                              <1> 		; beq 1f
  2609 00003C58 803D[48660000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2610                              <1> 		; tstb u.uid / test user id
  2611 00003C5F 760C                <1> 	jna	short sysexec_1
  2612                              <1> 		; beq 1f / super user
  2613 00003C61 8A0D[F7620000]      <1> 	mov	cl, [i.uid]
  2614 00003C67 880D[48660000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2615                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2616                              <1> 				 ; / as process user id
  2617                              <1> sysexec_1:
  2618                              <1> 	; 03/02/2022
  2619                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2620                              <1> 	; 18/10/2215
  2621                              <1> 	; 10/10/2015
  2622                              <1> 	; 21/07/2015, 24/07/2015
  2623                              <1> 	; 24/06/2015, 25/06/2015
  2624                              <1>         ; Moving arguments to the end of [u.upage]
  2625                              <1> 	; (by regarding page borders in user's memory space)
  2626                              <1> 	;
  2627                              <1> 	; 10/10/2015
  2628                              <1> 	; 21/07/2015
  2629 00003C6D 89E5                <1> 	mov	ebp, esp ; (**)
  2630                              <1> 	; 18/10/2015
  2631 00003C6F 89EF                <1> 	mov 	edi, ebp
  2632 00003C71 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2633                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2634 00003C76 29CF                <1> 	sub	edi, ecx
  2635 00003C78 89FC                <1> 	mov	esp, edi
  2636 00003C7A 31C0                <1> 	xor	eax, eax
  2637 00003C7C A3[24660000]        <1> 	mov 	[u.nread], eax ; 0
  2638                              <1> 	; 12/01/2022
  2639                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2640                              <1> 	; may leave it with any value after an error))
  2641                              <1> 	;mov	[argc], ax
  2642 00003C81 A2[7A660000]        <1> 	mov	[argc], al ; 0
  2643                              <1> 	;
  2644 00003C86 49                  <1> 	dec	ecx ; 256 - 1
  2645 00003C87 890D[20660000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2646                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2647                              <1> sysexec_2:
  2648 00003C8D 8B35[7C660000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2649 00003C93 E863020000          <1> 	call	get_argp
  2650                              <1> 	;mov	ecx, 4 
  2651                              <1> 	; 03/02/2022
  2652 00003C98 31C9                <1> 	xor	ecx, ecx
  2653 00003C9A B104                <1> 	mov	cl, 4
  2654                              <1> sysexec_3:
  2655 00003C9C 21C0                <1> 	and	eax, eax
  2656 00003C9E 7455                <1> 	jz	short sysexec_6
  2657                              <1> 	; 18/10/2015
  2658 00003CA0 010D[7C660000]      <1> 	add	[argv], ecx ; 4
  2659                              <1> 	;inc	word [argc]
  2660                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2661 00003CA6 FE05[7A660000]      <1> 	inc	byte [argc]
  2662                              <1> 	;
  2663 00003CAC A3[1C660000]        <1> 	mov	[u.base], eax
  2664                              <1>  	; 23/10/2015
  2665 00003CB1 66C705[61660000]00- <1> 	mov	word [u.pcount], 0
  2665 00003CB9 00                  <1>
  2666                              <1> sysexec_4:
  2667 00003CBA E826120000          <1> 	call	cpass ; get a character from user's core memory
  2668 00003CBF 750B                <1>         jnz	short sysexec_5
  2669                              <1> 		; (max. 255 chars + null)
  2670                              <1> 	; 18/10/2015
  2671 00003CC1 28C0                <1> 	sub 	al, al
  2672 00003CC3 AA                  <1> 	stosb
  2673 00003CC4 FF05[24660000]      <1> 	inc	dword [u.nread]
  2674 00003CCA EB29                <1> 	jmp	short sysexec_6
  2675                              <1> sysexec_5:
  2676 00003CCC AA                  <1> 	stosb
  2677 00003CCD 20C0                <1> 	and 	al, al
  2678 00003CCF 75E9                <1> 	jnz	short sysexec_4
  2679                              <1> 	;mov	ecx, 4
  2680                              <1> 	; 24/12/2021
  2681 00003CD1 29C9                <1> 	sub	ecx, ecx
  2682 00003CD3 B104                <1> 	mov	cl, 4
  2683                              <1> 	;cmp	[ncount], ecx ; 4
  2684                              <1> 	; 24/12/2021
  2685 00003CD5 66390D[78660000]    <1> 	cmp	[ncount], cx ; 4
  2686 00003CDC 72AF                <1> 	jb	short sysexec_2
  2687 00003CDE 8B35[74660000]      <1> 	mov	esi, [nbase]
  2688 00003CE4 010D[74660000]      <1> 	add	[nbase], ecx ; 4	
  2689 00003CEA 66290D[78660000]    <1> 	sub	[ncount], cx 
  2690 00003CF1 8B06                <1> 	mov	eax, [esi]
  2691 00003CF3 EBA7                <1> 	jmp	short sysexec_3
  2692                              <1> sysexec_6:
  2693                              <1> 	; 18/10/2015
  2694                              <1> 	; argument list transfer from user's core memory to
  2695                              <1> 	; kernel stack frame is OK here.
  2696                              <1> 	; [u.nread] = ; argument list length
  2697                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2698                              <1> 	;
  2699                              <1> 	; 18/10/2015
  2700                              <1> 	; 24/07/2015
  2701                              <1>         ; 21/07/2015
  2702                              <1> 	; 02/07/2015
  2703                              <1> 	; 25/06/2015
  2704                              <1> 	; 24/06/2015
  2705                              <1> 	; 23/06/2015
  2706                              <1> 	;
  2707 00003CF5 8B1D[59660000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2708 00003CFB 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2709 00003CFD 740A                <1> 	jz	short sysexec_7
  2710 00003CFF A1[55660000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2711 00003D04 E8EEE8FFFF          <1> 	call	deallocate_page_dir
  2712                              <1> sysexec_7:
  2713 00003D09 E81EE8FFFF          <1> 	call	make_page_dir
  2714                              <1> 	;jc	short sysexec_14
  2715                              <1> 	;jc	panic  ; allocation error 
  2716                              <1> 		       ; after a deallocation would be nonsence !?
  2717                              <1> 	; 08/01/2022
  2718 00003D0E 7243                <1> 	jc	short sysexec_panic
  2719                              <1> 
  2720                              <1> 	; 24/07/2015
  2721                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2722                              <1> 	;     of the user's page directory
  2723                              <1> 	;     (It is needed for interrupts!)
  2724                              <1> 	; 18/10/2015
  2725 00003D10 8B15[38620000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2726 00003D16 8B02                <1> 	mov	eax, [edx] ; physical address of
  2727                              <1> 			   ; kernel's first page table (1st 4 MB)
  2728                              <1> 			   ; (PDE 0 of kernel's page directory)
  2729 00003D18 8B15[55660000]      <1> 	mov 	edx, [u.pgdir]
  2730 00003D1E 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2731                              <1> 	;
  2732                              <1> 	; 20/07/2015
  2733 00003D20 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2734                              <1> 	; 18/10/2015
  2735 00003D25 BE[6C660000]        <1> 	mov	esi, pcore ; physical start address
  2736                              <1> sysexec_8:	
  2737 00003D2A B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2738 00003D2F E816E8FFFF          <1> 	call	make_page_table
  2739                              <1> 	;jc	panic
  2740                              <1> 	; 24/12/2021
  2741 00003D34 721D                <1> 	jc	short sysexec_panic
  2742                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2743 00003D36 E81DE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2744                              <1> 	;jc	panic
  2745                              <1> 	; 24/12/2021
  2746 00003D3B 7216                <1> 	jc	short sysexec_panic
  2747                              <1> 	;
  2748 00003D3D 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2749                              <1> 	; ebx = virtual address (24/07/2015)
  2750                              <1> 	; 24/12/2021
  2751                              <1> 	;call 	add_to_swap_queue
  2752                              <1> 	; 18/10/2015
  2753 00003D3F 81FE[70660000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2754 00003D45 7411                <1> 	je	short sysexec_9 ; yes
  2755 00003D47 BE[70660000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2756                              <1> 	; 20/07/2015
  2757 00003D4C BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2758                              <1> 	; ebx = virtual end address + segment base address - 4K
  2759 00003D51 EBD7                <1>         jmp     short sysexec_8
  2760                              <1> 
  2761                              <1> sysexec_panic:
  2762                              <1> 	; 26/03/2021
  2763 00003D53 E93BEDFFFF          <1> 	jmp	panic
  2764                              <1> 
  2765                              <1> sysexec_9:
  2766                              <1> 	; 18/10/2015
  2767                              <1> 	; 26/08/2015
  2768                              <1> 	; 25/06/2015
  2769                              <1> 	; move arguments from kernel stack to [ecore]
  2770                              <1> 	; (argument list/line will be copied from kernel stack
  2771                              <1> 	; frame to the last (stack) page of user's core memory)
  2772                              <1> 	; 18/10/2015
  2773 00003D58 8B3D[70660000]      <1> 	mov	edi, [ecore]
  2774 00003D5E 81C700100000        <1> 	add	edi, PAGE_SIZE
  2775                              <1> 	;movzx	eax, word [argc]
  2776                              <1> 	; 12/01/2022
  2777 00003D64 31C0                <1> 	xor	eax, eax
  2778 00003D66 A0[7A660000]        <1> 	mov	al, [argc]
  2779 00003D6B 08C0                <1> 	or	al, al
  2780                              <1> 	;or	eax, eax
  2781 00003D6D 7509                <1> 	jnz	short sysexec_10
  2782 00003D6F 89FB                <1> 	mov 	ebx, edi
  2783 00003D71 83EB04              <1> 	sub	ebx, 4 
  2784 00003D74 8903                <1> 	mov	[ebx], eax ; 0
  2785 00003D76 EB43                <1> 	jmp 	short sysexec_13
  2786                              <1> sysexec_10:
  2787 00003D78 8B0D[24660000]      <1> 	mov	ecx, [u.nread]
  2788                              <1> 	;mov 	esi, [argv]
  2789 00003D7E 89E6                <1> 	mov	esi, esp ; start address of argument list
  2790 00003D80 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2791                              <1> 
  2792                              <1> 	;;;;
  2793                              <1> 	; 09/05/2022
  2794                              <1> 	; (move edi -backward- to dword boundary)
  2795                              <1> 	; ((this will prevent 'general protection fault' error
  2796                              <1> 	;  as result of a lodsd or dword move instruction
  2797                              <1> 	;  at the end of argument list))
  2798 00003D82 83EF03              <1> 	sub	edi, 3
  2799 00003D85 83E7FC              <1> 	and	edi, ~3 ; (*)
  2800                              <1> 	;;;
  2801                              <1> 
  2802 00003D88 89C2                <1> 	mov	edx, eax
  2803                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2804 00003D8A FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2805 00003D8C C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2806                              <1> 	; edx <= 128
  2807 00003D8F 89FB                <1> 	mov	ebx, edi
  2808                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2809                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2810 00003D91 29D3                <1> 	sub 	ebx, edx
  2811 00003D93 89FA                <1> 	mov	edx, edi
  2812 00003D95 F3A4                <1> 	rep	movsb
  2813 00003D97 89D6                <1> 	mov 	esi, edx
  2814 00003D99 89DF                <1> 	mov 	edi, ebx
  2815 00003D9B BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2816 00003DA0 2B15[70660000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2817 00003DA6 AB                  <1> 	stosd	; eax = argument count	
  2818                              <1> sysexec_11:
  2819 00003DA7 89F0                <1> 	mov	eax, esi
  2820 00003DA9 01D0                <1> 	add	eax, edx
  2821 00003DAB AB                  <1> 	stosd  ; eax = virtual address
  2822 00003DAC FE0D[7A660000]      <1> 	dec	byte [argc]
  2823 00003DB2 7407                <1> 	jz	short sysexec_13
  2824                              <1> sysexec_12:
  2825 00003DB4 AC                  <1> 	lodsb
  2826 00003DB5 20C0                <1> 	and	al, al
  2827 00003DB7 75FB                <1> 	jnz	short sysexec_12
  2828 00003DB9 EBEC                <1> 	jmp	short sysexec_11
  2829                              <1> 	;
  2830                              <1> 	; 1:
  2831                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2832                              <1> 			     ; / pointers to arguments to be passed
  2833                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2834                              <1> 			      ; / u.quit = 1 take quit
  2835                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2836                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2837                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2838                              <1> 			       ; / system routine
  2839                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2840                              <1> 			       ; / set to take system routine
  2841                              <1> 		; mov $sstack,sp / stack space used during swapping
  2842                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2843                              <1> 		; mov $ecore,r5 / r5 has end of core
  2844                              <1> 		; mov $core,r4 / r4 has start of users core
  2845                              <1> 		; mov r4,u.base / u.base has start of users core
  2846                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2847                              <1> 	; 1:
  2848                              <1> 		; tst (r2)+ / argument char = "nul"
  2849                              <1> 		; bne 1b
  2850                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2851                              <1> 			  ; / end of argument pointer list
  2852                              <1> 	; 1:
  2853                              <1> 	     ; / move arguments to bottom of users core
  2854                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2855                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2856                              <1> 			    ; / ptr list
  2857                              <1> 		; blo 1f / branch to 1f when all arguments
  2858                              <1> 		       ; / are moved
  2859                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2860                              <1> 	; 2:
  2861                              <1> 		; tstb (r3)+
  2862                              <1> 		; bne 2b / scan argument for \0 (nul)
  2863                              <1> 
  2864                              <1> 	; 2:
  2865                              <1> 		; movb -(r3),-(r5) / move argument char 
  2866                              <1> 				 ; / by char starting at "ecore"
  2867                              <1> 		; cmp r3,(r2) / moved all characters in 
  2868                              <1> 			    ; / this argument
  2869                              <1> 		; bhi 2b / branch 2b if not
  2870                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2871                              <1> 			     ; / r5 has pointer to nth arg
  2872                              <1> 		; br 1b / string
  2873                              <1> 	; 1:
  2874                              <1> 		; clrb -(r5)
  2875                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2876                              <1> 			; / last word of argument strings
  2877                              <1> 		; mov $core,r2
  2878                              <1> 	
  2879                              <1> 	; 1: / move argument pointers into core following 
  2880                              <1> 	      ; / argument strings
  2881                              <1> 		; cmp r2,r4
  2882                              <1> 		; bhis 1f / branch to 1f when all pointers
  2883                              <1> 			; / are moved
  2884                              <1> 		; mov (r2)+,-(r5)
  2885                              <1> 		; br 1b
  2886                              <1> 	; 1:
  2887                              <1> 		; sub $core,r4 / gives number of arguments *2
  2888                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2889                              <1> 		       ; / the number of args stored
  2890                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2891                              <1> 			     ; / of the argument pointers
  2892                              <1> sysexec_13:
  2893                              <1> 	; 19/10/2015
  2894                              <1> 	; 18/10/2015
  2895                              <1> 	; 29/07/2015
  2896                              <1> 	; 25/07/2015
  2897                              <1> 	; 24/07/2015
  2898                              <1> 	; 20/07/2015
  2899                              <1> 	; 25/06/2015
  2900                              <1> 	; 24/06/2015
  2901                              <1> 	; 23/06/2015
  2902                              <1> 	;
  2903                              <1> 	; moving arguments to [ecore] is OK here..
  2904                              <1> 	; 18/10/2015
  2905 00003DBB 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2906                              <1> 	; ebx = beginning addres of argument list pointers
  2907                              <1> 	;	in user's stack
  2908                              <1> 	; 19/10/2015
  2909 00003DBD 2B1D[70660000]      <1> 	sub 	ebx, [ecore]
  2910 00003DC3 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2911                              <1> 			; end of core - 4096 (last page)
  2912                              <1> 			; (virtual address)
  2913 00003DC9 891D[7C660000]      <1> 	mov	[argv], ebx
  2914 00003DCF 891D[28660000]      <1> 	mov	[u.break], ebx ; available user memory
  2915                              <1> 	;
  2916 00003DD5 29C0                <1> 	sub	eax, eax
  2917 00003DD7 C705[20660000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2917 00003DDF 0000                <1>
  2918                              <1> 		; mov $14,u.count
  2919 00003DE1 C705[0C660000]-     <1> 	mov	dword [u.fofp], u.off
  2919 00003DE7 [18660000]          <1>
  2920                              <1> 		; mov $u.off,u.fofp
  2921 00003DEB A3[18660000]        <1> 	mov	[u.off], eax ; 0
  2922                              <1> 		; clr u.off / set offset in file to be read to zero
  2923                              <1> 	; 25/07/2015
  2924 00003DF0 A3[1C660000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2925                              <1> 	; 25/06/2015 
  2926 00003DF5 66A1[E0650000]      <1> 	mov	ax, [ii]
  2927                              <1> 	; AX = i-number of the executable file
  2928 00003DFB E8C10C0000          <1> 	call	readi
  2929                              <1> 		; jsr r0,readi / read in first six words of 
  2930                              <1> 			; / user's file, starting at $core
  2931                              <1> 		; mov sp,r5 / put users stack address in r5
  2932                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2933                              <1> 				; / from r5 (leaves number of words
  2934                              <1> 				; / less 26 available for
  2935                              <1> 			     	; / program in user core
  2936                              <1> 		; mov r5,u.count /
  2937                              <1> 	; 25/06/2015
  2938 00003E00 8B0D[28660000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2939 00003E06 890D[20660000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2940                              <1> 	;
  2941 00003E0C 8B0D[24660000]      <1> 	mov	ecx, [u.nread]
  2942 00003E12 890D[28660000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2943 00003E18 80F920              <1> 	cmp	cl, 32
  2944 00003E1B 7540                <1>         jne     short sysexec_15
  2945                              <1> 	;:
  2946                              <1> 	; 25/06/2015
  2947                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2948                              <1> 	; 18/10/2015
  2949 00003E1D 8B35[6C660000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2950                              <1> 		             ; (phys. start addr. of the exec. file)
  2951 00003E23 AD                  <1> 	lodsd
  2952 00003E24 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2953 00003E28 7533                <1> 	jne	short sysexec_15
  2954                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2955                              <1> 			      ; / if file is standard a.out format
  2956                              <1> 		; bne 1f / branch, if not standard format
  2957 00003E2A AD                  <1> 	lodsd
  2958 00003E2B 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2959 00003E2D AD                  <1> 	lodsd
  2960 00003E2E 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2961                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2962                              <1> 		              ; / number of bytes in program text	
  2963                              <1> 		; sub $14,r5 / subtract 12
  2964 00003E30 89CB                <1> 	mov	ebx, ecx
  2965                              <1> 	;
  2966                              <1> 	; 25/06/2015
  2967                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2968                              <1> 	;	and SINGLIX operating systems (as code template).
  2969                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2970                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2971                              <1> 	;	Overrun is not possible for current version. 	
  2972                              <1> 	;
  2973 00003E32 AD                  <1> 	lodsd	
  2974 00003E33 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2975 00003E35 3B1D[20660000]      <1> 	cmp	ebx, [u.count]
  2976 00003E3B 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2977                              <1> 	;
  2978                              <1> 	; 24/07/2015
  2979                              <1> 	; add bss section size to [u.break]
  2980 00003E3D 0105[28660000]      <1> 	add 	[u.break], eax
  2981                              <1> 	;
  2982 00003E43 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2983                              <1> 	;cmp	ecx, [u.count]
  2984                              <1> 	;jnb	short sysexec_16
  2985                              <1> 		; cmp r5,u.count /
  2986                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2987 00003E46 890D[20660000]      <1> 	mov	[u.count], ecx ; required read count
  2988                              <1> 		; mov r5,u.count
  2989                              <1> 	;
  2990 00003E4C EB2A                <1> 	jmp	short sysexec_16
  2991                              <1> 	;
  2992                              <1> sysexec_14:
  2993                              <1> 	; 23/06/2015
  2994                              <1> 	; insufficient (out of) memory
  2995 00003E4E C705[51660000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2995 00003E56 0000                <1>
  2996 00003E58 E974F3FFFF          <1> 	jmp	error
  2997                              <1> 	;
  2998                              <1> sysexec_15:
  2999                              <1> 	; 25/06/2015
  3000 00003E5D 0FB715[F8620000]    <1>         movzx   edx, word [i.size] ; file size
  3001 00003E64 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  3002 00003E66 7627                <1> 	jna	short sysexec_17 ; no need to next read
  3003 00003E68 01D1                <1> 	add	ecx, edx ; [i.size]
  3004 00003E6A 3B0D[20660000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  3005 00003E70 77DC                <1> 	ja	short sysexec_14
  3006 00003E72 8915[20660000]      <1> 	mov	[u.count], edx
  3007                              <1> sysexec_16:
  3008 00003E78 66A1[E0650000]      <1> 	mov	ax, [ii] ; i-number
  3009 00003E7E E83E0C0000          <1> 	call	readi
  3010                              <1> 		; add core+10,u.nread / add size of user data area 
  3011                              <1> 		                    ; / to u.nread
  3012                              <1> 		; br 2f
  3013                              <1> 	; 1:
  3014                              <1> 		; jsr r0,readi / read in rest of file
  3015                              <1> 	; 2:
  3016 00003E83 8B0D[24660000]      <1> 	mov	ecx, [u.nread]
  3017 00003E89 010D[28660000]      <1> 	add	[u.break], ecx
  3018                              <1> 		; mov u.nread,u.break / set users program break to end of 
  3019                              <1> 				    ; / user code
  3020                              <1> 		; add $core+14,u.break / plus data area
  3021                              <1> sysexec_17: ; 20/07/2015
  3022                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3023                              <1> 	; ('iclose' is not needed for regular files, from now on)
  3024                              <1> 	;;mov	ax, [ii] ; i-number
  3025                              <1> 	;call	iclose
  3026                              <1> 	;	; jsr r0,iclose / does nothing
  3027 00003E8F 31C0                <1>         xor     eax, eax
  3028 00003E91 FEC0                <1> 	inc	al
  3029 00003E93 66A3[40660000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3030 00003E99 66A3[42660000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3031                              <1> 	; 02/07/2015
  3032 00003E9F 833D[59660000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  3033 00003EA6 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3034                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3035 00003EA8 8B15[38620000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3036 00003EAE 8915[59660000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  3037                              <1> sysexec_18:
  3038                              <1> 	; 18/10/2015
  3039                              <1> 	; 05/08/2015
  3040                              <1> 	; 29/07/2015
  3041 00003EB4 8B2D[7C660000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3042                              <1> 			    ; list pointers (argument count)
  3043 00003EBA FA                  <1> 	cli
  3044 00003EBB 8B25[D4610000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3045                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3046                              <1> 			    ; for this process	 
  3047                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3048                              <1> 	;xor	eax, eax ; 0
  3049 00003EC1 FEC8                <1> 	dec	al ; eax = 0
  3050 00003EC3 66BA2300            <1> 	mov	dx, UDATA
  3051 00003EC7 6652                <1> 	push	dx  ; user's stack segment
  3052 00003EC9 55                  <1> 	push	ebp ; user's stack pointer
  3053                              <1> 		    ; (points to number of arguments)
  3054 00003ECA FB                  <1> 	sti
  3055 00003ECB 9C                  <1> 	pushfd	; EFLAGS
  3056                              <1> 		; Set IF for enabling interrupts in user mode	
  3057                              <1> 	;or	dword [esp], 200h 
  3058                              <1> 	;
  3059                              <1> 	;mov	bx, UCODE
  3060                              <1> 	;push	bx ; user's code segment
  3061 00003ECC 6A1B                <1> 	push	UCODE
  3062                              <1> 	;push	0
  3063 00003ECE 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3064                              <1> 		; clr -(r5) / popped into ps when rti in 
  3065                              <1> 			  ; / sysrele is executed
  3066                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3067                              <1> 		                ; / in sysrele is executed
  3068                              <1> 		;mov r5,0f / load second copyz argument
  3069                              <1> 		;tst -(r5) / decrement r5
  3070 00003ECF 8925[F4650000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3071                              <1> 	; 05/08/2015
  3072                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3073                              <1> 	; ('push dx' would cause to general protection fault, 
  3074                              <1> 	; after 'pop ds' etc.)
  3075                              <1> 	;
  3076                              <1> 	;; push dx ; ds (UDATA)
  3077                              <1> 	;; push dx ; es (UDATA)
  3078                              <1> 	;; push dx ; fs (UDATA)
  3079                              <1> 	;; push dx ; gs (UDATA)
  3080                              <1> 	;
  3081                              <1> 	; This is a trick to prevent general protection fault
  3082                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3083 00003ED5 8EC2                <1> 	mov 	es, dx ; UDATA
  3084 00003ED7 06                  <1> 	push 	es ; ds (UDATA)
  3085 00003ED8 06                  <1> 	push 	es ; es (UDATA)
  3086 00003ED9 06                  <1> 	push 	es ; fs (UDATA)
  3087 00003EDA 06                  <1> 	push	es ; gs (UDATA)
  3088 00003EDB 66BA1000            <1> 	mov	dx, KDATA
  3089 00003EDF 8EC2                <1> 	mov	es, dx
  3090                              <1> 	;
  3091                              <1> 	;; pushad simulation
  3092 00003EE1 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3093 00003EE3 50                  <1> 	push	eax ; eax (0)
  3094 00003EE4 50                  <1> 	push	eax ; ecx (0)
  3095 00003EE5 50                  <1> 	push	eax ; edx (0)
  3096 00003EE6 50                  <1> 	push	eax ; ebx (0)
  3097 00003EE7 55                  <1> 	push	ebp ; esp before pushad
  3098 00003EE8 50                  <1> 	push	eax ; ebp (0)
  3099 00003EE9 50                  <1> 	push	eax ; esi (0)		
  3100 00003EEA 50                  <1> 	push	eax ; edi (0)	
  3101                              <1> 	;
  3102 00003EEB A3[FC650000]        <1> 	mov	[u.r0], eax ; eax = 0
  3103 00003EF0 8925[F8650000]      <1> 	mov	[u.usp], esp
  3104                              <1> 		; mov r5,u.r0 /
  3105                              <1> 		; sub $16.,r5 / skip 8 words
  3106                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3107                              <1> 		;             / effectively zeroes all regs
  3108                              <1> 			    ; / when sysrele is executed
  3109                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3110                              <1> 		; clr u.break
  3111                              <1> 		; mov r5,sp / point sp to user's stack
  3112                              <1> 	;
  3113 00003EF6 E9F8F2FFFF          <1> 	jmp	sysret0
  3114                              <1> 	;jmp	sysret
  3115                              <1> 		; br sysret3 / return to core image at $core
  3116                              <1> 
  3117                              <1> get_argp:
  3118                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3119                              <1> 	; 18/10/2015 (nbase, ncount)
  3120                              <1> 	; 21/07/2015
  3121                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3122                              <1> 	; Get (virtual) address of argument from user's core memory
  3123                              <1> 	;
  3124                              <1> 	; INPUT:
  3125                              <1> 	;	esi = virtual address of argument pointer
  3126                              <1> 	; OUTPUT:
  3127                              <1> 	;	eax = virtual address of argument
  3128                              <1> 	;
  3129                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3130                              <1> 	;
  3131 00003EFB 833D[59660000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3132                              <1> 				    ; (the caller is kernel)
  3133                              <1> 	;jna	short get_argpk 
  3134                              <1> 	; 24/12/2021
  3135 00003F02 7719                <1> 	ja	short get_argp5
  3136                              <1> get_argpk:
  3137                              <1> 	; Argument is in kernel's memory space
  3138 00003F04 66C705[78660000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3138 00003F0C 10                  <1>
  3139 00003F0D 8935[74660000]      <1> 	mov	[nbase], esi
  3140 00003F13 8305[74660000]04    <1> 	add	dword [nbase], 4
  3141 00003F1A 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3142 00003F1C C3                  <1> 	retn
  3143                              <1> get_argp5:
  3144 00003F1D 89F3                <1>      	mov	ebx, esi
  3145 00003F1F E88BE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3146 00003F24 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3147 00003F26 A3[74660000]        <1> 	mov 	[nbase], eax ; physical address	
  3148 00003F2B 66890D[78660000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3149 00003F32 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3150                              <1> 	;cmp	cx, ax ; 4
  3151 00003F37 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3152 00003F39 734C                <1> 	jnb	short get_argp2
  3153 00003F3B 89F3                <1> 	mov	ebx, esi
  3154 00003F3D 01CB                <1> 	add	ebx, ecx
  3155 00003F3F E86BE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3156 00003F44 7237                <1> 	jc	short get_argp_err
  3157                              <1> 	;push	esi
  3158 00003F46 89C6                <1> 	mov	esi, eax
  3159 00003F48 66870D[78660000]    <1> 	xchg	cx, [ncount]
  3160 00003F4F 8735[74660000]      <1> 	xchg	esi, [nbase]
  3161 00003F55 B504                <1> 	mov	ch, 4
  3162 00003F57 28CD                <1> 	sub	ch, cl
  3163                              <1> get_argp0:
  3164 00003F59 AC                  <1> 	lodsb
  3165                              <1> 	;push	ax
  3166                              <1> 	; 24/12/2021
  3167 00003F5A 50                  <1> 	push	eax
  3168 00003F5B FEC9                <1> 	dec	cl
  3169 00003F5D 75FA                <1>         jnz     short get_argp0
  3170 00003F5F 8B35[74660000]      <1> 	mov	esi, [nbase]
  3171                              <1> 	; 21/07/2015
  3172 00003F65 0FB6C5              <1> 	movzx	eax, ch
  3173 00003F68 0105[74660000]      <1> 	add	[nbase], eax
  3174 00003F6E 662905[78660000]    <1> 	sub	[ncount], ax
  3175                              <1> get_argp1:
  3176 00003F75 AC                  <1> 	lodsb
  3177 00003F76 FECD                <1> 	dec	ch
  3178 00003F78 7423                <1>         jz      short get_argp3
  3179                              <1> 	;push	ax
  3180                              <1> 	; 24/12/2021
  3181 00003F7A 50                  <1> 	push	eax
  3182 00003F7B EBF8                <1> 	jmp     short get_argp1
  3183                              <1> 	; 24/12/2021
  3184                              <1> get_argp_err:
  3185 00003F7D A3[51660000]        <1> 	mov	[u.error], eax
  3186 00003F82 E94AF2FFFF          <1> 	jmp	error
  3187                              <1> get_argp2:
  3188                              <1> 	; 21/07/2015
  3189                              <1> 	;mov	eax, 4
  3190 00003F87 8B15[74660000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3191 00003F8D 0105[74660000]      <1> 	add	[nbase], eax
  3192 00003F93 662905[78660000]    <1> 	sub	[ncount], ax
  3193                              <1> 	;
  3194 00003F9A 8B02                <1> 	mov	eax, [edx]
  3195 00003F9C C3                  <1> 	retn
  3196                              <1> get_argp3:
  3197 00003F9D B103                <1> 	mov	cl, 3
  3198                              <1> get_argp4:
  3199 00003F9F C1E008              <1> 	shl	eax, 8
  3200                              <1> 	;pop	dx
  3201                              <1> 	; 24/12/2021
  3202 00003FA2 5A                  <1> 	pop	edx
  3203 00003FA3 88D0                <1> 	mov 	al, dl
  3204 00003FA5 E2F8                <1>         loop    get_argp4
  3205                              <1> 	;pop	esi
  3206 00003FA7 C3                  <1> 	retn	
  3207                              <1> 
  3208                              <1> sysfstat:
  3209                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3210                              <1> 	;	([idev] return in eax)
  3211                              <1> 	;	0 = root device
  3212                              <1> 	;	1 = mounted device (>0)
  3213                              <1> 	; 03/02/2022
  3214                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3215                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3216                              <1> 	;
  3217                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3218                              <1> 	; on open files instead of files given by name. It puts the
  3219                              <1> 	; buffer address on the stack, gets the i-number and
  3220                              <1> 	; checks to see if the file is open for reading or writing.
  3221                              <1> 	; If the file is open for writing (i-number is negative)
  3222                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3223                              <1> 	; is made.	
  3224                              <1> 	;
  3225                              <1> 	; Calling sequence:
  3226                              <1> 	;	sysfstat; buf
  3227                              <1> 	; Arguments:
  3228                              <1> 	;	buf - buffer address
  3229                              <1> 	;
  3230                              <1> 	; Inputs: *u.r0 - file descriptor
  3231                              <1> 	; Outputs: buffer is loaded with file information
  3232                              <1> 	; ...............................................................
  3233                              <1> 	;				
  3234                              <1> 	; Retro UNIX 8086 v1 modification:
  3235                              <1> 	;       'sysfstat' system call has two arguments; so,
  3236                              <1> 	;	* 1st argument, file descriptor is in BX register
  3237                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3238                              <1> 
  3239                              <1> 	; / set status of open file
  3240                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3241 00003FA8 51                  <1> 	push	ecx
  3242                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3243                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3244                              <1> 		; jsr r0,getf / get the files i-number
  3245                              <1> 	; BX = file descriptor (file number)
  3246 00003FA9 E8FE000000          <1> 	call	getf1
  3247                              <1> 	; 03/02/2022
  3248 00003FAE 21C0                <1> 	and	eax, eax
  3249                              <1> 	;and	ax, ax ; i-number of the file
  3250                              <1> 		; tst	r1 / is it 0?
  3251                              <1> 	;jz	error
  3252                              <1> 		; beq error3 / yes, error
  3253 00003FB0 750F                <1> 	jnz	short sysfstat1
  3254 00003FB2 C705[51660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3254 00003FBA 0000                <1>
  3255 00003FBC E910F2FFFF          <1> 	jmp	error
  3256                              <1> sysfstat1:
  3257 00003FC1 80FC80              <1> 	cmp	ah, 80h
  3258 00003FC4 7222                <1>         jb      short sysstat1
  3259                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3260 00003FC6 66F7D8              <1> 	neg	ax
  3261                              <1> 		; neg r1 / make it positive, then branch
  3262 00003FC9 EB1D                <1> 	jmp	short sysstat1
  3263                              <1> 		; br 1f / to 1f
  3264                              <1> sysstat:
  3265                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  3266                              <1> 	;	([idev] return in eax)
  3267                              <1> 	;	0 = root device
  3268                              <1> 	;	1 = mounted device (>0)
  3269                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3270                              <1> 	; 18/10/2015
  3271                              <1> 	; 07/10/2015
  3272                              <1> 	; 02/09/2015
  3273                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3274                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3275                              <1> 	;
  3276                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3277                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3278                              <1> 	; long and information about the file placed in it.	
  3279                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3280                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3281                              <1> 	; is then loaded and the results are given in the UNIX
  3282                              <1> 	; Programmers Manual sysstat (II).	
  3283                              <1> 	;
  3284                              <1> 	; Calling sequence:
  3285                              <1> 	;	sysstat; name; buf
  3286                              <1> 	; Arguments:
  3287                              <1> 	;	name - points to the name of the file
  3288                              <1> 	;	buf - address of a 34 bytes buffer
  3289                              <1> 	; Inputs: -
  3290                              <1> 	; Outputs: buffer is loaded with file information
  3291                              <1> 	; ...............................................................
  3292                              <1> 	;				
  3293                              <1> 	; Retro UNIX 8086 v1 modification: 
  3294                              <1> 	;       'sysstat' system call has two arguments; so,
  3295                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3296                              <1> 	;	to get sysstat system call arguments from the user;
  3297                              <1> 	;	* 1st argument, name is pointed to by BX register
  3298                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3299                              <1> 	;
  3300                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3301                              <1> 	;	      arguments which were in these registers;
  3302                              <1> 	;	      but, it returns by putting the 1st argument
  3303                              <1> 	;	      in 'u.namep' and the 2nd argument
  3304                              <1> 	;	      on top of stack. (1st argument is offset of the
  3305                              <1> 	;	      file/path name in the user's program segment.)		 	
  3306                              <1> 	
  3307                              <1> 	; / ; name of file; buffer - get files status
  3308                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3309 00003FCB 891D[14660000]      <1> 	mov	[u.namep], ebx
  3310 00003FD1 51                  <1> 	push	ecx
  3311 00003FD2 E806010000          <1> 	call	namei
  3312                              <1> 		; jsr r0,namei / get the i-number for the file
  3313                              <1> 	;jc	error
  3314                              <1> 		; br error3 / no such file, error
  3315 00003FD7 730F                <1> 	jnc	short sysstat1
  3316                              <1> 	; pop 	ecx
  3317                              <1> sysstat_err0:
  3318                              <1> 	; 'file not found !' error
  3319 00003FD9 C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3319 00003FE1 0000                <1>
  3320 00003FE3 E9E9F1FFFF          <1> 	jmp	error
  3321                              <1> 
  3322                              <1> ;statx: db 0
  3323                              <1> 
  3324                              <1> sysstat1: ; 1:
  3325 00003FE8 E800090000          <1> 	call	iget
  3326                              <1> 		; jsr r0,iget / get the i-node into core
  3327                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3328                              <1> 	; 02/09/2015
  3329 00003FED 8F05[1C660000]      <1> 	pop	dword [u.base]
  3330                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3331 00003FF3 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3332 00003FF8 730A                <1> 	jnc 	short sysstat2
  3333                              <1> sysstat_err1:
  3334 00003FFA A3[51660000]        <1> 	mov	dword [u.error], eax ; error code
  3335 00003FFF E9CDF1FFFF          <1> 	jmp	error
  3336                              <1> sysstat2:
  3337 00004004 A0[E0650000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3338 00004009 AA                  <1> 	stosb
  3339 0000400A FF05[1C660000]      <1> 	inc 	dword [u.base]
  3340                              <1> 	;dec 	cx
  3341                              <1> 	; 24/12/2021
  3342 00004010 49                  <1> 	dec	ecx
  3343 00004011 7505                <1> 	jnz	short sysstat3
  3344 00004013 E841000000          <1> 	call	sysstat_gpa
  3345                              <1> 	;jc	short sysstat_err1
  3346                              <1> sysstat3:
  3347 00004018 A0[E1650000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3348 0000401D AA                  <1> 	stosb
  3349                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3350 0000401E FF05[1C660000]      <1> 	inc 	dword [u.base]
  3351                              <1> 	;;dec 	word [u.pcount]
  3352                              <1> 	;dec	cx
  3353 00004024 49                  <1> 	dec	ecx ; 24/12/2021
  3354 00004025 7505                <1> 	jnz	short sysstat4
  3355 00004027 E82D000000          <1> 	call	sysstat_gpa
  3356                              <1> 	;jc	short sysstat_err1	
  3357                              <1> sysstat4:
  3358 0000402C BE[F4620000]        <1> 	mov	esi, inode
  3359                              <1> 		; mov $inode,r2 / r2 points to i-node
  3360                              <1> sysstat5: ; 1:
  3361 00004031 A4                  <1> 	movsb
  3362                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3363 00004032 FF05[1C660000]      <1> 	inc 	dword [u.base]
  3364                              <1> 	;;dec 	word [u.pcount]
  3365                              <1> 	;dec 	cx
  3366                              <1> 	; 24/12/2021
  3367 00004038 49                  <1> 	dec	ecx
  3368 00004039 7505                <1> 	jnz	short sysstat6
  3369 0000403B E819000000          <1> 	call	sysstat_gpa
  3370                              <1> 	;jc	short sysstat_err1
  3371                              <1> sysstat6:		
  3372 00004040 81FE[14630000]      <1> 	cmp	esi, inode + 32
  3373                              <1> 		; cmp r2,$inode+32 / done?
  3374 00004046 75E9                <1> 	jne	short sysstat5
  3375                              <1> 		; bne 1b / no, go back
  3376                              <1> 
  3377                              <1> 	;;;
  3378                              <1> 	; 09/05/2022
  3379                              <1> 	;*** additional feature *** -retro unix only- 
  3380                              <1> 	;
  3381                              <1> 	; !! return device number -of current inode- in eax !!
  3382                              <1> 	;
  3383                              <1> 	; (modification reason/purpose:
  3384                              <1> 	; to improve 'pwd' command's pathname output/result
  3385                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3386                              <1> 	; error due to same inode numbers in root file system
  3387                              <1> 	; and mounted file system.)
  3388                              <1> 	;
  3389 00004048 29C0                <1> 	sub	eax, eax
  3390 0000404A A0[E2650000]        <1> 	mov	al, [idev] ; [cdev]
  3391 0000404F A3[FC650000]        <1> 	mov	[u.r0], eax
  3392                              <1> 	;;;  
  3393                              <1> 
  3394 00004054 E998F1FFFF          <1> 	jmp	sysret
  3395                              <1> 		; br sysret3 / return through sysret
  3396                              <1> 	;
  3397                              <1> sysstat_gpa: ; get physical address of file status buffer
  3398                              <1> 	; 02/09/2015
  3399 00004059 8B1D[1C660000]      <1> 	mov 	ebx, [u.base]
  3400                              <1> 	; 07/10/2015
  3401 0000405F E84BE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3402                              <1> 	;jc	short sysstat_gpa1
  3403 00004064 7294                <1> 	jc	short sysstat_err1
  3404                              <1> 	; 18/10/2015
  3405 00004066 89C7                <1> 	mov	edi, eax ; physical address
  3406                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3407                              <1> ;sysstat_gpa1:
  3408 00004068 C3                  <1> 	retn
  3409                              <1> 
  3410                              <1> fclose:
  3411                              <1> 	; 08/01/2022
  3412                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3413                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3414                              <1> 	;            (32 bit offset pointer modification)
  3415                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3416                              <1> 	;
  3417                              <1> 	; Given the file descriptor (index to the u.fp list)
  3418                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3419                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3420                              <1> 	; u.fp list is cleared. If all the processes that opened
  3421                              <1> 	; that file close it, then fsp etry is freed and the file
  3422                              <1> 	; is closed. If not a return is taken. 
  3423                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3424                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3425                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3426                              <1> 	; a check is made to see if the file is special.	
  3427                              <1> 	;
  3428                              <1> 	; INPUTS ->
  3429                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3430                              <1> 	;    u.fp - list of entries in the fsp table
  3431                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3432                              <1> 	; OUTPUTS ->
  3433                              <1> 	;    r1 - contains the same file descriptor
  3434                              <1> 	;    r2 - contains i-number
  3435                              <1> 	;
  3436                              <1> 	; ((AX = R1))
  3437                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3438                              <1> 	;
  3439                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3440                              <1> 	;              if i-number of the file is 0. (error)  	
  3441                              <1> 
  3442                              <1> 	;movzx	edx, ax ; **
  3443                              <1> 	; 24/12/2021
  3444                              <1> 	;movzx	edx, al
  3445 00004069 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3446 0000406B 50                  <1> 	push	eax ; ***
  3447                              <1> 	;push	ax ; ***
  3448                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3449                              <1> 			     ; / the index to u.fp list)
  3450 0000406C E839000000          <1> 	call	getf
  3451                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3452                              <1> 			    ; / cdev has device =, u.fofp 
  3453                              <1> 			    ; / points to 3rd word of fsp entry
  3454 00004071 6683F801            <1> 	cmp	ax, 1 ; r1
  3455                              <1> 		; tst r1 / is i-number 0?
  3456 00004075 7231                <1> 	jb	short fclose_2
  3457                              <1> 		; beq 1f / yes, i-node not active so return
  3458                              <1> 		; tst (r0)+ / no, jump over error return
  3459 00004077 89D3                <1> 	mov	ebx, edx ; **
  3460                              <1> 	; 24/12/2021
  3461 00004079 89C2                <1> 	mov	edx, eax ; *
  3462                              <1> 	;mov 	dx, ax ; *
  3463                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3464                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3465                              <1> 			    ; / which is index to u.fp ; **
  3466 0000407B C683[02660000]00    <1> 	mov	byte [ebx+u.fp], 0
  3467                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3468 00004082 8B1D[0C660000]      <1> 	mov	ebx, [u.fofp]
  3469                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3470                              <1> fclose_0:
  3471 00004088 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3472                              <1> 		; decb 2(r1) / decrement the number of processes 
  3473                              <1> 			   ; / that have opened the file
  3474 0000408B 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3475                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3476                              <1> 	;
  3477                              <1> 	; 24/12/2021
  3478 0000408D 52                  <1> 	push	edx ; *
  3479                              <1> 	;push	dx ; *
  3480                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3481                              <1> 	;xor	ax, ax ; 0
  3482                              <1> 	; 24/12/2021
  3483 0000408E 31C0                <1> 	xor	eax, eax
  3484 00004090 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3485                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3486 00004094 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3487                              <1> 		; tstb	3(r1) / has this file been deleted
  3488 00004097 20C0                <1> 	and	al, al
  3489 00004099 7407                <1> 	jz	short fclose_1
  3490                              <1> 		; beq 2f / no, branch
  3491                              <1> 	; 08/01/2022
  3492 0000409B 89D0                <1> 	mov	eax, edx
  3493                              <1> 	;mov	ax, dx ; *
  3494                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3495                              <1> 	; AX = inode number
  3496 0000409D E8A0040000          <1> 	call	anyi
  3497                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3498                              <1> 			    ; / check if file appears in fsp again
  3499                              <1> fclose_1: ; 2:
  3500                              <1> 	; 24/12/2021
  3501 000040A2 58                  <1> 	pop	eax ; * 
  3502                              <1> 	;pop	ax ; *
  3503                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3504 000040A3 E8E8110000          <1> 	call	iclose ; close if it is special file 
  3505                              <1> 		; jsr r0,iclose / check to see if its a special file
  3506                              <1> fclose_2: ; 1:
  3507                              <1> 	; 24/12/2021
  3508 000040A8 58                  <1> 	pop	eax ; ***
  3509                              <1> 	;pop	ax ; ***
  3510                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3511 000040A9 C3                  <1> 	retn
  3512                              <1> 		; rts r0
  3513                              <1> 
  3514                              <1> 	; 09/01/2022
  3515                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3516                              <1> getf:	; / get the device number and the i-number of an open file
  3517                              <1> 	; 13/05/2015
  3518                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3519                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3520                              <1> 	;
  3521 000040AA 89C3                <1> 	mov	ebx, eax
  3522                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3523                              <1> 	; 08/01/2022
  3524 000040AC 29C0                <1> 	sub	eax, eax
  3525                              <1> 	;
  3526 000040AE 83FB0A              <1> 	cmp	ebx, 10
  3527                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3528 000040B1 7329                <1>         jnb	short getf2 ; 13/05/2015
  3529                              <1> 	;jnb	error
  3530                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3531                              <1> 			    ; / index in fsp table
  3532                              <1> 	; 08/01/2022
  3533 000040B3 8A83[02660000]      <1> 	mov	al, [ebx+u.fp]
  3534                              <1> 	;mov	bl, [ebx+u.fp]
  3535                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3536                              <1> 		                  ; / in fsp table
  3537                              <1> 	; 08/01/2022
  3538 000040B9 08C0                <1> 	or	al, al
  3539 000040BB 741F                <1> 	jz	short getf2	
  3540                              <1> 	;or	bl, bl
  3541                              <1> 	;jnz	short getf3
  3542                              <1> 	;;jz	short getf4
  3543                              <1> 		; beq 1f / if its zero return
  3544                              <1> ;getf2:
  3545                              <1> ;	; 08/01/2022
  3546                              <1> ;	; 'File not open !' error (ax=0)
  3547                              <1> ;	;sub	eax, eax
  3548                              <1> ;	retn
  3549                              <1> 
  3550                              <1> getf3:	
  3551                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3552                              <1> 	;
  3553                              <1> 	; 'fsp' table (10 bytes/entry)
  3554                              <1> 	; bit 15				   bit 0
  3555                              <1> 	; ---|-------------------------------------------
  3556                              <1> 	; r/w|		i-number of open file
  3557                              <1> 	; ---|-------------------------------------------
  3558                              <1> 	;		   device number
  3559                              <1> 	; -----------------------------------------------
  3560                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3561                              <1> 	; -----------------------------------------------
  3562                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3563                              <1> 	; ----------------------|------------------------
  3564                              <1> 	;  flag that says file 	| number of processes
  3565                              <1> 	;   has been deleted	| that have file open 
  3566                              <1> 	; ----------------------|------------------------
  3567                              <1> 	;
  3568                              <1> 	;mov	eax, 10
  3569                              <1> 	; 08/01/2022
  3570 000040BD B30A                <1> 	mov	bl, 10
  3571 000040BF F6E3                <1> 	mul	bl
  3572 000040C1 BB[BE630000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3573 000040C6 01C3                <1> 	add	ebx, eax
  3574                              <1> 		; asl r1
  3575                              <1> 		; asl r1 / multiply by 8 to get index into 
  3576                              <1> 		       ; / fsp table entry
  3577                              <1> 		; asl r1
  3578                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3579                              <1> 			      ; / in the fsp entry
  3580 000040C8 891D[0C660000]      <1> 	mov	[u.fofp], ebx
  3581                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3582                              <1> 			      ; / in fsp entry in u.fofp
  3583 000040CE 4B                  <1> 	dec	ebx
  3584 000040CF 4B                  <1> 	dec	ebx
  3585                              <1> 	;mov	ax, [ebx]
  3586                              <1> 	; 09/01/2022
  3587 000040D0 8A03                <1> 	mov	al, [ebx]
  3588 000040D2 A2[E3650000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3589                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3590                              <1> 			     ;;dev number is in 1 byte
  3591                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3592 000040D7 4B                  <1> 	dec	ebx
  3593 000040D8 4B                  <1> 	dec	ebx
  3594 000040D9 668B03              <1> 	mov	ax, [ebx]
  3595                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3596                              <1> getf2:	; 08/01/2022
  3597                              <1> getf4:	; 1:
  3598 000040DC C3                  <1> 	retn
  3599                              <1> 		; rts r0
  3600                              <1> 
  3601                              <1> namei:
  3602                              <1> 	; 15/05/2022 (mounted directory path, '..' method)
  3603                              <1> 	; 03/02/2022
  3604                              <1> 	; 09/01/2022
  3605                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3606                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3607                              <1> 	; 18/10/2015 (nbase, ncount)
  3608                              <1> 	; 12/10/2015
  3609                              <1> 	; 21/08/2015
  3610                              <1> 	; 18/07/2015
  3611                              <1> 	; 02/07/2015
  3612                              <1> 	; 17/06/2015
  3613                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3614                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3615                              <1> 	;
  3616                              <1> 	; 'namei' takes a file path name and returns i-number of
  3617                              <1> 	; the file in the current directory or the root directory
  3618                              <1> 	; (if the first character of the pathname is '/').	
  3619                              <1> 	;
  3620                              <1> 	; INPUTS ->
  3621                              <1> 	;    u.namep - points to a file path name
  3622                              <1> 	;    u.cdir - i-number of users directory
  3623                              <1> 	;    u.cdev - device number on which user directory resides	
  3624                              <1> 	; OUTPUTS ->
  3625                              <1> 	;    r1 - i-number of file
  3626                              <1> 	;    cdev
  3627                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3628                              <1> 	;               occurs in the search for file path name.
  3629                              <1> 	;	        If no match u.dirb points to the end of 
  3630                              <1> 	;               the directory and r1 = i-number of the current
  3631                              <1> 	;	        directory.	
  3632                              <1> 	; ((AX = R1))
  3633                              <1> 	;
  3634                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3635                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3636                              <1> 	;
  3637                              <1> 
  3638 000040DD 66A1[00660000]      <1> 	mov	ax, [u.cdir]
  3639                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3640                              <1> 			      ; / in r1
  3641                              <1> 	; 09/01/2022
  3642 000040E3 8A15[46660000]      <1> 	mov	dl, [u.cdrv]
  3643 000040E9 8815[E3650000]      <1> 	mov	[cdev], dl
  3644                              <1> 	;mov	dx, [u.cdrv]
  3645                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3646                              <1> 				    ; device/drive number is in 1 byte, 
  3647                              <1> 				    ; not in 1 word!
  3648                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3649                              <1> 				; / into cdev
  3650                              <1> 	; 12/10/2015
  3651                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3652                              <1>       	 ; convert virtual (pathname) addr to physical address
  3653 000040EF E868010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3654                              <1> 		; esi = physical address of [u.namep]
  3655                              <1> 		; ecx = byte count in the page
  3656 000040F4 803E2F              <1> 	cmp	byte [esi], '/'
  3657                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3658 000040F7 751D                <1> 	jne	short namei_1
  3659                              <1> 		; bne 1f
  3660 000040F9 FF05[14660000]      <1> 	inc	dword [u.namep]
  3661                              <1> 		; inc u.namep / go to next char
  3662                              <1> 	;dec	cx ; remain byte count in the page
  3663                              <1> 	; 24/12/2021
  3664 000040FF 49                  <1> 	dec	ecx
  3665 00004100 7506                <1> 	jnz	short namei_0
  3666                              <1> 	; 12/10/2015
  3667 00004102 E855010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3668                              <1> 		; esi = physical address (page start + offset)
  3669                              <1> 		; ecx = byte count in the page
  3670 00004107 4E                  <1> 	dec	esi
  3671                              <1> namei_0:
  3672 00004108 46                  <1> 	inc 	esi  ; go to next char
  3673 00004109 66A1[EC650000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3674                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3675 0000410F C605[E3650000]00    <1> 	mov	byte [cdev], 0
  3676                              <1> 		; clr cdev / clear device number
  3677                              <1> namei_1: ; 1:
  3678 00004116 F606FF              <1> 	test	byte [esi], 0FFh
  3679                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3680 00004119 74C1                <1> 	jz	short getf4
  3681                              <1> 	;jz	nig
  3682                              <1> 		; tstb *u.namep / is the character in file name a nul
  3683                              <1> 		; beq nig / yes, end of file name reached; 
  3684                              <1> 			; / branch to "nig"
  3685                              <1> namei_2: ; 1:
  3686                              <1> 	; 18/10/2015
  3687 0000411B 8935[74660000]      <1> 	mov 	[nbase], esi
  3688 00004121 66890D[78660000]    <1> 	mov 	[ncount], cx
  3689                              <1> 	;
  3690                              <1> 	;mov	dx, 2
  3691 00004128 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3692 0000412A E892080000          <1> 	call	access
  3693                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3694                              <1> 	; 'access' will not return here if user has not "r" permission !
  3695                              <1> 	; 03/02/2022
  3696 0000412F F605[F5620000]40    <1> 	test	byte [i.flgs+1], 40h
  3697                              <1> 	;test 	word [i.flgs], 4000h
  3698                              <1> 		; bit $40000,i.flgs / directory i-node?
  3699 00004136 746A                <1>         jz      short namei_err
  3700                              <1> 		; beq error3 / no, got an error
  3701                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3702 00004138 31C0                <1> 	xor	eax, eax
  3703 0000413A A3[18660000]        <1> 	mov	[u.off], eax ; 0
  3704 0000413F 66A1[F8620000]      <1> 	mov	ax, [i.size]
  3705 00004145 A3[10660000]        <1> 	mov	[u.dirp], eax
  3706                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3707                              <1> 		; clr u.off / u.off is file offset used by user
  3708 0000414A C705[0C660000]-     <1> 	mov	dword [u.fofp], u.off
  3708 00004150 [18660000]          <1>
  3709                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3710                              <1> 				  ; / the offset portion of fsp entry
  3711                              <1> namei_3: ; 2:
  3712 00004154 C705[1C660000]-     <1> 	mov	dword [u.base], u.dirbuf
  3712 0000415A [2E660000]          <1>
  3713                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3714                              <1> 				    ; / copied from a directory
  3715 0000415E C705[20660000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3715 00004166 0000                <1>
  3716                              <1>  		; mov $10.,u.count / u.count is byte count 
  3717                              <1> 				 ; / for reads and writes
  3718 00004168 66A1[E0650000]      <1> 	mov 	ax, [ii]
  3719                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3720 0000416E FE05[63660000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3721 00004174 E848090000          <1>     	call	readi
  3722                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3723                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3724 00004179 8B0D[24660000]      <1> 	mov 	ecx, [u.nread]
  3725 0000417F 09C9                <1> 	or 	ecx, ecx
  3726                              <1> 		; tst u.nread
  3727 00004181 741B                <1> 	jz	short nib
  3728                              <1> 		; ble nib / gives error return
  3729                              <1> 	;
  3730 00004183 668B1D[2E660000]    <1> 	mov 	bx, [u.dirbuf]
  3731 0000418A 6621DB              <1> 	and 	bx, bx       
  3732                              <1> 		; tst u.dirbuf /
  3733 0000418D 7522                <1> 	jnz	short namei_4
  3734                              <1> 		; bne 3f / branch when active directory entry 
  3735                              <1> 		       ; / (i-node word in entry non zero)
  3736 0000418F A1[18660000]        <1> 	mov	eax, [u.off]
  3737 00004194 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3738 00004197 A3[10660000]        <1> 	mov	[u.dirp], eax
  3739                              <1> 		; mov u.off,u.dirp
  3740                              <1> 		; sub $10.,u.dirp
  3741 0000419C EBB6                <1> 	jmp	short namei_3
  3742                              <1> 		; br 2b
  3743                              <1> 
  3744                              <1> 	; 18/07/2013
  3745                              <1> nib: 
  3746 0000419E 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3747 000041A0 F9                  <1> 	stc
  3748                              <1> nig:
  3749 000041A1 C3                  <1> 	retn
  3750                              <1> 
  3751                              <1> namei_err:
  3752                              <1> 	; 16/06/2015
  3753 000041A2 C705[51660000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3753 000041AA 0000                <1>
  3754 000041AC E920F0FFFF          <1> 	jmp	error
  3755                              <1> 
  3756                              <1> namei_4: ; 3:
  3757                              <1> 	; 18/10/2015
  3758                              <1> 	; 12/10/2015
  3759                              <1> 	; 21/08/2015
  3760                              <1> 	; 18/07/2015
  3761 000041B1 8B2D[14660000]      <1> 	mov	ebp, [u.namep]
  3762                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3763 000041B7 BF[30660000]        <1> 	mov 	edi, u.dirbuf + 2
  3764                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3765                              <1> 	; 18/10/2015
  3766 000041BC 8B35[74660000]      <1> 	mov	esi, [nbase]	
  3767 000041C2 668B0D[78660000]    <1> 	mov	cx, [ncount]
  3768                              <1> 	;
  3769 000041C9 6621C9              <1> 	and	cx, cx
  3770 000041CC 7505                <1> 	jnz	short namei_5	
  3771                              <1> 	;
  3772 000041CE E88F000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3773                              <1> 		; esi = physical address (page start + offset)
  3774                              <1> 		; ecx = byte count in the page
  3775                              <1> namei_5: ; 3:
  3776 000041D3 45                  <1> 	inc	ebp ; 18/07/2015
  3777 000041D4 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3778                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3779 000041D5 08C0                <1> 	or 	al, al
  3780 000041D7 741C                <1> 	jz 	short namei_7
  3781                              <1> 		; beq 3f / if char is nul, then the last char in string
  3782                              <1> 			; / has been moved
  3783 000041D9 3C2F                <1> 	cmp	al, '/'
  3784                              <1> 		; cmp r4,$'/ / is char a </>
  3785 000041DB 7418                <1> 	je 	short namei_7
  3786                              <1> 		; beq 3f	
  3787                              <1> 	; 24/12/2021
  3788 000041DD 49                  <1> 	dec	ecx
  3789                              <1> 	; 12/10/2015
  3790                              <1> 	;dec	cx ; remain byte count in the page
  3791 000041DE 7505                <1> 	jnz	short namei_6
  3792 000041E0 E87D000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3793                              <1> 		; esi = physical address (page start + offset)
  3794                              <1> 		; ecx = byte count in the page
  3795                              <1> namei_6:
  3796 000041E5 81FF[3E660000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3797                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3798                              <1> 				     ; / all 8 bytes of file name
  3799 000041EB 74E6                <1> 	je	short namei_5
  3800                              <1> 		; beq 3b
  3801 000041ED AE                  <1> 	scasb	
  3802                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3803                              <1> 			      ; / char read from directory
  3804 000041EE 74E3                <1> 	je 	short namei_5
  3805                              <1> 		; beq 3b / branch if chars match
  3806                              <1> namei_9:
  3807 000041F0 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3808                              <1> 		; br 2b / file names do not match go to next directory entry
  3809                              <1> namei_7: ; 3:
  3810 000041F5 81FF[3E660000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3811                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3812 000041FB 7406                <1> 	je	short namei_8
  3813                              <1> 		; beq 3f
  3814 000041FD 8A27                <1> 	mov 	ah, [edi]
  3815                              <1> 	;inc 	edi 
  3816 000041FF 20E4                <1> 	and 	ah, ah
  3817                              <1> 		; tstb (r3)+ /
  3818                              <1>         ;jnz	namei_3
  3819                              <1> 		; bne 2b
  3820                              <1> 	; 24/12/2021
  3821 00004201 75ED                <1> 	jnz	short namei_9	
  3822                              <1> namei_8: ; 3
  3823 00004203 892D[14660000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3824                              <1> 		; mov r2,u.namep / u.namep points to char 
  3825                              <1> 			       ; / following a / or nul
  3826                              <1> 	;mov	bx, [u.dirbuf]
  3827                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3828                              <1> 				; / entry to r1
  3829                              <1> 	;;;;
  3830                              <1> 	; 15/05/2022 - Retro UNIX (8086/386) feature only !
  3831                              <1> 	; ! 'pwd' utility modification !
  3832                              <1> 	; ((if directory entry name is a dotdot)))
  3833                              <1> 	;; check if it is mounted device's root directory inode
  3834                              <1> 	; and if so, replace it with parent dir inode number
  3835                              <1> 	;  of mounting directory in [mntp].
  3836                              <1> 
  3837 00004209 668B1D[2E660000]    <1> 	mov	bx, [u.dirbuf]
  3838                              <1> 
  3839 00004210 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3840 00004214 753C                <1> 	jne	short namei_11
  3841                              <1> 
  3842 00004216 663B1D[E0650000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3843 0000421D 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3844                              <1> 
  3845                              <1> 	;cmp	[idev], bh ; 0
  3846 0000421F 383D[E3650000]      <1> 	cmp	[cdev], bh ; 0
  3847                              <1> 			; 0 = root fs, dev num in [rdev]
  3848                              <1> 			; 1 = mounted, dev num in [mdev]
  3849 00004225 762B                <1> 	jna	short namei_11
  3850                              <1> 
  3851                              <1> 	; dotdot (parent directory link) check
  3852 00004227 66813D[30660000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3852 0000422F 2E                  <1>
  3853 00004230 7520                <1> 	jne	short namei_11
  3854 00004232 803D[32660000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3855 00004239 7517                <1> 	jne	short namei_11
  3856                              <1> 	
  3857                              <1> 	; (This may not be necessary because [idev] = 1
  3858                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3859 0000423B 66391D[E6650000]    <1> 	cmp	[mnti], bx ; 41
  3860 00004242 760E                <1> 	jna	short namei_11
  3861                              <1> 	
  3862                              <1> 	; change inumber to parent dir inum of mount directory
  3863 00004244 668B1D[E8650000]    <1> 	mov	bx, [mntp]
  3864 0000424B C605[E3650000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3865                              <1> namei_11:
  3866                              <1> 	;;;;
  3867                              <1> 
  3868 00004252 20C0                <1> 	and 	al, al
  3869                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3870                              <1> 		      ;  / if r4 = </> then go to next directory
  3871                              <1> 	; 15/05/2022
  3872 00004254 6689D8              <1> 	mov	ax, bx
  3873                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3874                              <1>   	; 24/12/2021
  3875 00004257 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3876                              <1> 	;jnz	namei_2 
  3877                              <1> 		; bne 1b
  3878                              <1> 	; AX = i-number of the file
  3879                              <1> ;;nig:
  3880                              <1> 	;retn	; 24/12/2021
  3881                              <1> 		; tst (r0)+ / gives non-error return
  3882                              <1> ;;nib:
  3883                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3884                              <1> 		       ; ax = 0 -> file not found 
  3885                              <1> ;;	stc	; 27/05/2013
  3886                              <1> ;;	retn
  3887                              <1> 		; rts r0
  3888                              <1> 
  3889                              <1> trans_addr_nmbp:
  3890                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3891                              <1> 	; 18/10/2015
  3892                              <1> 	; 12/10/2015
  3893 0000425C 8B2D[14660000]      <1> 	mov 	ebp, [u.namep]
  3894                              <1> trans_addr_nm:
  3895                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3896                              <1> 	; Convert virtual (pathname) address to physical address
  3897                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3898                              <1> 	; 18/10/2015
  3899                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3900                              <1> 	; 02/07/2015
  3901                              <1> 	; 17/06/2015
  3902                              <1> 	; 16/06/2015
  3903                              <1> 	;
  3904                              <1> 	; INPUTS: 
  3905                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3906                              <1> 	;	[u.pgdir] = user's page directory
  3907                              <1> 	; OUTPUT:
  3908                              <1> 	;       esi = physical address of the pathname
  3909                              <1> 	;	ecx = remain byte count in the page
  3910                              <1> 	;
  3911                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3912                              <1> 	;
  3913                              <1> 
  3914                              <1> 	; 08/01/2022
  3915 00004262 29C9                <1> 	sub	ecx, ecx
  3916                              <1> 	;
  3917 00004264 833D[59660000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3918 0000426B 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3919                              <1> 				     ; it is already physical address
  3920 0000426D 50                  <1>    	push	eax	
  3921 0000426E 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3922 00004270 E83AE6FFFF          <1>        	call	get_physical_addr ; get physical address
  3923 00004275 7204                <1> 	jc	short tr_addr_nm_err
  3924                              <1> 	; 18/10/2015
  3925                              <1> 	; eax = physical address 
  3926                              <1> 	; cx = remain byte count in page (1-4096) 
  3927                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3928 00004277 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3929 00004279 58                  <1> 	pop	eax 
  3930 0000427A C3                  <1> 	retn
  3931                              <1> 
  3932                              <1> tr_addr_nm_err:
  3933 0000427B A3[51660000]        <1> 	mov	[u.error], eax
  3934                              <1> 	;pop 	eax
  3935 00004280 E94CEFFFFF          <1> 	jmp	error
  3936                              <1> 
  3937                              <1> trans_addr_nmk:
  3938                              <1> 	; 12/10/2015
  3939                              <1> 	; 02/07/2015
  3940 00004285 8B35[14660000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3941                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3942                              <1> 	; 08/01/2022
  3943 0000428B B510                <1> 	mov	ch, PAGE_SIZE/256
  3944 0000428D C3                  <1> 	retn
  3945                              <1> 
  3946                              <1> syschdir:
  3947                              <1> 	; / makes the directory specified in the argument
  3948                              <1> 	; / the current directory
  3949                              <1> 	;
  3950                              <1> 	; 09/01/2022
  3951                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3952                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3953                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3954                              <1> 	;
  3955                              <1> 	; 'syschdir' makes the directory specified in its argument
  3956                              <1> 	; the current working directory.
  3957                              <1> 	;
  3958                              <1> 	; Calling sequence:
  3959                              <1> 	;	syschdir; name
  3960                              <1> 	; Arguments:
  3961                              <1> 	;	name - address of the path name of a directory
  3962                              <1> 	;	       terminated by nul byte.	
  3963                              <1> 	; Inputs: -
  3964                              <1> 	; Outputs: -
  3965                              <1> 	; ...............................................................
  3966                              <1> 	;				
  3967                              <1> 	; Retro UNIX 8086 v1 modification:
  3968                              <1> 	;	 The user/application program puts address of 
  3969                              <1> 	;	 the path name in BX register as 'syschdir' 
  3970                              <1> 	; 	 system call argument.
  3971                              <1> 
  3972 0000428E 891D[14660000]      <1> 	mov	[u.namep], ebx
  3973                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3974 00004294 E844FEFFFF          <1> 	call	namei
  3975                              <1> 		; jsr r0,namei / find its i-number
  3976                              <1> 	;jc	error
  3977                              <1> 		; br error3
  3978 00004299 730F                <1> 	jnc	short syschdir0
  3979                              <1> 	; 'directory not found !' error
  3980 0000429B C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3980 000042A3 0000                <1>
  3981 000042A5 E927EFFFFF          <1> 	jmp	error
  3982                              <1> syschdir0:
  3983                              <1> 	; 08/01/2022
  3984 000042AA B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3985 000042AC E810070000          <1> 	call	access
  3986                              <1> 		; jsr r0,access; 2 / get i-node into core
  3987                              <1> 	; 08/01/2022
  3988 000042B1 F605[F5620000]40    <1> 	test	byte [i.flgs+1], 40h
  3989                              <1> 	;test	word [i.flgs], 4000h
  3990                              <1> 		; bit $40000,i.flgs / is it a directory?
  3991                              <1> 	;jz	error 
  3992                              <1> 		; beq error3 / no error
  3993 000042B8 750F                <1> 	jnz	short syschdir1
  3994 000042BA C705[51660000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3994 000042C2 0000                <1>
  3995 000042C4 E908EFFFFF          <1> 	jmp	error
  3996                              <1> syschdir1:
  3997 000042C9 66A3[00660000]      <1> 	mov	[u.cdir], ax
  3998                              <1> 		; mov r1,u.cdir / move i-number to users 
  3999                              <1> 			      ; / current directory
  4000                              <1> 	; 09/01/2022
  4001 000042CF A0[E3650000]        <1> 	mov	al, [cdev]
  4002 000042D4 A2[46660000]        <1> 	mov	[u.cdrv], al
  4003                              <1> 	;mov	ax, [cdev]
  4004                              <1> 	;mov	[u.cdrv], ax
  4005                              <1> 		; mov cdev,u.cdev / move its device to users 
  4006                              <1> 			        ; / current device
  4007 000042D9 E913EFFFFF          <1> 	jmp	sysret
  4008                              <1> 		; br sysret3
  4009                              <1> 
  4010                              <1> syschmod: ; < change mode of file >
  4011                              <1> 	; 29/04/2022 (bugfix)
  4012                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4013                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4014                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4015                              <1> 	;
  4016                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4017                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4018                              <1> 	; changed to 'mode'.
  4019                              <1> 	;
  4020                              <1> 	; Calling sequence:
  4021                              <1> 	;	syschmod; name; mode
  4022                              <1> 	; Arguments:
  4023                              <1> 	;	name - address of the file name
  4024                              <1> 	;	       terminated by null byte.
  4025                              <1> 	;	mode - (new) mode/flags < attributes >
  4026                              <1> 	;	
  4027                              <1> 	; Inputs: -
  4028                              <1> 	; Outputs: -
  4029                              <1> 	; ...............................................................
  4030                              <1> 	;				
  4031                              <1> 	; Retro UNIX 8086 v1 modification: 
  4032                              <1> 	;       'syschmod' system call has two arguments; so,
  4033                              <1> 	;	* 1st argument, name is pointed to by BX register
  4034                              <1> 	;	* 2nd argument, mode is in CX register
  4035                              <1> 	;
  4036                              <1> 	; Mode bits (Flags):
  4037                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  4038                              <1> 	;	bit 14 - directory flag (4000h)
  4039                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  4040                              <1> 	;	bit 12 - large file flag (1000h)
  4041                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4042                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  4043                              <1> 	;	bit 4 - executable flag (10h)
  4044                              <1> 	;	bit 3 - read permission for owner (08h)
  4045                              <1> 	;	bit 2 - write permission for owner (04h)
  4046                              <1> 	;	bit 1 - read permission for non-owner (02h)
  4047                              <1> 	;	bit 0 - write permission for non-owner (01h)
  4048                              <1> 
  4049                              <1> 	; / name; mode
  4050 000042DE E815000000          <1> 	call	isown
  4051                              <1> 		;jsr r0,isown / get the i-node and check user status
  4052                              <1> 	; 09/01/2022
  4053 000042E3 F605[F5620000]40    <1> 	test	byte [i.flgs+1], 40h
  4054                              <1> 	;test	word [i.flgs], 4000h
  4055                              <1> 		; bit $40000,i.flgs / directory?
  4056 000042EA 7402                <1> 	jz	short syschmod1
  4057                              <1> 		; beq 2f / no
  4058                              <1> 	; AL = (new) mode
  4059 000042EC 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4060                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  4061                              <1> 			   ; / executable modes
  4062                              <1> syschmod1: ; 2:
  4063 000042EE A2[F4620000]        <1> 	mov	[i.flgs], al	
  4064                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  4065                              <1> 	;jmp	short isown1
  4066                              <1> 	;	; br 1f ; (jmp sysret4)
  4067                              <1> 	; 29/04/2022
  4068 000042F3 E9F9EEFFFF          <1> 	jmp	sysret
  4069                              <1> 
  4070                              <1> isown:
  4071                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4072                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4073                              <1> 	;
  4074                              <1> 	; 'isown' is given a file name (the 1st argument).
  4075                              <1> 	;  It find the i-number of that file via 'namei' 
  4076                              <1> 	;  then gets the i-node into core via 'iget'.
  4077                              <1> 	;  It then tests to see if the user is super user. 
  4078                              <1> 	;  If not, it cheks to see if the user is owner of 
  4079                              <1> 	;  the file. If he is not an error occurs.
  4080                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4081                              <1> 	;  the inode has been modified and the 2nd argument of
  4082                              <1> 	;  the call is put in r2.
  4083                              <1> 	;
  4084                              <1> 	; INPUTS ->
  4085                              <1> 	;    arguments of syschmod and syschown calls
  4086                              <1> 	; OUTPUTS ->
  4087                              <1> 	;    u.uid - id of user
  4088                              <1> 	;    imod - set to a 1
  4089                              <1> 	;    r2 - contains second argument of the system call				 	
  4090                              <1> 	;
  4091                              <1> 	;   ((AX=R2) output as 2nd argument)
  4092                              <1> 	;
  4093                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4094                              <1> 	;
  4095                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4096                              <1> 	;; ! 2nd argument on top of stack !
  4097                              <1> 	;; 22/06/2015 - 32 bit modifications
  4098                              <1> 	;; 07/07/2013
  4099 000042F8 891D[14660000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4100 000042FE 51                  <1> 	push 	ecx ;; 2nd argument
  4101                              <1> 	;;
  4102 000042FF E8D9FDFFFF          <1> 	call	namei
  4103                              <1> 		; jsr r0,namei / get its i-number
  4104                              <1>        ; Retro UNIX 8086 v1 modification !
  4105                              <1>        ; ax = 0 -> file not found 
  4106                              <1> 	;and	ax, ax
  4107                              <1> 	;jz	error
  4108                              <1> 	;jc	error ; 27/05/2013
  4109                              <1> 		; br error3
  4110 00004304 730F                <1> 	jnc	short isown0
  4111                              <1> 	; 'file not found !' error
  4112 00004306 C705[51660000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4112 0000430E 0000                <1>
  4113 00004310 E9BCEEFFFF          <1> 	jmp	error
  4114                              <1> isown0:
  4115 00004315 E8D3050000          <1> 	call	iget
  4116                              <1> 		; jsr r0,iget / get i-node into core
  4117 0000431A A0[48660000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4118 0000431F 08C0                <1> 	or	al, al
  4119                              <1> 		; tstb u.uid / super user?
  4120 00004321 7417                <1> 	jz	short isown1
  4121                              <1> 		; beq 1f / yes, branch
  4122 00004323 3A05[F7620000]      <1> 	cmp	al, [i.uid]
  4123                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4124                              <1> 				 ; / the file
  4125                              <1> 	;jne	error
  4126                              <1> 		; beq 1f / yes
  4127                              <1> 		; jmp error3 / no, error
  4128 00004329 740F                <1> 	je	short isown1
  4129                              <1> 
  4130 0000432B C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4130 00004333 0000                <1>
  4131                              <1> 			;  'permission denied !' error
  4132 00004335 E997EEFFFF          <1> 	jmp	error
  4133                              <1> isown1: ; 1:
  4134 0000433A E8B8060000          <1> 	call	setimod
  4135                              <1> 		; jsr r0,setimod / indicates 
  4136                              <1> 		;	       ; / i-node has been modified
  4137 0000433F 58                  <1> 	pop	eax ; 2nd argument
  4138                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4139                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4140 00004340 C3                  <1> 	retn
  4141                              <1> 		; rts r0
  4142                              <1> 
  4143                              <1> ;;arg:  ; < get system call arguments >
  4144                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4145                              <1> 	; of form:
  4146                              <1> 	;	sys 'routine' ; arg1
  4147                              <1> 	;		or
  4148                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4149                              <1> 	;		or
  4150                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4151                              <1> 	;	
  4152                              <1> 	; INPUTS ->
  4153                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4154                              <1> 	;	This pointers's value is actually the value of
  4155                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4156                              <1> 	;	made to process the sys instruction
  4157                              <1> 	;    r0 - contains the return address for the routine
  4158                              <1> 	;	that called arg. The data in the word pointer 
  4159                              <1> 	;	to by the return address is used as address
  4160                              <1> 	;	in which the extracted argument is stored   		
  4161                              <1> 	;    	
  4162                              <1> 	; OUTPUTS ->
  4163                              <1> 	;    'address' - contains the extracted argument 
  4164                              <1> 	;    u.sp+18 - is incremented by 2 
  4165                              <1> 	;    r1 - contains the extracted argument
  4166                              <1> 	;    r0 - points to the next instruction to be
  4167                              <1> 	;	 executed in the calling routine.
  4168                              <1> 	;
  4169                              <1>   
  4170                              <1> 	; mov u.sp,r1
  4171                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4172                              <1> 			; / into argument of arg2
  4173                              <1> 	; add $2,18.(r1) / point pc on stack 
  4174                              <1> 			      ; / to next system argument
  4175                              <1> 	; rts r0
  4176                              <1> 
  4177                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4178                              <1> 	; 'arg2' takes first argument in system call
  4179                              <1> 	;  (pointer to name of the file) and puts it in location
  4180                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4181                              <1> 	;  and on top of the stack
  4182                              <1> 	;	
  4183                              <1> 	; INPUTS ->
  4184                              <1> 	;    u.sp, r0
  4185                              <1> 	;    	
  4186                              <1> 	; OUTPUTS ->
  4187                              <1> 	;    u.namep
  4188                              <1> 	;    u.off 
  4189                              <1> 	;    u.off pushed on stack
  4190                              <1> 	;    r1
  4191                              <1> 	;
  4192                              <1> 
  4193                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4194                              <1> 				; / first arg in sys call
  4195                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4196                              <1> 				; / second arg in sys call
  4197                              <1> 	; mov r0,r1 / r0 points to calling routine
  4198                              <1> 	; mov (sp),r0 / put operation code back in r0
  4199                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4200                              <1> 			; / on stack
  4201                              <1> 	; jmp (r1) / return to calling routine
  4202                              <1> 
  4203                              <1> syschown: ; < change owner of file >
  4204                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4205                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4206                              <1> 	;
  4207                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4208                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4209                              <1> 	; changed to 'owner'
  4210                              <1> 	;
  4211                              <1> 	; Calling sequence:
  4212                              <1> 	;	syschown; name; owner
  4213                              <1> 	; Arguments:
  4214                              <1> 	;	name - address of the file name
  4215                              <1> 	;	       terminated by null byte.
  4216                              <1> 	;	owner - (new) owner (number/ID)
  4217                              <1> 	;	
  4218                              <1> 	; Inputs: -
  4219                              <1> 	; Outputs: -
  4220                              <1> 	; ...............................................................
  4221                              <1> 	;				
  4222                              <1> 	; Retro UNIX 8086 v1 modification: 
  4223                              <1> 	;       'syschown' system call has two arguments; so,
  4224                              <1> 	;	* 1st argument, name is pointed to by BX register
  4225                              <1> 	;	* 2nd argument, owner number is in CX register
  4226                              <1> 	;
  4227                              <1> 	; / name; owner
  4228 00004341 E8B2FFFFFF          <1> 	call	isown
  4229                              <1> 		; jsr r0,isown / get the i-node and check user status
  4230 00004346 803D[48660000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4231                              <1> 		; tstb u.uid / super user
  4232 0000434D 7418                <1> 	jz	short syschown1
  4233                              <1> 		; beq 2f / yes, 2f
  4234 0000434F F605[F4620000]20    <1>         test    byte [i.flgs], 20h ; 32
  4235                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4236                              <1> 	;jnz	error
  4237                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4238 00004356 740F                <1> 	jz	short syschown1
  4239                              <1> 	; 'permission denied !'
  4240 00004358 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4240 00004360 0000                <1>
  4241 00004362 E96AEEFFFF          <1> 	jmp	error
  4242                              <1> syschown1: ; 2:
  4243                              <1> 	; AL = owner (number/ID)
  4244 00004367 A2[F7620000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4245                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4246                              <1> 			       ; / in the i-node
  4247 0000436C E980EEFFFF          <1> 	jmp	sysret
  4248                              <1> 	; 1: 
  4249                              <1> 		; jmp sysret4
  4250                              <1> 	; 3:
  4251                              <1> 		; jmp	error
  4252                              <1> 
  4253                              <1> systime: ; / get time of year
  4254                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4255                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4256                              <1> 	;
  4257                              <1> 	; 20/06/2013
  4258                              <1> 	; 'systime' gets the time of the year.
  4259                              <1> 	; The present time is put on the stack.
  4260                              <1> 	;
  4261                              <1> 	; Calling sequence:
  4262                              <1> 	;	systime
  4263                              <1> 	; Arguments: -
  4264                              <1> 	;	
  4265                              <1> 	; Inputs: -
  4266                              <1> 	; Outputs: sp+2, sp+4 - present time
  4267                              <1> 	; ...............................................................
  4268                              <1> 	;	
  4269                              <1> 	; Retro UNIX 8086 v1 modification: 
  4270                              <1> 	;       'systime' system call will return to the user
  4271                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4272                              <1> 	;
  4273                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4274                              <1> 	;	system call for PC compatibility !!		 	
  4275                              <1> 
  4276 00004371 E8ACE9FFFF          <1> 	call 	epoch
  4277 00004376 A3[FC650000]        <1> 	mov 	[u.r0], eax
  4278                              <1> 		; mov s.time,4(sp)
  4279                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4280                              <1> 				   ; / on the stack
  4281                              <1> 		; br sysret4
  4282 0000437B E971EEFFFF          <1> 	jmp	sysret 
  4283                              <1> 
  4284                              <1> sysstime: ; / set time
  4285                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4286                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4287                              <1> 	;
  4288                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4289                              <1> 	;
  4290                              <1> 	; Calling sequence:
  4291                              <1> 	;	sysstime
  4292                              <1> 	; Arguments: -
  4293                              <1> 	;	
  4294                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4295                              <1> 	; Outputs: -
  4296                              <1> 	; ...............................................................
  4297                              <1> 	;	
  4298                              <1> 	; Retro UNIX 8086 v1 modification: 
  4299                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4300                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4301                              <1> 	; 
  4302                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4303                              <1> 	;	to get sysstime system call arguments from the user;
  4304                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4305                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4306                              <1> 	;
  4307                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4308                              <1> 	;	system call for PC compatibility !!	
  4309                              <1> 
  4310 00004380 803D[48660000]00    <1> 	cmp	byte [u.uid], 0
  4311                              <1> 		; tstb u.uid / is user the super user
  4312                              <1> 	;ja	error
  4313                              <1> 		; bne error4 / no, error
  4314 00004387 760F                <1> 	jna	short systime1
  4315                              <1> 	; 'permission denied !'
  4316 00004389 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4316 00004391 0000                <1>
  4317 00004393 E939EEFFFF          <1> 	jmp	error
  4318                              <1> systime1:
  4319                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4320                              <1> 	; EBX = unix (epoch) time (from user)
  4321 00004398 89D8                <1> 	mov	eax, ebx
  4322 0000439A E800EBFFFF          <1> 	call 	set_date_time
  4323                              <1> 		; mov 4(sp),s.time
  4324                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4325 0000439F E94DEEFFFF          <1> 	jmp	sysret
  4326                              <1> 		; br sysret4
  4327                              <1> 
  4328                              <1> sysbreak:
  4329                              <1> 	; 18/10/2015
  4330                              <1> 	; 07/10/2015
  4331                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4332                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4333                              <1> 	;
  4334                              <1> 	; 'sysbreak' sets the programs break points. 
  4335                              <1> 	; It checks the current break point (u.break) to see if it is
  4336                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4337                              <1> 	; even address (if it was odd) and the area between u.break
  4338                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4339                              <1> 	; in u.break and control is passed to 'sysret'.
  4340                              <1> 	;
  4341                              <1> 	; Calling sequence:
  4342                              <1> 	;	sysbreak; addr
  4343                              <1> 	; Arguments: -
  4344                              <1> 	;	
  4345                              <1> 	; Inputs: u.break - current breakpoint
  4346                              <1> 	; Outputs: u.break - new breakpoint 
  4347                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4348                              <1> 	; ...............................................................
  4349                              <1> 	;	
  4350                              <1> 	; Retro UNIX 8086 v1 modification:
  4351                              <1> 	;	The user/application program puts breakpoint address
  4352                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4353                              <1> 	; 	(argument transfer method 1)
  4354                              <1> 	;
  4355                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4356                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4357                              <1> 	;  NOTE:
  4358                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4359                              <1> 	;	'u.break' address) of user's memory for original unix's
  4360                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4361                              <1> 
  4362                              <1> 		; mov u.break,r1 / move users break point to r1
  4363                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4364                              <1> 		; blos 1f / yes, 1f
  4365                              <1> 	; 23/06/2015
  4366 000043A4 8B2D[28660000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4367                              <1> 	;and	ebp, ebp
  4368                              <1> 	;jz	short sysbreak_3 
  4369                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4370                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4371 000043AA 8B15[F4650000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4372 000043B0 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4373                              <1> 	; 07/10/2015
  4374 000043B3 891D[28660000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4375                              <1> 	;
  4376 000043B9 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4377                              <1> 			   ; with top of user's stack (virtual!)
  4378 000043BB 7327                <1> 	jnb	short sysbreak_3
  4379                              <1> 		; cmp r1,sp / is it the same or higher 
  4380                              <1> 			  ; / than the stack?
  4381                              <1> 		; bhis 1f / yes, 1f
  4382 000043BD 89DE                <1> 	mov	esi, ebx
  4383 000043BF 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4384 000043C1 7621                <1> 	jna	short sysbreak_3 
  4385                              <1> 	;push	ebx
  4386                              <1> sysbreak_1:
  4387 000043C3 89EB                <1> 	mov	ebx, ebp  
  4388 000043C5 E8E5E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4389 000043CA 0F82ABFEFFFF        <1> 	jc	tr_addr_nm_err
  4390                              <1> 	; 18/10/2015
  4391 000043D0 89C7                <1> 	mov	edi, eax 
  4392 000043D2 29C0                <1> 	sub	eax, eax ; 0
  4393                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4394 000043D4 39CE                <1> 	cmp	esi, ecx
  4395 000043D6 7302                <1> 	jnb	short sysbreak_2
  4396 000043D8 89F1                <1> 	mov	ecx, esi
  4397                              <1> sysbreak_2:
  4398 000043DA 29CE                <1> 	sub	esi, ecx
  4399 000043DC 01CD                <1> 	add	ebp, ecx
  4400 000043DE F3AA                <1> 	rep 	stosb
  4401 000043E0 09F6                <1> 	or	esi, esi
  4402 000043E2 75DF                <1> 	jnz	short sysbreak_1
  4403                              <1> 	;
  4404                              <1> 		; bit $1,r1 / is it an odd address
  4405                              <1> 		; beq 2f / no, its even
  4406                              <1> 		; clrb (r1)+ / yes, make it even
  4407                              <1> 	; 2: / clear area between the break point and the stack
  4408                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4409                              <1> 		; bhis 1f / yes, quit
  4410                              <1> 		; clr (r1)+ / clear word
  4411                              <1> 		; br 2b / go back
  4412                              <1> 	;pop	ebx
  4413                              <1> sysbreak_3: ; 1:
  4414                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4415                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4416                              <1> 			; / in u.break (set new break point)
  4417                              <1> 		; br sysret4 / br sysret
  4418 000043E4 E908EEFFFF          <1> 	jmp	sysret
  4419                              <1> 
  4420                              <1> maknod: 
  4421                              <1> 	; 11/02/2022
  4422                              <1> 	; 09/01/2022
  4423                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4424                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4425                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4426                              <1> 	;
  4427                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4428                              <1> 	; for this i-node in the current directory.
  4429                              <1> 	;
  4430                              <1> 	; INPUTS ->
  4431                              <1> 	;    r1 - contains mode
  4432                              <1> 	;    ii - current directory's i-number	
  4433                              <1> 	;    	
  4434                              <1> 	; OUTPUTS ->
  4435                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4436                              <1> 	;    i.flgs - flags in new i-node 
  4437                              <1> 	;    i.uid - filled with u.uid
  4438                              <1> 	;    i.nlks - 1 is put in the number of links
  4439                              <1> 	;    i.ctim - creation time				
  4440                              <1> 	;    i.ctim+2 - modification time
  4441                              <1> 	;    imod - set via call to setimod
  4442                              <1> 	;	
  4443                              <1> 	; ((AX = R1)) input
  4444                              <1> 	;
  4445                              <1> 	; (Retro UNIX Prototype : 
  4446                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4447                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4448                              <1> 
  4449                              <1> 	; / r1 contains the mode
  4450 000043E9 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4451                              <1> 		; bis $100000,r1 / allocate flag set
  4452 000043EC 6650                <1> 	push	ax ; * ; 24/12/2021
  4453                              <1> 		; mov r1,-(sp) / put mode on stack
  4454                              <1> 	; 31/07/2013
  4455 000043EE 66A1[E0650000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4456                              <1> 		; mov ii,r1 / move current i-number to r1
  4457 000043F4 B201                <1> 	mov	dl, 1 ; owner flag mask
  4458 000043F6 E8C6050000          <1> 	call	access	
  4459                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4460 000043FB 50                  <1> 	push	eax ; ** ; 24/12/2021
  4461                              <1> 		; mov r1,-(sp) / put i-number on stack
  4462 000043FC 66B82800            <1> 	mov	ax, 40
  4463                              <1> 		; mov $40.,r1 / r1 = 40
  4464                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4465 00004400 6640                <1> 	inc	ax
  4466                              <1> 		; inc r1 / r1 = r1 + 1
  4467 00004402 E87F060000          <1> 	call	imap
  4468                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4469                              <1> 			    ; /	inode map in r2 & m
  4470                              <1>   
  4471                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4472                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4473                              <1> 
  4474                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4475                              <1> 	;	       Inode count must be checked here
  4476                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4477                              <1> 
  4478                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4479                              <1> 	; (inode count check)
  4480                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4481                              <1> 
  4482 00004407 730F                <1> 	jnc	short maknod2
  4483                              <1> 
  4484                              <1> 	; no free inode in inode table !
  4485 00004409 C705[51660000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4485 00004411 0000                <1>
  4486                              <1> 			; miscellaneous/other errors
  4487 00004413 E9B9EDFFFF          <1> 	jmp	error	
  4488                              <1> maknod2: 
  4489 00004418 8413                <1> 	test	[ebx], dl
  4490                              <1> 		; bitb mq,(r2) / is the i-node active
  4491 0000441A 75E4                <1> 	jnz	short maknod1
  4492                              <1> 		; bne 1b / yes, try the next one
  4493 0000441C 0813                <1> 	or	[ebx], dl
  4494                              <1> 		; bisb mq,(r2) / no, make it active 
  4495                              <1> 			     ; / (put a 1 in the bit map)
  4496 0000441E E8CA040000          <1> 	call	iget
  4497                              <1> 		; jsr r0,iget / get i-node into core
  4498                              <1> 	; 09/01/2022
  4499 00004423 F605[F5620000]80    <1> 	test	byte [i.flgs+1], 80h
  4500                              <1> 	;test	word [i.flgs], 8000h 
  4501                              <1> 		; tst i.flgs / is i-node already allocated
  4502 0000442A 75D4                <1> 	jnz	short maknod1	
  4503                              <1> 		; blt 1b / yes, look for another one
  4504 0000442C 66A3[2E660000]      <1> 	mov	[u.dirbuf], ax
  4505                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4506 00004432 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4507                              <1> 		; mov (sp)+,r1 / get current i-number back
  4508 00004433 E8B5040000          <1> 	call	iget
  4509                              <1> 		; jsr r0,iget / get i-node in core
  4510 00004438 E857F7FFFF          <1> 	call	mkdir
  4511                              <1> 		; jsr r0,mkdir / make a directory entry 
  4512                              <1> 			     ; / in current directory
  4513 0000443D 66A1[2E660000]      <1> 	mov	ax, [u.dirbuf]
  4514                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4515 00004443 E8A5040000          <1> 	call	iget
  4516                              <1> 		; jsr r0,iget / get it into core
  4517                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4518                              <1> 	;mov	ecx, 8
  4519                              <1> 	; 09/01/2022 
  4520 00004448 29C9                <1> 	sub	ecx, ecx
  4521 0000444A B108                <1> 	mov	cl, 8
  4522 0000444C 31C0                <1> 	xor	eax, eax ; 0
  4523 0000444E BF[F4620000]        <1> 	mov	edi, inode 
  4524 00004453 F3AB                <1> 	rep	stosd
  4525                              <1> 	;
  4526 00004455 668F05[F4620000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4527                              <1> 		; mov (sp)+,i.flgs / fill flags
  4528 0000445C 8A0D[48660000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4529 00004462 880D[F7620000]      <1> 	mov 	[i.uid], cl
  4530                              <1> 		; movb u.uid,i.uid / user id	
  4531 00004468 C605[F6620000]01    <1> 	mov     byte [i.nlks], 1
  4532                              <1> 		; movb $1,i.nlks / 1 link
  4533                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4534                              <1> 	;mov	eax, [s.time]
  4535                              <1> 	;mov 	[i.ctim], eax
  4536                              <1> 	 	; mov s.time,i.ctim / time created
  4537                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4538                              <1> 	; Retro UNIX 8086 v1 modification !
  4539                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4540                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4541                              <1> 	;call	setimod
  4542                              <1> 	;	; jsr r0,setimod / set modified flag
  4543                              <1> 	;retn
  4544                              <1> 	;	; rts r0 / return
  4545                              <1> 	; 24/12/2021
  4546 0000446F E983050000          <1> 	jmp	setimod
  4547                              <1> 
  4548                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4549                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4550                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4551                              <1> 	;
  4552                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4553                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4554                              <1> 	; The file descriptor refers to a file open for reading or
  4555                              <1> 	; writing. The read (or write) pointer is set as follows:
  4556                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4557                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4558                              <1> 	;	  current location plus offset.
  4559                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4560                              <1> 	;	  size of file plus offset.
  4561                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4562                              <1> 	;
  4563                              <1> 	; Calling sequence:
  4564                              <1> 	;	sysseek; offset; ptrname
  4565                              <1> 	; Arguments:
  4566                              <1> 	;	offset - number of bytes desired to move 
  4567                              <1> 	;		 the r/w pointer
  4568                              <1> 	;	ptrname - a switch indicated above
  4569                              <1> 	;
  4570                              <1> 	; Inputs: r0 - file descriptor 
  4571                              <1> 	; Outputs: -
  4572                              <1> 	; ...............................................................
  4573                              <1> 	;	
  4574                              <1> 	; Retro UNIX 8086 v1 modification: 
  4575                              <1> 	;       'sysseek' system call has three arguments; so,
  4576                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4577                              <1> 	;	* 2nd argument, offset is in CX register
  4578                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4579                              <1> 	;	
  4580                              <1> 
  4581 00004474 E822000000          <1> 	call	seektell
  4582                              <1> 	; AX = u.count
  4583                              <1> 	; BX = *u.fofp
  4584                              <1> 		; jsr r0,seektell / get proper value in u.count
  4585                              <1> 		; add u.base,u.count / add u.base to it
  4586 00004479 0305[1C660000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4587 0000447F 8903                <1> 	mov	[ebx], eax
  4588                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4589 00004481 E96BEDFFFF          <1> 	jmp	sysret
  4590                              <1> 		; br sysret4
  4591                              <1> 
  4592                              <1> systell: ; / get the r/w pointer
  4593                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4594                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4595                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4596                              <1> 	;
  4597                              <1> 	; Retro UNIX 8086 v1 modification:
  4598                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4599                              <1> 	; 	    it returns with error !
  4600                              <1> 	; Inputs: r0 - file descriptor 
  4601                              <1> 	; Outputs: r0 - file r/w pointer
  4602                              <1> 
  4603                              <1> 	;xor	ecx, ecx ; 0
  4604                              <1> 	;mov	edx, 1 ; 05/08/2013
  4605                              <1> 	; 24/12/2021
  4606 00004486 29D2                <1> 	sub	edx, edx
  4607 00004488 FEC2                <1> 	inc	dl
  4608                              <1> 	; edx = 1
  4609                              <1> 	;call 	seektell
  4610 0000448A E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4611                              <1> 	;mov	ebx, [u.fofp]
  4612 0000448F 8B03                <1> 	mov	eax, [ebx]
  4613 00004491 A3[FC650000]        <1> 	mov	[u.r0], eax
  4614 00004496 E956EDFFFF          <1> 	jmp	sysret
  4615                              <1> 
  4616                              <1> ; Original unix v1 'systell' system call:
  4617                              <1> 		; jsr r0,seektell
  4618                              <1> 		; br error4
  4619                              <1> 
  4620                              <1> seektell:
  4621                              <1> 	; 03/02/2022
  4622                              <1> 	; 03/01/2016
  4623                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4624                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4625                              <1> 	;
  4626                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4627                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4628                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4629                              <1> 	; getf. The i-node is brought into core and then u.count
  4630                              <1> 	; is checked to see it is a 0, 1, or 2.
  4631                              <1> 	; If it is 0 - u.count stays the same
  4632                              <1> 	;          1 - u.count = offset (u.fofp)
  4633                              <1> 	;	   2 - u.count = i.size (size of file)
  4634                              <1> 	; 	 		
  4635                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4636                              <1> 	;	Argument 1, file descriptor is in BX;
  4637                              <1> 	;	Argument 2, offset is in CX;
  4638                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4639                              <1> 	;
  4640                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4641                              <1> 	; call 	arg
  4642                              <1> 	;
  4643                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4644                              <1> 	;
  4645 0000449B 890D[1C660000]      <1> 	mov 	[u.base], ecx ; offset
  4646                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4647                              <1> seektell0:
  4648 000044A1 8915[20660000]      <1> 	mov 	[u.count], edx
  4649                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4650                              <1> 	; mov	ax, bx
  4651                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4652                              <1> 			     ; / (index in u.fp list)
  4653                              <1> 	; call	getf
  4654                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4655                              <1> 	; BX = file descriptor (file number)
  4656 000044A7 E800FCFFFF          <1> 	call	getf1
  4657                              <1> 	; 03/02/2022
  4658 000044AC 09C0                <1> 	or	eax, eax
  4659                              <1> 	;or	ax, ax ; i-number of the file
  4660                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4661                              <1> 		             ; / put it on the stack
  4662                              <1> 	;jz	error
  4663                              <1> 		; beq error4 / if i-number is 0, not active so error
  4664 000044AE 750F                <1> 	jnz	short seektell1
  4665 000044B0 C705[51660000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4665 000044B8 0000                <1>
  4666 000044BA E912EDFFFF          <1> 	jmp	error
  4667                              <1> seektell1:
  4668                              <1> 	;push	eax
  4669 000044BF 80FC80              <1> 	cmp	ah, 80h
  4670 000044C2 7203                <1> 	jb	short seektell2
  4671                              <1> 		; bgt .+4 / if its positive jump
  4672 000044C4 66F7D8              <1> 	neg	ax
  4673                              <1> 		; neg r1 / if not make it positive
  4674                              <1> seektell2:
  4675 000044C7 E821040000          <1> 	call	iget
  4676                              <1> 		; jsr r0,iget / get its i-node into core
  4677 000044CC 8B1D[0C660000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4678 000044D2 803D[20660000]01    <1> 	cmp	byte [u.count], 1
  4679                              <1> 		; cmp u.count,$1 / is ptr name =1
  4680 000044D9 7705                <1> 	ja	short seektell3
  4681                              <1> 		; blt 2f / no its zero
  4682 000044DB 740A                <1> 	je	short seektell_4
  4683                              <1> 		; beq 1f / yes its 1
  4684 000044DD 31C0                <1> 	xor	eax, eax
  4685                              <1> 	;jmp	short seektell_5
  4686 000044DF C3                  <1> 	retn
  4687                              <1> seektell3:
  4688                              <1> 	; 03/01/2016
  4689                              <1> 	;movzx	eax, word [i.size]
  4690 000044E0 66A1[F8620000]      <1>         mov   	ax, [i.size]
  4691                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4692                              <1>                                    ; / in file in u.count
  4693                              <1> 	;jmp	short seektell_5
  4694                              <1> 		; br 2f
  4695 000044E6 C3                  <1> 	retn
  4696                              <1> seektell_4: ; 1: / ptrname =1
  4697                              <1> 	;mov	ebx, [u.fofp]
  4698 000044E7 8B03                <1> 	mov	eax, [ebx]
  4699                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4700                              <1> ;seektell_5: ; 2: / ptrname =0
  4701                              <1> 	;mov	[u.count], eax
  4702                              <1> 	;pop	eax 
  4703                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4704 000044E9 C3                  <1> 	retn
  4705                              <1> 		; rts r0
  4706                              <1> 
  4707                              <1> sysintr: ; / set interrupt handling
  4708                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4709                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4710                              <1> 	;
  4711                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4712                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4713                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4714                              <1> 	; If one does the interrupt character in the tty buffer is
  4715                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4716                              <1> 	; 'sysret' is just called.	
  4717                              <1> 	;
  4718                              <1> 	; Calling sequence:
  4719                              <1> 	;	sysintr; arg
  4720                              <1> 	; Argument:
  4721                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4722                              <1> 	;	    - if 1, intterupts cause their normal result
  4723                              <1> 	;		 i.e force an exit.
  4724                              <1> 	;	    - if arg is a location within the program,
  4725                              <1> 	;		control is passed to that location when
  4726                              <1> 	;		an interrupt occurs.	
  4727                              <1> 	; Inputs: -
  4728                              <1> 	; Outputs: -
  4729                              <1> 	; ...............................................................
  4730                              <1> 	;	
  4731                              <1> 	; Retro UNIX 8086 v1 modification: 
  4732                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4733                              <1> 	;	then branches into sysquit.
  4734                              <1> 	;
  4735 000044EA 66891D[40660000]    <1> 	mov	[u.intr], bx
  4736                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4737                              <1> 		; br 1f / go into quit routine
  4738 000044F1 E9FBECFFFF          <1> 	jmp	sysret
  4739                              <1> 
  4740                              <1> sysquit:
  4741                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4742                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4743                              <1> 	;
  4744                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4745                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4746                              <1> 	; tty exists. If one does the interrupt character in the tty
  4747                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4748                              <1> 	; 'sysret' is just called.	
  4749                              <1> 	;
  4750                              <1> 	; Calling sequence:
  4751                              <1> 	;	sysquit; arg
  4752                              <1> 	; Argument:
  4753                              <1> 	;	arg - if 0, this call diables quit signals from the
  4754                              <1> 	;		typewriter (ASCII FS)
  4755                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4756                              <1> 	;		cease and a core image to be produced.
  4757                              <1> 	;		 i.e force an exit.
  4758                              <1> 	;	    - if arg is an addres in the program,
  4759                              <1> 	;		a quit causes control to sent to that
  4760                              <1> 	;		location.	
  4761                              <1> 	; Inputs: -
  4762                              <1> 	; Outputs: -
  4763                              <1> 	; ...............................................................
  4764                              <1> 	;	
  4765                              <1> 	; Retro UNIX 8086 v1 modification: 
  4766                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4767                              <1> 	;	then branches into 'sysret'.
  4768                              <1> 	;
  4769 000044F6 66891D[42660000]    <1> 	mov	[u.quit], bx
  4770 000044FD E9EFECFFFF          <1> 	jmp	sysret
  4771                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4772                              <1> 	;1:
  4773                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4774                              <1> 			      ; / to r1
  4775                              <1> 		; beq sysret4 / return to user
  4776                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4777                              <1> 			   ; / in the tty buffer
  4778                              <1> 		; br sysret4 / return to user
  4779                              <1> 
  4780                              <1> syssetuid: ; / set process id
  4781                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4782                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4783                              <1> 	;
  4784                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4785                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4786                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4787                              <1> 	; Only the super user can make this call.	
  4788                              <1> 	;
  4789                              <1> 	; Calling sequence:
  4790                              <1> 	;	syssetuid
  4791                              <1> 	; Arguments: -
  4792                              <1> 	;
  4793                              <1> 	; Inputs: (u.r0) - contains the process id.
  4794                              <1> 	; Outputs: -
  4795                              <1> 	; ...............................................................
  4796                              <1> 	;	
  4797                              <1> 	; Retro UNIX 8086 v1 modification: 
  4798                              <1> 	;       BL contains the (new) user ID of the current process
  4799                              <1> 
  4800                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4801 00004502 3A1D[49660000]      <1> 	cmp	bl, [u.ruid] 
  4802                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4803                              <1> 			       ; / id number
  4804 00004508 741E                <1> 	je	short setuid1
  4805                              <1> 		; beq 1f / yes
  4806 0000450A 803D[48660000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4807                              <1> 		; tstb u.uid / no, is current user the super user?
  4808                              <1> 	;ja	error
  4809                              <1> 		; bne error4 / no, error
  4810 00004511 760F                <1> 	jna	short setuid0
  4811 00004513 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4811 0000451B 0000                <1>
  4812                              <1> 				; 'permission denied !' error
  4813 0000451D E9AFECFFFF          <1> 	jmp	error
  4814                              <1> setuid0:
  4815 00004522 881D[49660000]      <1> 	mov	[u.ruid], bl
  4816                              <1> setuid1: ; 1:
  4817 00004528 881D[48660000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4818                              <1> 		; movb r1,u.uid / put process id in u.uid
  4819                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4820 0000452E E9BEECFFFF          <1> 	jmp	sysret
  4821                              <1> 		; br sysret4 / system return
  4822                              <1> 
  4823                              <1> sysgetuid: ; < get user id >
  4824                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4825                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4826                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4827                              <1> 	;
  4828                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4829                              <1> 	; The real user ID identifies the person who is logged in,
  4830                              <1> 	; in contradistinction to the effective user ID, which
  4831                              <1> 	; determines his access permission at each moment. It is thus
  4832                              <1> 	; useful to programs which operate using the 'set user ID'
  4833                              <1> 	; mode, to find out who invoked them.	
  4834                              <1> 	;
  4835                              <1> 	; Calling sequence:
  4836                              <1> 	;	syssetuid
  4837                              <1> 	; Arguments: -
  4838                              <1> 	;
  4839                              <1> 	; Inputs: -
  4840                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4841                              <1> 	; ...............................................................
  4842                              <1> 	;	
  4843                              <1> 	; Retro UNIX 8086 v1 modification: 
  4844                              <1> 	;       AL contains the real user ID at return.
  4845                              <1> 	;
  4846                              <1> 	;movzx 	eax, byte [u.ruid]
  4847                              <1> 	; 09/01/2022
  4848 00004533 A0[49660000]        <1> 	mov	al, [u.ruid]
  4849 00004538 A3[FC650000]        <1> 	mov	[u.r0], eax
  4850                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4851 0000453D E9AFECFFFF          <1> 	jmp	sysret
  4852                              <1> 		; br sysret4 / systerm return, sysret
  4853                              <1> 
  4854                              <1> anyi: 
  4855                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4856                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4857                              <1> 	;
  4858                              <1> 	; 'anyi' is called if a file deleted while open.
  4859                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4860                              <1> 	;
  4861                              <1> 	; INPUTS ->
  4862                              <1> 	;    r1 - contains an i-number
  4863                              <1> 	;    fsp - start of table containing open files
  4864                              <1> 	;
  4865                              <1> 	; OUTPUTS ->
  4866                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4867                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4868                              <1> 	;    if file not found - bit in i-node map is cleared
  4869                              <1> 	;    			 (i-node is freed)
  4870                              <1> 	;               all blocks related to i-node are freed
  4871                              <1> 	;	        all flags in i-node are cleared
  4872                              <1> 	; ((AX = R1)) input
  4873                              <1> 	;
  4874                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4875                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4876                              <1> 	;
  4877                              <1> 		; / r1 contains an i-number
  4878 00004542 BB[C4630000]        <1> 	mov	ebx, fsp
  4879                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4880                              <1> anyi_1: ; 1:
  4881 00004547 663B03              <1> 	cmp	ax, [ebx]
  4882                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4883 0000454A 7433                <1> 	je	short anyi_3
  4884                              <1> 		; beq 1f / yes, 1f
  4885 0000454C 66F7D8              <1> 	neg	ax
  4886                              <1> 		; neg r1 / no complement r1
  4887 0000454F 663B03              <1> 	cmp	ax, [ebx]
  4888                              <1> 		; cmp r1,(r2) / do they match now?
  4889 00004552 742B                <1> 	je	short anyi_3
  4890                              <1> 		; beq 1f / yes, transfer
  4891                              <1> 		; / i-numbers do not match
  4892 00004554 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4893                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4894                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4895 00004557 81FB[B8650000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4896                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4897                              <1> 				; / are we at last entry in the table
  4898 0000455D 72E8                <1> 	jb	short anyi_1
  4899                              <1> 		; blt 1b / no, check next entries i-number
  4900                              <1> 	;cmp	ax, 32768
  4901 0000455F 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4902                              <1> 		; tst r1 / yes, no match
  4903                              <1> 		; bge .+4
  4904 00004562 7203                <1> 	jb	short anyi_2
  4905 00004564 66F7D8              <1> 	neg	ax
  4906                              <1> 		; neg r1 / make i-number positive
  4907                              <1> anyi_2:	
  4908 00004567 E81A050000          <1> 	call	imap
  4909                              <1> 		; jsr r0,imap / get address of allocation bit 
  4910                              <1> 			    ; / in the i-map in r2
  4911                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4912                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4913                              <1>  	; not	dx
  4914 0000456C F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4915                              <1>         ;and	[ebx], dx
  4916 0000456E 2013                <1> 	and 	[ebx], dl 
  4917                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4918 00004570 E8A4040000          <1> 	call	itrunc
  4919                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4920 00004575 66C705[F4620000]00- <1>  	mov 	word [i.flgs], 0
  4920 0000457D 00                  <1>
  4921                              <1> 		; clr i.flgs / clear all flags in the i-node
  4922 0000457E C3                  <1> 	retn
  4923                              <1> 		;rts	r0 / return
  4924                              <1> anyi_3: ; 1: / i-numbers match
  4925 0000457F FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4926                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4927                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4928 00004582 C3                  <1> 	retn
  4929                              <1> 		; rts r0
  2115                                  %include 'u3.s'        ; 10/05/2015
  2116                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2117                              <1> ; Last Modification: 24/12/2021
  2118                              <1> ; ----------------------------------------------------------------------------
  2119                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2120                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2121                              <1> ;
  2122                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2123                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2124                              <1> ; <Bell Laboratories (17/3/1972)>
  2125                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2126                              <1> ;
  2127                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2128                              <1> ;
  2129                              <1> ; ****************************************************************************
  2130                              <1> 
  2131                              <1> tswitch: ; Retro UNIX 386 v1
  2132                              <1> tswap:
  2133                              <1> 	; 01/09/2015
  2134                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2135                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2136                              <1> 	; time out swap, called when a user times out.
  2137                              <1> 	; the user is put on the low priority queue.
  2138                              <1> 	; This is done by making a link from the last user
  2139                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2140                              <1> 	; then he is swapped out.
  2141                              <1> 	;
  2142                              <1> 	; Retro UNIX 386 v1 modification ->
  2143                              <1> 	;       swap (software task switch) is performed by changing
  2144                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2145                              <1> 	;	as in Retro UNIX 8086 v1.
  2146                              <1> 	;
  2147                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2148                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2149                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2150                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2151                              <1> 	;	compatibles was using 1MB segmented memory 
  2152                              <1> 	;	in 8086/8088 times.
  2153                              <1> 	;
  2154                              <1> 	; INPUTS ->
  2155                              <1> 	;    u.uno - users process number
  2156                              <1> 	;    runq+4 - lowest priority queue
  2157                              <1> 	; OUTPUTS ->
  2158                              <1> 	;    r0 - users process number
  2159                              <1> 	;    r2 - lowest priority queue address
  2160                              <1> 	;
  2161                              <1> 	; ((AX = R0, BX = R2)) output
  2162                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2163                              <1> 	;
  2164 00004583 A0[4B660000]        <1> 	mov 	al, [u.uno]
  2165                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2166                              <1> 		; mov  $runq+4,r2 
  2167                              <1> 			; / move lowest priority queue address to r2
  2168 00004588 E8CD000000          <1>         call 	putlu
  2169                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2170                              <1> 		             ; / u.uno's user
  2171                              <1> 
  2172                              <1> switch: ; Retro UNIX 386 v1
  2173                              <1> swap:
  2174                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2175                              <1> 	; 02/09/2015
  2176                              <1> 	; 01/09/2015
  2177                              <1> 	; 31/08/2015
  2178                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2179                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2180                              <1> 	; 'swap' is routine that controls the swapping of processes
  2181                              <1> 	; in and out of core.
  2182                              <1> 	;
  2183                              <1> 	; Retro UNIX 386 v1 modification ->
  2184                              <1> 	;       swap (software task switch) is performed by changing
  2185                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2186                              <1> 	;	as in Retro UNIX 8086 v1.
  2187                              <1> 	;
  2188                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2189                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2190                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2191                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2192                              <1> 	;	compatibles was using 1MB segmented memory 
  2193                              <1> 	;	in 8086/8088 times.
  2194                              <1> 	;
  2195                              <1> 	; INPUTS ->
  2196                              <1> 	;    runq table - contains processes to run.
  2197                              <1> 	;    p.link - contains next process in line to be run.
  2198                              <1> 	;    u.uno - process number of process in core	
  2199                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2200                              <1> 	; OUTPUTS ->
  2201                              <1> 	;    (original unix v1 -> present process to its disk block)
  2202                              <1> 	;    (original unix v1 -> new process into core -> 
  2203                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2204                              <1> 	;	   for new process)
  2205                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2206                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2207                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2208                              <1> 	;	 for now, it will swap the process if there is not
  2209                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2210                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2211                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2212                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2213                              <1> 	;
  2214                              <1> 	;    u.pri -points to highest priority run Q.
  2215                              <1> 	;    r2 - points to the run queue.
  2216                              <1> 	;    r1 - contains new process number
  2217                              <1> 	;    r0 - points to place in routine or process that called
  2218                              <1> 	;	  swap all user parameters
  2219                              <1> 	;				
  2220                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2221                              <1> 	;
  2222                              <1> swap_0:
  2223                              <1> 		;mov $300,*$ps / processor priority = 6
  2224 0000458D BE[EE650000]        <1> 	mov	esi, runq
  2225                              <1> 		; mov $runq,r2 / r2 points to runq table
  2226                              <1> swap_1: ; 1: / search runq table for highest priority process
  2227 00004592 668B06              <1> 	mov	ax, [esi]
  2228 00004595 6621C0              <1> 	and 	ax, ax
  2229                              <1>        		; tst (r2)+ / are there any processes to run 
  2230                              <1> 			  ; / in this Q entry
  2231 00004598 7507                <1> 	jnz	short swap_2
  2232                              <1>        		; bne 1f / yes, process 1f
  2233                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2234                              <1> 			       ; / to end of table
  2235                              <1> 		; bne 1b / if not at end, go back
  2236 0000459A E8E0000000          <1> 	call	idle
  2237                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2238                              <1> 				       ; / all queues are empty
  2239 0000459F EBF1                <1> 	jmp	short swap_1
  2240                              <1> 		; br swap
  2241                              <1> swap_2: ; 1:
  2242 000045A1 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2243                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2244                              <1>  		; mov r2,u.pri / set present user to this run queue
  2245                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2246 000045A4 38E0                <1> 	cmp	al, ah
  2247                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2248                              <1> 			      ; / in this Q to be run
  2249 000045A6 740A                <1> 	je	short swap_3
  2250                              <1>        		; beq 1f / yes
  2251                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2252                              <1> 	;movzx	ebx, al
  2253 000045A8 8AA3[63630000]      <1> 	mov	ah, [ebx+p.link-1] 
  2254 000045AE 8826                <1>        	mov	[esi], ah
  2255                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2256                              <1> 				       ; / in line into run queue
  2257 000045B0 EB05                <1> 	jmp	short swap_4
  2258                              <1>        		; br 2f
  2259                              <1> swap_3: ; 1:
  2260                              <1> 	;xor	dx, dx
  2261                              <1> 	; 24/12/2021
  2262 000045B2 31D2                <1> 	xor	edx, edx
  2263 000045B4 668916              <1> 	mov	[esi], dx
  2264                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2265                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2266                              <1>       ; / in new process if required
  2267                              <1>        		; clr *$ps / clear processor status
  2268 000045B7 8A25[4B660000]      <1> 	mov 	ah, [u.uno]
  2269 000045BD 38C4                <1> 	cmp	ah, al
  2270                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2271                              <1> 			      ; / the process in core?
  2272 000045BF 743B                <1>        	je	short swap_8
  2273                              <1>        		; beq 2f / yes, don't have to swap
  2274                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2275                              <1> 			   ; / (address in routine that called swap)
  2276                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2277                              <1> 	; 01/09/2015
  2278                              <1> 	;mov	[u.usp], esp
  2279                              <1>        		; mov sp,u.usp / save stack pointer
  2280                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2281                              <1> 			       ; / to the stack pointer
  2282 000045C1 08E4                <1> 	or	ah, ah
  2283                              <1>        		; tstb u.uno / is the process # = 0
  2284 000045C3 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2285                              <1> 		; beq 1f / yes, kill process by overwriting
  2286                              <1> 	; 02/09/2015
  2287 000045C5 8925[F8650000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2288                              <1> 	;
  2289 000045CB E834000000          <1> 	call	wswap
  2290                              <1> 		; jsr r0,wswap / write out core to disk
  2291                              <1> 	 ; 31/08/2015
  2292                              <1> 	;movzx	ebx, al ; New (running) process number
  2293 000045D0 EB1C                <1> 	jmp 	short swap_7
  2294                              <1> swap_6:
  2295                              <1> 	; 31/08/2015
  2296                              <1> 	; Deallocate memory pages belong to the process
  2297                              <1> 	; which is being terminated
  2298                              <1> 	; 14/05/2015 ('sysexit')
  2299                              <1>  	; Deallocate memory pages of the process
  2300                              <1> 	; (Retro UNIX 386 v1 modification !)
  2301                              <1> 	;
  2302                              <1> 	; movzx ebx, al
  2303 000045D2 53                  <1> 	push	ebx
  2304 000045D3 A1[55660000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2305 000045D8 8B1D[59660000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2306 000045DE E814E0FFFF          <1> 	call	deallocate_page_dir
  2307 000045E3 A1[4C660000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2308 000045E8 E8A0E0FFFF          <1> 	call	deallocate_page
  2309 000045ED 5B                  <1> 	pop	ebx
  2310                              <1> swap_7: ;1: 
  2311                              <1> 	; 02/09/2015
  2312                              <1> 	; 31/08/2015
  2313                              <1> 	; 14/05/2015
  2314 000045EE C0E302              <1> 	shl	bl, 2 ; * 4 
  2315 000045F1 8B83[80630000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2316                              <1> 	;cli
  2317 000045F7 E831000000          <1> 	call	rswap
  2318                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2319                              <1> 		; jsr r0,rswap / read new process into core
  2320                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2321                              <1> 			      ; / to his program to its normal
  2322                              <1> 	; 01/09/2015
  2323                              <1> 	;mov	esp, [u.usp]	
  2324                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2325                              <1> 			     ; / new process stack
  2326                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2327                              <1> 			     ; / that just got swapped in, left off.,
  2328                              <1> 			     ; / i.e., transfer control to new process
  2329                              <1> 	;sti
  2330                              <1> swap_8: ;2:
  2331                              <1> 	; RETRO UNIX 8086 v1 modification !
  2332 000045FC C605[3E660000]04    <1> 	mov	byte [u.quant], time_count 
  2333                              <1> 		; movb $30.,uquant / initialize process time quantum
  2334 00004603 C3                  <1> 	retn
  2335                              <1> 		; rts r0 / return
  2336                              <1> 
  2337                              <1> wswap:  ; < swap out, swap to disk >
  2338                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2339                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2340                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2341                              <1> 	; appropriate disk area.
  2342                              <1> 	;
  2343                              <1> 	; Retro UNIX 386 v1 modification ->
  2344                              <1> 	;       User (u) structure content and the user's register content
  2345                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2346                              <1> 	;	saving 'u' structure and user registers for task switching).
  2347                              <1> 	;	u.usp - points to kernel stack address which contains
  2348                              <1> 	;		user's registers while entering system call.  
  2349                              <1> 	;	u.sp  - points to kernel stack address 
  2350                              <1> 	;		to return from system call -for IRET-.
  2351                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2352                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2353                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2354                              <1> 	;
  2355                              <1> 	; Retro UNIX 8086 v1 modification ->
  2356                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2357                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2358                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2359                              <1> 	;	compatibles was using 1MB segmented memory 
  2360                              <1> 	;	in 8086/8088 times.
  2361                              <1> 	;
  2362                              <1> 	; INPUTS ->
  2363                              <1> 	;    u.break - points to end of program
  2364                              <1> 	;    u.usp - stack pointer at the moment of swap
  2365                              <1> 	;    core - beginning of process program		
  2366                              <1> 	;    ecore - end of core 	
  2367                              <1> 	;    user - start of user parameter area		
  2368                              <1> 	;    u.uno - user process number	
  2369                              <1> 	;    p.dska - holds block number of process	
  2370                              <1> 	; OUTPUTS ->
  2371                              <1> 	;    swp I/O queue
  2372                              <1> 	;    p.break - negative word count of process 
  2373                              <1> 	;    r1 - process disk address	
  2374                              <1> 	;    r2 - negative word count
  2375                              <1> 	;
  2376                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2377                              <1> 	;
  2378                              <1> 	; INPUTS ->
  2379                              <1> 	;    u.uno - process number (to be swapped out)
  2380                              <1> 	; OUTPUTS ->
  2381                              <1> 	;    none
  2382                              <1> 	;
  2383                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2384                              <1> 	;
  2385 00004604 8B3D[4C660000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2386 0000460A B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2387 0000460F BE[F4650000]        <1> 	mov	esi, user ; active user (u) structure	
  2388 00004614 F3A5                <1> 	rep	movsd
  2389                              <1> 	;
  2390 00004616 8B35[F8650000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2391                              <1> 			     ;      points to user registers)
  2392 0000461C 8B0D[F4650000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2393                              <1> 			     ; (for IRET)
  2394                              <1> 			     ; [u.sp] -> EIP (user)
  2395                              <1> 			     ; [u.sp+4]-> CS (user)
  2396                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2397                              <1> 			     ; [u.sp+12] -> ESP (user)
  2398                              <1> 			     ; [u.sp+16] -> SS (user)	
  2399 00004622 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2400 00004624 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2401                              <1> 			     ; (for IRET) 	
  2402 00004627 C1E902              <1> 	shr	ecx, 2	     		
  2403 0000462A F3A5                <1> 	rep	movsd
  2404 0000462C C3                  <1> 	retn
  2405                              <1> 
  2406                              <1> 	; Original UNIX v1 'wswap' routine:
  2407                              <1> 	; wswap:
  2408                              <1> 		; mov *$30,u.emt / determines handling of emts
  2409                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2410                              <1> 				; / illegal instructions
  2411                              <1> 		; mov u.break,r2 / put process program break address in r2
  2412                              <1> 		; inc r2 / add 1 to it 
  2413                              <1> 		; bic $1,r2 / make it even
  2414                              <1> 		; mov r2,u.break / set break to an even location
  2415                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2416                              <1> 			     ; / at moment of swap in r3
  2417                              <1> 		; cmp r2,$core / is u.break less than $core
  2418                              <1> 		; blos 2f / yes
  2419                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2420                              <1>        		; bhis 2f / yes
  2421                              <1> 	; 1:
  2422                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2423                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2424                              <1> 		; bne 1b / no, keep packing
  2425                              <1> 	 	; br 1f / yes
  2426                              <1> 	; 2:
  2427                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2428                              <1> 	; 1:
  2429                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2430                              <1> 			   ; / (user up to end of stack gets written out)
  2431                              <1> 		; neg r2 / make it negative
  2432                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2433                              <1> 		; mov r2,swp+4 / word count
  2434                              <1> 		; movb u.uno,r1 / move user process number to r1
  2435                              <1> 		; asl r1 / x2 for index
  2436                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2437                              <1> 				     ; / into the p.break table
  2438                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2439                              <1> 				    ; /	for process to r1
  2440                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2441                              <1> 			     ; / (block number)
  2442                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2443                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2444                              <1> 	; 1:
  2445                              <1>        		; tstb swp+1 / is lt done writing?
  2446                              <1>        		; bne 1b / no, wait
  2447                              <1> 		; rts r0 / yes, return to swap
  2448                              <1> 
  2449                              <1> rswap:  ; < swap in, swap from disk >
  2450                              <1> 	; 15/09/2015
  2451                              <1> 	; 28/08/2015
  2452                              <1> 	; 14/05/2015
  2453                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2454                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2455                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2456                              <1> 	; from disk into core.
  2457                              <1> 	;
  2458                              <1> 	; Retro UNIX 386 v1 modification ->
  2459                              <1> 	;       User (u) structure content and the user's register content
  2460                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2461                              <1> 	;	saving 'u' structure and user registers for task switching).
  2462                              <1> 	;	u.usp - points to kernel stack address which contains
  2463                              <1> 	;		user's registers while entering system call.  
  2464                              <1> 	;	u.sp  - points to kernel stack address 
  2465                              <1> 	;		to return from system call -for IRET-.
  2466                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2467                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2468                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2469                              <1> 	;
  2470                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2471                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2472                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2473                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2474                              <1> 	;	compatibles was using 1MB segmented memory 
  2475                              <1> 	;	in 8086/8088 times.
  2476                              <1> 	;
  2477                              <1> 	; INPUTS ->
  2478                              <1> 	;    r1 - process number of process to be read in
  2479                              <1> 	;    p.break - negative of word count of process 
  2480                              <1> 	;    p.dska - disk address of the process		
  2481                              <1> 	;    u.emt - determines handling of emt's 	
  2482                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2483                              <1> 	; OUTPUTS ->
  2484                              <1> 	;    8 = (u.ilgins)
  2485                              <1> 	;    24 = (u.emt)
  2486                              <1> 	;    swp - bit 10 is set to indicate read 
  2487                              <1> 	;		(bit 15=0 when reading is done)	
  2488                              <1> 	;    swp+2 - disk block address
  2489                              <1> 	;    swp+4 - negative word count 	
  2490                              <1> 	;      ((swp+6 - address of user structure)) 
  2491                              <1> 	;
  2492                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2493                              <1> 	;
  2494                              <1> 	; INPUTS ->
  2495                              <1> 	;    AL	- new process number (to be swapped in)	 
  2496                              <1> 	; OUTPUTS ->
  2497                              <1> 	;    none
  2498                              <1> 	;
  2499                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2500                              <1> 	;
  2501                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2502 0000462D 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2503 0000462F B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2504 00004634 BF[F4650000]        <1> 	mov	edi, user ; active user (u) structure	
  2505 00004639 F3A5                <1> 	rep	movsd
  2506 0000463B 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2507 0000463C 8B3D[F8650000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2508                              <1> 			     ;      points to user registers)
  2509 00004642 8B0D[F4650000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2510                              <1> 			     ; (for IRET)
  2511                              <1> 			     ; [u.sp] -> EIP (user)
  2512                              <1> 			     ; [u.sp+4]-> CS (user)
  2513                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2514                              <1> 			     ; [u.sp+12] -> ESP (user)
  2515                              <1> 			     ; [u.sp+16] -> SS (user)		
  2516                              <1> 	; 28/08/2015
  2517 00004648 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2518 0000464A 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2519                              <1> 			     ; (for IRET) 	
  2520 0000464D C1E902              <1> 	shr	ecx, 2	       		
  2521 00004650 F3A5                <1> 	rep	movsd
  2522 00004652 8B25[F8650000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2523 00004658 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2524 00004659 C3                  <1> 	retn
  2525                              <1> 
  2526                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2527                              <1> 	;rswap:
  2528                              <1>        		; asl r1 / process number x2 for index
  2529                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2530                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2531                              <1>        		; bis $2000,swp / read
  2532                              <1>        		; jsr r0,ppoke / read it in 
  2533                              <1> 	; 1:
  2534                              <1>        		; tstb swp+1 / done
  2535                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2536                              <1>        		; mov u.emt,*$30 / yes move these
  2537                              <1>        		; mov u.ilgins,*$10 / back
  2538                              <1>        		; rts r0 / return
  2539                              <1> 
  2540                              <1> 	;unpack: ; / move stack back to its normal place
  2541                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2542                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2543                              <1> 		; blos 2f / yes, return
  2544                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2545                              <1> 			     ; / before swapping
  2546                              <1> 		; bhis 2f / yes, return
  2547                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2548                              <1> 		; add r3,r2
  2549                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2550                              <1> 	; 1:
  2551                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2552                              <1> 		; cmp r2,u.break / in core
  2553                              <1> 		; bne 1b
  2554                              <1> 	; 2:
  2555                              <1>        		; rts r0
  2556                              <1> 
  2557                              <1> putlu: 
  2558                              <1> 	; 12/09/2015
  2559                              <1> 	; 02/09/2015
  2560                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2561                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2562                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2563                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2564                              <1> 	; the last process on the queue to process in r1 by putting
  2565                              <1> 	; the process number in r1 into the last process's link.
  2566                              <1> 	;
  2567                              <1> 	; INPUTS ->
  2568                              <1> 	;    r1 - user process number
  2569                              <1> 	;    r2 - points to lowest priority queue 
  2570                              <1> 	;    p.dska - disk address of the process		
  2571                              <1> 	;    u.emt - determines handling of emt's 	
  2572                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2573                              <1> 	; OUTPUTS ->
  2574                              <1> 	;    r3 - process number of last process on the queue upon
  2575                              <1> 	;	  entering putlu
  2576                              <1> 	;    p.link-1 + r3 - process number in r1
  2577                              <1> 	;    r2 - points to lowest priority queue
  2578                              <1> 	;
  2579                              <1> 	; ((Modified registers: EDX, EBX)) 
  2580                              <1> 	;
  2581                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2582                              <1> 
  2583                              <1> 	; eBX = r2
  2584                              <1> 	; eAX = r1 (AL=r1b)
  2585                              <1> 
  2586 0000465A BB[EE650000]        <1> 	mov	ebx, runq
  2587 0000465F 0FB613              <1> 	movzx  	edx, byte [ebx]
  2588 00004662 43                  <1> 	inc	ebx
  2589 00004663 20D2                <1> 	and	dl, dl
  2590                              <1> 		; tstb (r2)+ / is queue empty?
  2591 00004665 740A                <1>        	jz	short putlu_1
  2592                              <1> 		; beq 1f / yes, branch
  2593 00004667 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2594                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2595                              <1> 			     ; / in r3
  2596 00004669 8882[63630000]      <1>        	mov	[edx+p.link-1], al
  2597                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2598                              <1> 			     ; / "last users" link
  2599 0000466F EB03                <1> 	jmp	short putlu_2
  2600                              <1> 		; br 2f /
  2601                              <1> putlu_1: ; 1:
  2602 00004671 8843FF              <1> 	mov	[ebx-1], al
  2603                              <1>        		; movb r1,-1(r2) / user is only user; 
  2604                              <1> 			    ; / put process no. at beginning and at end
  2605                              <1> putlu_2: ; 2: 
  2606 00004674 8803                <1> 	mov	[ebx], al
  2607                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2608                              <1> 			     ; / on the queue
  2609 00004676 88C2                <1> 	mov	dl, al
  2610 00004678 88B2[63630000]      <1>         mov     [edx+p.link-1], dh ; 0
  2611                              <1> 		; dec r2 / restore r2
  2612 0000467E C3                  <1>         retn
  2613                              <1> 		; rts r0
  2614                              <1> 
  2615                              <1> ;copyz:
  2616                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2617                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2618                              <1> ;       mov     (r0)+,r1
  2619                              <1> ;       mov     (r0)+,r2
  2620                              <1> ;1:
  2621                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2622                              <1> ;       cmp     r1,r2 
  2623                              <1> ;       blo     1b
  2624                              <1> ;       mov     (sp)+,r2 / restore r2
  2625                              <1> ;       mov     (sp)+,r1 / restore r1
  2626                              <1> ;       rts     r0 
  2627                              <1> 
  2628                              <1> idle:
  2629                              <1> 	; 01/09/2015
  2630                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2631                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2632                              <1> 	; (idle & wait loop)
  2633                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2634                              <1> 	; idle procedure!
  2635                              <1>       	;
  2636                              <1>   	; 01/09/2015
  2637 0000467F FB                  <1> 	sti
  2638                              <1>       	; 29/07/2013
  2639 00004680 F4                  <1>       	hlt
  2640 00004681 90                  <1>       	nop ; 10/10/2013
  2641 00004682 90                  <1>       	nop
  2642 00004683 90                  <1>       	nop
  2643                              <1>       	; 23/10/2013
  2644 00004684 90                  <1>       	nop
  2645 00004685 90                  <1>       	nop
  2646 00004686 90                  <1>       	nop
  2647 00004687 90                  <1>       	nop
  2648 00004688 C3                  <1>       	retn      
  2649                              <1> 
  2650                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2651                              <1> 	;clr *$ps / clear ps
  2652                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2653                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2654                              <1> 	;1 / wait for interrupt
  2655                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2656                              <1> 	;mov (sp)+,*$ps
  2657                              <1> 	;rts r0
  2658                              <1> 
  2659                              <1> clear:
  2660                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2661                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2662                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2663                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2664                              <1> 	; on the current device (cdev)
  2665                              <1> 	;	
  2666                              <1> 	; INPUTS ->
  2667                              <1> 	;    r1 - block number of block to be zeroed
  2668                              <1> 	;    cdev - current device number 
  2669                              <1> 	; OUTPUTS ->
  2670                              <1> 	;    a zeroed I/O buffer onto the current device
  2671                              <1> 	;    r1 - points to last entry in the I/O buffer
  2672                              <1> 	;
  2673                              <1> 	; ((AX = R1)) input/output
  2674                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2675                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2676                              <1> 
  2677 00004689 E88E0E0000          <1> 	call 	wslot
  2678                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2679                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2680 0000468E 89DF                <1> 	mov	edi, ebx ; r5
  2681 00004690 89C2                <1> 	mov	edx, eax
  2682 00004692 B980000000          <1> 	mov	ecx, 128
  2683                              <1> 		; mov $256.,r3
  2684 00004697 31C0                <1> 	xor	eax, eax
  2685 00004699 F3AB                <1> 	rep	stosd
  2686 0000469B 89D0                <1> 	mov	eax, edx
  2687                              <1> ; 1: 
  2688                              <1>        		; clr (r5)+ / zero data word in buffer
  2689                              <1>        		; dec r3
  2690                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2691                              <1> 	;call	dskwr
  2692                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2693                              <1>                              ; / block specified in r1
  2694                              <1> 	; eAX (r1) = block number
  2695                              <1> 	;retn
  2696                              <1> 		; rts r0
  2697                              <1> 	; 24/12/2021
  2698 0000469D E9870E0000          <1> 	jmp	dskwr
  2116                                  %include 'u4.s'        ; 15/04/2015
  2117                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2118                              <1> ; Last Modification: 26/02/2022
  2119                              <1> ; ----------------------------------------------------------------------------
  2120                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2121                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2122                              <1> ;
  2123                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2124                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2125                              <1> ; <Bell Laboratories (17/3/1972)>
  2126                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2127                              <1> ;
  2128                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2129                              <1> ;
  2130                              <1> ; ****************************************************************************
  2131                              <1> 
  2132                              <1> ;setisp:
  2133                              <1>        ;mov     r1,-(sp)
  2134                              <1>        ;mov     r2,-(sp)
  2135                              <1>        ;mov     r3,-(sp)
  2136                              <1>        ;mov     clockp,-(sp)
  2137                              <1>        ;mov     $s.syst+2,clockp
  2138                              <1>        ;jmp     (r0)
  2139                              <1> 
  2140                              <1> clock: ; / interrupt from 60 cycle clock
  2141                              <1> 	
  2142                              <1> 	; 14/10/2015
  2143                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2144                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2145                              <1> 
  2146                              <1>        ;mov     r0,-(sp) / save r0
  2147                              <1>        ;tst     *$lks / restart clock?
  2148                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2149                              <1>        ;inc     (r0)
  2150                              <1>        ;bne     1f
  2151                              <1>        ;inc     -(r0)
  2152                              <1> ;1:
  2153                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2154                              <1>        ;inc     (r0)
  2155                              <1>        ;bne     1f
  2156                              <1>        ;inc     -(r0)
  2157                              <1> ;1:
  2158                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2159                              <1> 
  2160 000046A2 803D[3E660000]00    <1> 	cmp	byte [u.quant], 0
  2161 000046A9 772C                <1> 	ja	short clk_1
  2162                              <1> 	;
  2163 000046AB 803D[F3650000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2164 000046B2 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2165 000046B4 803D[4B660000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2166 000046BB 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2167 000046BD 66833D[40660000]00  <1> 	cmp	word [u.intr], 0
  2168 000046C5 7616                <1> 	jna	short clk_2
  2169                              <1> clk_0:
  2170                              <1> 	; 14/10/2015
  2171 000046C7 FE05[F3650000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2172 000046CD 58                  <1> 	pop	eax ; return address to the timer interrupt
  2173                              <1> 	;
  2174 000046CE B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2175                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2176 000046D0 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2177                              <1> 	;
  2178 000046D2 E97FEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2179                              <1> clk_1:
  2180 000046D7 FE0D[3E660000]      <1> 	dec	byte [u.quant]
  2181                              <1> clk_2:
  2182 000046DD C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2183                              <1> 
  2184                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2185                              <1> 
  2186                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2187                              <1>        ;decb    (r0)
  2188                              <1>        ;bge     1f / if less than 0
  2189                              <1>        ;clrb    (r0) / make it 0
  2190                              <1> ;1: / decrement time out counts return now if priority was not 0
  2191                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2192                              <1>        ;bge     2f / yes, check time outs
  2193                              <1>        ;tstb    (r0) / no, user timed out?
  2194                              <1>        ;bne     1f / no
  2195                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2196                              <1>        ;bne     1f / no, 1f
  2197                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2198                              <1>        ;sys     0 / sysrele
  2199                              <1>        ;rti
  2200                              <1> ;2: / priority is high so just decrement time out counts
  2201                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2202                              <1> ;2:
  2203                              <1>        ;tstb    (r0) / is the time out?
  2204                              <1>        ;beq     3f / yes, 3f (get next entry)
  2205                              <1>        ;decb    (r0) / no, decrement the time
  2206                              <1>        ;bne     3f / isit zero now?
  2207                              <1>        ;incb    (r0) / yes, increment the time
  2208                              <1> ;3:
  2209                              <1>        ;inc     r0 / next entry
  2210                              <1>        ;cmp     r0,$touts / end of toutt table?
  2211                              <1>        ;blo     2b / no, check this entry
  2212                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2213                              <1>        ;rti / return from interrupt
  2214                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2215                              <1>        ;mov     (sp)+,r0 / restore r0
  2216                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2217                              <1>        ;jsr     r0,setisp / save registers
  2218                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2219                              <1>                                ;  / the table
  2220                              <1> ;1:
  2221                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2222                              <1>        ;beq     2f / yes
  2223                              <1>        ;decb    toutt(r0) / no, decrement the time
  2224                              <1>        ;bne     2f / is the time 0, now
  2225                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2226                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2227                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2228                              <1> ;2:
  2229                              <1>        ;dec     r0 / set up r0 for next entry
  2230                              <1>        ;bge     1b / finished? , no, go back
  2231                              <1>        ;br      retisp / yes, restore registers and do a rti
  2232                              <1> 
  2233                              <1> ;retisp:
  2234                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2235                              <1>        ;mov     (sp)+,r3
  2236                              <1>        ;mov     (sp)+,r2
  2237                              <1>        ;mov     (sp)+,r1
  2238                              <1>        ;mov     (sp)+,r0
  2239                              <1>        ;rti     / return from interrupt
  2240                              <1> 
  2241                              <1> 
  2242                              <1> wakeup: ; / wakeup processes waiting for an event 
  2243                              <1> 	; / by linking them to the queue
  2244                              <1> 	;
  2245                              <1> 	; 26/02/2022
  2246                              <1> 	; 15/09/2015
  2247                              <1> 	; 29/06/2015
  2248                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2249                              <1> 	;
  2250                              <1> 	; 15/05/2013 - 02/06/2014
  2251                              <1> 	; Retro UNIX 8086 v1 modification !
  2252                              <1> 	; (Process/task switching routine by using
  2253                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2254                              <1> 	;
  2255                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2256                              <1> 	; sleeping in the specified wait channel by creating a link 
  2257                              <1> 	; to it from the last user process on the run queue.
  2258                              <1> 	; If there is no process to wake up, nothing happens.
  2259                              <1> 	;
  2260                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2261                              <1> 	; 'switching' status of the current process (owns current tty)
  2262                              <1> 	; (via alt + function keys) to a process which has highest
  2263                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2264                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2265                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2266                              <1> 	; tty for tty switching by keyboard.)	 
  2267                              <1> 	; 
  2268                              <1> 	; INPUT -> 
  2269                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2270                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2271                              <1> 	;
  2272                              <1> 	; ((modified registers: EAX, EBX))
  2273                              <1> 	;
  2274 000046DE 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2275 000046E1 81C3[98620000]      <1> 	add	ebx, wlist
  2276 000046E7 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2277 000046E9 20C0                <1> 	and	al, al
  2278 000046EB 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2279                              <1> 	;
  2280 000046ED 30E4                <1> 	xor	ah, ah
  2281 000046EF 8825[3E660000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2282 000046F5 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2283                              <1> 	; 15/09/2015
  2284 000046F7 0FB6D8              <1> 	movzx	ebx, al
  2285                              <1> 	; 26/02/2022 (p.waitc is not used)
  2286                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2287 000046FA FEC4                <1> 	inc	ah
  2288 000046FC 88A3[73630000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2289                              <1> 	;
  2290 00004702 57                  <1> 	push	edi
  2291 00004703 52                  <1> 	push	edx
  2292 00004704 E851FFFFFF          <1> 	call	putlu
  2293 00004709 5A                  <1> 	pop	edx
  2294 0000470A 5F                  <1> 	pop	edi
  2295                              <1> wa0:
  2296 0000470B C3                  <1> 	retn
  2297                              <1> 
  2298                              <1> sleep: 
  2299                              <1> 	; 26/02/2022
  2300                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2301                              <1> 	; 15/09/2015
  2302                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2303                              <1> 	;
  2304                              <1> 	; 09/05/2013 - 20/03/2014
  2305                              <1> 	;
  2306                              <1> 	; Retro UNIX 8086 v1 modification !
  2307                              <1> 	; (Process/task switching and quit routine by using
  2308                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2309                              <1> 	;
  2310                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2311                              <1> 	; tty and tape output or input becomes available
  2312                              <1> 	; and process is put on waiting channel and swapped out,
  2313                              <1> 	; then -when the tty or tape is ready to write or read-
  2314                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2315                              <1> 	;
  2316                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2317                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2318                              <1> 	; status of the current process also INT 1Ch will count down
  2319                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2320                              <1> 	; to tty buffer of the current process and kernel will get
  2321                              <1> 	; user input by using tty buffer of the current process
  2322                              <1> 	; (instead of standard INT 16h interrupt).
  2323                              <1> 	; TTY output will be redirected to related video page of text mode
  2324                              <1> 	; (INT 10h will be called with different video page depending
  2325                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2326                              <1> 	; pseudo screens.)
  2327                              <1> 	;
  2328                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2329                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2330                              <1> 	; characters/data on serial port(s).
  2331                              <1> 	;
  2332                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2333                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2334                              <1> 	; 
  2335                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2336                              <1> 	;
  2337                              <1> 	;; 05/10/2013
  2338                              <1>         ;10/12/2013
  2339                              <1> 	;cmp   byte [u.uno], 1
  2340                              <1>         ;ja    short sleep0
  2341                              <1> 	;retn
  2342                              <1> 
  2343                              <1> 	; 20/03/2014
  2344                              <1> 	;mov	bx, [runq]
  2345                              <1> 	;cmp	bl, bh
  2346                              <1> 	;jne	short sleep0	
  2347                              <1> 	; 25/02/2014
  2348                              <1> 	;cmp word ptr [runq], 0
  2349                              <1> 	;ja short sleep0	
  2350                              <1> 	;retn
  2351                              <1> sleep0:
  2352                              <1> 	;
  2353 0000470C E849000000          <1> 	call	isintr
  2354                              <1> 	;jnz	sysret
  2355                              <1> 		; / wait for event
  2356                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2357                              <1> 			      ; / or quit from user
  2358                              <1>                		; br 2f / something happened
  2359                              <1> 			      ; / yes, his interrupt so return
  2360                              <1>                      	      ;	/ to user
  2361                              <1> 	; 24/12/2021
  2362 00004711 7405                <1> 	jz	short sleep_2
  2363                              <1> sleep_3:
  2364 00004713 E9D9EAFFFF          <1> 	jmp	sysret
  2365                              <1> sleep_2:
  2366                              <1> 	; 30/06/2015
  2367 00004718 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2368 0000471B 81C3[98620000]      <1> 	add	ebx, wlist
  2369 00004721 8A03                <1> 	mov	al, [ebx]
  2370 00004723 20C0                <1> 	and	al, al
  2371 00004725 7407                <1> 	jz	short sleep1
  2372 00004727 53                  <1> 	push	ebx
  2373 00004728 E82DFFFFFF          <1> 	call	putlu
  2374 0000472D 5B                  <1> 	pop	ebx
  2375                              <1> sleep1:
  2376 0000472E A0[4B660000]        <1> 	mov	al, [u.uno]    
  2377 00004733 8803                <1>   	mov	[ebx], al 	; put the process number
  2378                              <1> 				; in the wait channel
  2379                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2380                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2381                              <1> 				     ; / on the stack
  2382                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2383                              <1> 				     ; / to put to sleep in there
  2384                              <1>         ; 15/09/2015
  2385 00004735 0FB6D8              <1> 	movzx	ebx, al
  2386 00004738 C683[73630000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2387                              <1> 	; 26/02/2022 (p.waitc is not used)
  2388                              <1> 	;inc	ah
  2389                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2390                              <1> 	;
  2391 0000473F 66FF35[E3650000]    <1> 	push    word [cdev]
  2392                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2393 00004746 E842FEFFFF          <1> 	call	swap
  2394                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2395 0000474B 668F05[E3650000]    <1>         pop     word [cdev]
  2396                              <1> 		; mov (sp)+,cdev / restore device
  2397 00004752 E803000000          <1> 	call	isintr
  2398                              <1> 	; 22/09/2013
  2399                              <1> 	;jnz	sysret         
  2400                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2401                              <1>                		; br 2f / yes, return to new user
  2402                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2403                              <1> 				; / originally on the wait channel
  2404                              <1>        		; beq 1f / if 0 branch
  2405                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2406                              <1>        		; mov $300,*$ps / processor priority = 6
  2407                              <1> 		; jsr r0,putlu / create link to old process number
  2408                              <1>        		; clr *$ps / clear the status; process priority = 0
  2409                              <1> 	; 24/12/2021
  2410 00004757 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2411                              <1>      ;1:
  2412 00004759 C3                  <1> 	retn
  2413                              <1> 		; rts r0 / return
  2414                              <1>      ;2:
  2415                              <1>         ;;jmp	sysret
  2416                              <1> 		; jmp sysret / return to user
  2417                              <1> 
  2418                              <1> isintr:
  2419                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2420                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2421                              <1> 	;
  2422                              <1> 	; 09/05/2013 - 30/05/2014
  2423                              <1> 	;
  2424                              <1> 	; Retro UNIX 8086 v1 modification !
  2425                              <1> 	; (Process/task switching and quit routine by using
  2426                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2427                              <1> 	;
  2428                              <1> 	; Retro UNIX 8086 v1 modification:
  2429                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2430                              <1> 	;  and there is a 'quit' request by user;
  2431                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2432                              <1> 	;  "nothing to do". (20/10/2013)
  2433                              <1> 	;
  2434                              <1> 	; 20/10/2013
  2435 0000475A 66833D[2C660000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2436 00004762 761F                <1> 	jna	short isintr2 ; retn
  2437                              <1> 	; 03/09/2013
  2438                              <1> 	; (nothing to do)
  2439                              <1> 	;retn
  2440                              <1> 	; 22/09/2013
  2441 00004764 66833D[40660000]00  <1> 	cmp	word [u.intr], 0
  2442 0000476C 7615                <1> 	jna	short isintr2 ; retn
  2443                              <1> 	; 30/05/2014
  2444                              <1> 	;push	ax
  2445                              <1> 	; 24/12/2021
  2446 0000476E 50                  <1> 	push	eax
  2447 0000476F 66A1[42660000]      <1> 	mov	ax, [u.quit]
  2448 00004775 6609C0              <1> 	or	ax, ax ; 0 ?
  2449 00004778 7408                <1> 	jz	short isintr1 ; zf = 1
  2450 0000477A 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2451 0000477E 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2452                              <1> 	;xor	ax, ax ; zf = 1
  2453                              <1> 	; 24/12/2021
  2454 00004780 31C0                <1> 	xor	eax, eax ; zf = 1
  2455                              <1> isintr1:
  2456                              <1> 	;pop	ax
  2457                              <1> 	; 24/12/2021
  2458 00004782 58                  <1> 	pop	eax
  2459                              <1> isintr2: ; 22/09/2013
  2460                              <1> 	; zf=1 -> nothing to do
  2461 00004783 C3                  <1> 	retn
  2462                              <1> 
  2463                              <1> 	; UNIX v1 original 'isintr' routine... 
  2464                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2465                              <1>        	;mov     r2,-(sp) / save r2
  2466                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2467                              <1>         ;                 / typewriter
  2468                              <1>        	;beq     1f / if 0, do nothing except skip return
  2469                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2470                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2471                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2472                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2473                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2474                              <1>         ;              / of interrupts
  2475                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2476                              <1>      ;1:
  2477                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2478                              <1>      ;4:
  2479                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2480                              <1>        	;mov     (sp)+,r1
  2481                              <1>        	;rts     r0
  2482                              <1>      ;3: / interrupt char = quit (fs)
  2483                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2484                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2485                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2486                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2487                              <1>      ;1: / find process control tty entry in tty block
  2488                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2489                              <1>        	;beq     1f / block found go to 1f
  2490                              <1>        	;add     $8,r1 / look at next tty block
  2491                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2492                              <1>        	;blo     1b / no
  2493                              <1>        	;br      4b / no process control tty found so go to 4b
  2494                              <1>      ;1:
  2495                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2496                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2497                              <1>         ;                  / identifier
  2498                              <1>        	;inc     0f / increment
  2499                              <1>      ;1:
  2500                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2501                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2502                              <1>         ;             / being typed out after you hit the interrupt
  2503                              <1>         ;             / key
  2504                              <1>        	;br      1b
  2117                                  %include 'u5.s'        ; 03/06/2015
  2118                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2119                              <1> ; Last Modification: 22/04/2022
  2120                              <1> ; ----------------------------------------------------------------------------
  2121                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2122                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2123                              <1> ;
  2124                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2125                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2126                              <1> ; <Bell Laboratories (17/3/1972)>
  2127                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2128                              <1> ;
  2129                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2130                              <1> ;
  2131                              <1> ; ****************************************************************************
  2132                              <1> 
  2133                              <1> mget:
  2134                              <1> 	; 22/04/2022
  2135                              <1> 	; 09/01/2022
  2136                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2137                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2138                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2139                              <1> 	;
  2140                              <1> 	; Get existing or (allocate) a new disk block for file
  2141                              <1> 	; 
  2142                              <1> 	; INPUTS ->
  2143                              <1> 	;    u.fofp (file offset pointer)
  2144                              <1> 	;    inode 
  2145                              <1> 	;    u.off (file offset)
  2146                              <1> 	; OUTPUTS ->
  2147                              <1> 	;    r1 (physical block number)
  2148                              <1> 	;    r2, r3, r5 (internal)
  2149                              <1> 	;
  2150                              <1> 	; ((AX = R1)) output
  2151                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2152                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2153                              <1> 
  2154                              <1> 		; mov *u.fofp,mq / file offset in mq
  2155                              <1> 		; clr ac / later to be high sig
  2156                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2157                              <1> 		; mov mq,r2
  2158                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2159                              <1> 		; bne 4f / branch for large file
  2160                              <1> mget_0:	
  2161                              <1> 	; 09/01/2022
  2162 00004784 29C0                <1> 	sub	eax, eax
  2163 00004786 29D2                <1> 	sub	edx, edx
  2164 00004788 29C9                <1> 	sub	ecx, ecx
  2165 0000478A 29DB                <1> 	sub	ebx, ebx
  2166                              <1> 
  2167 0000478C 8B35[0C660000]      <1>         mov     esi, [u.fofp]
  2168                              <1>         ;movzx	ebx, byte [esi+1]
  2169                              <1> 	; 09/01/2022
  2170 00004792 46                  <1> 	inc	esi
  2171 00004793 8A1E                <1> 	mov	bl, [esi]
  2172                              <1> 
  2173                              <1> 	; BX = r2
  2174                              <1>         ; 24/12/2021
  2175 00004795 F605[F5620000]10    <1> 	test	byte [i.flgs+1], 10h
  2176                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2177                              <1> 				  ; is this a large or small file
  2178 0000479C 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2179                              <1> 
  2180 0000479E F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2181                              <1> 		; bit $!17,r2
  2182 000047A1 7525                <1> 	jnz 	short mget_2
  2183                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2184 000047A3 80E30E              <1>         and     bl, 0Eh  
  2185                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2186                              <1> 	; 09/01/2021
  2187 000047A6 668B83[FA620000]    <1> 	mov	ax, [ebx+i.dskp]
  2188                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2189                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2190                              <1> 	; 24/12/2021
  2191 000047AD 09C0                <1> 	or	eax, eax
  2192                              <1> 	;or 	ax, ax
  2193 000047AF 7516                <1> 	jnz 	short mget_1 
  2194                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2195                              <1> 		       ; / for file
  2196 000047B1 E8A6000000          <1> 	call 	alloc
  2197                              <1> 		; jsr r0,alloc / allocate a new block
  2198                              <1>          ; eAX (r1) = Physical block number
  2199 000047B6 668983[FA620000]    <1> 	mov 	[ebx+i.dskp], ax
  2200                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2201 000047BD E835020000          <1> 	call 	setimod	
  2202                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2203 000047C2 E8C2FEFFFF          <1> 	call	clear
  2204                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2205                              <1> mget_1: ; 2:
  2206                              <1>         ; eAX (r1) = Physical block number
  2207 000047C7 C3                  <1> 	retn 
  2208                              <1> 		; rts r0
  2209                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2210 000047C8 E88F000000          <1> 	call 	alloc
  2211                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2212                              <1> 	                     ; / block number in r1
  2213                              <1>         ; eAX (r1) = Physical block number
  2214 000047CD E84A0D0000          <1> 	call 	wslot
  2215                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2216                              <1> 			     ; / first data word in buffer
  2217                              <1>         ; eAX (r1) = Physical block number
  2218                              <1> 	; 09/01/2022
  2219 000047D2 31C9                <1> 	xor	ecx, ecx
  2220 000047D4 B108                <1> 	mov	cl, 8
  2221                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2222                              <1> 		   ; into new indirect block area for the new
  2223                              <1> 		   ; large file		
  2224 000047D6 89DF                <1> 	mov 	edi, ebx ; r5
  2225 000047D8 BE[FA620000]        <1> 	mov 	esi, i.dskp 
  2226                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2227                              <1> 			   ; / block pointers
  2228                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2229                              <1> 			  ; / large file
  2230                              <1> 	; 22/04/2022
  2231 000047DD 50                  <1> 	push	eax ; * ; bugfix
  2232                              <1> 
  2233                              <1> 	;xor 	ax, ax ; mov ax, 0
  2234                              <1> 	; 24/12/2021
  2235 000047DE 31C0                <1> 	xor	eax, eax
  2236                              <1> mget_3: ;1:
  2237 000047E0 66A5                <1> 	movsw
  2238                              <1> 		; mov (r2),(r5)+
  2239 000047E2 668946FE            <1> 	mov 	[esi-2], ax
  2240                              <1> 		; clr (r2)+
  2241 000047E6 E2F8                <1> 	loop	mget_3 ; 1b
  2242                              <1> 		; dec r3
  2243                              <1> 		; bgt 1b
  2244                              <1> 
  2245 000047E8 B1F8                <1> 	mov 	cl, 256-8
  2246                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2247                              <1> mget_4:	; 1
  2248 000047EA F366AB              <1> 	rep 	stosw
  2249                              <1> 		; clr (r5)+
  2250                              <1> 		; dec r3
  2251                              <1> 		; bgt 1b
  2252                              <1> 
  2253                              <1> 	; 22/04/2022
  2254                              <1> 	;pop	eax ; * ; bugfix
  2255                              <1> 
  2256                              <1> 	; 24/03/2013
  2257                              <1>         ; AX (r1) = Physical block number
  2258 000047ED E8370D0000          <1> 	call	dskwr
  2259                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2260                              <1> 
  2261                              <1> 	; 22/04/2022
  2262 000047F2 58                  <1> 	pop	eax ; * ; bugfix
  2263                              <1> 
  2264                              <1>         ; eAX (r1) = Physical block number
  2265 000047F3 66A3[FA620000]      <1> 	mov 	[i.dskp], ax
  2266                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2267                              <1> 	; 09/01/2022
  2268 000047F9 800D[F5620000]10    <1> 	or	byte [i.flgs+1], 10h
  2269                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2270                              <1> 		; bis $10000,i.flgs / set large file bit 
  2271                              <1> 				  ; / in i.flgs word of i-node
  2272 00004800 E8F2010000          <1> 	call	setimod
  2273                              <1> 		; jsr r0,setimod / set i-node modified flag
  2274 00004805 E97AFFFFFF          <1>         jmp     mget_0 
  2275                              <1> 		; br mget
  2276                              <1> 
  2277                              <1> mget_5:  ; 4 ; large file
  2278                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2279                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2280                              <1> 			    ; / in indirect block
  2281                              <1> 		; mov r2,-(sp) / save on stack (*)
  2282                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2283                              <1>        		          ; / indirect block
  2284                              <1> 		; bic $!16,r2
  2285 0000480A 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2286 0000480D 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2287                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2288                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2289                              <1> 	; There is always 1 indirect block for this file system
  2290                              <1> 	; 09/01/2022
  2291 0000480E 66A1[FA620000]      <1> 	mov	ax, [i.dskp]
  2292                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2293                              <1> 		; mov i.dskp(r2),r1
  2294                              <1> 	; 09/01/2022
  2295 00004814 09C0                <1> 	or	eax, eax
  2296                              <1> 	;or 	ax, ax ; R1
  2297 00004816 7515                <1> 	jnz 	short mget_6 ; 2f
  2298                              <1> 		; bne 2f / if no indirect block exists
  2299 00004818 E83F000000          <1> 	call 	alloc
  2300                              <1> 		; jsr r0,alloc / allocate a new block
  2301 0000481D 66A3[FA620000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2302                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2303 00004823 E8CF010000          <1> 	call 	setimod
  2304                              <1> 		; jsr r0,setimod / set i-node modified byte
  2305                              <1> 	; eAX = new block number
  2306 00004828 E85CFEFFFF          <1> 	call 	clear
  2307                              <1> 		; jsr r0,clear / clear new block
  2308                              <1> mget_6: ;2
  2309                              <1> 	; 05/03/2013
  2310                              <1> 	; eAX = r1, physical block number (of indirect block)
  2311 0000482D E8860C0000          <1> 	call 	dskrd ; read indirect block
  2312                              <1> 		; jsr r0,dskrd / read in indirect block
  2313 00004832 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2314                              <1> 		; mov (sp)+,r2 / get offset
  2315                              <1> 	; eAX = r1, physical block number (of indirect block)
  2316 00004833 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2317                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2318                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2319 00004834 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2320                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2321                              <1> 	                  ; / points to location of inter
  2322                              <1> 	; 09/01/2022
  2323 00004836 668B03              <1> 	mov	ax, [ebx]
  2324                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2325                              <1> 			      ; in file sought in R1 (AX)
  2326                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2327                              <1> 	               	    ; / sought in r1
  2328                              <1> 	; 09/01/2022
  2329 00004839 09C0                <1> 	or	eax, eax
  2330                              <1> 	;or 	ax, ax
  2331 0000483B 751D                <1>         jnz 	short mget_7 ; 2f
  2332                              <1> 		; bne 2f / if no block exists 
  2333 0000483D E81A000000          <1> 	call 	alloc
  2334                              <1> 		; jsr r0,alloc / allocate a new block
  2335 00004842 668903              <1> 	mov 	[ebx], ax ; R1
  2336                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2337                              <1> 	                    ; / indirect block
  2338 00004845 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2339                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2340 00004846 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2341 00004847 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2342 00004848 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2343                              <1> 		; mov (r2),-(sp) / save block number of new block
  2344                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2345 0000484A E8CD0C0000          <1> 	call 	wslot
  2346                              <1> 		; jsr r0,wslot
  2347                              <1>         ; eAX (r1) = physical block number
  2348                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2349 0000484F E8D50C0000          <1> 	call 	dskwr
  2350                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2351                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2352                              <1> 			     ; / back out on disk
  2353 00004854 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2354                              <1> 		; mov (sp),r1 / restore block number of new block	
  2355                              <1> 	; eAX (r1) = physical block number of new block
  2356 00004855 E82FFEFFFF          <1> 	call 	clear
  2357                              <1> 		; jsr r0,clear / clear new block	
  2358                              <1> mget_7: ; 2
  2359 0000485A 5A                  <1> 	pop 	edx ; **
  2360                              <1> 		; tst (sp)+ / bump stack pointer
  2361                              <1> 	; eAX (r1) = Block number of new block
  2362 0000485B C3                  <1> 	retn
  2363                              <1> 		; rts r0
  2364                              <1> 
  2365                              <1> alloc:
  2366                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2367                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2368                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2369                              <1> 	;
  2370                              <1> 	; get a free block and 
  2371                              <1> 	; set the corresponding bit in the free storage map
  2372                              <1> 	; 
  2373                              <1> 	; INPUTS ->
  2374                              <1> 	;    cdev (current device)
  2375                              <1> 	;    r2 
  2376                              <1> 	;    r3
  2377                              <1> 	; OUTPUTS ->
  2378                              <1> 	;    r1 (physical block number of block assigned)
  2379                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2380                              <1> 	;
  2381                              <1> 	; ((AX = R1)) output
  2382                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2383                              <1>         ;    ((Modified registers: DX, CX))  
  2384                              <1> 
  2385                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2386                              <1> 		;mov r3,-(sp)
  2387                              <1> 	;push 	ecx
  2388 0000485C 53                  <1> 	push 	ebx ; R2
  2389                              <1> 	;push 	edx ; R3
  2390 0000485D BB[CC760000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2391                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2392 00004862 803D[E3650000]00    <1> 	cmp 	byte [cdev], 0
  2393                              <1> 		; tst cdev
  2394 00004869 7605                <1> 	jna	short alloc_1
  2395                              <1> 		; beq 1f / drum is device
  2396 0000486B BB[D4780000]        <1> 	mov	ebx, mount
  2397                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2398                              <1> 			      ; / free storage map
  2399                              <1> alloc_1: ; 1
  2400                              <1> 	; 09/01/2022
  2401                              <1> 	;sub	ecx, ecx
  2402                              <1> 	;sub	edx, edx
  2403                              <1> 	;sub	eax, eax
  2404                              <1> 
  2405 00004870 668B0B              <1>         mov	cx, [ebx]
  2406                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2407                              <1> 			     ; / storage map
  2408                              <1> 	; 09/01/2022
  2409 00004873 C1E103              <1> 	shl	ecx, 3
  2410                              <1> 	;shl	cx, 3
  2411                              <1> 		; asl r1 / multiply r1 by eight gives 
  2412                              <1> 		; number of blocks in device
  2413                              <1> 		; asl r1
  2414                              <1> 		; asl r1
  2415                              <1> 	;;push	cx ;; 01/08/2013
  2416                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2417 00004876 31C0                <1> 	xor 	eax, eax ; 0
  2418                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2419                              <1> alloc_2: ; 1
  2420 00004878 43                  <1> 	inc 	ebx ; 18/8/2012
  2421 00004879 43                  <1> 	inc 	ebx ; 
  2422 0000487A 668B13              <1> 	mov 	dx, [ebx]
  2423                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2424                              <1> 	; 09/01/2022
  2425 0000487D 09D2                <1> 	or	edx, edx
  2426                              <1> 	;or 	dx, dx
  2427 0000487F 750D                <1> 	jnz 	short alloc_3 ; 1f
  2428                              <1> 		; bne 1f / branch if any free blocks in this word	
  2429 00004881 6683C010            <1> 	add 	ax, 16
  2430                              <1> 		; add $16.,r1
  2431                              <1> 	; 09/01/2022
  2432 00004885 39C8                <1> 	cmp	eax, ecx
  2433                              <1> 	;cmp 	ax, cx    
  2434                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2435 00004887 72EF                <1> 	jb 	short alloc_2
  2436                              <1> 		; blo 1b
  2437                              <1> 	; 14/11/2015
  2438                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2439                              <1> 	;	because of a (DMA or another) r/w error, 
  2440                              <1> 	;	we will be here, at 'jmp panic' code address,
  2441                              <1> 	;	even if the (disk) file system space is not full !!!
  2442                              <1> 	;	(cx = 0)	
  2443                              <1> 	;
  2444 00004889 E905E2FFFF          <1> 	jmp     panic 
  2445                              <1> 		; jmp panic / found no free storage
  2446                              <1> alloc_3: ; 1
  2447                              <1> 	; 09/01/2022
  2448 0000488E D1EA                <1> 	shr	edx, 1
  2449                              <1> 	;shr	dx, 1
  2450                              <1> 		; asr r3 / find a free block
  2451 00004890 7203                <1> 	jc	short alloc_4 ; 1f
  2452                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2453                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2454                              <1> 	; 09/01/2022
  2455 00004892 40                  <1> 	inc	eax
  2456                              <1> 	;inc	ax
  2457                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2458 00004893 EBF9                <1> 	jmp 	short alloc_3
  2459                              <1> 		; br 1b
  2460                              <1> alloc_4: ; 1:
  2461                              <1> 	;; pop cx ;; 01/08/2013
  2462                              <1> 		; tst (sp)+ / bump sp
  2463                              <1> 	; 02/04/2013 
  2464 00004895 E829000000          <1> 	call	free3
  2465                              <1> 		; jsr r0,3f / have found a free block
  2466                              <1> 	; 21/8/2012
  2467 0000489A 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2468 0000489D 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2469                              <1> 		; bic r3,(r2) / set bit for this block 
  2470                              <1> 		            ; / i.e. assign block
  2471                              <1> 		; br 2f
  2472 000048A0 EB09                <1> 	jmp 	short alloc_5
  2473                              <1> 
  2474                              <1> free:
  2475                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2476                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2477                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2478                              <1> 	;
  2479                              <1> 	; calculates byte address and bit position for given block number
  2480                              <1> 	; then sets the corresponding bit in the free storage map
  2481                              <1> 	; 
  2482                              <1> 	; INPUTS ->
  2483                              <1> 	;    r1 - block number for a block structured device
  2484                              <1> 	;    cdev - current device 
  2485                              <1> 	; OUTPUTS ->
  2486                              <1> 	;    free storage map is updated
  2487                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2488                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2489                              <1> 	;
  2490                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2491                              <1>         ;  ((Modified registers: DX, CX))  
  2492                              <1> 
  2493                              <1> 		;mov r2,-(sp) / save r2, r3
  2494                              <1> 		;mov r3,-(sp)
  2495                              <1> 	;push 	ecx
  2496 000048A2 53                  <1> 	push 	ebx ; R2
  2497                              <1> 	;push 	edx ; R3 
  2498                              <1> 
  2499 000048A3 E81B000000          <1>         call    free3
  2500                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2501                              <1> 				 ; / in free storage map for block
  2502 000048A8 660913              <1> 	or 	[ebx], dx  
  2503                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2504                              <1> 			    ;  / indicates free block	
  2505                              <1> 	; 0 -> allocated, 1 -> free
  2506                              <1> 
  2507                              <1> alloc_5:
  2508                              <1> 	; 07/04/2013
  2509                              <1> free_1: ; 2:
  2510                              <1> 	;pop 	edx
  2511                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2512 000048AB 5B                  <1> 	pop	ebx
  2513                              <1> 		; mov (sp)+,r2
  2514                              <1> 	; pop	ecx
  2515 000048AC 803D[E3650000]00    <1> 	cmp 	byte [cdev], 0
  2516                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2517                              <1> 			 ; / cdev = 1, mountable device
  2518 000048B3 7707                <1> 	ja	short alloc_6 ; 1f
  2519                              <1> 		; bne 1f
  2520                              <1> 	;mov	byte [smod], 1
  2521 000048B5 FE05[F1650000]      <1> 	inc 	byte [smod]
  2522                              <1> 		; incb smod / set super block modified for drum
  2523                              <1> 	; eAX (r1) = block number
  2524 000048BB C3                  <1> 	retn
  2525                              <1> 		; rts r0
  2526                              <1> free_2:
  2527                              <1> alloc_6: ; 1:
  2528                              <1> 	;mov 	byte [mmod], 1
  2529 000048BC FE05[F2650000]      <1> 	inc 	byte [mmod]
  2530                              <1> 		; incb	mmod 
  2531                              <1> 		  ; / set super block modified for mountable device
  2532                              <1> 	; eAX (r1) = block number
  2533 000048C2 C3                  <1> 	retn	
  2534                              <1> 		; rts r0
  2535                              <1> free3:
  2536                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2537                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2538                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2539                              <1> 	;
  2540                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2541                              <1> 	; 
  2542                              <1> alloc_free_3: ; 3
  2543                              <1> 	;mov 	dx, 1
  2544                              <1> 	; 09/01/2022
  2545 000048C3 31D2                <1> 	xor	edx, edx
  2546 000048C5 42                  <1> 	inc	edx
  2547                              <1> 	; edx = 1
  2548 000048C6 88C1                <1> 	mov 	cl, al
  2549                              <1> 		; mov r1,r2 / block number, k, = 1		
  2550 000048C8 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2551                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2552 000048CB 7402                <1> 	jz 	short free4
  2553                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2554                              <1> 			       ; / (k) mod 8
  2555                              <1> 	;shl 	dx, cl
  2556                              <1> 	; 09/01/2022
  2557 000048CD D3E2                <1> 	shl	edx, cl
  2558                              <1> free4:
  2559 000048CF 0FB7D8              <1> 	movzx 	ebx, ax
  2560                              <1> 		; mov r1,r2 / divide block number by 16
  2561                              <1> 	; 09/01/2022
  2562 000048D2 C1EB04              <1> 	shr	ebx, 4
  2563                              <1> 	;shr 	bx, 4
  2564                              <1> 		; asr r2
  2565                              <1> 		; asr r2
  2566                              <1> 		; asr r2
  2567                              <1> 		; asr r2
  2568                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2569                              <1> 		       ; / bit for block is in lower half of word
  2570                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2571                              <1> 		        ; / storage map
  2572                              <1> alloc_free_4: ; 1
  2573                              <1> 	; 09/01/2022
  2574 000048D5 D1E3                <1> 	shl	ebx, 1
  2575                              <1> 	;shl 	bx, 1
  2576                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2577 000048D7 81C3[CE760000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2578                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2579                              <1> 	    		        ; / with block bit in it 	
  2580 000048DD 803D[E3650000]00    <1> 	cmp	byte [cdev], 0
  2581                              <1> 		; tst cdev
  2582 000048E4 7606                <1> 	jna	short alloc_free_5
  2583                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2584 000048E6 81C308020000        <1> 	add	ebx, mount - systm
  2585                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2586                              <1> 				    ; / mountable device with bit of block to be
  2587                              <1> 				    ; / freed
  2588                              <1> alloc_free_5: ; 1 
  2589 000048EC C3                  <1> 	retn
  2590                              <1> 		; rts r0 / return to 'free'
  2591                              <1> 	      ; 2
  2592                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2593                              <1> 	
  2594                              <1> iget:
  2595                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2596                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2597                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2598                              <1> 	;
  2599                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2600                              <1> 	;
  2601                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2602                              <1> 	; 
  2603                              <1> 	; INPUTS ->
  2604                              <1> 	;    ii - current i-number, rootdir
  2605                              <1> 	;    cdev - new i-node device
  2606                              <1> 	;    idev - current i-node device
  2607                              <1> 	;    imod - current i-node modified flag
  2608                              <1> 	;    mnti - cross device file i-number
  2609                              <1> 	;    r1 - i-numbe rof new i-node
  2610                              <1> 	;    mntd - mountable device number		
  2611                              <1> 	; 	 
  2612                              <1> 	; OUTPUTS ->
  2613                              <1> 	;    cdev, idev, imod, ii, r1
  2614                              <1> 	;
  2615                              <1> 	; ((AX = R1)) input/output
  2616                              <1> 	;
  2617                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2618                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2619                              <1> 
  2620 000048ED 8A15[E3650000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2621 000048F3 8A35[E2650000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2622                              <1> 	;
  2623 000048F9 663B05[E0650000]    <1> 	cmp 	ax, [ii]
  2624                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2625 00004900 7504                <1> 	jne 	short iget_1
  2626                              <1> 		; bne 1f
  2627 00004902 38F2                <1> 	cmp	dl, dh
  2628                              <1> 		; cmp idev,cdev
  2629                              <1> 			  ; / is device number of i-node = current device
  2630 00004904 7472                <1>         je      short iget_5
  2631                              <1> 		; beq 2f
  2632                              <1> iget_1: ; 1:
  2633 00004906 30DB                <1> 	xor	bl, bl
  2634 00004908 381D[F0650000]      <1> 	cmp	[imod], bl ; 0	
  2635                              <1> 		; tstb imod / has i-node of current file
  2636                              <1> 			  ; / been modified i.e., imod set
  2637 0000490E 7629                <1> 	jna	short iget_2
  2638                              <1> 		; beq 1f
  2639 00004910 881D[F0650000]      <1> 	mov	[imod], bl ; 0
  2640                              <1> 		;  clrb	imod / if it has, 
  2641                              <1> 			   ; / we must write the new i-node out on disk
  2642                              <1> 	; 24/12/2021
  2643 00004916 50                  <1> 	push	eax ; *
  2644                              <1> 	;push	ax
  2645                              <1> 		; mov r1,-(sp)
  2646                              <1> 	;mov	dl, [cdev]
  2647 00004917 52                  <1> 	push	edx ; **
  2648                              <1> 	;push	dx
  2649                              <1> 		; mov cdev,-(sp)
  2650 00004918 66A1[E0650000]      <1> 	mov	ax, [ii]
  2651                              <1> 		; mov ii,r1
  2652                              <1> 	;mov	dh, [idev]
  2653 0000491E 8835[E3650000]      <1> 	mov	[cdev], dh
  2654                              <1> 		; mov idev,cdev
  2655 00004924 FEC3                <1> 	inc	bl ; 1
  2656                              <1> 	; 31/07/2013
  2657 00004926 881D[80660000]      <1> 	mov     [rw], bl ; 1 == write 
  2658                              <1> 	;;28/07/2013 rw -> u.rw
  2659                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2660 0000492C E848000000          <1> 	call	icalc
  2661                              <1> 		; jsr r0,icalc; 1
  2662                              <1> 	;pop	dx
  2663                              <1> 	; 24/12/2021
  2664 00004931 5A                  <1> 	pop	edx ; **
  2665 00004932 8815[E3650000]      <1> 	mov	[cdev], dl
  2666                              <1> 		; mov (sp)+,cdev
  2667                              <1> 	; 24/12/2021
  2668 00004938 58                  <1> 	pop	eax ; *
  2669                              <1> 	;pop	ax
  2670                              <1> 		; mov (sp)+,r1
  2671                              <1> iget_2: ; 1:
  2672 00004939 6621C0              <1> 	and	ax, ax
  2673                              <1> 		; tst r1 / is new i-number non zero
  2674 0000493C 7434                <1> 	jz	short iget_4 ; 2f
  2675                              <1> 		; beq 2f / branch if r1=0
  2676                              <1> 
  2677                              <1> 	;mov 	dl, [cdev]
  2678 0000493E 08D2                <1> 	or	dl, dl
  2679                              <1> 		; tst cdev / is the current device number non zero
  2680                              <1> 			 ; / (i.e., device =/ drum)
  2681 00004940 7517                <1> 	jnz	short iget_3 ;  1f
  2682                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2683 00004942 663B05[E6650000]    <1> 	cmp	ax, [mnti]			
  2684                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2685                              <1> 			    ; / file (root directory of mounted device)
  2686 00004949 750E                <1> 	jne	short iget_3 ; 1f
  2687                              <1> 		; bne 1f
  2688                              <1>         ;mov    bl, [mntd]
  2689 0000494B FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2690 0000494D 8815[E3650000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2691                              <1> 		; mov mntd,cdev / make mounted device the current device
  2692 00004953 66A1[EC650000]      <1> 	mov	ax, [rootdir]
  2693                              <1> 		; mov rootdir,r1
  2694                              <1> iget_3: ; 1:
  2695 00004959 66A3[E0650000]      <1> 	mov	[ii], ax
  2696                              <1> 		; mov r1,ii
  2697 0000495F 8815[E2650000]      <1> 	mov	[idev], dl ; cdev
  2698                              <1> 		; mov cdev,idev
  2699 00004965 30DB                <1> 	xor	bl, bl
  2700                              <1>         ; 31/07/2013
  2701 00004967 881D[80660000]      <1> 	mov     [rw], bl ; 0 == read 
  2702                              <1> 	;;28/07/2013 rw -> u.rw       
  2703                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2704 0000496D E807000000          <1> 	call	icalc
  2705                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2706                              <1> iget_4: ; 2:
  2707 00004972 66A1[E0650000]      <1> 	mov	ax, [ii]
  2708                              <1> 		; mov ii,r1
  2709                              <1> iget_5:
  2710 00004978 C3                  <1> 	retn
  2711                              <1> 		; rts r0
  2712                              <1> 
  2713                              <1> icalc:
  2714                              <1> 	; 04/04/2022 (47->31)
  2715                              <1> 	;	(Inode Table/List Address modification)
  2716                              <1> 	; 09/01/2022
  2717                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2718                              <1> 	; 02/07/2015
  2719                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2720                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2721                              <1> 	;
  2722                              <1> 	; calculate physical block number from i-number then
  2723                              <1> 	; read or write that block
  2724                              <1> 	;
  2725                              <1> 	; 'icalc' is called from 'iget'
  2726                              <1> 	;
  2727                              <1> 	; for original unix v1:
  2728                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2729                              <1>        	; / (i+31.) mod 16. bytes from its start
  2730                              <1> 	;
  2731                              <1> 	; for retro unix 8086 v1:
  2732                              <1> 	;  i-node is located in block (i+47)/16 and
  2733                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2734                              <1> 	;
  2735                              <1> 	; INPUTS ->
  2736                              <1> 	;    r1 - i-number of i-node
  2737                              <1> 	; 	 
  2738                              <1> 	; OUTPUTS ->
  2739                              <1> 	;    inode r/w
  2740                              <1> 	;
  2741                              <1> 	; ((AX = R1)) input
  2742                              <1> 	;
  2743                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2744                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2745                              <1> 	;
  2746 00004979 0FB7D0              <1> 	movzx	edx, ax	
  2747                              <1> 	;add	dx, 47
  2748                              <1> 	; 04/04/2022
  2749 0000497C 6683C21F            <1> 	add	dx, 31
  2750 00004980 89D0                <1> 	mov	eax, edx
  2751                              <1> 	;;add	ax, 47	; add 47 to inode number
  2752                              <1> 	;add	ax, 31
  2753                              <1> 		; add $31.,r1 / add 31. to i-number
  2754 00004982 50                  <1> 	push	eax
  2755                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2756                              <1> 	; 09/01/2022
  2757 00004983 C1E804              <1> 	shr	eax, 4
  2758                              <1> 	;shr 	ax, 4
  2759                              <1> 		; asr r1 / divide by 16.
  2760                              <1> 		; asr r1
  2761                              <1> 		; asr r1
  2762                              <1> 		; asr r1 / r1 contains block number of block
  2763                              <1> 		       ; / in which i-node exists
  2764 00004986 E82D0B0000          <1> 	call	dskrd
  2765                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2766                              <1> 	; 31/07/2013
  2767 0000498B 803D[80660000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2768                              <1> 	;; 28/07/2013 rw -> u.rw
  2769                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2770                              <1> 		; tst (r0)
  2771 00004992 7605                <1> 	jna	short icalc_1
  2772                              <1> 		; beq 1f / branch to wslot when argument
  2773                              <1> 		       ; / in icalc call = 1
  2774                              <1> 	; eAX = r1 = block number
  2775 00004994 E8830B0000          <1> 	call	wslot
  2776                              <1> 		; jsr r0,wslot / set up data buffer for write
  2777                              <1> 			     ; / (will be same buffer as dskrd got)
  2778                              <1> 	; eBX = r5 points to first word in data area for this block
  2779                              <1> icalc_1: ; 1:
  2780 00004999 5A                  <1> 	pop	edx 
  2781 0000499A 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2782                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2783                              <1> 			      ; / gives (i+31.) mod 16
  2784 0000499D C1E205              <1> 	shl 	edx, 5
  2785                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2786 000049A0 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2787 000049A2 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2788                              <1>           	; eSI (r5) points to first word in i-node i.	
  2789                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2790                              <1> 			     ; / 32.*(i+31.)mod16
  2791                              <1> 		; mov $5,lsh / for i-node i.
  2792                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2793 000049A4 BF[F4620000]        <1> 	mov	edi, inode
  2794                              <1> 		; mov $inode,r1 / inode is address of first word 
  2795                              <1> 			      ; / of current i-node
  2796                              <1> 	; 09/01/2022
  2797 000049A9 29C9                <1> 	sub	ecx, ecx
  2798 000049AB B108                <1> 	mov	cl, 8 
  2799                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2800                              <1> 		; mov $16.,r3
  2801                              <1>        ; 31/07/2013
  2802 000049AD 382D[80660000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2803                              <1>        ;;28/07/2013 rw -> u.rw                 
  2804                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2805                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2806 000049B3 7609                <1> 	jna	short icalc_3
  2807                              <1> 		; beq 2f / r0 now contains proper return address 
  2808                              <1> 		       ; / for rts r0
  2809                              <1> icalc_2: ; 1:
  2810 000049B5 87F7                <1> 	xchg 	esi, edi
  2811                              <1> 	; overwrite old i-node (in buffer to be written)
  2812 000049B7 F3A5                <1> 	rep 	movsd
  2813                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2814                              <1> 		; dec r3
  2815                              <1> 		; bgt 1b
  2816                              <1> 	;call	dskwr
  2817                              <1> 		; jsr r0,dskwr / write inode out on device
  2818                              <1> 	;retn
  2819                              <1> 		; rts r0
  2820                              <1> 	; 24/12/2021
  2821 000049B9 E96B0B0000          <1> 	jmp	dskwr
  2822                              <1> 
  2823                              <1> icalc_3: ; 2:
  2824                              <1> 	; copy new i-node into inode area of (core) memory
  2825 000049BE F3A5                <1> 	rep 	movsd
  2826                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2827                              <1> 		                ; / "inode" area of core
  2828                              <1> 		; dec r3
  2829                              <1> 		; bgt 2b
  2830 000049C0 C3                  <1> 	retn
  2831                              <1> 		; rts r0
  2832                              <1> 
  2833                              <1> access:
  2834                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2835                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2836                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2837                              <1> 	;
  2838                              <1> 	; check whether user is owner of file or user has read or write
  2839                              <1> 	; permission (based on i.flgs).
  2840                              <1> 	;
  2841                              <1> 	; INPUTS ->
  2842                              <1> 	;    r1 - i-number of file
  2843                              <1> 	;    u.uid
  2844                              <1> 	; arg0 -> (owner flag mask)	 		
  2845                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2846                              <1> 	; OUTPUTS ->
  2847                              <1> 	;    inode (or jump to error)
  2848                              <1> 	;
  2849                              <1> 	; ((AX = R1)) input/output
  2850                              <1> 	;
  2851                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2852                              <1> 	
  2853                              <1> 	;push	dx  ; save flags (DL)
  2854                              <1> 	; 24/12/2021
  2855 000049C1 52                  <1> 	push	edx ; save flags (DL)
  2856 000049C2 E826FFFFFF          <1> 	call	iget
  2857                              <1> 		; jsr r0,iget / read in i-node for current directory
  2858                              <1> 			    ; / (i-number passed in r1)
  2859 000049C7 8A0D[F4620000]      <1> 	mov	cl, [i.flgs]
  2860                              <1> 		; mov i.flgs,r2
  2861                              <1> 	; 24/12/2021
  2862 000049CD 5A                  <1> 	pop	edx ; restore flags (DL)
  2863                              <1> 	;pop	dx  ; restore flags (DL)
  2864 000049CE 8A35[48660000]      <1> 	mov	dh, [u.uid]
  2865 000049D4 3A35[F7620000]      <1> 	cmp	dh, [i.uid]
  2866                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2867 000049DA 7503                <1> 	jne	short access_1
  2868                              <1> 		; bne 1f / no, then branch
  2869 000049DC C0E902              <1> 	shr	cl, 2
  2870                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2871                              <1> 		        ; / read/write bits
  2872                              <1> 		; asrb r2
  2873                              <1> access_1: ; 1:
  2874 000049DF 20D1                <1> 	and	cl, dl
  2875                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2876                              <1> 			     ; / in access call
  2877 000049E1 7513                <1> 	jnz	short access_2
  2878                              <1> 		; bne 1f
  2879 000049E3 08F6                <1> 	or	dh, dh	; super user (root) ?
  2880                              <1> 		; tstb u.uid
  2881 000049E5 740F                <1> 	jz	short access_2 ; yes, super user
  2882                              <1> 	;jnz	error
  2883                              <1> 		; beq 1f
  2884                              <1> 		; jmp error
  2885 000049E7 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2885 000049EF 0000                <1>
  2886                              <1> 			; 'permission denied !' error
  2887 000049F1 E9DBE7FFFF          <1> 	jmp	error
  2888                              <1> 
  2889                              <1> access_2: ; 1:
  2890                              <1> 	; DL = flags
  2891 000049F6 C3                  <1> 	retn
  2892                              <1> 		; rts r0
  2893                              <1> 
  2894                              <1> setimod:
  2895                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2896                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2897                              <1> 	;
  2898                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2899                              <1> 	; the inode has been modified. Also puts the time of modification
  2900                              <1> 	; into the inode.
  2901                              <1> 	;
  2902                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2903                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2904                              <1> 	;
  2905                              <1> 	
  2906                              <1> 	;push 	edx
  2907 000049F7 50                  <1> 	push	eax
  2908                              <1> 
  2909 000049F8 C605[F0650000]01    <1> 	mov 	byte [imod], 1
  2910                              <1> 		; movb $1,imod / set current i-node modified bytes
  2911                              <1> 	; Erdogan Tan 14-7-2012
  2912 000049FF E81EE3FFFF          <1> 	call 	epoch
  2913                              <1> 		 ; mov s.time,i.mtim 
  2914                              <1> 			    ; / put present time into file modified time
  2915                              <1> 		 ; mov s.time+2,i.mtim+2
  2916                              <1> 
  2917 00004A04 A3[0E630000]        <1> 	mov 	[i.mtim], eax
  2918                              <1> 	
  2919                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2920                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2921 00004A09 833D[0A630000]00    <1> 	cmp	dword [i.ctim], 0
  2922 00004A10 7505                <1> 	jnz	short setimod_ok
  2923                              <1> 
  2924 00004A12 A3[0A630000]        <1> 	mov 	[i.ctim], eax
  2925                              <1> 
  2926                              <1> setimod_ok: ; 31/07/2013
  2927 00004A17 58                  <1> 	pop	eax
  2928                              <1> 	;pop	edx
  2929                              <1> 	
  2930 00004A18 C3                  <1> 	retn
  2931                              <1> 		; rts r0
  2932                              <1> 
  2933                              <1> itrunc:
  2934                              <1> 	; 03/02/2022
  2935                              <1> 	; 09/01/2022
  2936                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2937                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2938                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2939                              <1> 	;
  2940                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2941                              <1> 	;  to zero length.
  2942                              <1> 	;
  2943                              <1> 	; INPUTS ->
  2944                              <1> 	;    r1 - i-number of i-node
  2945                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2946                              <1> 	;    i.flgs - large file flag		
  2947                              <1> 	;    i.size - size of file	
  2948                              <1> 	; 	 
  2949                              <1> 	; OUTPUTS ->
  2950                              <1> 	;    i.flgs - large file flag is cleared
  2951                              <1> 	;    i.size - set to 0	
  2952                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2953                              <1> 	;    setimod - set to indicate i-node has been modified
  2954                              <1> 	;    r1 - i-number of i-node  					
  2955                              <1> 	;
  2956                              <1> 	; ((AX = R1)) input/output
  2957                              <1> 	;
  2958                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2959                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2960                              <1> 
  2961 00004A19 E8CFFEFFFF          <1> 	call	iget
  2962                              <1> 		; jsr r0,iget
  2963 00004A1E BE[FA620000]        <1> 	mov	esi, i.dskp
  2964                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2965 00004A23 31C0                <1> 	xor	eax, eax
  2966                              <1> itrunc_1: ; 1:
  2967 00004A25 66AD                <1> 	lodsw
  2968                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2969                              <1> 	; 09/01/2022
  2970 00004A27 09C0                <1> 	or	eax, eax
  2971                              <1> 	;or 	ax, ax
  2972 00004A29 7433                <1> 	jz	short itrunc_5
  2973                              <1> 		; beq 5f
  2974 00004A2B 56                  <1> 	push	esi
  2975                              <1> 		; mov r2,-(sp)
  2976                              <1> 	; 09/01/2022
  2977 00004A2C F605[F5620000]10    <1> 	test	byte [i.flgs+1], 10h
  2978                              <1> 	;test	word [i.flgs], 1000h
  2979                              <1> 		; bit $10000,i.flgs / test large file bit?
  2980 00004A33 7423                <1> 	jz	short itrunc_4
  2981                              <1> 		; beq 4f / if clear, branch
  2982 00004A35 50                  <1> 	push	eax
  2983                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2984 00004A36 E87D0A0000          <1> 	call	dskrd
  2985                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2986                              <1> 			     ; / pointed to by r5
  2987                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2988                              <1> 	; 09/01/2022
  2989 00004A3B 31C9                <1> 	xor	ecx, ecx
  2990 00004A3D FEC5                <1> 	inc	ch ; mov ch, 1
  2991                              <1> 	; ecx = 256
  2992                              <1> 	;mov	ecx, 256
  2993                              <1> 		; mov $256.,r3 / move word count into r3
  2994 00004A3F 89DE                <1> 	mov	esi, ebx
  2995                              <1> itrunc_2: ; 2:
  2996 00004A41 66AD                <1> 	lodsw
  2997                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2998                              <1> 			     ; / physical block number
  2999                              <1> 	; 09/01/2022
  3000 00004A43 21C0                <1> 	and	eax, eax
  3001                              <1> 	;and	ax, ax
  3002 00004A45 7407                <1> 	jz	short itrunc_3
  3003                              <1> 		; beq 3f / branch if zero
  3004                              <1> 	; 24/12/2021
  3005 00004A47 51                  <1> 	push	ecx
  3006                              <1> 	;push	cx
  3007                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3008                              <1> 	;push	esi
  3009                              <1> 		; mov r5,-(sp)
  3010 00004A48 E855FEFFFF          <1> 	call	free
  3011                              <1> 		; jsr r0,free / free block in free storage map
  3012                              <1> 	;pop	esi
  3013                              <1> 		; mov(sp)+,r5
  3014                              <1> 	;pop	cx
  3015 00004A4D 59                  <1> 	pop	ecx
  3016                              <1> 		; mov (sp)+,r3
  3017                              <1> itrunc_3: ; 3:
  3018 00004A4E E2F1                <1> 	loop	itrunc_2
  3019                              <1> 		; dec r3 / decrement word count
  3020                              <1> 		; bgt 2b / branch if positive
  3021 00004A50 58                  <1> 	pop	eax
  3022                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3023                              <1> 			     ; / indirect block
  3024                              <1> 	; 01/08/2013
  3025                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3026                              <1> 	; 03/02/2022
  3027 00004A51 8025[F5620000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  3028                              <1> itrunc_4: ; 4:
  3029 00004A58 E845FEFFFF          <1> 	call	free
  3030                              <1> 		; jsr r0,free / free indirect block
  3031 00004A5D 5E                  <1> 	pop	esi
  3032                              <1> 		; mov (sp)+,r2
  3033                              <1> itrunc_5: ; 5:
  3034 00004A5E 81FE[0A630000]      <1> 	cmp	esi, i.dskp+16
  3035                              <1> 		; cmp r2,$i.dskp+16.
  3036 00004A64 72BF                <1> 	jb	short itrunc_1	
  3037                              <1> 		; bne 1b / branch until all i.dskp entries check
  3038                              <1> 	; 03/02/2022
  3039                              <1> 	;and	byte [i.flgs+1], 0EFh
  3040                              <1> 	; 01/08/2013
  3041                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3042                              <1> 		; bic $10000,i.flgs / clear large file bit
  3043 00004A66 BF[FA620000]        <1> 	mov	edi, i.dskp
  3044                              <1> 	;mov	cx, 8
  3045                              <1> 	;xor 	ax, ax
  3046                              <1> 	; 09/01/2022
  3047 00004A6B 29C9                <1> 	sub	ecx, ecx
  3048 00004A6D B108                <1> 	mov	cl, 8
  3049 00004A6F 29C0                <1> 	sub	eax, eax
  3050 00004A71 66A3[F8620000]      <1> 	mov	[i.size], ax ; 0
  3051                              <1> 		; clr i.size / zero file size
  3052 00004A77 F366AB              <1> 	rep	stosw
  3053                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3054                              <1> 			   ; / zero block pointers
  3055 00004A7A E878FFFFFF          <1> 	call	setimod
  3056                              <1> 		; jsr r0,setimod / set i-node modified flag
  3057 00004A7F 66A1[E0650000]      <1> 	mov	ax, [ii]
  3058                              <1> 		; mov ii,r1
  3059 00004A85 C3                  <1> 	retn
  3060                              <1> 		; rts r0
  3061                              <1> 
  3062                              <1> imap:
  3063                              <1> 	; 11/02/2022
  3064                              <1> 	; 03/02/2022
  3065                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3066                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3067                              <1> 	;
  3068                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3069                              <1> 	; allocation bit for an i-node whose number in r1.
  3070                              <1> 	;
  3071                              <1> 	; INPUTS ->
  3072                              <1> 	;    r1 - contains an i-number
  3073                              <1> 	;    fsp - start of table containing open files
  3074                              <1> 	;
  3075                              <1> 	; OUTPUTS ->
  3076                              <1> 	;    r2 - byte address of byte with the allocation bit
  3077                              <1> 	;    mq - a mask to locate the bit position.	
  3078                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3079                              <1> 	;
  3080                              <1> 	; ((AX = R1)) input/output
  3081                              <1> 	; ((DL/DX = MQ)) output
  3082                              <1> 	; ((BX = R2)) output
  3083                              <1> 	;
  3084                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3085                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3086                              <1> 	;
  3087                              <1> 		; / get the byte that has the allocation bit for 
  3088                              <1> 		; / the i-number contained in r1
  3089                              <1> 	;mov	dx, 1
  3090 00004A86 B201                <1> 	mov	dl, 1
  3091                              <1> 		; mov $1,mq / put 1 in the mq
  3092 00004A88 0FB7D8              <1> 	movzx	ebx, ax
  3093                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3094                              <1>  		          ; / in the map we must find
  3095 00004A8B 6683EB29            <1> 	sub	bx, 41
  3096                              <1> 		; sub $41.,r2 / r2 has i-41
  3097 00004A8F 88D9                <1> 	mov	cl, bl
  3098                              <1> 		; mov r2,r3 / r3 has i-41
  3099 00004A91 80E107              <1> 	and	cl, 7
  3100                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3101                              <1> 			   ; / the bit position
  3102 00004A94 7402                <1> 	jz	short imap1
  3103                              <1> 	;shl	dx, cl
  3104 00004A96 D2E2                <1> 	shl	dl, cl
  3105                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3106                              <1> imap1:			   ; / to the left to mask the correct bit
  3107                              <1> 	; 03/02/2022
  3108 00004A98 C1EB03              <1> 	shr	ebx, 3
  3109                              <1> 	;shr	bx, 3
  3110                              <1> 		; asr r2
  3111                              <1> 		; asr r2
  3112                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3113                              <1> 		       ; / from the start of the map
  3114                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3115 00004A9B BE[CC760000]        <1> 	mov	esi, systm
  3116                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3117                              <1> 				; / the super block for drum
  3118                              <1> 	;cmp	word [cdev], 0
  3119 00004AA0 803D[E3650000]00    <1> 	cmp	byte [cdev], 0
  3120                              <1> 		; tst cdev / is the device the disk
  3121 00004AA7 7606                <1> 	jna	short imap2
  3122                              <1> 		; beq 1f / yes
  3123 00004AA9 81C608020000        <1> 	add	esi, mount - systm
  3124                              <1> 		; add $mount-systm,r2 / for mounted device,
  3125                              <1> 			; / r2 points to 1st word of its super block
  3126                              <1> imap2: ; 1:
  3127 00004AAF 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3128                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3129 00004AB2 6683C304            <1> 	add	bx, 4
  3130 00004AB6 01F3                <1> 	add	ebx, esi
  3131                              <1>         	; add (sp)+,r2 / ?
  3132                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3133                              <1> 		      ;; (2 + free map size + 2)
  3134                              <1> 		; add $2,r2 / ?
  3135                              <1> 
  3136                              <1> 	; 11/02/2022
  3137 00004AB8 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3138 00004ABE 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3139                              <1> 			  ; if inode num overs inode count
  3140                              <1> 
  3141                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3142                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3143                              <1> 
  3144                              <1> 	; 11/02/2022
  3145                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3146                              <1> 	;	(number of requested inode > inode count)
  3147                              <1> 
  3148 00004AC0 C3                  <1> 	retn
  3149                              <1> 		; rts r0
  2118                                  %include 'u6.s'        ; 31/05/2015
  2119                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS6.INC
  2120                              <1> ; Last Modification: 19/07/2022
  2121                              <1> ; ----------------------------------------------------------------------------
  2122                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2123                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2124                              <1> ;
  2125                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2126                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2127                              <1> ; <Bell Laboratories (17/3/1972)>
  2128                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2129                              <1> ;
  2130                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2131                              <1> ;
  2132                              <1> ; ****************************************************************************
  2133                              <1> 
  2134                              <1> readi:
  2135                              <1> 	; 11/01/2022
  2136                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2137                              <1> 	; 20/05/2015
  2138                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2139                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2140                              <1> 	;
  2141                              <1> 	; Reads from an inode whose number in R1
  2142                              <1> 	; 
  2143                              <1> 	; INPUTS ->
  2144                              <1> 	;    r1 - inode number
  2145                              <1> 	;    u.count - byte count user desires
  2146                              <1> 	;    u.base - points to user buffer
  2147                              <1> 	;    u.fofp - points to word with current file offset
  2148                              <1> 	; OUTPUTS ->
  2149                              <1> 	;    u.count - cleared
  2150                              <1> 	;    u.nread - accumulates total bytes passed back
  2151                              <1> 	;
  2152                              <1> 	; ((AX = R1)) input/output
  2153                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2154                              <1>         ;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -15/07/2022- 
  2155                              <1> 
  2156 00004AC1 31D2                <1> 	xor	edx, edx ; 0
  2157 00004AC3 8915[24660000]      <1> 	mov 	[u.nread], edx ; 0
  2158                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2159 00004AC9 668915[61660000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2160 00004AD0 3915[20660000]      <1> 	cmp 	[u.count], edx ; 0
  2161                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2162 00004AD6 7701                <1> 	ja 	short readi_1 ; 1f
  2163                              <1> 		 ; bgt 1f / yes, branch
  2164 00004AD8 C3                  <1> 	retn
  2165                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2166                              <1> readi_1: ; 1:
  2167                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2168 00004AD9 6683F828            <1> 	cmp	ax, 40
  2169                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2170                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2171                              <1>         ;ja	dskr 
  2172                              <1> 		 ; ble 1f / yes, branch
  2173                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2174                              <1> 		 ;         / read file with i-node number (r1)
  2175                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2176                              <1> 	; 24/12/2021
  2177 00004ADD 7605                <1> 	jna	short readi_3
  2178 00004ADF E9CF000000          <1> 	jmp	dskr
  2179                              <1> readi_3:
  2180                              <1> 	; (20/05/2015)
  2181 00004AE4 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2182                              <1> 	; 1:
  2183 00004AE5 0FB6D8              <1> 	movzx	ebx, al
  2184                              <1> 	; 11/01/2022
  2185 00004AE8 C1E302              <1> 	shl	ebx, 2
  2186                              <1> 	;shl	bx, 2
  2187                              <1> 		 ; asl r1 / multiply inode number by 2
  2188 00004AEB 81C3[EF4A0000]      <1> 	add	ebx, readi_2 - 4
  2189 00004AF1 FF23                <1> 	jmp	dword [ebx]	
  2190                              <1> 		 ; jmp *1f-2(r1)
  2191                              <1> readi_2: ; 1:
  2192 00004AF3 [3F4B0000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2193                              <1> 		 ;rtty / tty; r1=2
  2194                              <1> 		 ;rppt / ppt; r1=4
  2195 00004AF7 [8F4B0000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2196                              <1> 		 ;rmem / mem; r1=6
  2197                              <1> 		 ;rrf0 / rf0
  2198                              <1> 		 ;rrk0 / rk0
  2199                              <1> 		 ;rtap / tap0
  2200                              <1> 		 ;rtap / tap1
  2201                              <1> 		 ;rtap / tap2
  2202                              <1> 		 ;rtap / tap3
  2203                              <1> 		 ;rtap / tap4
  2204                              <1> 		 ;rtap / tap5
  2205                              <1> 		 ;rtap / tap6
  2206                              <1> 		 ;rtap / tap7
  2207 00004AFB [79530000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2208 00004AFF [79530000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2209 00004B03 [79530000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2210 00004B07 [79530000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2211 00004B0B [79530000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2212 00004B0F [79530000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2213 00004B13 [A44B0000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2214 00004B17 [8B4B0000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2215                              <1> 		 ;rcvt / tty0
  2216 00004B1B [8B4B0000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2217                              <1> 		 ;rcvt / tty1
  2218 00004B1F [8B4B0000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2219                              <1> 		 ;rcvt / tty2
  2220 00004B23 [8B4B0000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2221                              <1> 		 ;rcvt / tty3
  2222 00004B27 [8B4B0000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2223                              <1> 		 ;rcvt / tty4
  2224 00004B2B [8B4B0000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2225                              <1> 		 ;rcvt / tty5
  2226 00004B2F [8B4B0000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2227                              <1> 		 ;rcvt / tty6
  2228 00004B33 [8B4B0000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2229                              <1> 		 ;rcvt / tty7
  2230 00004B37 [8B4B0000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2231                              <1> 		 ;rcrd / crd
  2232 00004B3B [8B4B0000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2233                              <1> 
  2234                              <1> rtty: ; / read from console tty
  2235                              <1> 	; 11/01/2022
  2236                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2237                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2238                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2239                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2240                              <1> 	;	     must be written immediate on video page (screen)
  2241                              <1> 	;	     when it is required.	
  2242                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2243                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2244                              <1> 	;
  2245                              <1> 	; Console tty buffer is PC keyboard buffer
  2246                              <1> 	; and keyboard-keystroke handling is different than original
  2247                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2248                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2249                              <1> 	;
  2250                              <1> 	; 06/12/2013
  2251 00004B3F 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2252 00004B46 8A83[53630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2253                              <1> rttys:
  2254                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2255                              <1> 	               ; / of the control and status block
  2256                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2257                              <1> 		       ; / tty buffer
  2258                              <1> 	; 28/07/2013
  2259 00004B4C A2[50660000]        <1> 	mov 	[u.ttyn], al
  2260                              <1> 	; 13/01/2014
  2261 00004B51 FEC0                <1> 	inc	al
  2262 00004B53 A2[2C660000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2263                              <1> rtty_nc: ; 01/02/2014
  2264                              <1> 	; 29/09/2013
  2265                              <1> 	;mov	ecx, 10
  2266                              <1> 	; 11/01/2022
  2267 00004B58 29C9                <1> 	sub	ecx, ecx
  2268 00004B5A B10A                <1> 	mov	cl, 10
  2269                              <1> rtty_1: 	; 01/02/2014
  2270                              <1> 	;push 	cx ; 29/09/2013
  2271                              <1> 	; 24/12/2021
  2272 00004B5C 51                  <1> 	push	ecx
  2273                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2274 00004B5D B001                <1> 	mov 	al, 1
  2275 00004B5F E8200B0000          <1> 	call 	getc
  2276                              <1> 	; 24/12/2021
  2277 00004B64 59                  <1> 	pop	ecx
  2278                              <1> 	;pop 	cx ; 29/09/2013	
  2279 00004B65 7516                <1> 	jnz	short rtty_2
  2280                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2281                              <1> 	               ; / of chars. Is this number non-zero?
  2282 00004B67 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2283                              <1> 	; 05/10/2013
  2284 00004B69 8A25[50660000]      <1> 	mov	ah, [u.ttyn]
  2285                              <1> 	; 29/09/2013
  2286 00004B6F E898FBFFFF          <1> 	call	sleep
  2287                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2288                              <1>                 ;           / (120 chars.)
  2289                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2290 00004B74 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2291                              <1> 
  2292                              <1> rtty_idle:
  2293                              <1> 	; 29/07/2013
  2294 00004B76 E804FBFFFF          <1> 	call 	idle
  2295 00004B7B EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2296                              <1> 	;1:
  2297                              <1> 		; tst 2(r5) / is the number of characters zero
  2298                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2299                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2300                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2301                              <1> 		          ; / contains the next char.
  2302                              <1> 		; dec 2(r5) / decrement the character count
  2303                              <1> rtty_2:
  2304 00004B7D 30C0                <1> 	xor 	al, al
  2305 00004B7F E8000B0000          <1> 	call 	getc
  2306 00004B84 E896000000          <1> 	call	passc
  2307                              <1> 		; jsr r0,passc / move the character to core (user)
  2308                              <1> 	;; 17/10/2015 - 16/07/2015
  2309                              <1> 	; 19/06/2014
  2310                              <1> 	;;jnz	short rtty_nc
  2311 00004B89 58                  <1> 	pop	eax  ; (20/05/2015)
  2312 00004B8A C3                  <1> 	retn 
  2313                              <1> ;ret1:
  2314                              <1> 		; jmp ret / return to caller via 'ret'
  2315                              <1> 
  2316                              <1> rcvt:   ; < receive/read character from tty >
  2317                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2318                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2319                              <1> 	;
  2320                              <1> 	; Retro UNIX 8086 v1 modification !
  2321                              <1> 	; 
  2322                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2323                              <1> 	;		(exactly different than this one)
  2324                              <1> 	;	was in 'u9.s' file.
  2325                              <1> 	;
  2326 00004B8B 2C0A                <1> 	sub 	al, 10
  2327                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2328                              <1> 	; 16/07/2013
  2329                              <1> 	; 21/05/2013
  2330 00004B8D EBBD                <1>         jmp     short rttys
  2331                              <1>       
  2332                              <1> ;rppt: / read paper tape
  2333                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2334                              <1> ;			 / places
  2335                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2336                              <1> ;		       / also enables read bit in prs
  2337                              <1> ;	jsr	r0,passc / place character in users buffer area
  2338                              <1> ;	br	rppt
  2339                              <1> 
  2340                              <1> rmem: ; / transfer characters from memory to a user area of core
  2341                              <1> 	; 17/10/2015
  2342                              <1> 	; 11/06/2015
  2343                              <1> 	; 24/05/2015
  2344                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2345                              <1> 	;
  2346 00004B8F 8B35[0C660000]      <1> 	mov     esi, [u.fofp]
  2347                              <1> rmem_1:
  2348 00004B95 8B1E                <1>         mov     ebx, [esi]        
  2349                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2350                              <1> 		               ; / to be transferred to user
  2351 00004B97 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2352                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2353                              <1> 			    ; / char in memory file
  2354 00004B99 8A03                <1> 	mov	al, [ebx]
  2355                              <1> 		; movb (r1),r1 / get character from memory file, 
  2356                              <1> 		             ; / put it in r1
  2357 00004B9B E87F000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2358                              <1> 			     ;  / the next byte of the users core area
  2359                              <1> 		; br rmem / continue
  2360 00004BA0 75F3                <1> 	jnz	short rmem_1
  2361                              <1> ret_:
  2362 00004BA2 58                  <1> 	pop	eax ; 09/06/2015
  2363 00004BA3 C3                  <1> 	retn
  2364                              <1> 
  2365                              <1> rlpr:
  2366                              <1> ;1:
  2367                              <1> ;rcrd:
  2368 00004BA4 C705[51660000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2368 00004BAC 0000                <1>
  2369 00004BAE E91EE6FFFF          <1> 	jmp	error
  2370                              <1> 		;jmp	error / see 'error' routine
  2371                              <1> 
  2372                              <1> dskr:
  2373                              <1> 	; 19/07/2022
  2374                              <1> 	; 12/10/2015
  2375                              <1> 	; 21/08/2015
  2376                              <1> 	; 25/07/2015
  2377                              <1> 	; 10/07/2015
  2378                              <1> 	; 16/06/2015
  2379                              <1> 	; 31/05/2015
  2380                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2381                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2382                              <1> dskr_0:
  2383 00004BB3 50                  <1> 	push	eax
  2384                              <1> 		; mov (sp),r1 / i-number in r1
  2385                              <1> 	; AX = i-number
  2386 00004BB4 E834FDFFFF          <1> 	call	iget
  2387                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2388 00004BB9 0FB715[F8620000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2389                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2390 00004BC0 8B1D[0C660000]      <1> 	mov	ebx, [u.fofp]
  2391 00004BC6 2B13                <1> 	sub	edx, [ebx]
  2392                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2393                              <1>         ; 12/10/2015
  2394                              <1> 	; jna     short ret_ 
  2395                              <1> 		; blos ret
  2396 00004BC8 7709                <1> 	ja	short dskr_1
  2397                              <1> 	;
  2398                              <1> dskr_retn: ; 12/10/2015
  2399 00004BCA 58                  <1> 	pop	eax
  2400 00004BCB C605[63660000]00    <1> 	mov	byte [u.kcall], 0
  2401 00004BD2 C3                  <1> 	retn	
  2402                              <1> dskr_1: 
  2403 00004BD3 3B15[20660000]      <1> 	cmp     edx, [u.count] 
  2404                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2405                              <1> 			       ; / to carry out read
  2406 00004BD9 7306                <1> 	jnb	short dskr_2
  2407                              <1> 		; bhis 1f
  2408 00004BDB 8915[20660000]      <1> 	mov	[u.count], edx
  2409                              <1> 		; mov r2,u.count / no, just read to end of file
  2410                              <1> dskr_2: ; 1:
  2411                              <1> 	; AX = i-number
  2412 00004BE1 E89EFBFFFF          <1> 	call	mget
  2413                              <1> 		; jsr r0,mget / returns physical block number of block 
  2414                              <1> 			    ; / in file where offset points
  2415                              <1> 	; EAX = physical block number
  2416 00004BE6 E8CD080000          <1> 	call	dskrd
  2417                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2418                              <1> 			     ; / 1st word of data in buffer
  2419                              <1> 	; 09/06/2015
  2420 00004BEB 803D[63660000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2421 00004BF2 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2422 00004BF4 66833D[61660000]00  <1> 	cmp	word [u.pcount], 0
  2423 00004BFC 7705                <1> 	ja	short dskr_4
  2424                              <1> dskr_3:
  2425                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2426 00004BFE E857000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2427                              <1> dskr_4:
  2428                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2429 00004C03 E83D030000          <1> 	call	sioreg
  2430                              <1> 		; jsr r0,sioreg
  2431                              <1> 
  2432                              <1> 	; 19/07/2022
  2433                              <1> 	;xchg	esi, edi
  2434                              <1> 	
  2435                              <1> 	; 19/07/2022
  2436                              <1> 	;  EDX = user data offset (previous value of [u.pbase])
  2437                              <1> 	;  ESI = pointer to file offset 
  2438                              <1> 	;  EDI = system (I/O) buffer offset
  2439                              <1> 	;  ECX = byte count
  2440                              <1> 	;  EBX = system buffer (data) address	
  2441                              <1> 	;  EAX = remain bytes after byte count within page frame 
  2442                              <1> 
  2443 00004C08 010E                <1> 	add	[esi], ecx 
  2444                              <1> 			; new file offset (old offset + byte count)
  2445                              <1> 	;
  2446 00004C0A 89FE                <1> 	mov	esi, edi ; sector (I/O) buffer offset
  2447 00004C0C 89D7                <1> 	mov	edi, edx
  2448                              <1> 
  2449                              <1> 	; EDI = file (user data) offset
  2450                              <1> 	; ESI = sector (I/O) buffer offset
  2451                              <1> 	; ECX = byte count
  2452 00004C0E F3A4                <1> 	rep	movsb
  2453                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2454                              <1> 		                 ; / starting at u.base
  2455                              <1> 		; dec r3
  2456                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2457                              <1> 	; 25/07/2015
  2458                              <1> 	; eax = remain bytes in buffer
  2459                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2460 00004C10 09C0                <1> 	or	eax, eax
  2461 00004C12 75EA                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2462                              <1> 	; 03/08/2013
  2463                              <1> 	;pop	eax
  2464 00004C14 390D[20660000]      <1> 	cmp	[u.count], ecx ; 0
  2465                              <1> 		; tst u.count / all bytes read off disk
  2466                              <1> 		; bne dskr
  2467                              <1> 		; br ret
  2468                              <1>         ;ja	short dskr_0
  2469                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2470                              <1> 	;retn
  2471                              <1> 	; 12/10/2015
  2472 00004C1A 76AE                <1> 	jna	short dskr_retn
  2473 00004C1C 58                  <1> 	pop	eax  ; (i-node number)
  2474 00004C1D EB94                <1> 	jmp	short dskr_0
  2475                              <1> 	
  2476                              <1> passc:
  2477                              <1> 	; 18/10/2015
  2478                              <1> 	; 10/07/2015
  2479                              <1> 	; 01/07/2015
  2480                              <1> 	; 08/06/2015
  2481                              <1> 	; 04/06/2015
  2482                              <1> 	; 20/05/2015
  2483                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2484                              <1> 	;
  2485                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2486                              <1> 	;		      to physical address
  2487 00004C1F 66833D[61660000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2488                              <1> 			     ; 1-4095 --> use previous physical base address
  2489                              <1> 			     ; in [u.pbase]
  2490 00004C27 7705                <1> 	ja	short passc_3
  2491                              <1> 	; 08/06/2015 - 10/07/2015
  2492 00004C29 E82C000000          <1> 	call	trans_addr_w
  2493                              <1> passc_3:
  2494                              <1> 	; 19/05/2015
  2495 00004C2E 66FF0D[61660000]    <1> 	dec	word [u.pcount]
  2496                              <1> 	;
  2497 00004C35 8B1D[5D660000]      <1> 	mov	ebx, [u.pbase]
  2498 00004C3B 8803                <1> 	mov	[ebx], al
  2499                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2500                              <1> 		               ; / users buffer
  2501 00004C3D FF05[1C660000]      <1> 	inc	dword [u.base]
  2502                              <1> 		; inc u.base / increment the pointer to point to 
  2503                              <1> 			  ; / the next byte in users buffer
  2504 00004C43 FF05[5D660000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2505 00004C49 FF05[24660000]      <1> 	inc	dword [u.nread]
  2506                              <1> 		; inc u.nread / increment the number of bytes read
  2507 00004C4F FF0D[20660000]      <1> 	dec	dword [u.count]
  2508                              <1> 		; dec u.count / decrement the number of bytes to be read
  2509                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2510 00004C55 C3                  <1> 	retn
  2511                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2512                              <1> 		             ; / 'readi' by:
  2513                              <1> 		;/ (1) pop the return address off the stack into r0
  2514                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2515                              <1> 	;1:
  2516                              <1> 		; clr	*$ps / clear processor status
  2517                              <1> 		; rts r0 / return to address currently on top of stack
  2518                              <1> 
  2519                              <1> trans_addr_r:
  2520                              <1> 	; Translate virtual address to physical address 
  2521                              <1> 	; for reading from user's memory space
  2522                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2523                              <1> 	; 18/10/2015
  2524                              <1> 	; 10/07/2015
  2525                              <1> 	; 09/06/2015
  2526                              <1> 	; 08/06/2015 
  2527                              <1> 	; 04/06/2015
  2528                              <1> 	;
  2529                              <1> 	; 18/10/2015
  2530 00004C56 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2531 00004C58 EB04                <1> 	jmp 	short trans_addr_rw
  2532                              <1> 
  2533                              <1> 	;push	eax
  2534                              <1> 	;push	ebx
  2535                              <1> 	;mov	ebx, [u.base]
  2536                              <1> 	;call	get_physical_addr ; get physical address
  2537                              <1> 	;;jnc	short cpass_0
  2538                              <1> 	;jnc	short passc_1
  2539                              <1> 	;mov	[u.error], eax
  2540                              <1> 	;;pop	ebx
  2541                              <1> 	;;pop	eax
  2542                              <1> 	;jmp	error
  2543                              <1> ;cpass_0:
  2544                              <1> 	; 18/10/2015
  2545                              <1> 	; 20/05/2015
  2546                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2547                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2548                              <1> 	;pop	ebx
  2549                              <1> 	;pop	eax
  2550                              <1> 	;retn	; 08/06/2015
  2551                              <1> 
  2552                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2553                              <1> trans_addr_w:
  2554                              <1> 	; 31/12/2021
  2555                              <1> 	; Translate virtual address to physical address 
  2556                              <1> 	; for writing to user's memory space
  2557                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2558                              <1> 	; 18/10/2015
  2559                              <1> 	; 29/07/2015
  2560                              <1> 	; 10/07/2015
  2561                              <1> 	; 09/06/2015
  2562                              <1> 	; 08/06/2015
  2563                              <1> 	; 04/06/2015 (passc)
  2564                              <1> 	;
  2565                              <1> 	; 18/10/2015
  2566 00004C5A 29D2                <1> 	sub	edx, edx
  2567 00004C5C FEC2                <1> 	inc	dl ; 1 (write access sign)
  2568                              <1> trans_addr_rw:
  2569 00004C5E 50                  <1> 	push	eax
  2570 00004C5F 53                  <1> 	push	ebx
  2571                              <1> 	; 18/10/2015
  2572 00004C60 52                  <1> 	push 	edx ; r/w sign (in DL)
  2573                              <1> 	;
  2574 00004C61 8B1D[1C660000]      <1> 	mov	ebx, [u.base]
  2575 00004C67 E843DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2576 00004C6C 730A                <1> 	jnc	short passc_0
  2577 00004C6E A3[51660000]        <1> 	mov	[u.error], eax
  2578                              <1> 	;pop	edx
  2579                              <1> 	;pop 	ebx
  2580                              <1> 	;pop	eax
  2581 00004C73 E959E5FFFF          <1> 	jmp	error
  2582                              <1> passc_0:
  2583 00004C78 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2584 00004C7B 5A                  <1> 	pop	edx ; 18/10/2015
  2585 00004C7C 7517                <1> 	jnz	short passc_1
  2586                              <1> 	; 18/10/2015
  2587 00004C7E 20D2                <1> 	and 	dl, dl
  2588 00004C80 7413                <1> 	jz	short passc_1
  2589                              <1> 	; 20/05/2015
  2590                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2591                              <1> 	; EBX = linear address
  2592 00004C82 51                  <1> 	push 	ecx
  2593 00004C83 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2594 00004C84 E897DBFFFF          <1> 	call 	copy_page
  2595 00004C89 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2596 00004C8A 59                  <1> 	pop	ecx
  2597 00004C8B 7217                <1> 	jc	short passc_2
  2598                              <1> 	; 24/12/2021
  2599                              <1> 	;push	eax ; physical address of the new/allocated page
  2600                              <1> 	;call	add_to_swap_queue
  2601                              <1> 	;pop	eax
  2602                              <1> 	; 18/10/2015
  2603 00004C8D 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2604                              <1> 	;mov 	ecx, PAGE_SIZE
  2605                              <1> 	;sub	ecx, ebx 
  2606 00004C93 01D8                <1> 	add	eax, ebx  
  2607                              <1> passc_1: 
  2608                              <1> 	; 18/10/2015
  2609                              <1> 	; 20/05/2015
  2610 00004C95 A3[5D660000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2611 00004C9A 66890D[61660000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2612 00004CA1 5B                  <1> 	pop	ebx
  2613 00004CA2 58                  <1> 	pop	eax
  2614 00004CA3 C3                  <1> 	retn	; 08/06/2015
  2615                              <1> passc_2:
  2616 00004CA4 C705[51660000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2616 00004CAC 0000                <1>
  2617                              <1> 	;pop 	ebx
  2618                              <1> 	;pop	eax
  2619 00004CAE E91EE5FFFF          <1> 	jmp	error
  2620                              <1> 
  2621                              <1> writei:
  2622                              <1> 	; 13/06/2022
  2623                              <1> 	; 03/02/2022
  2624                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2625                              <1> 	; 20/05/2015
  2626                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2627                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2628                              <1> 	;
  2629                              <1> 	; Write data to file with inode number in R1
  2630                              <1> 	; 
  2631                              <1> 	; INPUTS ->
  2632                              <1> 	;    r1 - inode number
  2633                              <1> 	;    u.count - byte count to be written
  2634                              <1> 	;    u.base - points to user buffer
  2635                              <1> 	;    u.fofp - points to word with current file offset
  2636                              <1> 	; OUTPUTS ->
  2637                              <1> 	;    u.count - cleared
  2638                              <1> 	;    u.nread - accumulates total bytes passed back	
  2639                              <1> 	; ((AX = R1))
  2640                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2641                              <1> 	;    ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -15/07/2022-
  2642                              <1> 
  2643 00004CB3 31C9                <1> 	xor	ecx, ecx
  2644 00004CB5 890D[24660000]      <1> 	mov 	[u.nread], ecx  ; 0
  2645                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2646                              <1> 		            ; / read or write calls
  2647 00004CBB 66890D[61660000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2648 00004CC2 390D[20660000]      <1> 	cmp 	[u.count], ecx
  2649                              <1> 	;	; tst u.count / test the byte count specified by the user
  2650 00004CC8 770B                <1> 	ja 	short writei_1 ; 1f
  2651                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2652                              <1> 
  2653                              <1> 	; 13/06/2022 - ('get/read LPT printer status' modification)
  2654 00004CCA 83F810              <1> 	cmp	eax, 16  ; LPR_INODE ; lpt (parallel port printer) ?
  2655 00004CCD 7505                <1> 	jne	short writei_0
  2656 00004CCF E924010000          <1> 	jmp	lpr_stat	; get/read line status
  2657                              <1> writei_0:
  2658 00004CD4 C3                  <1> 	retn
  2659                              <1> 	;	; rts r0 / no, return - no writing to do
  2660                              <1> writei_1: ;1:
  2661                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2662 00004CD5 6683F828            <1> 	cmp 	ax, 40
  2663                              <1> 		; cmp r1,$40.
  2664                              <1> 		; / does the i-node number indicate a special file?
  2665                              <1> 	;ja	dskw 
  2666                              <1> 		; bgt dskw / no, branch to standard file output
  2667                              <1> 	; 24/12/2021
  2668 00004CD9 7605                <1> 	jna	short writei_3
  2669 00004CDB E958010000          <1> 	jmp	dskw
  2670                              <1> writei_3:
  2671                              <1> 	; (20/05/2015)
  2672 00004CE0 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2673 00004CE1 0FB6D8              <1> 	movzx	ebx, al
  2674                              <1> 	; 03/02/2022
  2675 00004CE4 C1E302              <1> 	shl	ebx, 2
  2676                              <1> 	;shl	bx, 2
  2677                              <1> 		; asl r1 / yes, calculate the index into the special file
  2678 00004CE7 81C3[EB4C0000]      <1> 	add	ebx, writei_2 - 4
  2679 00004CED FF23                <1> 	jmp	dword [ebx]	
  2680                              <1> 		; jmp *1f-2(r1)
  2681                              <1> 		; / jump table and jump to the appropriate routine
  2682                              <1> writei_2: ;1:
  2683 00004CEF [3B4D0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2684                              <1> 		 ;wtty / tty; r1=2
  2685                              <1> 		 ;wppt / ppt; r1=4
  2686 00004CF3 [8E4D0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2687                              <1> 		 ;wmem / mem; r1=6
  2688                              <1> 		 ;wrf0 / rf0
  2689                              <1> 		 ;wrk0 / rk0
  2690                              <1> 		 ;wtap / tap0
  2691                              <1> 		 ;wtap / tap1
  2692                              <1> 		 ;wtap / tap2
  2693                              <1> 		 ;wtap / tap3
  2694                              <1> 		 ;wtap / tap4
  2695                              <1> 		 ;wtap / tap5
  2696                              <1> 		 ;wtap / tap6
  2697                              <1> 		 ;wtap / tap7
  2698 00004CF7 [EE530000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2699 00004CFB [EE530000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2700 00004CFF [EE530000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2701 00004D03 [EE530000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2702 00004D07 [EE530000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2703 00004D0B [EE530000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2704 00004D0F [BE4D0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2705 00004D13 [884D0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2706                              <1> 		 ;xmtt / tty0
  2707 00004D17 [884D0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2708                              <1> 		 ;xmtt / tty1
  2709 00004D1B [884D0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2710                              <1> 		 ;xmtt / tty2
  2711 00004D1F [884D0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2712                              <1> 		 ;xmtt / tty3
  2713 00004D23 [884D0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2714                              <1> 		 ;xmtt / tty4
  2715 00004D27 [884D0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2716                              <1> 		 ;xmtt / tty5
  2717 00004D2B [884D0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2718                              <1> 		 ;xmtt / tty6
  2719 00004D2F [884D0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2720                              <1> 		 ;xmtt / tty7
  2721 00004D33 [884D0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2722                              <1> 		; / wlpr / lpr
  2723 00004D37 [884D0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2724                              <1> 
  2725                              <1> wtty: ; write to console tty (write to screen)
  2726                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2727                              <1> 	; 18/11/2015
  2728                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2729                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2730                              <1> 	;
  2731                              <1> 	; Console tty output is on current video page
  2732                              <1> 	; Console tty character output procedure is changed here
  2733                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2734                              <1> 	;
  2735 00004D3B 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2736 00004D42 8AA3[53630000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2737 00004D48 88E0                <1> 	mov	al, ah ; 07/07/2014
  2738                              <1> wttys:	
  2739                              <1> 	; 10/10/2013
  2740 00004D4A 8825[50660000]      <1> 	mov 	[u.ttyn], ah
  2741                              <1> 	; 13/01/2014
  2742 00004D50 FEC0                <1> 	inc	al
  2743 00004D52 A2[2D660000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2744                              <1> wtty_nc: ; 15/05/2013
  2745                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2746 00004D57 E889010000          <1> 	call	cpass
  2747                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2748                              <1> 		             ; / none go to return address in syswrite
  2749                              <1> 		; tst r1 / is character = null
  2750                              <1> 		; beq wtty / yes, get next character
  2751                              <1> 	; 10/10/2013
  2752 00004D5C 7428                <1> 	jz	short wret
  2753                              <1> 	;1 : 
  2754                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2755                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2756                              <1> 		;	          / than 20
  2757                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2758                              <1> 	; 27/06/2014
  2759                              <1> wtty_1:
  2760                              <1> 	; AH = tty number
  2761                              <1> 	; AL = ASCII code of the character
  2762                              <1> 	; 15/04/2014
  2763                              <1> 	;push	ax
  2764                              <1> 	; 24/12/2021
  2765 00004D5E 50                  <1> 	push	eax
  2766 00004D5F E88E090000          <1> 	call	putc ; 14/05/2013
  2767 00004D64 731D                <1> 	jnc	short wtty_2
  2768                              <1> 	; 18/11/2015
  2769 00004D66 E814F9FFFF          <1> 	call	idle
  2770                              <1> 	;mov	ax, [esp]
  2771                              <1> 	; 24/12/2021
  2772 00004D6B 8B0424              <1> 	mov	eax, [esp]
  2773 00004D6E E87F090000          <1> 	call	putc
  2774 00004D73 730E                <1> 	jnc	short wtty_2 
  2775                              <1> 	; 02/06/2014
  2776 00004D75 8A25[50660000]      <1> 	mov	ah, [u.ttyn]
  2777 00004D7B E88CF9FFFF          <1> 	call	sleep
  2778                              <1> 	;pop	ax
  2779                              <1> 	; 24/12/2021
  2780 00004D80 58                  <1> 	pop	eax
  2781 00004D81 EBDB                <1> 	jmp 	short wtty_1
  2782                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2783                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2784                              <1> 			      ; / console tty and
  2785                              <1> 		; br 	2f / place character in list; if none available
  2786                              <1> 		   	  ; / branch to put process to sleep
  2787                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2788                              <1> wtty_2:
  2789                              <1> 	; 15/04/2014
  2790                              <1> 	;pop	ax
  2791                              <1> 	; 24/12/2021
  2792 00004D83 58                  <1> 	pop	eax
  2793 00004D84 EBD1                <1> 	jmp	short wtty_nc
  2794                              <1> 		; br wtty
  2795                              <1> wret:	; 10/10/2013 (20/05/2015)
  2796 00004D86 58                  <1> 	pop	eax
  2797 00004D87 C3                  <1> 	retn
  2798                              <1> 	;2:
  2799                              <1> 		;mov	r1,-(sp) / place character on stack
  2800                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2801                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2802                              <1> 		;br	1b / try again to place character in clist and output
  2803                              <1> 
  2804                              <1> xmtt:   ; < send/write character to tty >
  2805                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2806                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2807                              <1> 	;
  2808                              <1> 	; Retro UNIX 8086 v1 modification !
  2809                              <1> 	; 
  2810                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2811                              <1> 	;		(exactly different than this one)
  2812                              <1> 	;	was in 'u9.s' file.
  2813                              <1> 	;
  2814 00004D88 2C0A                <1> 	sub 	al, 10
  2815                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2816                              <1> 	; 10/10/2013
  2817 00004D8A 88C4                <1> 	mov	ah, al
  2818                              <1> 	; 28/07/2013
  2819 00004D8C EBBC                <1> 	jmp	short wttys
  2820                              <1> 
  2821                              <1> ;wppt:
  2822                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2823                              <1> ;		         / if none return to writei's calling routine
  2824                              <1> ;	jsr	r0,pptoc / output character on ppt
  2825                              <1> ;	br	wppt
  2826                              <1> 
  2827                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2828                              <1> 	; 17/10/2015
  2829                              <1> 	; 11/06/2015
  2830                              <1> 	; 24/05/2015
  2831                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2832                              <1> 	;
  2833 00004D8E 813D[F1060000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2833 00004D94 [A2460000]          <1>
  2834 00004D98 7415                <1>         je      short wmem_acc_err
  2835                              <1> 	;
  2836 00004D9A 8B35[0C660000]      <1>         mov     esi, [u.fofp] 
  2837                              <1> wmem_1:
  2838 00004DA0 E840010000          <1> 	call	cpass
  2839                              <1> 		; jsr r0,cpass / get next character from users area of
  2840                              <1> 			     ; / core and put it in r1
  2841                              <1>         	; mov r1,-(sp) / put character on the stack
  2842                              <1> 	; 20/09/2013
  2843 00004DA5 74DF                <1> 	jz	short wret ; wmem_2  
  2844 00004DA7 8B1E                <1>         mov     ebx, [esi]
  2845                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2846 00004DA9 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2847                              <1> 		; inc *u.fofp / increment file offset to point to next
  2848                              <1> 			    ; / available location in file
  2849 00004DAB 8803                <1> 	mov	[ebx], al	
  2850                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2851                              <1> 			        ; / assigned to it
  2852 00004DAD EBF1                <1> 	jmp	short wmem_1
  2853                              <1> 		; br wmem / continue
  2854                              <1> 	;1:
  2855                              <1> 	;jmp	error / ?
  2856                              <1> ;wmem_2:	
  2857                              <1> ;	; 20/09/2013
  2858                              <1> ;	pop	ax
  2859                              <1> ;	retn
  2860                              <1> 
  2861                              <1> wmem_acc_err:
  2862 00004DAF C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2862 00004DB7 0000                <1>
  2863 00004DB9 E913E4FFFF          <1> 	jmp	error
  2864                              <1> 
  2865                              <1> ;wlpr:
  2866                              <1> 	; 13/06/2022
  2867                              <1> 	;mov	dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2868                              <1> 	;jmp	error   ; ... Printing procedure will be located here ...
  2869                              <1> 		;/	jsr	r0,cpass
  2870                              <1> 		;/	cmp	r0,$'a
  2871                              <1> 		;/	blo	1f
  2872                              <1> 		;/	cmp	r1,$'z
  2873                              <1> 		;/	bhi	1f
  2874                              <1> 		;/	sub	$40,r1
  2875                              <1> 		;/1:
  2876                              <1> 		;/	jsr	r0,lptoc
  2877                              <1> 		;/	br	wlpr
  2878                              <1> 		; br rmem / continue
  2879                              <1> 
  2880                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 - PRINTER BIOS (Functions)
  2881                              <1> 
  2882                              <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM)
  2883                              <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987
  2884                              <1> ;; 23/03/2018 - Retro DOS v2.0
  2885                              <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2)
  2886                              <1> 
  2887                              <1> ; IBM ROMBIOS (INT 17h) STATUS BITS
  2888                              <1> 
  2889                              <1> NOTBUSYSTATUS	equ 10000000b	; NOT BUSY
  2890                              <1> ACKSTATUS	equ 01000000b	; ACKNOWLEDGE (FOR WHAT?)
  2891                              <1> NOPAPERSTATUS	equ 00100000b	; NO MORE PAPER
  2892                              <1> SELECTEDSTATUS	equ 00010000b	; THE PRINTER SAID IT WAS SELECTED
  2893                              <1> IOERRSTATUS	equ 00001000b	; SOME KIND ERROR
  2894                              <1> RESERVED	equ 00000110b	; NOPS
  2895                              <1> TIMEOUTSTATUS	equ 00000001b	; TIME OUT.
  2896                              <1> 
  2897                              <1> ;----------------------------------------------------------------
  2898                              <1> ;								:
  2899                              <1> ;		WRITE TO PRINTER DEVICE 			:
  2900                              <1> ;								:
  2901                              <1> ;   CX has count of bytes to be printed 			:
  2902                              <1> ;   ES:DI point to source buffer contains characters		:
  2903                              <1> ;   AuxNum (in msbio.asm) has printer number			:
  2904                              <1> ;								:
  2905                              <1> ;----------------------------------------------------------------
  2906                              <1> 
  2907                              <1> wlpr:
  2908                              <1> 	; 15/07/2022
  2909                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2910                              <1> PRN$WRIT:
  2911                              <1> 	; INPUT:
  2912                              <1> 	;	[u.count] = count of characters to be printed
  2913                              <1> 	;	[u.base] = buffer address in user's memory space
  2914                              <1> 	;
  2915                              <1> 	;	(if ECX = 0, printer status will be returned)
  2916                              <1> 	
  2917                              <1> 	;xor	ebx, ebx
  2918                              <1> PRN$LOOP:
  2919 00004DBE E822010000          <1> 	call	cpass		  ; Get a character into AL
  2920 00004DC3 7431                <1> 	jz	short pr_exit
  2921                              <1> 	;
  2922 00004DC5 B302                <1> 	mov	bl, 2  ; retry count
  2923                              <1> PRN$OUT:
  2924                              <1> 	; al = character which will be printed
  2925 00004DC7 30E4                <1> 	xor	ah, ah ; 0	  ; PRINT THE CHARACTER IN (AL)
  2926 00004DC9 E850000000          <1> 	call	PRNOP
  2927 00004DCE 74EE                <1> 	jz	short PRN$LOOP 	  ; if error, try to print again
  2928                              <1> PrRetry:
  2929                              <1> 	; al = character
  2930 00004DD0 FECB                <1> 	dec	bl
  2931 00004DD2 75F3                <1> 	jnz	short PRN$OUT
  2932                              <1> pr_err_exit:
  2933 00004DD4 0FB6C0              <1> 	movzx	eax, al
  2934 00004DD7 A3[51660000]        <1> 	mov	[u.error], eax
  2935 00004DDC A3[FC650000]        <1> 	mov	[u.r0], eax ; error code in AL
  2936                              <1> 	;mov 	ebp, [u.sp]
  2937 00004DE1 8B1D[F4650000]      <1> 	mov	ebx, [u.sp] ; 15/07/2022
  2938                              <1> 			; Kernel stack at the beginning of sys call
  2939 00004DE7 8B15[24660000]      <1> 	mov	edx, [u.nread]
  2940 00004DED 4A                  <1> 	dec	edx ; last char failed
  2941                              <1> 	;mov	[ebp+20], edx ; count of printed characters in edx
  2942 00004DEE 895314              <1> 	mov	[ebx+20], edx ; 15/07/2022
  2943 00004DF1 E9DBE3FFFF          <1> 	jmp	error
  2944                              <1> pr_exit:
  2945 00004DF6 58                  <1> 	pop	eax ; inode number
  2946                              <1> 
  2947                              <1> 	;mov	eax, [u.nread]
  2948                              <1> 	;mov	[u.r0], eax ; count of printed chacters
  2949                              <1> 	;jmp	sysret
  2950 00004DF7 C3                  <1> 	retn	; return from writei to syswrite (rw0)
  2951                              <1> 
  2952                              <1> ; 13/06/2022
  2953                              <1> 
  2954                              <1> ;----------------------------------------------------------------
  2955                              <1> ;								:
  2956                              <1> ;		PRINTER STATUS ROUTINE				:
  2957                              <1> ;								:
  2958                              <1> ;----------------------------------------------------------------
  2959                              <1> ;
  2960                              <1> 
  2961                              <1> lpr_stat:
  2962                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2963                              <1> PRN$STAT:
  2964 00004DF8 E81F000000          <1> 	call	PRNSTAT		  ; get the status
  2965 00004DFD 750E                <1> 	jnz	short prn_stat_retn
  2966                              <1> 				  ; if error jump to error routine
  2967                              <1> 	;mov	al, 9		  ; AGAIN, ASSUME OUT OF PAPER...
  2968 00004DFF B01F                <1> 	mov	al, ERR_PRN_PAPER
  2969 00004E01 F6C420              <1> 	test	ah, NOPAPERSTATUS
  2970 00004E04 7507                <1> 	jnz	short prn_stat_retn
  2971 00004E06 F6C480              <1> 	test	ah, NOTBUSYSTATUS
  2972 00004E09 750D                <1> 	jnz	short prn_stat_ok ; if not busy return (with cf=0)
  2973 00004E0B B022                <1> 	mov	al, ERR_PRN_BUSY  ; else busy, return to busy exit
  2974                              <1> prn_stat_retn:
  2975                              <1> 	; al = error code
  2976                              <1> 	; ah = status flags
  2977 00004E0D A3[FC650000]        <1> 	mov	[u.r0], eax
  2978                              <1> 	;movzx	eax, al
  2979                              <1> 	;mov 	[u.error], eax
  2980 00004E12 58                  <1> 	pop	eax ; discard return address to syswrite
  2981 00004E13 E9D9E3FFFF          <1> 	jmp	sysret
  2982                              <1> prn_stat_ok:
  2983 00004E18 30C0                <1> 	xor	al, al ; 0
  2984 00004E1A EBF1                <1> 	jmp	short prn_stat_retn
  2985                              <1> 
  2986                              <1> ;
  2987                              <1> ;   PRNSTAT	get printer status
  2988                              <1> ;   PRNOP	print a character
  2989                              <1> ;
  2990                              <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS
  2991                              <1> ; printer routines.  The routines share code which calls on the bios and
  2992                              <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ
  2993                              <1> ; only by the value put into AH before the ROM-BIOS call.
  2994                              <1> ;
  2995                              <1> ;   INPUT	if PRNOP then character in AL
  2996                              <1> ;
  2997                              <1> ;   OUTPUT	- AL holds error code
  2998                              <1> ;		- AH status byte from printer
  2999                              <1> ;		- flag NZ if error
  3000                              <1> 
  3001                              <1> PRNSTAT:
  3002 00004E1C B402                <1> 	mov	ah, 2		  ; set command for get status 
  3003                              <1> 
  3004                              <1> PRNOP:
  3005                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  3006                              <1> 	;
  3007                              <1> 	; Print character (on paper)
  3008                              <1> 
  3009                              <1> 	; INPUT:
  3010                              <1> 	;	al = character to be printed
  3011                              <1> 	; OUTPUT:
  3012                              <1> 	;	zf = 1 -> ok
  3013                              <1> 	;	zf = 0 -> error code in AL
  3014                              <1> 
  3015 00004E1E E8080B0000          <1> 	call	int17h	 ; call lpt bios
  3016                              <1> 	
  3017 00004E23 F6C408              <1> 	test	ah, IOERRSTATUS	  ; I/O ERROR?
  3018 00004E26 740A                <1> 	jz	short short prnop_chk_nrdy ; NO, TRY NOT READY
  3019                              <1> 
  3020                              <1> 	; AT THIS POINT, WE KNOW WE HAVE AN ERROR.
  3021                              <1> 	; THE CONVERSE IS NOT TRUE.
  3022                              <1> 
  3023                              <1> 	;mov	al, 9		  ; FIRST, ASSUME OUT OF PAPER
  3024 00004E28 B01F                <1> 	mov	al, ERR_PRN_PAPER
  3025 00004E2A F6C420              <1> 	test	ah, NOPAPERSTATUS ; OUT OF PAPER SET?
  3026 00004E2D 7502                <1> 	jnz	short PRNOP1	  ; YES, ERROR IS SET
  3027                              <1> 	;mov	al, ERR_PRN_IO
  3028 00004E2F FEC0                <1> 	inc	al		  ; INDICATE I/O ERROR
  3029                              <1> PRNOP1: 
  3030                              <1> 
  3031                              <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT)
  3032                              <1> 
  3033 00004E31 C3                  <1> 	retn			  ; RETURN WITH ERROR
  3034                              <1>  
  3035                              <1> ; THE BITS SAID NO ERROR.
  3036                              <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE.
  3037                              <1> 
  3038                              <1> prnop_chk_nrdy:
  3039                              <1> 	;mov	al, 2		  ; ASSUME NOT-READY
  3040 00004E32 B019                <1> 	mov	al, ERR_PRN_TIMEOUT ; ''time out !' error
  3041                              <1> 	
  3042 00004E34 F6C401              <1> 	test	ah, TIMEOUTSTATUS ; IS TIME-OUT SET?
  3043                              <1> 				  ; IF NZ THEN ERROR, ELSE OK???
  3044                              <1> PRNOP2: 
  3045 00004E37 C3                  <1> 	retn
  3046                              <1> 
  3047                              <1> 
  3048                              <1> dskw: ; / write routine for non-special files
  3049                              <1> 	;
  3050                              <1> 	; 19/07/2022
  3051                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  3052                              <1> 	;
  3053                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3054                              <1> 	; 25/07/2015
  3055                              <1> 	; 16/06/2015
  3056                              <1> 	; 09/06/2015
  3057                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  3058                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  3059                              <1> 	;
  3060                              <1> 	; 01/08/2013 (mkdir_w check)
  3061                              <1> 
  3062                              <1> 	;push	ax ; 26/04/2013
  3063                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  3064                              <1> 	; 24/12/2021
  3065 00004E38 50                  <1> 	push	eax
  3066                              <1> 	; AX = inode number
  3067 00004E39 E8AFFAFFFF          <1> 	call	iget
  3068                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  3069                              <1> 		            ; / read i-node 'r1' into i-node area of core
  3070 00004E3E 8B1D[0C660000]      <1>         mov     ebx, [u.fofp] 
  3071 00004E44 8B13                <1> 	mov 	edx, [ebx]
  3072                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  3073                              <1> 			       ; / in the fsp entry for this file] in r2
  3074 00004E46 0315[20660000]      <1> 	add 	edx, [u.count]	
  3075                              <1> 		; add u.count,r2 / no. of bytes to be written
  3076                              <1> 			       ; / + file offset is put in r2
  3077                              <1> 	; 16/06/2015        
  3078 00004E4C 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  3079 00004E52 760F                <1> 	jna	short dskw_0
  3080 00004E54 C705[51660000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  3080 00004E5C 0000                <1>
  3081 00004E5E E96EE3FFFF          <1> 	jmp	error
  3082                              <1> dskw_0:	
  3083 00004E63 663B15[F8620000]    <1> 	cmp     dx, [i.size]
  3084                              <1> 		; cmp r2,i.size / is this greater than the present size of
  3085                              <1> 		              ; / the file?
  3086 00004E6A 760C                <1> 	jna	short dskw_1
  3087                              <1> 		; blos 1f / no, branch
  3088 00004E6C 668915[F8620000]    <1>         mov     [i.size], dx
  3089                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  3090                              <1> 			      ; / file offset + no. of data bytes
  3091 00004E73 E87FFBFFFF          <1> 	call	setimod
  3092                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  3093                              <1> 		          ; / modified), stuff time of modification into
  3094                              <1> 	          	  ; / core image of i-node
  3095                              <1> dskw_1: ; 1:	
  3096 00004E78 E807F9FFFF          <1> 	call	mget
  3097                              <1> 	; EAX = Block number
  3098                              <1> 		; jsr r0,mget / get the block no. in which to write 
  3099                              <1> 			    ; /	the next data byte
  3100                              <1> 	; eax = block number
  3101 00004E7D 8B1D[0C660000]      <1> 	mov     ebx, [u.fofp]
  3102 00004E83 8B13                <1> 	mov	edx, [ebx]
  3103 00004E85 81E2FF010000        <1> 	and	edx, 1FFh  
  3104                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  3105 00004E8B 750C                <1> 	jnz	short dskw_2
  3106                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  3107                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  3108 00004E8D 813D[20660000]0002- <1> 	cmp	dword [u.count], 512
  3108 00004E95 0000                <1>
  3109                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  3110                              <1> 				  ; / an entire block? (i.e., no. of
  3111 00004E97 7305                <1> 	jnb	short dskw_3
  3112                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  3113                              <1> 			; / Yes, branch. Don't have to read block
  3114                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  3115                              <1>    		; / overwritten).
  3116 00004E99 E81A060000          <1> 	call	dskrd
  3117                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  3118                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  3119                              <1> dskw_3: ; 3:
  3120                              <1> 	; EAX (r1) = block/sector number
  3121 00004E9E E879060000          <1> 	call	wslot
  3122                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  3123                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  3124 00004EA3 803D[63660000]00    <1> 	cmp	byte [u.kcall], 0
  3125 00004EAA 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  3126                              <1> 	;
  3127 00004EAC 66833D[61660000]00  <1> 	cmp	word [u.pcount], 0
  3128 00004EB4 7705                <1> 	ja	short dskw_5
  3129                              <1> dskw_4:
  3130                              <1> 	; [u.base] = virtual address to transfer (as source address)
  3131 00004EB6 E89BFDFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  3132                              <1> dskw_5:
  3133                              <1> 	; EBX (r5) = system (I/O) buffer address
  3134 00004EBB E885000000          <1> 	call	sioreg
  3135                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  3136                              <1> 			     ; / r1 = address of data, r2 points to location
  3137                              <1> 			     ; / in buffer in which to start writing data
  3138                              <1> 	; 19/07/2022
  3139                              <1> 	;  EDX = user data offset (previous value of [u.pbase])
  3140                              <1> 	;  ESI = pointer to file offset 
  3141                              <1> 	;  EDI = system (I/O) buffer offset
  3142                              <1> 	;  ECX = byte count
  3143                              <1> 	;  EBX = system buffer (data) address	
  3144                              <1> 	;  EAX = remain bytes after byte count within page frame 
  3145                              <1> 
  3146                              <1> 	; 19/07/2022 - Erdogan Tan
  3147                              <1> 	; BugFix (Also original unix v1 kernel code has this bug!)
  3148                              <1> 	; ((Against a possible disk write failure/error, 
  3149                              <1> 	;   file offset must not be updated/increased before 'dskwr'
  3150                              <1> 	;   but it was updated in 'sioreg'. I have modified 'sioreg'
  3151                              <1> 	;   and 'dskw' procedures for that.))
  3152                              <1> 
  3153                              <1> 	; 19/07/2022
  3154 00004EC0 56                  <1> 	push	esi ; *	 ; save file offset (pointer)
  3155 00004EC1 51                  <1> 	push	ecx ; ** ; save byte count
  3156 00004EC2 89D6                <1> 	mov	esi, edx
  3157                              <1> 
  3158                              <1> 	; ESI = file (user data) offset
  3159                              <1> 	; EDI = sector (I/O) buffer offset
  3160                              <1> 	; ECX = byte count
  3161                              <1> 	;
  3162 00004EC4 F3A4                <1>   	rep	movsb
  3163                              <1> 		; movb (r1 )+,(r2)+ 
  3164                              <1> 		         ; / transfer a byte of data to the I/O buffer
  3165                              <1> 		; dec r3 / decrement no. of bytes to be written
  3166                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  3167                              <1> 	; 25/07/2015
  3168                              <1> 	; eax = remain bytes in buffer
  3169                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  3170 00004EC6 09C0                <1> 	or	eax, eax
  3171 00004EC8 75EC                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)
  3172                              <1> dskw_6:
  3173 00004ECA E85A060000          <1> 	call	dskwr
  3174                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  3175                              <1> 
  3176                              <1> 	; 19/07/2022
  3177                              <1> 	; (there is not a disk write error, we can increase file offset)
  3178 00004ECF 58                  <1> 	pop	eax ; ** ; byte count
  3179 00004ED0 5F                  <1> 	pop	edi ; *  ; file offset (pointer)
  3180                              <1> 	;
  3181 00004ED1 0107                <1> 	add	[edi], eax
  3182                              <1> 			; new file offset (old offset + byte count)
  3183                              <1> 
  3184 00004ED3 833D[20660000]00    <1>         cmp     dword [u.count], 0
  3185                              <1> 		; tst u.count / any more data to write?
  3186 00004EDA 779C                <1> 	ja	short dskw_1
  3187                              <1> 		; bne 1b / yes, branch
  3188                              <1> 	; 03/08/2013
  3189 00004EDC C605[63660000]00    <1> 	mov	byte [u.kcall], 0
  3190                              <1> 	; 20/09/2013 (;;)
  3191                              <1> 	;pop	ax
  3192                              <1> 	; 24/12/2021
  3193 00004EE3 58                  <1> 	pop	eax
  3194 00004EE4 C3                  <1> 	retn
  3195                              <1> 	;;jmp 	short dskw_ret 
  3196                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  3197                              <1> 
  3198                              <1> cpass: ; / get next character from user area of core and put it in r1
  3199                              <1> 	; 18/10/2015
  3200                              <1> 	; 10/10/2015
  3201                              <1> 	; 10/07/2015
  3202                              <1> 	; 02/07/2015
  3203                              <1> 	; 01/07/2015
  3204                              <1> 	; 24/06/2015
  3205                              <1> 	; 08/06/2015
  3206                              <1> 	; 04/06/2015
  3207                              <1> 	; 20/05/2015
  3208                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3209                              <1> 	;
  3210                              <1> 	; INPUTS -> 
  3211                              <1> 	;     [u.base] = virtual address in user area
  3212                              <1> 	;     [u.count] = byte count (max.)
  3213                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  3214                              <1> 	; OUTPUTS -> 
  3215                              <1> 	;     AL = the character which is pointed by [u.base]
  3216                              <1> 	;     zf = 1 -> transfer count has been completed	
  3217                              <1>         ;
  3218                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  3219                              <1> 	;
  3220                              <1> 	;
  3221 00004EE5 833D[20660000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  3222                              <1> 		; tst u.count / have all the characters been transferred
  3223                              <1> 			    ; / (i.e., u.count, # of chars. left
  3224 00004EEC 763F                <1> 	jna	short cpass_3
  3225                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  3226 00004EEE FF0D[20660000]      <1> 	dec	dword [u.count]
  3227                              <1> 		; dec u.count / no, decrement u.count
  3228                              <1>         ; 19/05/2015 
  3229                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  3230                              <1> 	;		      to physical address
  3231 00004EF4 66833D[61660000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  3232                              <1> 			     ; 1-4095 --> use previous physical base address
  3233                              <1> 			     ; in [u.pbase]
  3234 00004EFC 770E                <1> 	ja	short cpass_1
  3235                              <1> 	; 02/07/2015
  3236 00004EFE 833D[59660000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  3237 00004F05 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  3238                              <1> 	; 08/06/2015 - 10/07/2015
  3239 00004F07 E84AFDFFFF          <1> 	call	trans_addr_r
  3240                              <1> cpass_1:
  3241                              <1> 	; 02/07/2015
  3242                              <1> 	; 24/06/2015
  3243 00004F0C 66FF0D[61660000]    <1> 	dec	word [u.pcount]
  3244                              <1> cpass_2: 
  3245                              <1> 	; 10/10/2015
  3246                              <1> 	; 02/07/2015
  3247 00004F13 8B15[5D660000]      <1> 	mov	edx, [u.pbase]
  3248 00004F19 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3249                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3250                              <1> 				; / by u.base and put it in r1
  3251 00004F1B FF05[24660000]      <1> 	inc	dword [u.nread]
  3252                              <1> 		; inc u.nread / increment no. of bytes transferred
  3253 00004F21 FF05[1C660000]      <1> 	inc	dword [u.base]
  3254                              <1> 		; inc u.base / increment the buffer address to point to the
  3255                              <1> 			   ; / next byte
  3256 00004F27 FF05[5D660000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3257                              <1> cpass_3:
  3258 00004F2D C3                  <1> 	retn
  3259                              <1> 		; rts	r0 / next byte
  3260                              <1> 	; 1: 
  3261                              <1> 		; mov (sp)+,r0 
  3262                              <1> 		         ; / put return address of calling routine into r0
  3263                              <1> 		; mov (sp)+,r1 / i-number in r1
  3264                              <1> 		; rts r0 / non-local return
  3265                              <1> cpass_k:
  3266                              <1> 	; 02/07/2015
  3267                              <1> 	; The caller is os kernel 
  3268                              <1> 	; (get sysexec arguments from kernel's memory space)
  3269                              <1> 	;
  3270 00004F2E 8B1D[1C660000]      <1> 	mov	ebx, [u.base]
  3271 00004F34 66C705[61660000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3271 00004F3C 10                  <1>
  3272 00004F3D 891D[5D660000]      <1> 	mov	[u.pbase], ebx
  3273 00004F43 EBCE                <1> 	jmp	short cpass_2
  3274                              <1> 	
  3275                              <1> sioreg:
  3276                              <1> 	; 19/07/2022
  3277                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  3278                              <1> 	; 25/07/2015
  3279                              <1> 	; 18/07/2015
  3280                              <1> 	; 02/07/2015
  3281                              <1> 	; 17/06/2015
  3282                              <1> 	; 09/06/2015
  3283                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3284                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3285                              <1> 	;
  3286                              <1> 	; INPUTS -> 
  3287                              <1> 	;     EBX = system buffer (data) address (r5)
  3288                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3289                              <1> 	;     [u.base] = virtual address of the user buffer
  3290                              <1> 	;     [u.pbase] = physical address of the user buffer
  3291                              <1> 	;     [u.count] = byte count
  3292                              <1> 	;     [u.pcount] = byte count within page frame 			
  3293                              <1> 	; OUTPUTS -> 
  3294                              <1> 	;     ESI = user data offset (r1)
  3295                              <1> 	;     EDI = system (I/O) buffer offset (r2)
  3296                              <1> 	;     ECX = byte count (r3)
  3297                              <1> 	;     EAX = remain bytes after byte count within page frame
  3298                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3299                              <1>         ;
  3300                              <1> 	; ((Modified registers:  EDX))
  3301                              <1> 
  3302                              <1> 	; 19/07/2022
  3303                              <1> 	; OUTPUTS -> 
  3304                              <1> 	;	EDX = user data offset (previous value of [u.pbase])
  3305                              <1> 	;	ESI = pointer to file offset 
  3306                              <1> 	; 	EDI = system (I/O) buffer offset
  3307                              <1> 	;	ECX = byte count
  3308                              <1> 	;	EBX = system buffer (data) address	
  3309                              <1> 	;	EAX = remain bytes after byte count within page frame
  3310                              <1>  
  3311 00004F45 8B35[0C660000]      <1>         mov     esi, [u.fofp]
  3312 00004F4B 8B3E                <1>         mov     edi, [esi]
  3313                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3314 00004F4D 89F9                <1> 	mov	ecx, edi
  3315                              <1> 		; mov r2,r3 / and also to r3
  3316 00004F4F 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3317                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3318 00004F55 81E7FF010000        <1> 	and	edi, 1FFh
  3319                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3320 00004F5B 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3321                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3322                              <1> 			  ; / where data is to be placed
  3323                              <1>                 ; mov u.base,r1 / address of data is in r1
  3324 00004F5D F7D9                <1> 	neg	ecx
  3325                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3326                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3327 00004F5F 3B0D[20660000]      <1> 	cmp	ecx, [u.count]
  3328                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3329                              <1> 			       ; / to be written to the file
  3330 00004F65 7606                <1> 	jna	short sioreg_0
  3331                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3332                              <1> 			 ; / in the file block as the number to be written
  3333 00004F67 8B0D[20660000]      <1> 	mov	ecx, [u.count]
  3334                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3335                              <1> 			       ; / bytes as the number to be written
  3336                              <1> sioreg_0:
  3337                              <1> 	; 17/06/2015
  3338 00004F6D 803D[63660000]00    <1> 	cmp	byte [u.kcall], 0 
  3339 00004F74 7613                <1> 	jna	short sioreg_1
  3340                              <1> 	; 25/07/2015
  3341                              <1> 	; the caller is 'mkdir' or 'namei'
  3342 00004F76 A1[1C660000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3343 00004F7B A3[5D660000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3344 00004F80 66890D[61660000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3345 00004F87 EB0B                <1> 	jmp	short sioreg_2
  3346                              <1> sioreg_1:
  3347                              <1> 	; 25/07/2015
  3348                              <1> 	; 18/07/2015
  3349                              <1> 	; 09/06/2015 
  3350 00004F89 0FB715[61660000]    <1> 	movzx	edx, word [u.pcount]
  3351                              <1> 		; ecx and [u.pcount] are always > 0, here
  3352 00004F90 39D1                <1> 	cmp	ecx, edx	
  3353 00004F92 7728                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3354                              <1> sioreg_2: ; 2:
  3355 00004F94 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3356                              <1> sioreg_3:
  3357 00004F96 010D[24660000]      <1> 	add 	[u.nread], ecx
  3358                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3359                              <1> 			         ; / during write is put into u.nread
  3360 00004F9C 290D[20660000]      <1> 	sub 	[u.count], ecx
  3361                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3362                              <1> 			       ; / must be written or read
  3363 00004FA2 010D[1C660000]      <1> 	add 	[u.base], ecx
  3364                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3365                              <1> 			      ; / data bytes
  3366                              <1>         ; 19/07/2022
  3367                              <1> 	;add 	[esi], ecx 
  3368                              <1> 	;	; add r3,*u.fofp / new file offset = number of bytes done
  3369                              <1> 			       ; / + old file offset
  3370                              <1> 	; 25/07/2015
  3371                              <1> 	;mov	esi, [u.pbase]
  3372                              <1> 	; 19/07/2022
  3373 00004FA8 8B15[5D660000]      <1> 	mov	edx, [u.pbase]
  3374                              <1> 
  3375 00004FAE 66290D[61660000]    <1> 	sub	[u.pcount], cx
  3376 00004FB5 010D[5D660000]      <1> 	add	[u.pbase], ecx
  3377 00004FBB C3                  <1>         retn
  3378                              <1> 		; rts r0
  3379                              <1> 		; transfer count > [u.pcount]
  3380                              <1> sioreg_4:
  3381                              <1> 	; 25/07/2015
  3382                              <1> 	; transfer count > [u.pcount] 
  3383                              <1> 	; (ecx > edx)
  3384 00004FBC 89C8                <1> 	mov	eax, ecx
  3385 00004FBE 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3386 00004FC0 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3387 00004FC2 EBD2                <1> 	jmp	short sioreg_3
  2119                                  %include 'u7.s'        ; 18/04/2015
  2120                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS7.INC
  2121                              <1> ; Last Modification: 13/06/2022
  2122                              <1> ; ----------------------------------------------------------------------------
  2123                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2124                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2125                              <1> ;
  2126                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2127                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2128                              <1> ; <Bell Laboratories (17/3/1972)>
  2129                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2130                              <1> ;
  2131                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2132                              <1> ;
  2133                              <1> ; ****************************************************************************
  2134                              <1> 
  2135                              <1> sysmount: ; / mount file system; args special; name
  2136                              <1> 	; 15/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2137                              <1> 	; 09/02/2022
  2138                              <1> 	; 08/02/2022
  2139                              <1> 	; 07/02/2022
  2140                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2141                              <1> 	; 14/11/2015
  2142                              <1> 	; 24/10/2015
  2143                              <1> 	; 13/10/2015
  2144                              <1> 	; 10/07/2015
  2145                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2146                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2147                              <1> 	;
  2148                              <1> 	; 'sysmount' anounces to the system that a removable 
  2149                              <1> 	; file system has been mounted on a special file.
  2150                              <1> 	; The device number of the special file is obtained via
  2151                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2152                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2153                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2154                              <1> 	; to read file system into core, i.e. the first block on the
  2155                              <1> 	; mountable file system is read in. This block is super block
  2156                              <1> 	; for the file system. This call is super user restricted.	
  2157                              <1> 	;
  2158                              <1> 	; Calling sequence:
  2159                              <1> 	;	sysmount; special; name
  2160                              <1> 	; Arguments:
  2161                              <1> 	;	special - pointer to name of special file (device)
  2162                              <1> 	;	name -  pointer to name of the root directory of the
  2163                              <1> 	;		newly mounted file system. 'name' should 
  2164                              <1> 	;		always be a directory.
  2165                              <1> 	; Inputs: - 
  2166                              <1> 	; Outputs: -
  2167                              <1> 	; ...............................................................
  2168                              <1> 	;				
  2169                              <1> 	; Retro UNIX 8086 v1 modification: 
  2170                              <1> 	;       'sysmount' system call has two arguments; so,
  2171                              <1> 	;	* 1st argument, special is pointed to by BX register
  2172                              <1> 	;	* 2nd argument, name is in CX register
  2173                              <1> 	;
  2174                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2175                              <1> 	;	       already modified for IBM PC compatibility and 
  2176                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2177                              <1> 	
  2178                              <1> 	;call	arg2
  2179                              <1> 		; jsr r0,arg2 / get arguments special and name
  2180 00004FC4 891D[14660000]      <1> 	mov	[u.namep], ebx
  2181                              <1> 	; 09/02/2022
  2182                              <1> 	;push	ecx ; directory name
  2183 00004FCA 66833D[E6650000]00  <1> 	cmp	word [mnti], 0
  2184                              <1> 		; tst mnti / is the i-number of the cross device file
  2185                              <1> 			 ; / zero?
  2186                              <1> 	;;ja	error
  2187                              <1>         	; bne errora / no, error
  2188                              <1> 	;ja	sysmnt_err0
  2189                              <1> 	; 11/01/2022
  2190 00004FD2 7605                <1> 	jna	short sysmnt_0
  2191 00004FD4 E968010000          <1> 	jmp	sysmnt_err0
  2192                              <1> sysmnt_0:
  2193                              <1> 	; 09/02/2022
  2194 00004FD9 51                  <1> 	push	ecx ; directory name
  2195 00004FDA E84A010000          <1> 	call	getspl
  2196                              <1> 		; jsr r0,getspl / get special files device number in r1
  2197                              <1> 	; 09/02/2022
  2198 00004FDF 8F05[14660000]      <1> 	pop	dword [u.namep] ; directory name
  2199                              <1> 	; 13/10/2015
  2200                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2201                              <1> 	; 11/01/2022
  2202 00004FE5 29DB                <1> 	sub	ebx, ebx
  2203 00004FE7 88C3                <1> 	mov	bl, al
  2204 00004FE9 F683[7E5D0000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2205 00004FF0 750F                <1> 	jnz	short sysmnt_1
  2206                              <1> sysmnt_err1:
  2207 00004FF2 C705[51660000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2207 00004FFA 0000                <1>
  2208 00004FFC E9D0E1FFFF          <1> 	jmp	error
  2209                              <1> sysmnt_1:
  2210                              <1> 	; 09/02/2022
  2211                              <1> 	;pop	dword [u.namep]
  2212                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2213                              <1> 				  ; / on the device
  2214                              <1> 	; 14/11/2015
  2215 00005001 53                  <1> 	push	ebx ; 13/10/2015
  2216                              <1> 		; mov r1,-(sp) / save the device number
  2217                              <1>         ;
  2218 00005002 E8D6F0FFFF          <1> 	call	namei
  2219                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2220                              <1> 		       ; ax = 0 -> file not found 	
  2221                              <1> 	;jz	error
  2222                              <1> 	;jc	error
  2223                              <1> 		; jsr r0,namei / get the i-number of the file
  2224                              <1>                	; br errora
  2225 00005007 730F                <1> 	jnc	short sysmnt_2
  2226                              <1> sysmnt_err2:
  2227 00005009 C705[51660000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2227 00005011 0000                <1>
  2228 00005013 E9B9E1FFFF          <1> 	jmp	error
  2229                              <1> sysmnt_2:	
  2230 00005018 66A3[E6650000]      <1> 	mov	[mnti], ax
  2231                              <1>         	; mov r1,mnti / put it in mnti
  2232                              <1> 
  2233                              <1> 	; 15/05/2022
  2234                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2235 0000501E 66A1[E0650000]      <1> 	mov	ax, [ii]
  2236 00005024 66A3[E8650000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2237                              <1> 
  2238                              <1> 	; 11/01/2022
  2239 0000502A BB[CC780000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2240                              <1> sysmnt_3: ;1:
  2241                              <1>         ;cmp	byte [ebx+1], 0
  2242                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2243                              <1> 			   ; / dismountable device set?
  2244                              <1>         ;jna	short sysmnt_4		
  2245                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2246                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2247                              <1> 	;jmp	short sysmnt_3
  2248                              <1> sysmnt_4:   
  2249 0000502F 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2250 00005030 A2[E5650000]        <1> 	mov	[mdev], al
  2251                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2252 00005035 8803                <1> 	mov	[ebx], al
  2253                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2254                              <1> 			      ; / of the I/O queue entry
  2255                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2256                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2257 00005037 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2258                              <1> 		; bis $2000,sb1 / set the read bit
  2259                              <1> 	; Retro UNIX 386 v1 modification : 
  2260                              <1> 	;	32 bit block number at buffer header offset 4
  2261 0000503C C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2262 00005043 E8AB050000          <1> 	call 	diskio
  2263 00005048 7345                <1> 	jnc	short sysmnt_5
  2264 0000504A 31C0                <1> 	xor 	eax, eax
  2265 0000504C 66A3[E6650000]      <1> 	mov	[mnti], ax ; 0
  2266 00005052 A2[E5650000]        <1> 	mov	[mdev], al ; 0
  2267                              <1> 	;mov	[cdev], al ; 0
  2268                              <1> 	; 08/02/2022
  2269 00005057 803D[64660000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2270 0000505E 7508                <1> 	jne	short sysmnt_err3
  2271                              <1> 	; yes, clear [u.brwdev] for next check
  2272                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2273 00005060 FE05[64660000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2274 00005066 EB0A                <1> 	jmp	short sysmnt_err4
  2275                              <1> sysmnt_err3:	; 08/02/2022
  2276                              <1> 	; no, set [u.error] to disk read error
  2277 00005068 C705[51660000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2277 00005070 0000                <1>
  2278                              <1> sysmnt_err4:
  2279                              <1> 	; 08/02/2022
  2280                              <1> 	; 14/11/2015
  2281 00005072 FEC8                <1> 	dec 	al
  2282 00005074 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2283 00005076 FEC0                <1> 	inc	al
  2284 00005078 48                  <1> 	dec	eax
  2285 00005079 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2286 0000507C E950E1FFFF          <1> 	jmp	error
  2287                              <1> sysmnt_invd:
  2288                              <1> 	; 08/02/2022
  2289 00005081 C705[51660000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2289 00005089 0000                <1>
  2290                              <1> 				 ;'invalid fs/superblock !' error
  2291 0000508B 30C0                <1> 	xor	al, al
  2292 0000508D EBE3                <1> 	jmp	short sysmnt_err4	
  2293                              <1> 
  2294                              <1> sysmnt_5:
  2295                              <1> 	; 08/02/2022
  2296                              <1> 	; 11/01/2022 (BugFix)
  2297                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2298                              <1> 	; (Following check is needed to prevent mounting an
  2299                              <1> 	; invalid file system (invalid super block).
  2300                              <1> 	; 
  2301 0000508F 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2302 00005092 C0E002              <1> 	shl	al, 2 ; 4*index
  2303 00005095 8B88[625D0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2304 0000509B C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2305                              <1> 	; ecx = number of free map bytes (required)
  2306                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2307 0000509E 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2308                              <1> 	; edx = number of free blocks map bytes
  2309                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2310                              <1> 	; 07/02/2022
  2311                              <1> 	;xor	al, al ; 08/02/2022
  2312 000050A2 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2313                              <1> 			 ; (in sectors), if they are not equal
  2314                              <1> 			 ; the disk to be mounted is an...	
  2315 000050A4 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2316                              <1> 			 ; (which has not got a valid super block)
  2317                              <1> 	;
  2318 000050A6 C6430100            <1> 	mov	byte [ebx+1], 0
  2319                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2320                              <1> ;sysmnt_6: ;1:
  2321                              <1> 	;;cmp	byte [sb1+1], 0
  2322                              <1> 		; tstb sb1+1 / done reading?
  2323                              <1>    	;;jna	sysret
  2324                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2325                              <1> 	;;jmp	short sysmnt_6
  2326                              <1> 		; bne 1b / no, wait
  2327                              <1>         	; br sysreta / yes
  2328 000050AA E942E1FFFF          <1> 	jmp	sysret
  2329                              <1> 
  2330                              <1> sysumount: ; / special dismount file system
  2331                              <1> 	; 15/05/2022
  2332                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3)
  2333                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2334                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2335                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2336                              <1> 	;
  2337                              <1> 	; 04/11/2013
  2338                              <1> 	; 09/07/2013
  2339                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2340                              <1> 	; indicated as an argument is no longer contain a removable
  2341                              <1> 	; file system. 'getspl' gets the device number of the special
  2342                              <1> 	; file. If no file system was mounted on that device an error
  2343                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2344                              <1> 	; to 'sysret'.
  2345                              <1> 	;
  2346                              <1> 	; Calling sequence:
  2347                              <1> 	;	sysmount; special
  2348                              <1> 	; Arguments:
  2349                              <1> 	;	special - special file to dismount (device)
  2350                              <1> 	;
  2351                              <1> 	; Inputs: - 
  2352                              <1> 	; Outputs: -
  2353                              <1> 	; ...............................................................
  2354                              <1> 	;				
  2355                              <1> 	; Retro UNIX 8086 v1 modification: 
  2356                              <1> 	;       'sysumount' system call has one argument; so,
  2357                              <1> 	;	* Single argument, special is pointed to by BX register
  2358                              <1> 	;
  2359                              <1> 	
  2360                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2361                              <1> 	;call	arg
  2362                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2363 000050AF 891D[14660000]      <1>         mov	[u.namep], ebx
  2364 000050B5 E86F000000          <1> 	call	getspl
  2365                              <1> 		; jsr r0,getspl / get the device number in r1
  2366                              <1> 
  2367                              <1> 	;;;
  2368                              <1> 	; 09/05/2022 - Erdogan Tan
  2369                              <1> 	; (I have added [mnti] check because
  2370                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2371                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2372                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2373                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2374 000050BA 66833D[E6650000]00  <1> 	cmp	word [mnti], 0
  2375 000050C2 767D                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2376                              <1> 	;;;
  2377                              <1> 
  2378 000050C4 3A05[E5650000]      <1> 	cmp	al, [mdev]
  2379                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2380 000050CA 7575                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2381                              <1> 	;jne	error
  2382                              <1>         	; bne errora / no error
  2383 000050CC 30C0                <1> 	xor	al, al ; ah = 0
  2384                              <1> sysumnt_0: ;1:
  2385                              <1>      	; 11/01/2022
  2386                              <1> 	;cmp 	[sb1+1], al ; 0
  2387                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2388                              <1> 	;		   ; / (inhibit bit set)?
  2389                              <1> 	;jna	short sysumnt_1		
  2390                              <1> 	;	; bne 1b / yes, wait
  2391                              <1> 	;call	idle ; (wait for hardware interrupt)
  2392                              <1> 	;jmp	short sysumnt_0
  2393                              <1> sysumnt_1:        
  2394                              <1> 	; 15/05/2022
  2395                              <1> 	; change user's current directory to mounting directory
  2396                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2397 000050CE 3805[46660000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2398 000050D4 7643                <1> 	jna	short sysumnt_4
  2399                              <1> 	;;;
  2400                              <1> 	; 15/05/2022
  2401                              <1> 	; It is needed to change the parent process's current
  2402                              <1> 	; directory because shell runs (/etc/umount) 
  2403                              <1> 	; as child process.
  2404 000050D6 31DB                <1> 	xor	ebx, ebx 
  2405 000050D8 8A1D[4B660000]      <1> 	mov	bl, [u.uno]
  2406 000050DE D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2407 000050E0 81C3[32630000]      <1> 	add	ebx, p.ppid-2
  2408 000050E6 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2409 000050E9 BE[14630000]        <1> 	mov	esi, p.pid
  2410 000050EE 29C9                <1> 	sub	ecx, ecx
  2411 000050F0 B110                <1> 	mov	cl, nproc ; 16  
  2412                              <1> sysumnt_2:	
  2413 000050F2 66AD                <1> 	lodsw
  2414 000050F4 6639D0              <1> 	cmp	ax, dx
  2415 000050F7 7402                <1> 	je	short sysumnt_3
  2416 000050F9 E2F7                <1> 	loop	sysumnt_2
  2417                              <1> sysumnt_3:
  2418 000050FB 31C0                <1> 	xor	eax, eax
  2419 000050FD 81EE[14630000]      <1> 	sub	esi, p.pid
  2420 00005103 D1E6                <1> 	shl	esi, 1
  2421 00005105 8B9E[80630000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2422                              <1> 	; ebx points to user (u) structure in upage
  2423 0000510B 668B15[E6650000]    <1> 	mov	dx, [mnti]
  2424                              <1> 	;mov	[u.cdir], dx
  2425                              <1> 	;mov	[u.cdrv], al ; 0
  2426 00005112 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2427 00005116 884352              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2428                              <1> 	;;;
  2429                              <1> sysumnt_4: 
  2430 00005119 A2[E5650000]        <1> 	mov	[mdev], al ; 0
  2431                              <1> 	     	; clr mntd / no, clear these
  2432 0000511E 66A3[E6650000]      <1>    	mov	[mnti], ax ; 0
  2433                              <1>         	; clr mnti
  2434                              <1> 
  2435                              <1> 	;; 15/05/2022
  2436                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2437                              <1> 	;mov	ax, dx  ; [u.cdir]
  2438                              <1> 	;call	iget
  2439                              <1> 
  2440 00005124 E9C8E0FFFF          <1>         jmp	sysret
  2441                              <1> 		; br sysreta / return
  2442                              <1> 
  2443                              <1> getspl: ; / get device number from a special file name
  2444 00005129 E8AFEFFFFF          <1> 	call	namei
  2445                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2446                              <1> 		       ; ax = 0 -> file not found 	
  2447                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2448                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2449 0000512E 7305                <1> 	jnc	short getspl_0
  2450 00005130 E9D4FEFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2451                              <1> getspl_0:
  2452                              <1> 	;jz	error
  2453                              <1> 	;jc	error
  2454                              <1> 		; jsr r0,namei / get the i-number of the special file
  2455                              <1>                 ; br errora / no such file
  2456 00005135 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2457                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2458                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2459 00005139 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2460                              <1> 	;jc	error
  2461                              <1> 		; ble errora / less than 0?  yes, error
  2462 0000513B 6683F805            <1>         cmp	ax, 5 ;
  2463                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2464                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2465                              <1> 	;;ja	error
  2466                              <1> 		; bgt errora / yes, error
  2467                              <1> 	; 11/01/2022
  2468 0000513F 760F                <1> 	jna	short getspl_retn
  2469                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2470                              <1> ;iopen_retn:
  2471                              <1> ;	retn
  2472                              <1> 		; rts r0 / return with device number in r1
  2473                              <1> sysmnt_err0:
  2474 00005141 C705[51660000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2474 00005149 0000                <1>
  2475 0000514B E981E0FFFF          <1> 	jmp	error
  2476                              <1> 
  2477                              <1> getspl_retn:
  2478                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2479                              <1> 	; 11/01/2022
  2480                              <1> iopen_retn:
  2481 00005150 C3                  <1> 	retn
  2482                              <1> 
  2483                              <1> iopen:	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2484                              <1> 	;		(Printer initialization)
  2485                              <1> 	; 11/01/2022
  2486                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2487                              <1> 	; 19/05/2015
  2488                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2489                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2490                              <1> 	;
  2491                              <1> 	; open file whose i-number is in r1
  2492                              <1> 	; 
  2493                              <1> 	; INPUTS ->
  2494                              <1> 	;    r1 - inode number
  2495                              <1> 	; OUTPUTS ->
  2496                              <1> 	;    file's inode in core	
  2497                              <1> 	;    r1 - inode number (positive)
  2498                              <1> 	;
  2499                              <1> 	; ((AX = R1))
  2500                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2501                              <1> 	;        
  2502                              <1> ; / open file whose i-number is in r1
  2503 00005151 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2504                              <1> 		; tst r1 / write or read access?
  2505 00005154 7568                <1>         jnz	short iopen_2
  2506                              <1> 		; blt 2f / write, go to 2f
  2507 00005156 B202                <1> 	mov	dl, 2 ; read access
  2508 00005158 E864F8FFFF          <1> 	call	access
  2509                              <1>         	; jsr r0,access; 2 
  2510                              <1> 	; / get inode into core with read access
  2511                              <1> 	; DL=2
  2512                              <1> iopen_0:
  2513 0000515D 6683F828            <1>         cmp	ax, 40
  2514                              <1> 		; cmp r1,$40. / is it a special file
  2515 00005161 77ED                <1>         ja	short iopen_retn
  2516                              <1> 		; bgt  3f / no. 3f
  2517 00005163 50                  <1> 	push	eax ; 08/01/2022
  2518                              <1> 	;push	ax
  2519                              <1> 		; mov r1,-(sp) / yes, figure out
  2520 00005164 0FB6D8              <1> 	movzx	ebx, al
  2521 00005167 C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2522                              <1> 	;shl	bx, 2
  2523                              <1> 		; asl r1
  2524 0000516A 81C3[6E510000]      <1>         add     ebx, iopen_1 - 4
  2525 00005170 FF23                <1> 	jmp	dword [ebx]
  2526                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2527                              <1> iopen_1: ; 1:
  2528 00005172 [D6510000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2529                              <1>  		 ;otty / tty ; r1=2
  2530                              <1>         	 ;oppt / ppt ; r1=4
  2531 00005176 [8E520000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2532                              <1> 		 ;sret / mem ; r1=6
  2533                              <1> 		 ;sret / rf0
  2534                              <1>         	 ;sret / rk0
  2535                              <1>         	 ;sret / tap0
  2536                              <1>         	 ;sret / tap1
  2537                              <1>         	 ;sret / tap2
  2538                              <1>         	 ;sret / tap3
  2539                              <1>         	 ;sret / tap4
  2540                              <1>         	 ;sret / tap5
  2541                              <1>         	 ;sret / tap6
  2542                              <1>         	 ;sret / tap7
  2543 0000517A [8E520000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2544 0000517E [8E520000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2545 00005182 [8E520000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2546 00005186 [8E520000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2547 0000518A [8E520000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2548 0000518E [8E520000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2549                              <1> 	;;dd	error ; lpr, AX = 9 (error !)
  2550                              <1>         ;dd	sret ; lpr, AX = 9 (runix)
  2551                              <1> 	; 13/06/2022 - (lpt_init)
  2552 00005192 [5A530000]          <1>         dd	ejec ; lpr, AX = 9 (runix)
  2553 00005196 [E7510000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2554                              <1> 		 ;ocvt / tty0
  2555 0000519A [E7510000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2556                              <1> 		 ;ocvt / tty1
  2557 0000519E [E7510000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2558                              <1> 		 ;ocvt / tty2
  2559 000051A2 [E7510000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2560                              <1> 		 ;ocvt / tty3
  2561 000051A6 [E7510000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2562                              <1> 		 ;ocvt / tty4
  2563 000051AA [E7510000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2564                              <1> 		 ;ocvt / tty5
  2565 000051AE [E7510000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2566                              <1> 		 ;ocvt / tty6
  2567 000051B2 [E7510000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2568                              <1> 		 ;ocvt / tty7
  2569 000051B6 [E7510000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2570                              <1> 		 ;error / crd
  2571 000051BA [E7510000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2572                              <1> 
  2573                              <1> iopen_2: ; 2: / check open write access
  2574 000051BE 66F7D8              <1> 	neg	ax
  2575                              <1> 		;neg r1 / make inode number positive
  2576 000051C1 B201                <1> 	mov	dl, 1 ; write access
  2577 000051C3 E8F9F7FFFF          <1> 	call	access
  2578                              <1> 		;jsr r0,access; 1 / get inode in core
  2579                              <1> 	; DL=1
  2580                              <1> 	; 11/01/2022
  2581 000051C8 F605[F5620000]40    <1> 	test	byte [i.flgs+1], 40h
  2582                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2583                              <1>  		; bit $40000,i.flgs / is it a directory?
  2584 000051CF 748C                <1> 	jz	short iopen_0
  2585                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2586                              <1> 	;jmp	error ; permission denied !
  2587 000051D1 E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2588                              <1> 	;;jnz	error		
  2589                              <1>        		; bne 2f / yes, transfer (error)
  2590                              <1>         ;;jmp	short iopen_0
  2591                              <1> 	;cmp	ax, 40
  2592                              <1> 		; cmp r1,$40. / no, is it a special file?
  2593                              <1>         ;ja	short iopen_2
  2594                              <1> 		; bgt 3f / no, return
  2595                              <1> 	;push	ax
  2596                              <1> 		; mov r1,-(sp) / yes
  2597                              <1> 	;movzx	ebx, al
  2598                              <1> 	;shl	bx, 1
  2599                              <1> 		; asl r1
  2600                              <1> 	;add	ebx, ipen_3 - 2
  2601                              <1> 	;jmp	dword [ebx]
  2602                              <1> 		; jmp *1f-2(r1) / figure out 
  2603                              <1> 			; / which special file it is and transfer
  2604                              <1> ;iopen_3: ; 1:
  2605                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2606                              <1>  		 ;otty / tty ; r1=2
  2607                              <1>         	 ;leadr / ppt ; r1=4
  2608                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2609                              <1> 		 ;sret / mem ; r1=6
  2610                              <1> 		 ;sret / rf0
  2611                              <1>         	 ;sret / rk0
  2612                              <1>         	 ;sret / tap0
  2613                              <1>         	 ;sret / tap1
  2614                              <1>         	 ;sret / tap2
  2615                              <1>         	 ;sret / tap3
  2616                              <1>         	 ;sret / tap4
  2617                              <1>         	 ;sret / tap5
  2618                              <1>         	 ;sret / tap6
  2619                              <1>         	 ;sret / tap7
  2620                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2621                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2622                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2623                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2624                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2625                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2626                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2627                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2628                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2629                              <1> 		 ;ocvt / tty0
  2630                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2631                              <1> 		 ;ocvt / tty1
  2632                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2633                              <1> 		 ;ocvt / tty2
  2634                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2635                              <1> 		 ;ocvt / tty3
  2636                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2637                              <1> 		 ;ocvt / tty4
  2638                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2639                              <1> 		 ;ocvt / tty5
  2640                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2641                              <1> 		 ;ocvt / tty6
  2642                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2643                              <1> 		 ;ocvt / tty7
  2644                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2645                              <1> 		 ;/ ejec / lpr
  2646                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2647                              <1> 
  2648                              <1> otty: ;/ open console tty for reading or writing
  2649                              <1> 	; 03/03/2022
  2650                              <1> 	; 02/03/2022
  2651                              <1> 	; 26/02/2022
  2652                              <1> 	; 09/02/2022
  2653                              <1> 	; 06/02/2022
  2654                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2655                              <1> 	; 16/11/2015
  2656                              <1> 	; 12/11/2015
  2657                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2658                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2659                              <1> 	; 16/07/2013
  2660                              <1> 	; Retro UNIX 8086 v1 modification:
  2661                              <1> 	;  If a tty is open for read or write by
  2662                              <1> 	;     a process (u.uno), only same process can open
  2663                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2664                              <1> 	;
  2665                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2666                              <1> 	;
  2667 000051D6 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2668 000051DD 8A83[53630000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2669                              <1> 	; 13/01/2014
  2670                              <1> 	;jmp	short ottyp
  2671                              <1> 	; 26/02/2022
  2672 000051E3 88C4                <1> 	mov	ah, al
  2673 000051E5 EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2674                              <1> ocvt:
  2675 000051E7 2C0A                <1> 	sub	al, 10
  2676                              <1> ;ottyp:	; (call from sysstty)
  2677                              <1> 	; 08/01/2022
  2678 000051E9 31DB                <1> 	xor	ebx, ebx
  2679                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2680                              <1> 	; 26/02/2022
  2681 000051EB B4FF                <1> 	mov	ah, 0FFh
  2682                              <1> ottypc:
  2683                              <1> 	; 03/03/2022
  2684                              <1> 	; 26/02/2022
  2685                              <1> 	; 09/02/2022
  2686                              <1> 	; 08/01/2022
  2687                              <1> 	; 16/11/2015
  2688                              <1> 	; 12/11/2015
  2689                              <1> 	; 18/05/2015 (32 bit modifications)
  2690                              <1> 	; 06/12/2013 - 13/07/2014
  2691 000051ED 88C6                <1> 	mov	dh, al ; tty number
  2692                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2693                              <1> 	; 08/01/2022
  2694 000051EF 88C3                <1> 	mov	bl, al
  2695 000051F1 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2696                              <1> 	; 26/01/2014	
  2697 000051F3 81C3[84620000]      <1> 	add 	ebx, ttyl
  2698 000051F9 668B0B              <1> 	mov 	cx, [ebx]
  2699                              <1> 		   ; CL = lock value (0 or process number)
  2700                              <1> 		   ; CH = open count 
  2701 000051FC 20C9                <1> 	and 	cl, cl
  2702                              <1> 	; 13/01/2014
  2703                              <1> 	;jz 	short otty_ret
  2704                              <1> 	; 08/01/2022
  2705 000051FE 7447                <1> 	jz 	short ottys_0
  2706                              <1> 	;
  2707                              <1> 	; 16/11/2015
  2708 00005200 3A0D[4B660000]      <1> 	cmp 	cl, [u.uno]
  2709 00005206 746E                <1> 	je	short ottys_3
  2710                              <1> 	;
  2711                              <1> 	;
  2712                              <1> 	; 26/02/2022
  2713                              <1> 	; (is it the console tty of the current process?)
  2714                              <1> 	; ((fast check/permit for console tty open function))
  2715 00005208 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2716 0000520A 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2717                              <1> 	;
  2718                              <1> 	; 26/02/2022
  2719                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2720                              <1> 	;shl 	bl, 1
  2721                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2722                              <1> 	;;movzx ebx, byte [u.uno]
  2723                              <1> 	;mov	bl, [u.uno]
  2724                              <1> 	;shl 	bl, 1
  2725                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2726                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2727                              <1> 	; 26/02/2022 (BugFix) ; *
  2728 0000520C 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2729 0000520F D1E6                <1> 	shl 	esi, 1
  2730 00005211 668B86[12630000]    <1> 	mov 	ax, [esi+p.pid-2]
  2731 00005218 96                  <1> 	xchg	esi, eax
  2732 00005219 A0[4B660000]        <1> 	mov	al, [u.uno]
  2733 0000521E D0E0                <1> 	shl 	al, 1
  2734 00005220 663BB0[32630000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2735 00005227 744D                <1> 	je 	short ottys_3 ; *
  2736                              <1> 	; 26/02/2022
  2737                              <1> 	; check console tty of the process
  2738                              <1> 	; (open permission must be given if the -requested- tty is
  2739                              <1> 	;  console tty of current process)
  2740 00005229 D0E8                <1> 	shr	al, 1
  2741 0000522B 38B0[53630000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2742 00005231 7443                <1> 	je 	short ottys_3
  2743                              <1> 	;
  2744                              <1> 	; the tty is locked by another process
  2745                              <1> 	; except the parent process (p.ppid)
  2746                              <1>         ;
  2747                              <1> 	; 09/02/2022
  2748                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2749                              <1> 	;		; permission denied ! error
  2750                              <1> otty_err: ; 13/01/2014
  2751                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2752                              <1> 	;;jnz	error
  2753                              <1> 	; 05/12/2021
  2754                              <1> 	;jz	short otty_stc_retn
  2755                              <1> 	;jmp	error
  2756                              <1> 	; 09/02/2022
  2757 00005233 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2758 00005236 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2759                              <1> 	; iopen (dl=1 or dl=2)
  2760 00005238 C705[51660000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2760 00005240 0000                <1>
  2761                              <1> 			; permission denied ! error
  2762 00005242 E98ADFFFFF          <1> 	jmp	error
  2763                              <1> ;otty_stc_retn:
  2764                              <1> 	;stc
  2765                              <1> 	;retn
  2766                              <1> ottys_0:
  2767                              <1> 	; 08/01/2022
  2768                              <1> otty_ret: 
  2769                              <1> 	; 13/01/2014
  2770 00005247 80FE07              <1> 	cmp 	dh, 7
  2771 0000524A 7624                <1> 	jna	short ottys_2
  2772                              <1> 	; 16/11/2015
  2773                              <1> com_port_check:
  2774 0000524C BE[A2620000]        <1> 	mov	esi, com1p
  2775 00005251 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2776 00005254 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2777 00005256 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2778                              <1> ottys_1:
  2779                              <1> 	; 12/11/2015
  2780 00005257 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2781 0000525A 7714                <1> 	ja	short com_port_ready
  2782                              <1> 	;
  2783                              <1> 	; 09/02/2022
  2784 0000525C 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2785 0000525F 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2786 00005261 C705[51660000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2786 00005269 0000                <1>
  2787                              <1> 			   ; device not ready ! error
  2788                              <1> 	;jmp	short otty_err
  2789 0000526B E961DFFFFF          <1> 	jmp	error
  2790                              <1> com_port_ready:
  2791                              <1> ottys_2:
  2792                              <1> 	; 02/03/2022
  2793                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2794                              <1> 	;jnz	short ottys_3
  2795 00005270 8A0D[4B660000]      <1> 	mov	cl, [u.uno]
  2796                              <1> ottys_3:
  2797 00005276 FEC5                <1> 	inc 	ch
  2798 00005278 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2799                              <1> 	; 06/12/2013
  2800 0000527B FEC6                <1> 	inc	dh ; tty number + 1
  2801 0000527D BB[2C660000]        <1> 	mov	ebx, u.ttyp
  2802                              <1> 	; 13/01/2014
  2803 00005282 F6C202              <1> 	test	dl, 2 ; open for read sign
  2804 00005285 7501                <1> 	jnz	short ottys_4
  2805 00005287 43                  <1> 	inc	ebx
  2806                              <1> ottys_4:
  2807                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2808 00005288 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2809                              <1> 	; 09/02/2022
  2810 0000528A 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2811 0000528C 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2812                              <1> sret:
  2813                              <1> 	;pop 	ax
  2814 0000528E 58                  <1> 	pop	eax ; 08/01/2022
  2815                              <1> otty_retn:	; 09/02/2022
  2816                              <1> iclose_retn:	
  2817 0000528F C3                  <1> 	retn
  2818                              <1> 
  2819                              <1> 	;
  2820                              <1> 	; Original UNIX v1 'otty' routine:
  2821                              <1> 	;	
  2822                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2823                              <1>         ;                 / reader status reg
  2824                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2825                              <1>         ;                 / punch status reg
  2826                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2827                              <1>         ;                          / console tty buffer
  2828                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2829                              <1>         ;            / console tty
  2830                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2831                              <1>         ;             / buffer header
  2832                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2833                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2834                              <1>         ;                 / tty
  2835                              <1>         ;br     sret / ?
  2836                              <1> ;sret:
  2837                              <1> 		;clr *$ps / set processor priority to zero
  2838                              <1> ;	pop	ax
  2839                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2840                              <1> ;3:
  2841                              <1> ;	retn
  2842                              <1>         	;rts r0
  2843                              <1> 	
  2844                              <1> ;ocvt:	; < open tty >
  2845                              <1> 	; 13/01/2014
  2846                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2847                              <1> 	; 24/09/2013 consistency check -> ok
  2848                              <1> 	; 16/09/2013
  2849                              <1> 	; 03/09/2013
  2850                              <1> 	; 27/08/2013
  2851                              <1> 	; 16/08/2013
  2852                              <1> 	; 16/07/2013
  2853                              <1> 	; 27/05/2013
  2854                              <1> 	; 21/05/2013
  2855                              <1> 	;
  2856                              <1> 	; Retro UNIX 8086 v1 modification !
  2857                              <1> 	; 
  2858                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2859                              <1> 	;	(exactly different than this one)
  2860                              <1> 	;	was in 'u9.s' file.
  2861                              <1> 	;
  2862                              <1> 	; 16/07/2013
  2863                              <1> 	; Retro UNIX 8086 v1 modification:
  2864                              <1> 	;  If a tty is open for read or write by
  2865                              <1> 	;     a process (u.uno), only same process can open
  2866                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2867                              <1> 	;
  2868                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2869                              <1> 
  2870                              <1> 	; 16/09/2013
  2871                              <1> 	; sub 	al, 10
  2872                              <1> 	
  2873                              <1> 	; 06/12/2013
  2874                              <1> 	;cmp	al, 7
  2875                              <1>         ;jna     short ottyp
  2876                              <1> 	; 13/01/2014
  2877                              <1> 	;jmp	short ottyp
  2878                              <1> 
  2879                              <1> ;oppt: / open paper tape for reading or writing
  2880                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2881                              <1> ;        tstb   pptiflg / is file already open
  2882                              <1> ;        bne    2f / yes, branch
  2883                              <1> ;1:
  2884                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2885                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2886                              <1> ;               br .+4 / for paper tape input and place in free list
  2887                              <1> ;        br     1b
  2888                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2889                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2890                              <1> ;        br     sret
  2891                              <1> ;2:
  2892                              <1> ;        jmp    error / file already open
  2893                              <1> 
  2894                              <1> iclose:
  2895                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2896                              <1> 	; 19/05/2015
  2897                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2898                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2899                              <1> 	;
  2900                              <1> 	; close file whose i-number is in r1
  2901                              <1> 	; 
  2902                              <1> 	; INPUTS ->
  2903                              <1> 	;    r1 - inode number
  2904                              <1> 	; OUTPUTS ->
  2905                              <1> 	;    file's inode in core	
  2906                              <1> 	;    r1 - inode number (positive)
  2907                              <1> 	;
  2908                              <1> 	; ((AX = R1))
  2909                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2910                              <1> 	;        
  2911                              <1> ;/ close file whose i-number is in r1
  2912 00005290 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2913 00005292 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2914                              <1> 		; tst r1 / test i-number
  2915                              <1>         ;jnz	short iclose_2
  2916                              <1> 		; blt 2f / if neg., branch
  2917 00005295 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2918                              <1> 	; 16/07/2013 
  2919 00005297 66F7D8              <1> 	neg	ax ; make it positive
  2920                              <1> 	; 12/01/2014
  2921 0000529A FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2922                              <1> iclose_0:
  2923 0000529C 6683F828            <1> 	cmp	ax, 40
  2924                              <1> 		; cmp r1,$40. / is it a special file
  2925 000052A0 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2926                              <1> 		; bgt 3b / no, return
  2927                              <1> 	; 12/01/2014
  2928                              <1> 	; DL=2 -> special file was opened for reading
  2929                              <1> 	; DL=1 -> special file was opened for writing
  2930 000052A2 50                  <1> 	push	eax ; 08/01/2022
  2931                              <1> 	;push	ax
  2932                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2933 000052A3 0FB6D8              <1> 	movzx	ebx, al
  2934                              <1> 	; 08/01/2022
  2935 000052A6 C0E302              <1> 	shl	bl, 2
  2936                              <1> 	;shl	bx, 2
  2937                              <1> 		; asl r1
  2938 000052A9 81C3[AD520000]      <1> 	add	ebx, iclose_1 - 4
  2939 000052AF FF23                <1> 	jmp	dword [ebx]
  2940                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2941                              <1> iclose_1 :
  2942 000052B1 [FD520000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2943 000052B5 [58530000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2944 000052B9 [58530000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2945 000052BD [58530000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2946 000052C1 [58530000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2947 000052C5 [58530000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2948 000052C9 [58530000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2949 000052CD [58530000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2950 000052D1 [58530000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2951                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2952                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2953 000052D5 [0C530000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2954 000052D9 [0C530000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2955 000052DD [0C530000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2956 000052E1 [0C530000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2957 000052E5 [0C530000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2958 000052E9 [0C530000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2959 000052ED [0C530000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2960 000052F1 [0C530000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2961 000052F5 [0C530000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2962 000052F9 [0C530000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2963                              <1> 
  2964                              <1> 	; 1:
  2965                              <1> 	;        ctty   / tty
  2966                              <1> 	;        cppt   / ppt
  2967                              <1> 	;        sret   / mem
  2968                              <1> 	;        sret   / rf0
  2969                              <1> 	;        sret   / rk0
  2970                              <1> 	;        sret   / tap0
  2971                              <1> 	;        sret   / tap1
  2972                              <1> 	;        sret   / tap2
  2973                              <1> 	;        sret   / tap3
  2974                              <1> 	;        sret   / tap4
  2975                              <1> 	;        sret   / tap5
  2976                              <1> 	;        sret   / tap6
  2977                              <1> 	;        sret   / tap7
  2978                              <1> 	;        ccvt   / tty0
  2979                              <1> 	;        ccvt   / tty1
  2980                              <1> 	;        ccvt   / tty2
  2981                              <1> 	;        ccvt   / tty3
  2982                              <1> 	;        ccvt   / tty4
  2983                              <1> 	;        ccvt   / tty5
  2984                              <1> 	;        ccvt   / tty6
  2985                              <1> 	;        ccvt   / tty7
  2986                              <1> 	;        error / crd
  2987                              <1> 
  2988                              <1> ;iclose_2: ; 2: / negative i-number
  2989                              <1> 	;neg	ax
  2990                              <1> 		;neg r1 / make it positive
  2991                              <1> 	;cmp	ax, 40
  2992                              <1> 		;cmp r1,$40. / is it a special file?
  2993                              <1>         ;ja	short @b
  2994                              <1> 		;bgt    3b / no. return
  2995                              <1> 	;push	ax
  2996                              <1> 		;mov r1,-(sp)
  2997                              <1> 	;movzx	ebx, al
  2998                              <1> 	;shl	bx, 1
  2999                              <1> 		;asl r1 / yes. compute jump address and transfer
  3000                              <1> 	;add	ebx, iclose_3 - 2
  3001                              <1> 	;jmp	dword [ebx]
  3002                              <1> 		;jmp *1f-2(r1) / figure out 
  3003                              <1> ;iclose_3:
  3004                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  3005                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  3006                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  3007                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  3008                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  3009                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  3010                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  3011                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  3012                              <1> 	 ;dd	sret ; lpr, AX = 9	
  3013                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  3014                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  3015                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  3016                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  3017                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  3018                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  3019                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  3020                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  3021                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  3022                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  3023                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  3024                              <1> 	
  3025                              <1> 	;1:
  3026                              <1> 	;      	ctty   / tty
  3027                              <1> 	;       leadr  / ppt
  3028                              <1> 	;       sret   / mem
  3029                              <1> 	;       sret   / rf0
  3030                              <1> 	;       sret   / rk0
  3031                              <1> 	;       sret   / tap0
  3032                              <1> 	;       sret   / tap1
  3033                              <1> 	;       sret   / tap2
  3034                              <1> 	;       sret   / tap3
  3035                              <1> 	;       sret   / tap4
  3036                              <1> 	;       sret   / tap5
  3037                              <1> 	;       sret   / tap6
  3038                              <1> 	;       sret   / tap7
  3039                              <1> 	;       ccvt   / tty0
  3040                              <1> 	;       ccvt   / tty1
  3041                              <1> 	;       ccvt   / tty2
  3042                              <1> 	;       ccvt   / tty3
  3043                              <1> 	;       ccvt   / tty4
  3044                              <1> 	;       ccvt   / tty5
  3045                              <1> 	;       ccvt   / tty6
  3046                              <1> 	;       ccvt   / tty7
  3047                              <1> 	;/      ejec   / lpr
  3048                              <1> 
  3049                              <1> ctty: ; / close console tty
  3050                              <1> 	; 26/02/2022
  3051                              <1> 	; 09/02/2022
  3052                              <1> 	; 06/02/2022
  3053                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3054                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  3055                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  3056                              <1> 	;
  3057                              <1> 	; Retro UNIX 8086 v1 modification !
  3058                              <1> 	; (DL = 2 -> it is open for reading)
  3059                              <1> 	; (DL = 1 -> it is open for writing)
  3060                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  3061                              <1> 	;
  3062                              <1> 	; 06/12/2013
  3063 000052FD 0FB61D[4B660000]    <1>         movzx   ebx, byte [u.uno] ; process number
  3064 00005304 8A83[53630000]      <1>         mov     al, [ebx+p.ttyc-1]
  3065                              <1> 	; 13/01/2014
  3066                              <1> 	;jmp	short cttyp
  3067                              <1> 	; 06/02/2022
  3068 0000530A EB04                <1> 	jmp	short ctty_0
  3069                              <1> ccvt:
  3070 0000530C 2C0A                <1> 	sub 	al, 10
  3071                              <1> cttyp:	; (call from sysstty)
  3072                              <1> 	; 08/01/2022
  3073 0000530E 31DB                <1> 	xor	ebx, ebx
  3074                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  3075                              <1> 	; 08/01/2022
  3076                              <1> 	; 18/05/2015 (32 bit modifications)
  3077                              <1> 	; 16/08/2013 - 26/01/2014
  3078                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3079                              <1> 	; 08/01/2022
  3080 00005310 88C3                <1> 	mov	bl, al
  3081 00005312 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3082                              <1> 	; 26/01/2014
  3083 00005314 81C3[84620000]      <1> 	add 	ebx, ttyl
  3084 0000531A 88C6                <1> 	mov 	dh, al ; tty number
  3085 0000531C 668B03              <1> 	mov 	ax, [ebx]
  3086                              <1> 		   ; AL = lock value (0 or process number)
  3087                              <1> 		   ; AH = open count 
  3088 0000531F 20E4                <1> 	and 	ah, ah
  3089 00005321 7514                <1> 	jnz	short ctty_ret
  3090                              <1>   	; 09/02/2022
  3091 00005323 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3092 00005326 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3093                              <1> 	; iclose (dl=1 or dl=2)
  3094 00005328 C705[51660000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3094 00005330 0000                <1>
  3095                              <1> 			; device not open ! error
  3096                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3097 00005332 E99ADEFFFF          <1> 	jmp	error
  3098                              <1> 	; 26/01/2014
  3099                              <1> ctty_ret:
  3100 00005337 FECC                <1> 	dec 	ah ; decrease open count
  3101 00005339 7502                <1> 	jnz	short ctty_1
  3102 0000533B 30C0                <1> 	xor	al, al ; unlock/free tty
  3103                              <1> ctty_1:
  3104 0000533D 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3105                              <1> 	;
  3106 00005340 BB[2C660000]        <1> 	mov	ebx, u.ttyp
  3107                              <1> 	;test	dl, 1 ; open for write sign
  3108                              <1> 	;jz	short ctty_2
  3109                              <1> 	; 26/02/2022
  3110 00005345 F6C202              <1> 	test	dl, 2 ; open for read sign
  3111 00005348 7501                <1> 	jnz	short ctty_2
  3112 0000534A 43                  <1> 	inc	ebx
  3113                              <1> ctty_2:
  3114 0000534B FEC6                <1> 	inc	dh ; tty number + 1
  3115 0000534D 3A33                <1> 	cmp	dh, [ebx]
  3116                              <1> 	;jne	short cret
  3117 0000534F 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3118                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3119 00005351 C60300              <1> 	mov	byte [ebx], 0
  3120                              <1> ctty_3:
  3121                              <1> 	; 09/02/2022
  3122 00005354 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3123 00005356 7401                <1> 	jz	short ctty_4
  3124                              <1> cret:
  3125                              <1> 	;pop	ax
  3126                              <1> 	; 08/01/2022
  3127 00005358 58                  <1> 	pop	eax
  3128                              <1> ctty_stc_retn:	; 09/02/2022
  3129                              <1> ctty_4:
  3130 00005359 C3                  <1> 	retn
  3131                              <1> 
  3132                              <1> ;ctty_err: ; 13/01/2014
  3133                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3134                              <1> ;	jnz	error
  3135                              <1> ;	stc
  3136                              <1> ;	retn
  3137                              <1> 
  3138                              <1> 	; Original UNIX v1 'ctty' routine:
  3139                              <1> 	;	
  3140                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3141                              <1> 	;		;/ point r5 to the console tty buffer
  3142                              <1>         ;decb   (r5) / dec number of processes using console tty
  3143                              <1>         ;br     sret / return via sret
  3144                              <1> 
  3145                              <1> ;ccvt:	; < close tty >
  3146                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3147                              <1> 	;
  3148                              <1> 	; Retro UNIX 8086 v1 modification !
  3149                              <1> 	; 
  3150                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3151                              <1> 	;		(exactly different than this one)
  3152                              <1> 	;	was in 'u9.s' file.
  3153                              <1> 	;
  3154                              <1> 	; DL = 2 -> it is open for reading
  3155                              <1> 	; DL = 1 -> it is open for writing
  3156                              <1> 	;
  3157                              <1> 	; 17/09/2013
  3158                              <1> 	;sub 	al, 10
  3159                              <1> 	;cmp	al, 7
  3160                              <1> 	;jna	short cttyp
  3161                              <1> 	; 13/01/2014
  3162                              <1> 	;jmp	short cttyp
  3163                              <1> 
  3164                              <1> ;cppt: / close paper tape
  3165                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3166                              <1> ;1:
  3167                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3168                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3169                              <1> ;                          / and assign to free list
  3170                              <1> ;               br sret
  3171                              <1> ;        br     1b
  3172                              <1> 
  3173                              <1> ;ejec:	
  3174                              <1> ;	jmp	error
  3175                              <1> ;/ejec:
  3176                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3177                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3178                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3179                              <1> ;/       br     sret / return to caller via 'sret'
  3180                              <1> 
  3181                              <1> ejec:
  3182                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  3183                              <1> 	;	     - Printer Initialization
  3184                              <1> lpt_init:	
  3185                              <1> 	; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985
  3186                              <1> 	;
  3187                              <1> 	; Default printer port: 378h ; LPT1
  3188                              <1> 	
  3189 0000535A B401                <1>  	mov	ah, 1  ; INITIALIZE THE PRINTER PORT
  3190                              <1> 	;call	int17h
  3191 0000535C E8BDFAFFFF          <1> 	call	PRNOP
  3192 00005361 7414                <1> 	jz	short lpt_init_ok
  3193                              <1> 	
  3194                              <1> 	; replace error code with 'device not ready' error
  3195                              <1> 	; (this may be better for 'sysopen')
  3196 00005363 B80F000000          <1> 	mov	eax, ERR_PRN_NOT_RDY
  3197 00005368 A3[51660000]        <1> 	mov	[u.error], eax
  3198                              <1> 	;jmp	sysret ; (may be) ? ([u.r0] = file descriptor)
  3199 0000536D A3[FC650000]        <1> 	mov	[u.r0], eax
  3200 00005372 E95ADEFFFF          <1> 	jmp	error ; (better)	
  3201                              <1> 	
  3202                              <1> lpt_init_ok:
  3203                              <1> 	;jmp	short cret
  3204 00005377 58                  <1> 	pop	eax    ; inode number
  3205 00005378 C3                  <1> 	retn
  3206                              <1> 	
  2120                                  %include 'u8.s'        ; 11/06/2015
  2121                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS8.INC
  2122                              <1> ; Last Modification: 19/07/2022
  2123                              <1> ; ----------------------------------------------------------------------------
  2124                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2125                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2126                              <1> ;
  2127                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2128                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2129                              <1> ; <Bell Laboratories (17/3/1972)>
  2130                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2131                              <1> ;
  2132                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2133                              <1> ;
  2134                              <1> ; ****************************************************************************
  2135                              <1> 
  2136                              <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2137                              <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2138                              <1> ;---------------------------------------------------------------------
  2139                              <1> ; Buffer Header: -8 bytes-
  2140                              <1> ; word 1 - byte 0 - device (disk index) number (0 to 5)
  2141                              <1> ;	   byte 1 - status bits
  2142                              <1> ;	 	bit 0 - valid buffer bit (1 = valid, 0 = invalid, new)
  2143                              <1> ;		bit 1 - write bit (also modified bit)
  2144                              <1> ;		bit 2 - read bit	
  2145                              <1> ;		bit 3 to bit 7 are not used
  2146                              <1> ; word 2 - byte & byte 3 not used
  2147                              <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7:
  2148                              <1> ;		physical block/sector address (32 bit LBA)
  2149                              <1> ;---------------------------------------------------------------------
  2150                              <1> 
  2151                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2152                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2153                              <1> ;; Word 1, byte 0 = device id
  2154                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2155                              <1> ;;          bit 9 = write bit
  2156                              <1> ;;	    bit 10 = read bit	  
  2157                              <1> ;;	    bit 12 = waiting to write bit	
  2158                              <1> ;;	    bit 13 = waiting to read bit
  2159                              <1> ;;	    bit 15 = inhibit bit
  2160                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2161                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2162                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2163                              <1> ;;
  2164                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2165                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2166                              <1> ;;
  2167                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2168                              <1> ;; Word 1, Byte 0 = device id
  2169                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2170                              <1> ;;          bit 9 = write bit
  2171                              <1> ;;	    bit 10 = read bit	  
  2172                              <1> ;;	    bit 12 = waiting to write bit	
  2173                              <1> ;;	    bit 13 = waiting to read bit
  2174                              <1> ;;	    bit 15 = inhibit bit
  2175                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2176                              <1> ;;
  2177                              <1> ;; Original UNIX v1 ->
  2178                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2179                              <1> ;; Original UNIX v1 -> 
  2180                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2181                              <1> ;;
  2182                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2183                              <1> ;;
  2184                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2185                              <1> ;;          0 = fd0
  2186                              <1> ;;	    1 = fd1
  2187                              <1> ;;	    2 = hd0
  2188                              <1> ;;	    3 = hd1
  2189                              <1> ;;	    4 = hd2
  2190                              <1> ;;	    5 = hd3
  2191                              <1> 
  2192                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2193                              <1> 
  2194                              <1> 	; 08/02/2022
  2195                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2196                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2197                              <1> 	; 26/04/2013
  2198                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2199                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2200                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2201                              <1> 
  2202                              <1> 	; 08/02/2022
  2203                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2204                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2205                              <1> 	; 26/04/2013
  2206                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2207                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2208                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2209                              <1> 
  2210                              <1> bread: 
  2211                              <1> 	; 19/07/2022
  2212                              <1> 	; 15/07/2022
  2213                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2214                              <1> 	; 08/02/2022
  2215                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2216                              <1> 	; 14/07/2015
  2217                              <1> 	; 10/07/2015
  2218                              <1> 	; 09/06/2015
  2219                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2220                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2221                              <1> 	;	
  2222                              <1> 	; / read a block from a block structured device
  2223                              <1> 	;
  2224                              <1> 	; INPUTS ->
  2225                              <1> 	;    [u.fofp] points to the block number
  2226                              <1> 	;    ECX = maximum block number allowed on device
  2227                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2228                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2229                              <1> 	;    [u.count]	number of bytes to read in
  2230                              <1> 	; OUTPUTS ->
  2231                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2232                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2233                              <1> 	;
  2234                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX, ESI, EDI))
  2235                              <1> 	;
  2236                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2237                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2238                              <1> 	;	is increased by 1. For example: If user/program request 
  2239                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2240                              <1> 	;  	the next block number just as 512 byte reading is done.
  2241                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2242                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2243                              <1> 	;       enough to keep byte position/offset of the disk), this
  2244                              <1> 	;	defect will not be corrected, user/program must request
  2245                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2246                              <1> 	;       for achieving correct result. In future version(s), 
  2247                              <1> 	;	this defect will be corrected by using different 
  2248                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2249                              <1> 
  2250                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2251                              <1> 			       ; / (only works on tape)
  2252                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2253                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2254                              <1> ;1:
  2255                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2256                              <1> 			    ; / maximum block # allowed on device
  2257                              <1> 		; jnb short @f
  2258                              <1> 		; bhis	1f / yes, 1f (error)
  2259                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2260                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2261                              <1> 		; mov (sp)+,r1 / return block # to r1
  2262                              <1> 		; inc r1 / bump block # to next consecutive block
  2263                              <1> 		; dec (sp) / "2-1-cold" on stack
  2264                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2265                              <1> ;1:
  2266                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2267                              <1> 	;push	ecx ; **
  2268                              <1> 	; 26/04/2013
  2269                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2270 00005379 2C03                <1> 	sub	al, 3
  2271                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2272 0000537B A2[64660000]        <1> 	mov	[u.brwdev], al
  2273                              <1> 	; 09/06/2015
  2274                              <1> 	;movzx	ebx, al
  2275                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2276                              <1> 	; 12/01/2022 (BugFix)
  2277 00005380 C0E002              <1> 	shl	al, 2 ; * 4
  2278 00005383 8B88[625D0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2279                              <1> bread_0:
  2280 00005389 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2281                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2282                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2283 0000538A 8B1D[0C660000]      <1> 	mov	ebx, [u.fofp]
  2284 00005390 8B03                <1> 	mov	eax, [ebx]
  2285 00005392 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2286                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2287                              <1> 			       ; / block #
  2288 00005395 39C8                <1> 	cmp	eax, ecx
  2289                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2290                              <1>        	                     ; / block number allowed
  2291                              <1> 	;jnb	error 	     ; 18/04/2013
  2292                              <1> 		; bhis error10 / yes, error
  2293                              <1> 	; 08/02/2022
  2294                              <1> 	;jb	short bread_1
  2295                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2296                              <1> 	;jmp	error
  2297 00005397 7346                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2298                              <1> bread_1:
  2299                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2300                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2301                              <1> 	; EAX = Block number (zero based)
  2302                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2303                              <1> preread: ;; call preread
  2304 00005399 BF[64660000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2305 0000539E E8DC010000          <1> 	call	bufaloc_0 ; 26/04/2013
  2306                              <1> 	;; jc 	error
  2307                              <1> 	; EBX = Buffer (Header) Address -Physical-
  2308                              <1>         ; EAX = Block/Sector number (r1)
  2309                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2310                              <1> 	; 14/03/2013
  2311 000053A3 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2312                              <1>        		; br 1f / branch if block already in a I/O buffer
  2313 000053A5 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2314                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2315 000053AA E8A8010000          <1> 	call	poke
  2316                              <1>         	; jsr r0,poke / perform the read
  2317                              <1> 	;;jc	error ;2 0/07/2013
  2318                              <1> ; 1:
  2319                              <1>  		; clr *$ps / ps = 0
  2320                              <1>         	; rts r0
  2321                              <1> 	; 08/02/2022
  2322 000053AF 7305                <1> 	jnc	short bread_2
  2323 000053B1 E919010000          <1> 	jmp	dskrd_err
  2324                              <1> 	;
  2325                              <1> ;; return from preread
  2326                              <1> bread_2:
  2327                              <1> 	; 15/07/2022
  2328                              <1> 	;or	word [ebx], 4000h 
  2329                              <1> 	;	; bis $40000,(r5) 
  2330                              <1> 	;		; / set bit 14 of the 1st word of the I/O buffer
  2331                              <1> bread_3: ; 1:
  2332                              <1> 	; 15/07/2022
  2333                              <1> 	;test	word [ebx], 2400h
  2334                              <1> 	;	; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2335                              <1> 	;jz	short bread_4
  2336                              <1> 	;	; beq 1f / no
  2337                              <1> 	;	; cmp cdev,$1 / disk or drum?
  2338                              <1> 	;	; ble 2f / yes
  2339                              <1> 	;	; tstb uquant / is the time quantum = 0?
  2340                              <1> 	;	; bne 2f / no, 2f
  2341                              <1> 	;	; mov r5,-(sp) / yes, save r5 (buffer address)
  2342                              <1> 	;	; jsr r0,sleep; 31. 
  2343                              <1> 	;		; / put process to sleep in channel 31 (tape)
  2344                              <1> 	;	; mov (sp)+,r5 / restore r5
  2345                              <1> 	;	; br 1b / go back
  2346                              <1> ; 2: / drum or disk
  2347                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2348                              <1> 	;call	idle
  2349                              <1> 	;	; jsr r0,idle; s.wait+2 / wait
  2350                              <1> 	;jmp	short bread_3
  2351                              <1>        	;	; br 1b
  2352                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2353                              <1> 	;and	word [ebx], 0BFFFh ; 1011111111111111b
  2354                              <1> 	;	; bic $40000,(r5) / clear bit 14
  2355                              <1>        	;	; jsr r0,tstdeve / test device for error (tape)
  2356                              <1> 	; 15/07/2022
  2357 000053B6 83C308              <1> 	add	ebx, 8
  2358                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2359                              <1> 	; 09/06/2015
  2360 000053B9 66833D[61660000]00  <1> 	cmp	word [u.pcount], 0
  2361 000053C1 7705                <1> 	ja	short bread_5
  2362 000053C3 E892F8FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2363                              <1> bread_5:
  2364                              <1> 	; EBX = system (I/O) buffer address
  2365 000053C8 E87C000000          <1> 	call	dioreg
  2366                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2367                              <1> 
  2368                              <1> 	; 19/07/2022
  2369                              <1> 	; EDI = user data offset (previous value of [u.pbase])
  2370                              <1> 	; ESI = pointer to file offset 
  2371                              <1> 	; EAX = system (I/O) buffer offset (>= EBX)
  2372                              <1> 	; ECX = byte count
  2373                              <1> 	; EBX = system buffer (data) address
  2374                              <1> 
  2375                              <1> 	; 19/07/2022
  2376 000053CD 010E                <1> 	add	[esi], ecx ; new file (disk) offset
  2377 000053CF 89C6                <1> 	mov	esi, eax
  2378                              <1> 
  2379                              <1> 	; esi = start address of the transfer (in the buffer)
  2380                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2381                              <1> 	; ecx = transfer count (in bytes)
  2382                              <1> 	;
  2383                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2384                              <1> ;   / of users data
  2385 000053D1 F3A4                <1> 	rep	movsb
  2386                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2387                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2388                              <1>        		; bne 1b
  2389 000053D3 59                  <1> 	pop	ecx ; **
  2390 000053D4 833D[20660000]00    <1> 	cmp	dword [u.count], 0
  2391                              <1> 		; tst u.count / done
  2392 000053DB 77AC                <1> 	ja	short bread_0 ; 09/06/2015
  2393                              <1>        		; beq 1f / yes, return
  2394                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2395                              <1>        		; br bread / read some more
  2396                              <1> ; 1:
  2397 000053DD 58                  <1> 	pop	eax ; ****
  2398                              <1>        		; mov (sp)+,r0
  2399 000053DE C3                  <1>         retn		; 09/06/2015
  2400                              <1> 	;jmp	ret_ 
  2401                              <1> 		;jmp ret  / jump to routine that called readi
  2402                              <1> 
  2403                              <1> 	; 08/02/2022
  2404                              <1> brw_oov_err:
  2405 000053DF C705[51660000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2405 000053E7 0000                <1>
  2406 000053E9 E9E3DDFFFF          <1> 	jmp	error
  2407                              <1> 
  2408                              <1> 	; 08/02/2022
  2409                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2410                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2411                              <1> 	; 26/04/2013
  2412                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2413                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2414                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2415                              <1> 
  2416                              <1> 	; 08/02/2022
  2417                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2418                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2419                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2420                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2421                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2422                              <1> 
  2423                              <1> bwrite:
  2424                              <1> 	; 19/07/2022
  2425                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2426                              <1> 	; 15/07/2022
  2427                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2428                              <1> 	; 08/02/2022
  2429                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2430                              <1> 	; 14/07/2015
  2431                              <1> 	; 10/07/2015
  2432                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2433                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2434                              <1> 	;	
  2435                              <1> 	;; / write on block structured device
  2436                              <1> 	;
  2437                              <1> 	; INPUTS ->
  2438                              <1> 	;    [u.fofp] points to the block number
  2439                              <1> 	;    ECX = maximum block number allowed on device
  2440                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2441                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2442                              <1> 	;    [u.count]	number of bytes to user desires to write
  2443                              <1> 	; OUTPUTS ->
  2444                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2445                              <1> 	;
  2446                              <1> 	; ((Modified registers: EDX, ECX, EBX, ESI, EDI))
  2447                              <1> 	;
  2448                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2449                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2450                              <1> 	;	is increased by 1. For example: If user/program request 
  2451                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2452                              <1> 	;  	the next block number just as 512 byte writing is done.
  2453                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2454                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2455                              <1> 	;       enough to keep byte position/offset of the disk), this
  2456                              <1> 	;	defect will not be corrected, user/program must request
  2457                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2458                              <1> 	;       for achieving correct result. In future version(s), 
  2459                              <1> 	;	this defect will be corrected by using different 
  2460                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2461                              <1> 
  2462                              <1>        		; jsr r0,tstdeve / test the device for an error
  2463                              <1> 	;push	ecx ; **
  2464                              <1> 	; 26/04/2013
  2465                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2466 000053EE 2C03                <1> 	sub	al, 3
  2467                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2468 000053F0 A2[64660000]        <1> 	mov	[u.brwdev], al
  2469                              <1> 	; 09/06/2015
  2470                              <1> 	;movzx	ebx, al
  2471                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2472                              <1> 	; 12/01/2022 (BugFix)
  2473 000053F5 C0E002              <1> 	shl	al, 2 ; * 4
  2474 000053F8 8B88[625D0000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2475                              <1> bwrite_0:
  2476 000053FE 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2477                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2478                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2479 000053FF 8B1D[0C660000]      <1> 	mov	ebx, [u.fofp]
  2480 00005405 8B03                <1> 	mov	eax, [ebx]       
  2481 00005407 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2482                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2483 0000540A 39C8                <1> 	cmp	eax, ecx
  2484                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2485                              <1>        	                     ; / block number allowed
  2486                              <1> 	;jnb	error	     ; 18/04/2013
  2487                              <1> 		; bhis error10 / yes, error
  2488                              <1>      	; 08/02/2022
  2489                              <1> 	;jb	short bwrite_1
  2490                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2491                              <1> 	;jmp	error
  2492 0000540C 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2493                              <1> bwrite_1:
  2494                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2495                              <1> 		; inc *u.fofp / no, increment block number
  2496                              <1> 	; 09/06/2015 - 10/07/2015
  2497 0000540E 66833D[61660000]00  <1> 	cmp	word [u.pcount], 0
  2498 00005416 7705                <1> 	ja	short bwrite_2
  2499 00005418 E839F8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2500                              <1> bwrite_2:
  2501 0000541D BF[64660000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2502 00005422 E8C9000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2503                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2504                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2505 00005427 E81D000000          <1>         call	dioreg
  2506                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2507                              <1> 
  2508                              <1> 	; 19/07/2022
  2509                              <1> 	; EDI = user data offset (previous value of [u.pbase])
  2510                              <1> 	; ESI = pointer to file offset 
  2511                              <1> 	; EAX = system (I/O) buffer offset (>= EBX)
  2512                              <1> 	; ECX = byte count
  2513                              <1> 	; EBX = system buffer (data) address
  2514                              <1> 
  2515                              <1> 	; 19/07/2022 - Erdogan Tan
  2516                              <1> 	; ((Against a possible disk write failure/error, 
  2517                              <1> 	;   file offset must not be updated/increased before 'dskwr'
  2518                              <1> 	;   but it was updated in 'dioreg'. I have modified 'dioreg'
  2519                              <1> 	;   and 'bwrite' procedures for that.))
  2520                              <1> 
  2521                              <1> 	; 19/07/2022
  2522 0000542C 56                  <1> 	push	esi ; (!)  ; save file offset (pointer)
  2523 0000542D 51                  <1> 	push	ecx ; (!!) ; save byte count
  2524                              <1> 	;mov	esi, eax
  2525                              <1> 	
  2526                              <1> 	; esi = destination address (in the buffer)
  2527                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2528                              <1> 	; ecx = transfer count (in bytes)
  2529                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2530                              <1> 	;xchg 	esi, edi ; 14/07/2015
  2531                              <1> 
  2532                              <1> 	; 19/07/2022
  2533 0000542E 89FE                <1> 	mov	esi, edi
  2534 00005430 89C7                <1> 	mov	edi, eax
  2535                              <1> 
  2536 00005432 F3A4                <1> 	rep	movsb
  2537                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2538                              <1>        		; dec r3 / area to the I/O buffer
  2539                              <1>        		; bne 1b
  2540                              <1> 
  2541 00005434 E8F0000000          <1> 	call	dskwr
  2542                              <1> 		; jsr r0,dskwr / write it out on the device
  2543                              <1> 
  2544                              <1> 	; 19/07/2022
  2545                              <1> 	; (there is not a disk write error, we can increase file offset)
  2546 00005439 58                  <1> 	pop	eax ; (!!) ; byte count
  2547 0000543A 5F                  <1> 	pop	edi ; (!)  ; file offset (pointer)
  2548                              <1> 	;
  2549 0000543B 0107                <1> 	add	[edi], eax ; new file offset (old offset + byte count)
  2550                              <1> 
  2551 0000543D 59                  <1> 	pop	ecx ; **
  2552                              <1> 
  2553 0000543E 833D[20660000]00    <1>         cmp     dword [u.count], 0
  2554                              <1> 		; tst u.count / done
  2555 00005445 77B7                <1> 	ja	short bwrite_0 ; 09/06/2015
  2556                              <1> 		; beq 1f / yes, 1f
  2557                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2558                              <1>        		; br bwrite / go back and write next block
  2559                              <1> ; 1:
  2560 00005447 58                  <1> 	pop	eax ; ****
  2561                              <1>        		; mov (sp)+,r0
  2562 00005448 C3                  <1> 	retn		; 09/06/2015
  2563                              <1>         ;jmp	ret_ 
  2564                              <1> 		; jmp ret / return to routine that called writei
  2565                              <1> ;error10:
  2566                              <1> ;       jmp     error  ; / see 'error' routine
  2567                              <1> 
  2568                              <1> dioreg:
  2569                              <1> 	; 19/07/2022
  2570                              <1> 	;	(file offset bugfix for 'dskwr' error return situation)
  2571                              <1> 	; 04/02/2022
  2572                              <1> 	; 14/07/2015
  2573                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2574                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2575                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2576                              <1> 	;	
  2577                              <1> 	; bookkeeping on block transfers of data
  2578                              <1> 	;
  2579                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2580                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2581                              <1> 	; 10/07/2015
  2582                              <1> 	; * returns byte offset from beginning of current sector buffer
  2583                              <1> 	; (beginning of data) in ESI
  2584                              <1> 	
  2585                              <1> 	; 19/07/2022
  2586                              <1> 	; OUTPUTS:
  2587                              <1> 	;   EDI = user data offset (previous value of [u.pbase])
  2588                              <1> 	;   ESI = pointer to file offset 
  2589                              <1> 	;   EAX = system (I/O) buffer offset
  2590                              <1> 	;   ECX = byte count
  2591                              <1> 	;   EBX = system buffer (data) address	
  2592                              <1> 
  2593 00005449 8B0D[20660000]      <1> 	mov	ecx, [u.count]
  2594                              <1> 		; mov u.count,r3 / move char count to r3
  2595                              <1> 	; 04/02/2022
  2596 0000544F 31D2                <1> 	xor	edx, edx
  2597 00005451 B602                <1> 	mov	dh, 2
  2598                              <1> 	; edx = 512
  2599 00005453 39D1                <1> 	cmp	ecx, edx ; 512
  2600                              <1> 	;cmp 	ecx, 512
  2601                              <1> 		; cmp r3,$512. / more than 512. char?
  2602 00005455 7602                <1> 	jna	short dioreg_0
  2603                              <1> 		; blos 1f / no, branch
  2604 00005457 89D1                <1> 	mov	ecx, edx ; 512
  2605                              <1> 	;mov	ecx, 512
  2606                              <1> 		; mov $512.,r3 / yes, just take 512.
  2607                              <1> dioreg_0:
  2608                              <1> 	; 09/06/2015
  2609 00005459 663B0D[61660000]    <1> 	cmp	cx, [u.pcount]
  2610 00005460 7607                <1> 	jna	short dioreg_1
  2611 00005462 668B0D[61660000]    <1> 	mov	cx, [u.pcount]
  2612                              <1> dioreg_1:
  2613                              <1> ; 1:
  2614 00005469 8B15[1C660000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2615                              <1> 	        ; mov u.base,r2 / put users base in r2
  2616 0000546F 010D[24660000]      <1> 	add	[u.nread], ecx
  2617                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2618 00005475 290D[20660000]      <1> 	sub	[u.count], ecx
  2619                              <1> 		; sub r3,u.count / update count
  2620 0000547B 010D[1C660000]      <1> 	add	[u.base], ecx
  2621                              <1> 		; add r3,u.base / update base
  2622                              <1> 	; 10/07/2015
  2623                              <1> 	; Retro UNIX 386 v1 - modification !
  2624                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2625                              <1> 	; (It will point to next byte position instead of next block no.)
  2626 00005481 8B35[0C660000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2627 00005487 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2628                              <1> 	; 19/07/2022
  2629                              <1> 	;add	[esi], ecx ; ecx is added to set the next byte position
  2630 00005489 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2631                              <1> 	;mov	esi, ebx   ; beginning of data in sector/block buffer
  2632                              <1> 	;add	esi, eax   ; esi contains start address of the transfer
  2633                              <1> 	; 19/07/2022
  2634 0000548E 01D8                <1> 	add	eax, ebx   ; eax contains start address of the transfer	
  2635                              <1> 	; 09/06/2015 - 10/07/2015
  2636 00005490 66290D[61660000]    <1> 	sub	[u.pcount], cx
  2637 00005497 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2638 0000549D 8B3D[5D660000]      <1> 	mov	edi, [u.pbase]
  2639 000054A3 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2640 000054A9 01D7                <1> 	add	edi, edx
  2641 000054AB 893D[5D660000]      <1> 	mov	[u.pbase], edi
  2642 000054B1 010D[5D660000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2643 000054B7 C3                  <1> 	retn
  2644                              <1> 		; rts r0 / return
  2645                              <1> 
  2646                              <1> dskrd:
  2647                              <1> 	; 15/07/2022
  2648                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2649                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2650                              <1> 	; 18/08/2015
  2651                              <1> 	; 02/07/2015
  2652                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2653                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2654                              <1> 	;
  2655                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2656                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2657                              <1> 	; (number specified in r1) in the acquired buffer.)
  2658                              <1> 	; If the device is busy at the time dskrd is called,	
  2659                              <1> 	; dskrd calls idle.
  2660                              <1> 	; 
  2661                              <1> 	; INPUTS ->
  2662                              <1> 	;    r1 - block number
  2663                              <1> 	;    cdev - current device number 
  2664                              <1> 	; OUTPUTS ->
  2665                              <1> 	;    r5 - points to first data word in I/O buffer
  2666                              <1> 	;
  2667                              <1> 	; ((AX = R1)) input/output
  2668                              <1> 	; ((BX = R5)) output 
  2669                              <1> 	;
  2670                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI))  
  2671                              <1> 	;
  2672 000054B8 E8B5000000          <1> 	call 	bufaloc
  2673                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2674                              <1> 			       ; / get a free I/O buffer
  2675                              <1> 	;;jc	error ; 20/07/2013
  2676 000054BD 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2677                              <1>        		; br 1f / branch if block already in a I/O buffer
  2678                              <1> 
  2679                              <1> 	; 15/07/2022
  2680                              <1> 	; (buffer header byte 1, bit 2 is disk read bit/flag)
  2681                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2682 000054BF 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2683                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2684                              <1> 		               ; / I/O queue entry for buffer
  2685 000054C4 E88E000000          <1> 	call	poke
  2686                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2687                              <1> 			    ; /	bit 10=1 says read
  2688                              <1> 	; 09/06/2015
  2689                              <1> 	;jnc	short dskrd_1
  2690                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2691                              <1> 	;jmp	error
  2692                              <1> 	; 08/02/2022
  2693 000054C9 7204                <1> 	jc	short dskrd_3
  2694                              <1> dskrd_1: ; 1:
  2695                              <1>        	; 15/07/2022
  2696                              <1> 	;
  2697                              <1> 	;	;clr *$ps
  2698                              <1>        	;test	word [ebx], 2400h
  2699                              <1> 	;	; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2700                              <1> 	;			; / jump to idle
  2701                              <1>        	;jz	short dskrd_2
  2702                              <1> 	;	; beq 1f
  2703                              <1>         ;;;mov   ecx, [s.wait_]
  2704                              <1>        	;call	idle
  2705                              <1> 	;	; jsr r0,idle; s.wait+2
  2706                              <1> 	;jmp 	short dskrd_1
  2707                              <1>        	;	; br 1b
  2708                              <1> dskrd_2: ; 1:
  2709 000054CB 83C308              <1>         add	ebx, 8
  2710                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2711                              <1> 			  ; / just read in
  2712 000054CE C3                  <1>        	retn
  2713                              <1> 		; rts r0
  2714                              <1> dskrd_err: 
  2715                              <1> 	; 08/02/2022
  2716                              <1> 	; (jump from 'bread' error)	
  2717                              <1> dskrd_3:	
  2718                              <1> 	; 08/02/2022
  2719 000054CF 803D[64660000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2720 000054D6 7509                <1> 	jne	short dskrd_4 ; no
  2721                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2722 000054D8 C605[64660000]00    <1> 	mov	byte [u.brwdev], 0
  2723 000054DF EB0A                <1> 	jmp	short dskrd_5
  2724                              <1> dskrd_4:
  2725 000054E1 C705[51660000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2725 000054E9 0000                <1>
  2726                              <1> dskrd_5:
  2727 000054EB E9E1DCFFFF          <1> 	jmp	error
  2728                              <1> 
  2729                              <1> bwslot:
  2730                              <1> 	; 15/07/2022
  2731                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2732                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2733                              <1> 	; 10/07/2015
  2734                              <1> 	;	If the block/sector is not placed in a buffer
  2735                              <1> 	;	before 'wslot', it must be read before
  2736                              <1> 	;	it is written! (Otherwise transfer counts less
  2737                              <1> 	;	than 512 bytes will be able to destroy existing 
  2738                              <1> 	;	data on disk.)
  2739                              <1> 	;
  2740                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2741                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2742                              <1> 	; Retro UNIX 8086 v1 modification !
  2743                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2744                              <1> 	; INPUT -> EDI - points to device id (in u.brwdev)	
  2745                              <1> 	;	-> EAX = block number
  2746                              <1> 	;
  2747 000054F0 E88A000000          <1> 	call	bufaloc_0
  2748 000054F5 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2749                              <1> 	; 12/01/2022
  2750                              <1> 	; ebx = buffer header address
  2751                              <1> bwslot_0:
  2752                              <1> 	; 10/07/2015
  2753 000054F7 8B35[0C660000]      <1> 	mov	esi, [u.fofp]
  2754 000054FD 8B06                <1> 	mov	eax, [esi]
  2755 000054FF 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2756 00005504 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2757                              <1> 		       ; recent disk data must be placed in the buffer
  2758 00005506 813D[20660000]0002- <1> 	cmp	dword [u.count], 512
  2758 0000550E 0000                <1>
  2759 00005510 730F                <1> 	jnb	short wslot_0	
  2760                              <1> bwslot_1:
  2761 00005512 E8A8FFFFFF          <1> 	call	dskrd_0
  2762                              <1> 	; 12/01/2022
  2763                              <1> 	; ebx = buffer data address = buffer header address + 8
  2764 00005517 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2765 0000551A EB05                <1> 	jmp 	short wslot_0
  2766                              <1> 
  2767                              <1> wslot:
  2768                              <1> 	; 15/07/2022
  2769                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2770                              <1> 	;
  2771                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2772                              <1> 	; 		(32 bit modifications)
  2773                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2774                              <1> 	;
  2775                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2776                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2777                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2778                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2779                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2780                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2781                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2782                              <1> 	;
  2783                              <1> 	; INPUTS ->
  2784                              <1>  	;    r1 - block number
  2785                              <1> 	;    cdev - current (block/disk) device number
  2786                              <1>  	;
  2787                              <1> 	; OUTPUTS ->
  2788                              <1> 	;    bufp - bits 9 and 15 are set, 
  2789                              <1> 	;           the remainder of the word left unchanged
  2790                              <1> 	;    r5 - points to first data word in I/O buffer
  2791                              <1> 	;
  2792                              <1> 	; ((AX = R1)) input/output
  2793                              <1> 	; ((BX = R5)) output 
  2794                              <1> 	;
  2795                              <1>         ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 
  2796                              <1> 
  2797 0000551C E851000000          <1> 	call	bufaloc
  2798                              <1> 	; 10/07/2015
  2799                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2800                              <1>         	; br 1f / word in buffer in r5
  2801                              <1> 	; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2802                              <1>         ; EAX = Block/Sector number (r1)
  2803                              <1> wslot_0: ;1:
  2804                              <1> 	; 14/07/2022
  2805                              <1> 	;
  2806                              <1>      	;test	word [ebx], 2400h
  2807                              <1> 	;	; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2808                              <1> 	;			; / of I/O queue entry
  2809                              <1> 	;jz	short wslot_1
  2810                              <1>         ;       ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2811                              <1> 	;	       ; / or not waiting to read)
  2812                              <1> 	;
  2813                              <1> 	;;mov	ecx, [s.wait_] ; 29/07/2013
  2814                              <1> 	;call	idle
  2815                              <1> 	;	; jsr r0,idle; / if buffer is reading or writing to read,
  2816                              <1>        	;                   ; / idle
  2817                              <1> 	;jmp	short wslot_0
  2818                              <1> 	;	; br 1b / till finished
  2819                              <1> wslot_1: ;1:
  2820                              <1> 	;or	word [ebx], 8200h
  2821                              <1>        	;	; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2822                              <1>         ;			; / (write, inhibit bits)
  2823                              <1> 	;	; clr *$ps / clear processor status
  2824                              <1> 
  2825                              <1> 	; 15/07/2022
  2826                              <1> 	; (set disk write bit/flag)
  2827                              <1> 	;or	word [ebx], 200h	
  2828 00005521 43                  <1> 	inc	ebx
  2829 00005522 800B02              <1> 	or	byte [ebx], 2
  2830 00005525 83C307              <1> 	add	ebx, 7
  2831                              <1> 
  2832                              <1> 	;add	ebx, 8 ; 11/06/2015
  2833                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2834                              <1> 			  ; / for this block
  2835                              <1> dskwr_1:	; 08/02/2022
  2836 00005528 C3                  <1>        	retn
  2837                              <1> 		; rts r0
  2838                              <1> dskwr:
  2839                              <1> 	; 15/07/2022
  2840                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2841                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2842                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2843                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2844                              <1> 	;
  2845                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2846                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2847                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2848                              <1> 	; previously has supplied all the information required in the
  2849                              <1> 	; I/O queue entry.
  2850                              <1> 	;
  2851                              <1> 	; (Modified registers: ECX, EDX, EBX, ESI, EDI)
  2852                              <1> 	;
  2853                              <1> 	;
  2854 00005529 8B1D[B8650000]      <1> 	mov	ebx, [bufp]
  2855                              <1> 	; 15/07/2022
  2856                              <1> 	;and	word [ebx], 7FFFh ; 0111111111111111b
  2857                              <1> 	;	; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2858                              <1>                                   ; / bottom of queue
  2859                              <1> 	; 15/07/2022
  2860                              <1> 	; (set disk write bit)
  2861                              <1> 	; ('wslot' already sets disk write bit/flag)
  2862                              <1> 	;mov	word [ebx], 200h
  2863                              <1> 	
  2864 0000552F E823000000          <1> 	call	poke
  2865                              <1> 	; 09/06/2015
  2866 00005534 73F2                <1> 	jnc	short dskwr_1
  2867                              <1> 	; 08/02/2022
  2868 00005536 803D[64660000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2869 0000553D 7509                <1> 	jne	short dskwr_0 ; no
  2870                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2871 0000553F C605[64660000]00    <1> 	mov	byte [u.brwdev], 0
  2872 00005546 EB0A                <1> 	jmp	short dskwr_2
  2873                              <1> dskwr_0:
  2874 00005548 C705[51660000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2874 00005550 0000                <1>
  2875                              <1> dskwr_2:
  2876 00005552 E97ADCFFFF          <1> 	jmp	error
  2877                              <1> ;dskwr_1:
  2878                              <1> ;	retn
  2879                              <1> 
  2880                              <1> ;ppoke:
  2881                              <1>        		; mov $340,*$ps
  2882                              <1>        		; jsr r0,poke
  2883                              <1>        		; clr *$ps
  2884                              <1> 		; rts r0
  2885                              <1> 
  2886                              <1> poke:
  2887                              <1> 	; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2888                              <1> 	; 14/07/2022
  2889                              <1> 	;	! Major Modification !
  2890                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2891                              <1> 	;
  2892                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2893                              <1> 	; 24/10/2015
  2894                              <1> 	; 20/08/2015
  2895                              <1> 	; 18/08/2015
  2896                              <1> 	; 02/07/2015
  2897                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2898                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2899                              <1> 	;
  2900                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2901                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2902                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2903                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2904                              <1> 	;
  2905                              <1> 	; Basic I/O functions for all block structured devices
  2906                              <1> 	;
  2907                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2908                              <1> 	;
  2909                              <1> 	; 20/07/2013 modifications
  2910                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2911                              <1> 	; INPUTS -> 
  2912                              <1> 	;        EBX = buffer header address
  2913                              <1> 	; OUTPUTS ->
  2914                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2915                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2916                              <1> 	;		(drive not ready or r/w error!)
  2917                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2918                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2919                              <1> 	;        (also it indicates invalid buffer data)
  2920                              <1> 	
  2921                              <1> 	; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  2922                              <1> 	; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22)
  2923                              <1> 	; Buffer header:
  2924                              <1> 	;	byte 0 - device/disk (index) number
  2925                              <1> 	;	byte 1 - status
  2926                              <1> 	;	    before 'poke'	
  2927                              <1> 	;		bit 0 - valid bit 
  2928                              <1> 	;		   (0 for new buffer)
  2929                              <1> 	;		   (1 for existing buffer)	
  2930                              <1> 	;		bit 1 - write (modified) bit, disk write flag
  2931                              <1> 	;		bit 2 - read bit, disk read flag
  2932                              <1> 	;	    after 'poke'
  2933                              <1> 	;		if disk r/w is successed
  2934                              <1> 	;		   bit 0 = 1
  2935                              <1> 	;		   bit 1 = 0
  2936                              <1> 	;		   bit 2 = 0
  2937                              <1> 	;		if disk r/w is failed
  2938                              <1> 	;		   bit 0 = 0 (invalid buffer)
  2939                              <1> 	;		   bit 1 = 0 (write bit)
  2940                              <1> 	;		   bit 2 = 0 (read bit)	
  2941                              <1>  	;
  2942                              <1> 	;	byte 2 & byte 3 - not used
  2943                              <1> 	;	byte 4 to byte 7 - disk block/sector address
  2944                              <1> 	
  2945                              <1> 	; 04/02/2022
  2946 00005557 50                  <1> 	push	eax
  2947 00005558 E896000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2948 0000555D 58                  <1> 	pop	eax
  2949 0000555E 730D                <1> 	jnc	short seta ; 14/07/2022
  2950                              <1> 	
  2951                              <1> 	; 14/07/2022
  2952                              <1> 	; (invalidate buffer)
  2953                              <1> 	
  2954                              <1> 	; 02/07/2015 (32 bit modification)
  2955                              <1> 	; 20/07/2013
  2956 00005560 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2957                              <1>        		; mov $-1,2(r1) / destroy associativity
  2958 00005567 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2959                              <1> 		; clrb 1(r1) / do not do I/O
  2960                              <1> 	;stc
  2961 0000556C C3                  <1> 	retn
  2962                              <1>         	; rts r0
  2963                              <1> seta: 
  2964 0000556D C6430101            <1> 	mov	byte [ebx+1], 1 ; clear write/read bits, set valid bit
  2965                              <1> 	;clc
  2966 00005571 C3                  <1> 	retn
  2967                              <1> 
  2968                              <1> %if 0
  2969                              <1> 
  2970                              <1> poke:
  2971                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2972                              <1> 	; 24/10/2015
  2973                              <1> 	; 20/08/2015
  2974                              <1> 	; 18/08/2015
  2975                              <1> 	; 02/07/2015
  2976                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2977                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2978                              <1> 	;
  2979                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2980                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2981                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2982                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2983                              <1> 	;
  2984                              <1> 	; Basic I/O functions for all block structured devices
  2985                              <1> 	;
  2986                              <1>         ; (Modified registers: ECX, EDX, ESI, EDI)
  2987                              <1> 	;
  2988                              <1> 	; 20/07/2013 modifications
  2989                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2990                              <1> 	; INPUTS -> 
  2991                              <1> 	;        (EBX = buffer header address)
  2992                              <1> 	; OUTPUTS ->
  2993                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2994                              <1> 	;	 cf=1 -> error, word [EBX] = 0FFFFh
  2995                              <1> 	;		(drive not ready or r/w error!)
  2996                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2997                              <1> 	;	 (dword [EBX+4] = 0FFFFFFFFh means RW/IO error)
  2998                              <1> 	;        (also it indicates invalid buffer data)
  2999                              <1> 	;
  3000                              <1> 	push	ebx
  3001                              <1>        		; mov r1,-(sp)
  3002                              <1>        		; mov r2,-(sp)
  3003                              <1>        		; mov r3,-(sp)
  3004                              <1> 	push 	eax ; Physical Block Number (r1) (mget)
  3005                              <1> 	;
  3006                              <1> 	; 09/06/2015
  3007                              <1> 	; (permit read/write after a disk  R/W error)
  3008                              <1> 	mov	cl, [ebx] ; device id (0 to 5)
  3009                              <1> 	mov	al, 1
  3010                              <1> 	shl	al, cl
  3011                              <1> 	test 	al, [active] ; busy ? (error)
  3012                              <1> 	jz	short poke_0
  3013                              <1> 	not	al
  3014                              <1> 	and	[active], al ; reset busy bit for this device only
  3015                              <1> poke_0:
  3016                              <1>         mov     esi, bufp + (4*(nbuf+2)) 
  3017                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  3018                              <1> 					 ; / I/O queue pointer
  3019                              <1> poke_1: ; 1:
  3020                              <1>         sub	esi, 4
  3021                              <1> 	mov	ebx, [esi]
  3022                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  3023                              <1> 	mov	ax, [ebx] ; 17/07/2013
  3024                              <1>        	test	ah, 06h
  3025                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  3026                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  3027                              <1> 			       ; / queue entry
  3028                              <1>         jz      short poke_5
  3029                              <1> 		; beq 2f / branch to 2f if both are clear
  3030                              <1> 	; 31/07/2013
  3031                              <1> 	;test	ah, 0B0h ; (*)
  3032                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  3033                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  3034                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  3035                              <1> 		; bne 2f / branch if any are set
  3036                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  3037                              <1>     		; movb (r1),r3 / get device id
  3038                              <1> 	movzx	ecx, al ; 18/08/2015
  3039                              <1> 	;mov	edi, ecx ; 26/04/2013
  3040                              <1> 	xor 	eax, eax ; 0
  3041                              <1> 	;cmp 	[edi+drv.error], al ; 0
  3042                              <1> 		; tstb deverr(r3) / test for errors on this device
  3043                              <1>        	;jna	short poke_2 
  3044                              <1> 		; beq 3f / branch if no errors
  3045                              <1> 	; 02/07/2015
  3046                              <1> 	;dec	eax
  3047                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  3048                              <1>        		; mov $-1,2(r1) / destroy associativity
  3049                              <1> 	;shr	eax, 24
  3050                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  3051                              <1> 		; clrb 1(r1) / do not do I/O
  3052                              <1> 	;jmp	short poke_5
  3053                              <1>         ;       ; br 2f
  3054                              <1>                 ; rts r0
  3055                              <1> poke_2: ; 3:
  3056                              <1> 	; 02/07/2015
  3057                              <1> 	inc	cl ; 0FFh -> 0
  3058                              <1> 	jz	short poke_5
  3059                              <1> 	inc	al ; mov ax, 1
  3060                              <1> 	dec	cl
  3061                              <1> 	jz	short poke_3
  3062                              <1> 	; 26/04/2013 Modification
  3063                              <1> 	;inc	al ; mov ax, 1
  3064                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  3065                              <1> 	;jz	short poke_3 ; cl = 0
  3066                              <1> 	shl	al, cl ; shl ax, cl
  3067                              <1> poke_3:
  3068                              <1> 	;test	[active], ax
  3069                              <1> 	test	[active], al
  3070                              <1> 		; bit $2,active / test disk busy bit
  3071                              <1> 	jnz     short poke_5
  3072                              <1> 		; bne 2f / branch if bit is set
  3073                              <1> 	;or	[active], ax
  3074                              <1> 	or	[active], al
  3075                              <1> 		; bis $2,active / set disk busy bit
  3076                              <1> 	;push	ax
  3077                              <1> 	; 24/12/2021
  3078                              <1> 	push	eax
  3079                              <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  3080                              <1> 	;mov    [edi+drv.error], ah
  3081                              <1> 	; 24/12/2021
  3082                              <1> 	pop	eax
  3083                              <1> 	;pop	ax
  3084                              <1> 	jnc	short poke_4 ; 20/07/2013
  3085                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  3086                              <1> 	;jna	short poke_4
  3087                              <1> 		; tstb deverr(r3) / test for errors on this device
  3088                              <1>        		; beq 3f / branch if no errors
  3089                              <1> 	; 02/07/2015 (32 bit modification)
  3090                              <1> 	; 20/07/2013
  3091                              <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  3092                              <1>        		; mov $-1,2(r1) / destroy associativity
  3093                              <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  3094                              <1> 		; clrb 1(r1) / do not do I/O
  3095                              <1> 	jmp     short poke_5
  3096                              <1> poke_4:	; 20/07/2013
  3097                              <1> 	; 17/07/2013
  3098                              <1> 	not 	al 
  3099                              <1> 	and	[active], al ; reset, not busy
  3100                              <1> 	; EBX = system I/O buffer header (queue entry) address
  3101                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  3102                              <1> 	mov	ax, [ebx]
  3103                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  3104                              <1>         and	ax, 600h
  3105                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  3106                              <1> 	and 	word [ebx], 0F9FFh
  3107                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  3108                              <1> 	shl	ah, 3
  3109                              <1>        		; rol r3
  3110                              <1>                 ; rol r3
  3111                              <1>                 ; rol r3	
  3112                              <1> 	or	[ebx], ax
  3113                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  3114                              <1> 			   ; bits 12 and 13
  3115                              <1> 	call	idle ; 18/01/2014
  3116                              <1> 	;; sti
  3117                              <1> 	;hlt 	; wait for a hardware interrupt
  3118                              <1> 	;; cli
  3119                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  3120                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  3121                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  3122                              <1> 	; method, this procedure will wait for a time according to
  3123                              <1> 	; multi tasking and time sharing concept.
  3124                              <1> 	;
  3125                              <1> 	; 24/10/2015
  3126                              <1> 	;not	ax 
  3127                              <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  3128                              <1> 	and	[ebx], ax ; clear bits 12 and 13
  3129                              <1> poke_5: ;2:
  3130                              <1>         cmp     esi, bufp
  3131                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  3132                              <1>                             ; / has been scanned
  3133                              <1> 	ja      short poke_1
  3134                              <1> 		; bhi 1b
  3135                              <1> 	; 24/03/2013
  3136                              <1>        		; mov (sp)+,r3
  3137                              <1>        		; mov (sp)+,r2
  3138                              <1>        		; mov (sp)+,r1
  3139                              <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  3140                              <1> 	pop 	ebx
  3141                              <1> 	; 02/07/2015 (32 bit modification)
  3142                              <1> 	; 20/07/2013
  3143                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  3144                              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  3145                              <1> 	;	
  3146                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  3147                              <1> 	; or written successfully; even if an error occurs while
  3148                              <1> 	; reading to or writing from other buffers. 20/07/2013
  3149                              <1> 	;
  3150                              <1> 	; 09/06/2015
  3151                              <1> 	cmc
  3152                              <1> 	retn
  3153                              <1>                 ; rts r0
  3154                              <1> 
  3155                              <1> %endif
  3156                              <1> 
  3157                              <1> bufaloc:
  3158                              <1> 	; 15/07/2022
  3159                              <1> 	;	Retro UNIX 386 v1.1 (Kernel v0.2.1.6)
  3160                              <1> 	; 14/07/2022
  3161                              <1> 	;	Retro UNIX 386 v1 (Kernel v0.2.0.22)
  3162                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3163                              <1> 	; 20/08/2015
  3164                              <1> 	; 19/08/2015
  3165                              <1> 	; 02/07/2015
  3166                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3167                              <1> 	;	     (32 bit modifications)	
  3168                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  3169                              <1> 	;
  3170                              <1> 	; bufaloc - Block device I/O buffer allocation
  3171                              <1> 	; 
  3172                              <1> 	; INPUTS ->
  3173                              <1> 	;    r1 - block number
  3174                              <1> 	;    cdev - current (block/disk) device number
  3175                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  3176                              <1> 	; OUTPUTS ->
  3177                              <1> 	;    r5 - pointer to buffer allocated
  3178                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  3179                              <1> 	;
  3180                              <1> 	; ((AX = R1)) input/output
  3181                              <1> 	; ((BX = R5)) output
  3182                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  3183                              <1> 	;    zf=1 -> block already in a I/O buffer
  3184                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  3185                              <1> 	;    ((DL = Device ID))
  3186                              <1> 	;    (((DH = 0 or 1)))
  3187                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  3188                              <1> 	;    ((CX and DH will not be used after return)))
  3189                              <1> 
  3190                              <1> 	; 14/07/2022
  3191                              <1> 	;	Modified registers: EBX, ECX, EDX, ESI, EDI
  3192                              <1> 
  3193                              <1> 	;;push 	esi ; ***
  3194                              <1> 		; mov r2,-(sp) / save r2 on stack
  3195                              <1>        		; mov $340,*$ps / set processor priority to 7
  3196                              <1> 	; 20/07/2013
  3197                              <1> 	; 26/04/2013
  3198                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  3199                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  3200                              <1> 	;add	edi, ebx
  3201                              <1> 	; 09/01/2022
  3202 00005572 0FB63D[E3650000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  3203 00005579 81C7[E4650000]      <1> 	add	edi, rdev
  3204                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  3205                              <1> 			;; EDI points to device id.
  3206 0000557F 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  3207                              <1> 	; 11/06/2015
  3208 00005582 80BB[7E5D0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  3209 00005589 720F                <1> 	jb	short bufaloc_9
  3210 0000558B C705[51660000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3210 00005593 0000                <1>
  3211 00005595 E937DCFFFF          <1> 	jmp	error
  3212                              <1> bufaloc_9:
  3213 0000559A 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  3214                              <1> bufaloc_10: ; 02/07/2015
  3215                              <1> 	; 14/07/2022
  3216                              <1> 	;xor 	ebp, ebp ; 0
  3217                              <1> 	;push	ebp ; 0
  3218                              <1>         ;mov	ebp, esp	
  3219 0000559C 31FF                <1> 	xor	edi, edi ; 0	
  3220 0000559E 57                  <1> 	push	edi
  3221                              <1> bufaloc_1: ;1:
  3222                              <1> 		; clr -(sp) / vacant buffer
  3223 0000559F BE[B8650000]        <1>         mov 	esi, bufp
  3224                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  3225                              <1> 			     ; / entrys in buffer area
  3226                              <1> bufaloc_2: ;2:
  3227 000055A4 8B1E                <1> 	mov	ebx, [esi]
  3228                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3229                              <1> 			    ; queue entry into r5
  3230                              <1> 	; 14/07/2022
  3231 000055A6 8B0B                <1> 	mov	ecx, [ebx]	
  3232                              <1> 	;test	word [ebx], 0F600h
  3233                              <1> 	; 15/07/2022
  3234 000055A8 F6C501              <1> 	test	ch, 1 ; valid buffer (content) ?
  3235                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3236 000055AB 7505                <1>         jnz	short bufaloc_3 ; yes
  3237                              <1> 		; bne 3f / branch when 
  3238                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3239                              <1>                        ; / (i.e., buffer busy)
  3240                              <1> 	;mov    [ebp], esi ; pointer to I/0 queue entry
  3241                              <1> 	; 14/07/2022
  3242                              <1> 	; save free buffer pointer 
  3243 000055AD 893424              <1> 	mov	[esp], esi
  3244                              <1>                 ; mov r2,(sp) ;/ save pointer to last non-busy buffer
  3245                              <1> 			; / found points to word 2 of I/O queue entry)
  3246                              <1> 	; continue to see if requested sector/block buffer
  3247                              <1> 	;	already is one of existing (valid) buffers
  3248                              <1> 	;jmp	short bufaloc_4
  3249 000055B0 EB0E                <1> 	jmp	short bufaloc_11 ; 14/07/2022
  3250                              <1> bufaloc_3: ;3:
  3251                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3252                              <1> 	;
  3253 000055B2 38D1                <1> 	cmp	cl, dl ; 14/07/2022
  3254                              <1> 	;cmp	[ebx], dl	
  3255                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3256                              <1> 			       ; / as current device
  3257 000055B4 7508                <1> 	jne	short bufaloc_4
  3258                              <1>        		; bne 3f
  3259 000055B6 394304              <1> 	cmp	[ebx+4], eax
  3260                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3261                              <1> 			     ; / same as current block number
  3262 000055B9 7503                <1>        	jne	short bufaloc_4
  3263                              <1> 		; bne 3f
  3264                              <1> 	;add	esp, 4
  3265 000055BB 59                  <1> 	pop	ecx
  3266                              <1>        		; tst (sp)+ / bump stack pointer
  3267 000055BC EB1D                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3268                              <1> 				; jump to bufaloc_6 in original Unix v1
  3269                              <1>        		; br 1f / use this buffer
  3270                              <1> bufaloc_4: ;3:
  3271                              <1> 	; 14/07/2022
  3272                              <1> 	; save last valid buffer 
  3273                              <1> 	; (will be used if there is not a free buffer)
  3274 000055BE 89F7                <1> 	mov	edi, esi	
  3275                              <1> bufaloc_11:
  3276 000055C0 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3277                              <1> 	;
  3278 000055C3 81FE[D8650000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3279                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3280 000055C9 72D9                <1> 	jb	short bufaloc_2
  3281                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3282                              <1>                        ; / buffers not checked)
  3283 000055CB 5E                  <1>         pop	esi
  3284                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3285                              <1> 			     ; / to last free block
  3286 000055CC 09F6                <1>        	or	esi, esi 
  3287 000055CE 7502                <1> 	jnz	short bufaloc_5
  3288                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3289                              <1> 	        ; / if a free buffer is found branch to 2f
  3290                              <1> 
  3291                              <1> 	; 14/07/2022        
  3292                              <1> 	; if there is not a free buffer
  3293                              <1> 	; we can use last valid buffer (the oldest buffer)
  3294                              <1> 	; ((ptr to new buffer is located at head of buff ptr chain))
  3295 000055D0 89FE                <1> 	mov	esi, edi
  3296                              <1> 
  3297                              <1> 	;;mov  ecx, [s.wait_]
  3298                              <1> 	;call	idle
  3299                              <1> 	;	; jsr r0,idle; s.wait+2 / idle if no free buffers
  3300                              <1> 	;jmp 	short bufaloc_10 ; 02/07/2015
  3301                              <1>        	;	; br 1b
  3302                              <1> bufaloc_5: ;2:
  3303                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3304                              <1> 	; 14/07/2022
  3305                              <1> 	;inc	dh ; Retro UNIX 8086 v1 modification
  3306                              <1> bufaloc_6: ;1:
  3307 000055D2 8B1E                <1>         mov    	ebx, [esi] 
  3308                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3309                              <1> 			     ; / entry in r5
  3310                              <1> 	;; 26/04/2013
  3311                              <1>         ;;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3312                              <1> 	;mov 	[ebx], dl
  3313                              <1> 		; movb cdev,(r5) / put current device number 
  3314                              <1> 				 ; / in I/O queue entry
  3315                              <1> 	; 14/07/2022
  3316                              <1> 	; invalidate buffer before r/w (new) disk sector/block
  3317                              <1> 	;mov	[ebx+1], dh ; 0
  3318                              <1> 	; 14/07/2022
  3319 000055D4 8913                <1> 	mov	[ebx], edx  ; dh = 0
  3320                              <1> 	
  3321 000055D6 894304              <1> 	mov 	[ebx+4], eax
  3322                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3323                              <1> 			     ; / of I/O queue entry
  3324                              <1> 	; 14/07/2022
  3325 000055D9 FEC6                <1> 	inc	dh ; dh = 1
  3326                              <1> bufaloc_7: ;1:
  3327 000055DB 81FE[B8650000]      <1>         cmp	esi, bufp
  3328                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3329                              <1> 			     ; / and put latest assigned
  3330 000055E1 760B                <1> 	jna	short bufaloc_8	
  3331                              <1>        		; blos 1f / buffer on the top 
  3332                              <1> 			; / (this makes if the lowest priority)
  3333                              <1> 	; 14/07/2022
  3334 000055E3 89F7                <1> 	mov	edi, esi
  3335 000055E5 83EE04              <1> 	sub	esi, 4
  3336 000055E8 8B0E                <1> 	mov	ecx, [esi]
  3337 000055EA 890F                <1> 	mov	[edi], ecx ; 14/07/2022
  3338                              <1> 	;mov	[esi+4], ecx
  3339                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3340 000055EC EBED                <1> 	jmp 	short bufaloc_7        
  3341                              <1> 		; br 1b
  3342                              <1> bufaloc_8: ;1:
  3343 000055EE 891E                <1>         mov	[esi], ebx
  3344                              <1> 		; mov r5,(r2)
  3345                              <1> 	;;pop	esi ; ***
  3346                              <1>        		; mov (sp)+,r2 / restore r2
  3347 000055F0 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3348                              <1> 		; Retro UNIX 8086 v1 modification
  3349                              <1> 		; zf=1 --> block already is in an I/O buffer
  3350                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3351 000055F2 C3                  <1> 	retn
  3352                              <1> 		; rts r0
  3353                              <1> 
  3354                              <1> diskio:
  3355                              <1> 	; 12/07/2022
  3356                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3357                              <1> 	;	((simplified and shortened 'diskio.s' code))
  3358                              <1> 	; 12/02/2022
  3359                              <1> 	; 10/02/2022
  3360                              <1> 	; 08/02/2022
  3361                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3362                              <1> 	; 10/07/2015
  3363                              <1> 	; 02/07/2015
  3364                              <1> 	; 16/06/2015
  3365                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3366                              <1> 	;	     (80386 protected mode modifications)	
  3367                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3368                              <1> 	;
  3369                              <1> 	; Retro UNIX 8086 v1 feature only !
  3370                              <1> 	;
  3371                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3372                              <1> 	; 04/07/2009 - 20/07/2011
  3373                              <1> 	;
  3374                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3375                              <1> 	;
  3376                              <1>         ; INPUTS ->
  3377                              <1> 	; 	   EBX = System I/O Buffer header address
  3378                              <1> 	;
  3379                              <1>         ; OUTPUTS -> cf=0 --> done 
  3380                              <1> 	; 	     cf=1 --> error code in AH
  3381                              <1> 	;	     ; 08/02/2022
  3382                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3383                              <1> 	;		error code in [u.error]
  3384                              <1> 	;		
  3385                              <1> 	; (Modified registers: EAX, ECX, EDX)
  3386                              <1> 	
  3387                              <1> ;rw_disk_sector:
  3388                              <1> 	; 12/07/2022
  3389                              <1> 	; 08/07/2022
  3390                              <1> 	; 12/02/2022
  3391                              <1> 	; 10/02/2022
  3392                              <1> 	; 08/02/2022
  3393                              <1> 	; 10/07/2015
  3394                              <1> 	; 02/07/2015
  3395                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3396                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3397                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3398                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3399                              <1> 	;
  3400                              <1> 	;;mov	dx, 0201h ; Read 1 sector/block
  3401                              <1> 	;mov	dh, 2
  3402                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3403 000055F3 B602                <1> 	mov	dh, 2 ; Write 1 sector/block
  3404 000055F5 668B03              <1> 	mov	ax, [ebx] 
  3405                              <1> 	;
  3406 000055F8 56                  <1> 	push	esi ; ****
  3407 000055F9 53                  <1> 	push	ebx ; ***
  3408                              <1> 	;
  3409 000055FA 0FB6C8              <1> 	movzx	ecx, al
  3410 000055FD 89CE                <1> 	mov	esi, ecx
  3411                              <1> 	;
  3412 000055FF 38F1                <1> 	cmp	cl, dh ; 2
  3413 00005601 7202                <1> 	jb	short rwdsk0
  3414 00005603 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3415                              <1> rwdsk0:
  3416                              <1> 	; 12/07/2022
  3417                              <1> 	;mov	[drv], al
  3418 00005605 81C6[7E5D0000]      <1> 	add	esi, drv.status
  3419                              <1> 	; 11/06/2015
  3420 0000560B 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3421 0000560E 7204                <1> 	jb      short rwdsk1
  3422                              <1> 	; 'drive not ready' error
  3423                              <1> 	; 10/02/2022
  3424                              <1> 	; 08/02/2022
  3425                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3426                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3427                              <1> 	;;jmp	error
  3428                              <1> 	;stc	; cf = 1
  3429                              <1> 	;retn
  3430                              <1> 	; 10/02/2022
  3431 00005610 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3432 00005612 EB1F                <1> 	jmp	short rwdsk_err1
  3433                              <1> rwdsk1:
  3434                              <1> 	;test	ah, 2
  3435                              <1> 	;;test	ax, 200h ; Bit 9 of word 0 (status word)
  3436                              <1> 	;		 ; write bit
  3437                              <1> 	;jz	short rwdsk2
  3438                              <1> 	
  3439                              <1> 	;;test	ah, 4
  3440                              <1> 	;;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3441                              <1> 	;;		 ; read bit
  3442                              <1> 	;;jz	short diskio_ret
  3443                              <1> 
  3444                              <1> 	;inc	dh ; 03h = write
  3445                              <1> 
  3446                              <1> 	; 08/07/2022
  3447 00005614 84F4                <1> 	test	ah, dh ; test ah, 2
  3448 00005616 7502                <1> 	jnz	short rwdsk2 ; dh = 02h = write
  3449 00005618 FECE                <1> 	dec	dh
  3450                              <1> 		; dh = 01h = read
  3451                              <1> rwdsk2:
  3452 0000561A 88C2                <1> 	mov	dl, al
  3453 0000561C 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3454 0000561F 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3455 00005621 C0E102              <1> 	shl	cl, 2
  3456 00005624 81C1[625D0000]      <1> 	add	ecx, drv.size ; disk size
  3457 0000562A 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3458 0000562C 7214                <1> 	jb      short rwdsk3
  3459                              <1>  	; 'out of volume' error
  3460                              <1> 	; 10/02/2022
  3461                              <1> 	; 08/02/2022
  3462                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3463                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3464                              <1> 	;;jmp	error
  3465                              <1> 	;stc	; cf = 1
  3466                              <1> 	;retn
  3467                              <1> 	; 10/02/2022
  3468 0000562E B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3469                              <1> rwdsk_err1:
  3470 00005633 C605[64660000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3471 0000563A 890D[51660000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3472 00005640 EB27                <1> 	jmp	short rwdsk_err2
  3473                              <1> rwdsk3:
  3474                              <1> 	; 11/06/2015
  3475 00005642 83C304              <1> 	add	ebx, 4 ; buffer address
  3476 00005645 C605[82660000]04    <1> 	mov	byte [retry_count], 4
  3477                              <1> 	; 12/07/2022
  3478                              <1> 	;test	byte [esi], 1 ; LBA ready ?
  3479                              <1>         ;jz	short rwdsk_chs
  3480                              <1> rwdsk_lba:
  3481                              <1> 	; LBA read/write (with private LBA function) 
  3482                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3483 0000564C 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3484 0000564F 89C1                <1> 	mov	ecx, eax ; sector number
  3485                              <1> 	; ebx = buffer (data) address
  3486                              <1> 	; dl = physical drive number (0, 1, 80h, 81h, 82h, 83h)
  3487                              <1> rwdsk_lba_retry:
  3488                              <1> 	;mov	dl, [drv]
  3489                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3490                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3491                              <1> 	;;mov	ah, 1Ch - 03h ; LBA write function number - 3
  3492                              <1> 	;mov	ah, 2 ; LBA write function number - 2
  3493                              <1> 	;add	ah, dh		
  3494                              <1> 	;mov	al, 1
  3495                              <1> 	;int	13h
  3496                              <1> 	;call	int13h
  3497                              <1> 	; 12/07/2022
  3498 00005651 88F0                <1> 	mov	al, dh	; function (1 or 2)
  3499                              <1> 			; (1 = read, 2 = write )
  3500                              <1> 	; ecx = disk sector address (LBA)
  3501                              <1> 	; ebx = buffer address
  3502                              <1> 	;  dl = (physical) disk number
  3503                              <1> 	;  al = function (r/w)
  3504 00005653 E8FCC9FFFF          <1> 	call	DISK_IO
  3505                              <1> 
  3506 00005658 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3507 0000565A 730E                <1> 	jnc	short rwdsk_lba_ok
  3508 0000565C 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3509 0000565F 7408                <1>         je      short rwdsk_lba_fails
  3510 00005661 FE0D[82660000]      <1> 	dec	byte [retry_count]
  3511 00005667 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3512                              <1> rwdsk_err2:	; 10/02/2022
  3513                              <1> rwdsk_lba_fails:
  3514 00005669 F9                  <1> 	stc
  3515                              <1> rwdsk_lba_ok:
  3516 0000566A 5B                  <1> 	pop	ebx ; ***
  3517 0000566B 5E                  <1> 	pop	esi ; ****
  3518 0000566C C3                  <1> 	retn
  3519                              <1> rwdsk_lba_reset:
  3520                              <1> 	;mov	ah, 0Dh ; Alternate reset
  3521                              <1> 	;int	13h
  3522                              <1> 	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3523                              <1> 	;mov	ah, 5 ; Alternate reset	 
  3524                              <1> 	;call	int13h
  3525                              <1> 	;jnc	short rwdsk_lba_retry
  3526                              <1> 	; 12/07/2022
  3527 0000566D 30C0                <1> 	xor	al, al ; 0 ; reset
  3528 0000566F E8E0C9FFFF          <1> 	call	DISK_IO
  3529 00005674 73DB                <1> 	jnc	short rwdsk_lba_retry
  3530                              <1> 
  3531 00005676 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3532 00005678 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3533                              <1> 
  3534                              <1> 	; 12/07/2022 
  3535                              <1> 	;	(CHS Read/Write setup is not needed here.)
  3536                              <1> 	; 	(LBA address will be converted to CHS parameters 
  3537                              <1> 	;	in 'DISK_IO' procedure when/if it is required.)
  3538                              <1>  
  3539                              <1> ;	; CHS read (convert LBA address to CHS values)	
  3540                              <1> ;rwdsk_chs:
  3541                              <1> ;	; 10/07/2015
  3542                              <1> ;	sub	esi, drv.status
  3543                              <1> ;	mov	ecx, esi
  3544                              <1> ;	add 	esi, drv.error
  3545                              <1> ;	; 02/07/2015
  3546                              <1> ;	; 16/06/2015
  3547                              <1> ;	; 11/06/2015 
  3548                              <1> ;	push	ebx ; ** ; buffer
  3549                              <1> ;	shl	ecx, 1
  3550                              <1> ;	push	ecx ; * 
  3551                              <1> ;	;
  3552                              <1> ;	mov	ebx, ecx
  3553                              <1> ;	mov	[rwdsk], dh ; 02/07/2015
  3554                              <1> ;	xor	edx, edx ; 0
  3555                              <1> ;	; 09/01/2022
  3556                              <1> ;	;sub	ecx, ecx 
  3557                              <1> ;       add     ebx, drv.spt
  3558                              <1> ;	mov	cx, [ebx] ; sector per track
  3559                              <1> ;		; EDX:EAX = LBA
  3560                              <1> ;	div	ecx
  3561                              <1> ;	mov	cl, dl	; sector number - 1
  3562                              <1> ;	inc	cl	; sector number (1 based)
  3563                              <1> ;	pop	ebx ; * ; 11/06/2015
  3564                              <1> ;	;push	cx
  3565                              <1> ;	; 09/01/2022
  3566                              <1> ;	push	ecx
  3567                              <1> ;	add     ebx, drv.heads
  3568                              <1> ;	mov	cx, [ebx] ; heads
  3569                              <1> ;	xor	edx, edx
  3570                              <1> ;		; EAX = cylinders * heads + head
  3571                              <1> ;	div	ecx
  3572                              <1> ;	;pop	cx     ; sector number
  3573                              <1> ;	; 09/01/2022
  3574                              <1> ;	pop	ecx
  3575                              <1> ;	mov	dh, dl ; head number
  3576                              <1> ;	mov	dl, [drv]
  3577                              <1> ;	mov	ch, al ; cylinder (bits 0-7)
  3578                              <1> ;	shl	ah, 6
  3579                              <1> ;	or	cl, ah ; cylinder (bits 8-9)
  3580                              <1> ;		       ; sector (bits 0-7)
  3581                              <1> ;	pop	ebx ; ** ; buffer ; 11/06/2015
  3582                              <1> ;		; CL = sector (bits 0-5)
  3583                              <1> ;		;      cylinder (bits 8-9 -> bits 6-7)
  3584                              <1> ;		; CH = cylinder (bits 0-7)
  3585                              <1> ;		; DH = head
  3586                              <1> ;		; DL = drive
  3587                              <1> ;	;
  3588                              <1> ;	mov	byte [retry_count], 4
  3589                              <1> ;rwdsk_retry:	
  3590                              <1> ;	;mov	ah, [rwdsk] ; 02h = read, 03h = write
  3591                              <1> ;	; 08/07/2022
  3592                              <1> ;	mov	ah, [rwdsk] ; 01h = read, 02h = write
  3593                              <1> ;	mov	al, 1 ; sector count	
  3594                              <1> ;	;int	13h
  3595                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3596                              <1> ;	call	int13h
  3597                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3598                              <1> ;	jnc	short rwdsk_ok ; ah = 0
  3599                              <1> ;	cmp	ah, 80h ; time out ?
  3600                              <1> ;	je	short rwdsk_fails
  3601                              <1> ;	dec	byte [retry_count]
  3602                              <1> ;	jnz	short rwdsk_reset
  3603                              <1> ;rwdsk_fails:
  3604                              <1> ;	stc
  3605                              <1> ;rwdsk_ok:
  3606                              <1> ;	pop	ebx ; ***
  3607                              <1> ;	pop	esi ; ****
  3608                              <1> ;	retn
  3609                              <1> ;rwdsk_reset:
  3610                              <1> ;	; 02/02/2015
  3611                              <1> ;	sub	ah, ah
  3612                              <1> ;	cmp	dl, 80h
  3613                              <1> ;	jb	short rwdsk_fd_reset
  3614                              <1> ;	;mov	ah, 0Dh ; Alternate reset
  3615                              <1> ;	; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  3616                              <1> ;	mov	ah, 5  ; Alternate reset
  3617                              <1> ;rwdsk_fd_reset:
  3618                              <1> ;	;int	13h
  3619                              <1> ;	call	int13h
  3620                              <1> ;	jnc	short rwdsk_retry
  3621                              <1> ;	mov	[esi], ah ; error code ; 10/07/2015
  3622                              <1> ;	jmp 	short rwdsk_ok
  3623                              <1> 
  3624                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3625                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3626                              <1> ;
  3627                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3628                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3629                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3630                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3631                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3632                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3633                              <1> ; as in original unix v1.
  3634                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3635                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3636                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3637                              <1> ;
  3638                              <1> ; Erdogan tan (10/07/2015) 
  3639                              <1> 
  3640                              <1> ;drum: / interrupt handler
  3641                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3642                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3643                              <1> ;                                      / error
  3644                              <1> ;               br 3f / no, error
  3645                              <1> ;       br      2f / error
  3646                              <1> ;
  3647                              <1> ;disk:
  3648                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3649                              <1> ;       jmp     *$0f
  3650                              <1> ;0:
  3651                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3652                              <1> ;      	        br 3f / no, errors
  3653                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3654                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3655                              <1> ;                        / to 1f
  3656                              <1> ;       br      4f
  3657                              <1> ;1:
  3658                              <1> ;       bit     $20000,rkcs
  3659                              <1> ;       beq     4f / wait for seek complete
  3660                              <1> ;       mov     $0b,0b-2
  3661                              <1> ;       mov     rkap,r1
  3662                              <1> ;2:
  3663                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3664                              <1> ;                          / the disk buffer
  3665                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3666                              <1> ;       inc     r1
  3667                              <1> ;       asr     (r1)
  3668                              <1> ;       asr     (r1)
  3669                              <1> ;       asr     (r1) / reissue request
  3670                              <1> ;       dec     r1
  3671                              <1> ;3:
  3672                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3673                              <1> ;       mov     ac,-(sp)
  3674                              <1> ;       mov     mq,-(sp) / put these on the stack
  3675                              <1> ;       mov     sc,-(sp)
  3676                              <1> ;       jsr     r0,poke
  3677                              <1> ;       mov     (sp)+,sc
  3678                              <1> ;       mov     (sp)+,mq / pop them off stack
  3679                              <1> ;       mov     (sp)+,ac
  3680                              <1> ;4:
  3681                              <1> ;       jmp     retisp / u4-3
  3682                              <1> ;
  3683                              <1> ;trapt:                  / r2 points to the
  3684                              <1> ;       mov     (r0)+,r2 / device control register
  3685                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3686                              <1> ;       tst     (sp)+
  3687                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3688                              <1> ;       bge     4b / device still active so branch
  3689                              <1> ;       bit     (r0),active / was device busy?
  3690                              <1> ;       beq     4b / no, stray interrupt
  3691                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3692                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3693                              <1> ;       bge     2f / if no error jump to 2f
  3694                              <1> ;       tst     (r0)+ / skip on error
  3695                              <1> ; 2:
  3696                              <1> ;       jmp     (r0)
  2121                                  %include 'u9.s'        ; 29/06/2015
  2122                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS9.INC
  2123                              <1> ; Last Modification: 13/06/2022
  2124                              <1> ; ----------------------------------------------------------------------------
  2125                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2126                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2127                              <1> ;
  2128                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2129                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2130                              <1> ; <Bell Laboratories (17/3/1972)>
  2131                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2132                              <1> ;
  2133                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2134                              <1> ;
  2135                              <1> ; ****************************************************************************
  2136                              <1> 
  2137                              <1> getch:
  2138                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2139                              <1> 	; 30/06/2015
  2140                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2141 0000567A 28C0                <1> 	sub	al, al ; 0
  2142                              <1> getch_q: ; 06/08/2015
  2143 0000567C 8A25[66620000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2144 00005682 EB06                <1>         jmp     short getc_n
  2145                              <1> 
  2146                              <1> getc: 
  2147                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2148                              <1> 	; 12/11/2015
  2149                              <1> 	; 15/09/2015
  2150                              <1> 	; 01/07/2015
  2151                              <1> 	; 30/06/2015
  2152                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2153                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2154                              <1> 	;
  2155                              <1> 	; Retro UNIX 8086 v1 modification !
  2156                              <1> 	; 
  2157                              <1> 	; 'getc' gets (next) character 
  2158                              <1> 	;	 from requested TTY (keyboard) buffer 
  2159                              <1> 	; INPUTS ->
  2160                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2161                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2162                              <1> 	;	(Keyboard buffer will point to 
  2163                              <1> 	;			next character at next call)
  2164                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2165                              <1> 	;	(Keyboard buffer will point to 
  2166                              <1> 	;			current character at next call)
  2167                              <1> 	; OUTPUTS ->
  2168                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2169                              <1> 	;     			 ZF=0 -> AX has (current) character
  2170                              <1> 	;      AL = ascii code
  2171                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2172                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2173                              <1> 	; Original UNIX V1 'getc': 
  2174                              <1> 	;		get a character off character list
  2175                              <1> 	;
  2176                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2177                              <1> 	;
  2178                              <1> 	; 30/06/2015 (32 bit modifications)
  2179                              <1> 	; 16/07/2013
  2180                              <1> 	; mov 	[getctty], ah
  2181                              <1> 	;
  2182                              <1> 
  2183 00005684 8A25[50660000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2184                              <1> getc_n:
  2185                              <1> 	; 30/06/2015
  2186 0000568A 08E4                <1> 	or	ah, ah
  2187 0000568C 740D                <1> 	jz	short getc0 
  2188 0000568E D0E4                <1> 	shl	ah, 1
  2189 00005690 0FB6DC              <1> 	movzx	ebx, ah
  2190 00005693 81C3[68620000]      <1> 	add	ebx, ttychr
  2191 00005699 EB05                <1> 	jmp	short getc1
  2192                              <1> getc0:
  2193 0000569B BB[68620000]        <1> 	mov	ebx, ttychr
  2194                              <1> getc1:
  2195 000056A0 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2196                              <1> 				; (by kb_int)	
  2197 000056A3 6609C9              <1> 	or	cx, cx
  2198 000056A6 7507                <1> 	jnz	short getc2
  2199 000056A8 20C0                <1> 	and 	al, al
  2200 000056AA 7415                <1> 	jz	short getc_s
  2201                              <1> 	;xor	ax, ax
  2202                              <1> 	; 24/12/2021
  2203 000056AC 31C0                <1> 	xor	eax, eax
  2204 000056AE C3                  <1> 	retn
  2205                              <1> getc2:	
  2206 000056AF 20C0                <1> 	and	al, al
  2207 000056B1 6689C8              <1> 	mov	ax, cx
  2208 000056B4 66B90000            <1> 	mov	cx, 0
  2209 000056B8 7506                <1> 	jnz	short getc3
  2210                              <1> getc_sn:
  2211 000056BA 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2212 000056BD 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2213                              <1> getc3:
  2214 000056C0 C3                  <1> 	retn
  2215                              <1> getc_s:
  2216                              <1> 	; 12/11/2015
  2217                              <1> 	; 15/09/2015
  2218                              <1> 	; 01/07/2015
  2219                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2220                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2221                              <1> 	;
  2222                              <1> 	; tty  of the current process is not 
  2223                              <1> 	; current tty (ptty); so, current process only 
  2224                              <1> 	; can use keyboard input when its tty becomes 
  2225                              <1> 	; current tty (ptty).
  2226                              <1> 	; 'sleep' is for preventing an endless lock
  2227                              <1> 	; during this tty input request.
  2228                              <1> 	; (Because, the user is not looking at the video page
  2229                              <1> 	; of the process to undersand there is a keyboard
  2230                              <1> 	; input request.)
  2231                              <1> 	;
  2232                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2233                              <1> 	;
  2234                              <1> 	; 05/10/2013
  2235                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2236                              <1> 	;
  2237                              <1> 	; 10/10/2013
  2238                              <1> gcw0:
  2239 000056C1 B10A                <1> 	mov	cl, 10 ; ch = 0
  2240                              <1> gcw1:	
  2241                              <1> 	; 12/11/2015
  2242 000056C3 E816DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2243                              <1> 	; 10/10/2013
  2244 000056C8 E8B2EFFFFF          <1> 	call	idle
  2245 000056CD 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2246                              <1> 				; (by kb_int)
  2247 000056D0 6609C0              <1> 	or	ax, ax
  2248                              <1> ;	jnz	short gcw3
  2249 000056D3 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2250                              <1> 	; 30/06/2015
  2251 000056D5 FEC9                <1> 	dec	cl
  2252 000056D7 75EA                <1> 	jnz	short gcw1
  2253                              <1> 	;
  2254 000056D9 8A25[50660000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2255                              <1> ;	; 10/12/2013
  2256                              <1> ;	cmp 	ah, [ptty]
  2257                              <1> ;	jne	short gcw2
  2258                              <1> ;	; 14/02/2014
  2259                              <1> ;	cmp	byte [u.uno], 1
  2260                              <1> ;	jna	short gcw0		
  2261                              <1> ;gcw2:
  2262 000056DF E828F0FFFF          <1> 	call	sleep
  2263                              <1> 	;
  2264                              <1> 	; 20/09/2013
  2265 000056E4 8A25[50660000]      <1> 	mov	ah, [u.ttyn]
  2266 000056EA 30C0                <1> 	xor 	al, al
  2267 000056EC EB9C                <1> 	jmp	short getc_n
  2268                              <1> ;gcw3:
  2269                              <1> gcw2: 	; 15/09/2015
  2270                              <1> 	; 10/10/2013
  2271 000056EE 30C9                <1> 	xor	cl, cl
  2272 000056F0 EBC8                <1> 	jmp	short getc_sn
  2273                              <1> 
  2274                              <1> putc:	
  2275                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2276                              <1> 	; 13/08/2015
  2277                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2278                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2279                              <1> 	;
  2280                              <1> 	; Retro UNIX 8086 v1 modification !
  2281                              <1> 	; 
  2282                              <1> 	; 'putc' puts a character 
  2283                              <1> 	;	 onto requested (tty) video page or
  2284                              <1> 	;	 serial port
  2285                              <1> 	; INPUTS ->
  2286                              <1> 	;     AL = ascii code of the character
  2287                              <1> 	;     AH = video page (tty) number (0 to 7)
  2288                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2289                              <1> 	; OUTPUTS ->
  2290                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2291                              <1> 	;      			ZF=0 -> AX has (current) character
  2292                              <1> 	;     cf=0 and AH = 0 -> no error
  2293                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2294                              <1> 	; 
  2295                              <1> 	; Original UNIX V1 'putc': 
  2296                              <1> 	;     put a character at the end of character list
  2297                              <1> 	;
  2298                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2299                              <1> 	;
  2300 000056F2 80FC07              <1> 	cmp	ah, 7
  2301                              <1>         ;ja	sndc
  2302 000056F5 770A                <1>         ja      short sndc ; 24/12/2024
  2303                              <1> 	; 30/06/2015
  2304 000056F7 0FB6DC              <1> 	movzx	ebx, ah
  2305                              <1> 	; 13/08/2015
  2306 000056FA B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2307 000056FC E9A1BCFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2308                              <1> 
  2309                              <1> sndc:   ; <Send character>
  2310                              <1> 	;
  2311                              <1> 	; 12/01/2022
  2312                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2313                              <1> 	; 17/11/2015
  2314                              <1> 	; 16/11/2015
  2315                              <1> 	; 11/11/2015
  2316                              <1> 	; 10/11/2015
  2317                              <1> 	; 09/11/2015
  2318                              <1> 	; 08/11/2015
  2319                              <1> 	; 07/11/2015
  2320                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2321                              <1> 	; 29/10/2015
  2322                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2323                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2324                              <1> 	;
  2325                              <1> 	; Retro UNIX 8086 v1 feature only !
  2326                              <1> 	;
  2327                              <1> 	; ah = [u.ttyn]
  2328                              <1> 	;
  2329                              <1> 	; 30/06/2015
  2330 00005701 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2331                              <1> 	; 07/11/2015
  2332 00005704 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2333                              <1> sndc0:
  2334                              <1> 	; 07/11/2015
  2335 00005707 E84EF0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2336 0000570C 7405                <1> 	jz	short sndc1
  2337 0000570E E8CBDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2338                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2339                              <1> sndc1:
  2340                              <1> 	; 16/11/2015
  2341                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2342                              <1> 	; 24/12/2021
  2343 00005713 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2344                              <1> sndcx:
  2345 00005715 8A83[AA620000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2346 0000571B 8AA3[A8620000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2347                              <1> 	;
  2348                              <1> 	; 17/11/2015
  2349                              <1> 	; check 'request for response' status
  2350 00005721 80BB[A4620000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2351 00005728 740A                <1> 	jz	short query
  2352                              <1> response:
  2353 0000572A FE05[A7620000]      <1> 	inc 	byte [comqr] ; query or response status
  2354 00005730 B0FF                <1> 	mov	al, 0FFh	 
  2355 00005732 EB14                <1> 	jmp	short sndc3
  2356                              <1> query:
  2357 00005734 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2358 00005736 750E                <1> 	jnz 	short sndc2 ; normal character
  2359                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2360                              <1> 	;je	short sndc2  ; yes, already responded
  2361                              <1> 	; 16/11/2015
  2362                              <1> 	; query: request for response (again)
  2363 00005738 8883[A8620000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2364 0000573E FE05[A7620000]      <1> 	inc 	byte [comqr] ; query or response status
  2365 00005744 EB02                <1> 	jmp	short sndc3
  2366                              <1> sndc2:
  2367 00005746 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2368                              <1> sndc3:
  2369 00005748 8883[AA620000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2370 0000574E 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2371                              <1> 	; 30/06/2015
  2372 00005750 E832D5FFFF          <1> 	call	sp_status ; get serial port status
  2373                              <1> 	; AL = Line status, AH = Modem status
  2374                              <1> 	; 07/11/2015
  2375 00005755 A880                <1> 	test	al, 80h
  2376 00005757 7504                <1> 	jnz	short sndc4
  2377 00005759 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2378 0000575B 751A                <1> 	jnz	short sndc5
  2379                              <1> sndc4: 	; Check line status again
  2380                              <1> 	; 16/11/2015
  2381                              <1> 	;push	cx
  2382                              <1> 	; 24/12/2021
  2383 0000575D 51                  <1> 	push	ecx
  2384                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2385                              <1> 	; 12/01/2022
  2386 0000575E 31C9                <1> 	xor	ecx, ecx
  2387 00005760 B106                <1> 	mov	cl, 6
  2388 00005762 E832BDFFFF          <1> 	call	WAITF
  2389                              <1> 	;pop	cx
  2390                              <1> 	; 24/12/1021
  2391 00005767 59                  <1> 	pop	ecx
  2392                              <1> 	;
  2393 00005768 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2394 0000576A E818D5FFFF          <1> 	call	sp_status ; get serial port status
  2395                              <1> 	; 16/11/2015
  2396                              <1> 	; 09/11/2015
  2397                              <1> 	; 08/11/2015
  2398 0000576F A880                <1> 	test	al, 80h	; time out error
  2399 00005771 7565                <1>         jnz     short sndc7
  2400 00005773 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2401 00005775 7461                <1>         jz	short sndc7
  2402                              <1> sndc5:  
  2403 00005777 8A83[AA620000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2404 0000577D 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2405 00005781 28DE                <1> 	sub	dh, bl
  2406 00005783 EE                  <1> 	out	dx, al	   ; send on serial port
  2407                              <1> 	; 10/11/2015
  2408                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2409                              <1> 	; (to improve text flow to the terminal)
  2410                              <1> 	; ('diskette.inc': 'WAITF')
  2411                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2412                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2413                              <1> 	;push	cx
  2414                              <1> 	; 24/12/2021
  2415 00005784 51                  <1> 	push	ecx
  2416                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2417                              <1> 	; 12/01/2022
  2418 00005785 29C9                <1> 	sub	ecx, ecx
  2419 00005787 B106                <1> 	mov	cl, 6
  2420 00005789 E80BBDFFFF          <1> 	call	WAITF
  2421                              <1> 	;pop	cx
  2422                              <1> 	; 24/12/1021
  2423 0000578E 59                  <1> 	pop	ecx
  2424                              <1>     	;
  2425                              <1> 	; 07/11/2015
  2426 0000578F 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2427                              <1> 	;
  2428 00005791 E8F1D4FFFF          <1> 	call	sp_status ; get serial port status
  2429                              <1> 	; AL = Line status, AH = Modem status
  2430                              <1> 	;
  2431 00005796 E8BFEFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2432 0000579B 7405                <1> 	jz	short sndc6
  2433 0000579D E83CDBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2434                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2435                              <1> sndc6:
  2436 000057A2 3C80                <1> 	cmp	al, 80h
  2437 000057A4 7332                <1> 	jnb	short sndc7		
  2438                              <1> 	;
  2439 000057A6 803D[A7620000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2440 000057AD 7244                <1> 	jb	short sndc8 	; no, normal character
  2441 000057AF 883D[A7620000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2442                              <1> 	; 17/11/2015
  2443 000057B5 E8C5EEFFFF          <1> 	call	idle
  2444                              <1> 	;
  2445 000057BA 38BB[AA620000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2446                              <1>         ;ja	sndc2       ; response (will be followed by
  2447                              <1> 			    ; a normal character)
  2448                              <1> 	; 24/12/2021
  2449 000057C0 7602                <1> 	jna	short sndc_10
  2450 000057C2 EB82                <1> 	jmp	sndc2
  2451                              <1> sndc_10:
  2452                              <1> 	; Query request must be responded by the terminal
  2453                              <1> 	; before sending a normal character !
  2454 000057C4 53                  <1> 	push	ebx
  2455                              <1> 	;push	cx ; *** cl = character (to be sent)
  2456                              <1> 	; 24/12/2021
  2457 000057C5 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2458 000057C6 8A25[50660000]      <1> 	mov	ah, [u.ttyn]
  2459 000057CC E83BEFFFFF          <1> 	call	sleep ; this process will be awakened by
  2460                              <1> 		      ; received data available interrupt
  2461                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2462                              <1> 	; 24/12/2021
  2463 000057D1 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2464 000057D2 5B                  <1> 	pop	ebx
  2465 000057D3 E93DFFFFFF          <1>         jmp	sndcx
  2466                              <1> sndc7:
  2467                              <1> 	 ; 16/11/2015
  2468 000057D8 803D[A7620000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2469 000057DF 7213                <1> 	jb	short sndc9 	; no
  2470                              <1> 	;
  2471 000057E1 88BB[A8620000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2472 000057E7 88BB[AA620000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2473                              <1> 	;
  2474 000057ED 883D[A7620000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2475                              <1> sndc8:
  2476 000057F3 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2477                              <1> sndc9:
  2478                              <1> 	; AL = Line status, AH = Modem status
  2479 000057F4 C3                  <1> 	retn
  2480                              <1> 
  2481                              <1> get_cpos:
  2482                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2483                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2484                              <1> 	;
  2485                              <1> 	; INPUT -> bl = video page number
  2486                              <1> 	; RETURN -> dx = cursor position
  2487                              <1> 
  2488 000057F5 53                  <1> 	push	ebx
  2489 000057F6 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2490 000057F9 D0E3                <1> 	shl	bl, 1
  2491 000057FB 81C3[56620000]      <1> 	add	ebx, cursor_posn
  2492 00005801 668B13              <1> 	mov	dx, [ebx]
  2493 00005804 5B                  <1> 	pop	ebx
  2494 00005805 C3                  <1> 	retn
  2495                              <1> 
  2496                              <1> read_ac_current:
  2497                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2498                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2499                              <1> 	;
  2500                              <1> 	; INPUT -> bl = video page number
  2501                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2502                              <1> 
  2503 00005806 E8FDBCFFFF          <1> 	call 	find_position ; 'video.inc'
  2504                              <1> 	; dx = status port
  2505                              <1> 	; esi = cursor location/address
  2506 0000580B 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2507 00005811 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2508 00005814 C3                  <1> 	retn
  2509                              <1> 
  2510                              <1> syssleep:
  2511                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2512                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2513                              <1> 	;
  2514                              <1> 	; Retro UNIX 8086 v1 feature only
  2515                              <1> 	; (INPUT -> none)
  2516                              <1> 	;
  2517 00005815 0FB61D[4B660000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2518 0000581C 8AA3[53630000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2519 00005822 E8E5EEFFFF          <1> 	call	sleep
  2520 00005827 E9C5D9FFFF          <1> 	jmp	sysret
  2521                              <1> 
  2522                              <1> 	; 27/02/2022
  2523                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2524                              <1> %if 0
  2525                              <1> 
  2526                              <1> vp_clr:
  2527                              <1> 	; Reset/Clear Video Page
  2528                              <1> 	;
  2529                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2530                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2531                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2532                              <1> 	;
  2533                              <1> 	; Retro UNIX 8086 v1 feature only !
  2534                              <1> 	;
  2535                              <1> 	; INPUTS -> 
  2536                              <1> 	;   BL = video page number	 
  2537                              <1> 	;
  2538                              <1> 	; OUTPUT ->
  2539                              <1> 	;   none
  2540                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2541                              <1> 	;
  2542                              <1> 	; 04/12/2013
  2543                              <1> 	sub	al, al
  2544                              <1> 	; al = 0 (clear video page)
  2545                              <1> 	; bl = video page
  2546                              <1> 	mov	ah, 07h
  2547                              <1> 	; ah = 7 (attribute/color)
  2548                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2549                              <1> 	; 24/12/2021
  2550                              <1> 	xor	ecx, ecx
  2551                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2552                              <1> 	call	scroll_up
  2553                              <1> 	; bl = video page
  2554                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2555                              <1> 	; 24/12/2021
  2556                              <1> 	xor	edx, edx 
  2557                              <1> 	jmp 	set_cpos
  2558                              <1> 
  2559                              <1> %endif
  2560                              <1> 
  2561                              <1> sysmsg:
  2562                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2563                              <1> 	; 11/11/2015
  2564                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2565                              <1> 	; Print user-application message on user's console tty
  2566                              <1> 	;
  2567                              <1> 	; Input -> EBX = Message address
  2568                              <1> 	;	   ECX = Message length (max. 255)
  2569                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2570                              <1> 	;
  2571 0000582C 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2572                              <1> 	;ja	sysret ; nothing to do with big message size
  2573 00005832 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2574 00005834 08C9                <1> 	or	cl, cl
  2575                              <1> 	;jz	sysret
  2576 00005836 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2577 00005838 20D2                <1> 	and	dl, dl
  2578 0000583A 7502                <1> 	jnz	short sysmsg0
  2579 0000583C B207                <1> 	mov	dl, 07h ; default color
  2580                              <1> 		; (black background, light gray character)
  2581                              <1> sysmsg0:
  2582 0000583E 891D[1C660000]      <1> 	mov	[u.base], ebx
  2583 00005844 8815[67620000]      <1> 	mov	[ccolor], dl ; color attributes
  2584 0000584A 89E5                <1> 	mov	ebp, esp
  2585 0000584C 31DB                <1> 	xor	ebx, ebx ; 0
  2586 0000584E 891D[24660000]      <1> 	mov	[u.nread], ebx ; 0
  2587                              <1> 	;
  2588 00005854 381D[63660000]      <1> 	cmp	[u.kcall], bl ; 0
  2589 0000585A 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2590                              <1> 	;
  2591 0000585C 890D[20660000]      <1> 	mov	[u.count], ecx
  2592 00005862 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2593                              <1> 	; 24/12/2021
  2594                              <1> 	; (dword alignment for esp)
  2595 00005863 F6C103              <1> 	test	cl, 3
  2596 00005866 7404                <1> 	jz	short sysmsg_7
  2597 00005868 80C903              <1> 	or	cl, 3
  2598 0000586B 41                  <1> 	inc	ecx
  2599                              <1> sysmsg_7:
  2600 0000586C 29CC                <1> 	sub	esp, ecx
  2601 0000586E 89E7                <1> 	mov	edi, esp
  2602 00005870 89E6                <1> 	mov	esi, esp
  2603 00005872 66891D[61660000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2604                              <1> 	; 11/11/2015
  2605 00005879 8A25[2C660000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2606                              <1> 	; 0 = none
  2607 0000587F FECC                <1> 	dec	ah
  2608 00005881 790C                <1> 	jns	short sysmsg1 
  2609 00005883 8A1D[4B660000]      <1> 	mov	bl, [u.uno] ; process number	
  2610 00005889 8AA3[53630000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2611                              <1> sysmsg1:
  2612 0000588F 8825[50660000]      <1> 	mov	[u.ttyn], ah
  2613                              <1> sysmsg2:
  2614 00005895 E84BF6FFFF          <1> 	call	cpass
  2615 0000589A 7416                <1> 	jz	short sysmsg5
  2616 0000589C AA                  <1> 	stosb
  2617 0000589D 20C0                <1> 	and	al, al
  2618 0000589F 75F4                <1> 	jnz	short sysmsg2
  2619                              <1> sysmsg3:
  2620 000058A1 80FC07              <1> 	cmp	ah, 7 ; tty number
  2621 000058A4 7711                <1> 	ja	short sysmsg6 ; serial port
  2622 000058A6 E83E000000          <1> 	call	print_cmsg
  2623                              <1> sysmsg4:
  2624 000058AB 89EC                <1> 	mov	esp, ebp	
  2625                              <1> sysmsg8: ; 24/12/2021	
  2626 000058AD E93FD9FFFF          <1> 	jmp	sysret
  2627                              <1> sysmsg5:
  2628 000058B2 C60700              <1> 	mov	byte [edi], 0
  2629 000058B5 EBEA                <1> 	jmp	short sysmsg3
  2630                              <1> sysmsg6:
  2631 000058B7 8A06                <1> 	mov	al, [esi]
  2632 000058B9 E843FEFFFF          <1> 	call	sndc
  2633 000058BE 72EB                <1> 	jc	short sysmsg4
  2634 000058C0 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2635 000058C3 76E6                <1> 	jna	short sysmsg4
  2636 000058C5 46                  <1> 	inc 	esi
  2637 000058C6 8A25[50660000]      <1> 	mov	ah, [u.ttyn]
  2638 000058CC EBE9                <1> 	jmp	short sysmsg6
  2639                              <1> 
  2640                              <1> sysmsgk: ; Temporary (01/07/2015)
  2641                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2642                              <1> 	; (ECX -character count- will not be considered)
  2643 000058CE 8B35[1C660000]      <1> 	mov	esi, [u.base]
  2644 000058D4 8A25[66620000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2645 000058DA 8825[50660000]      <1> 	mov	[u.ttyn], ah
  2646 000058E0 C605[63660000]00    <1> 	mov	byte [u.kcall], 0
  2647 000058E7 EBB8                <1> 	jmp	short sysmsg3
  2648                              <1> 	
  2649                              <1> print_cmsg: 
  2650                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2651                              <1> 	;
  2652                              <1> 	; print message (on user's console tty) 
  2653                              <1> 	;	with requested color
  2654                              <1> 	;
  2655                              <1> 	; INPUTS:
  2656                              <1> 	;	esi = message address
  2657                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2658                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2659                              <1> 	;
  2660 000058E9 AC                  <1> 	lodsb
  2661                              <1> pcmsg1:
  2662 000058EA 56                  <1> 	push 	esi
  2663 000058EB 0FB61D[50660000]    <1>         movzx   ebx, byte [u.ttyn]
  2664 000058F2 8A25[67620000]      <1> 	mov	ah, [ccolor]
  2665 000058F8 E8A5BAFFFF          <1> 	call 	write_tty
  2666 000058FD 5E                  <1> 	pop	esi
  2667 000058FE AC                  <1> 	lodsb
  2668 000058FF 20C0                <1> 	and 	al, al  ; 0
  2669 00005901 75E7                <1> 	jnz 	short pcmsg1
  2670 00005903 C3                  <1> 	retn
  2671                              <1> 
  2672                              <1> sysgeterr:
  2673                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2674                              <1> 	; 09/12/2015
  2675                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2676                              <1> 	; Get last error number or page fault count
  2677                              <1> 	; (for debugging)
  2678                              <1> 	;
  2679                              <1> 	; Input -> EBX = return type
  2680                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2681                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2682                              <1> 	;	   FFFFFFFEh = total page fault count
  2683                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2684                              <1> 	;
  2685                              <1> 	; Output -> EAX = last error number or page fault count
  2686                              <1> 	;	   (depending on EBX input)
  2687                              <1> 	; 	
  2688 00005904 21DB                <1> 	and 	ebx, ebx
  2689 00005906 750F                <1> 	jnz	short glerr_2
  2690                              <1> glerr_0:
  2691 00005908 A1[51660000]        <1> 	mov	eax, [u.error]
  2692                              <1> glerr_1:
  2693 0000590D A3[FC650000]        <1> 	mov	[u.r0], eax
  2694                              <1>  	;retn
  2695                              <1> 	; 16/02/2022 (BugFix)
  2696 00005912 E9DAD8FFFF          <1> 	jmp	sysret
  2697                              <1> glerr_2:
  2698 00005917 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2699 00005918 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2700 0000591A 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2701 0000591B 75EB                <1> 	jnz	short glerr_0
  2702 0000591D A1[EC620000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2703 00005922 EBE9                <1>         jmp     short glerr_1
  2704                              <1> glerr_3:
  2705 00005924 A1[65660000]        <1> 	mov 	eax, [u.pfcount]
  2706 00005929 EBE2                <1> 	jmp	short glerr_1
  2707                              <1> 
  2708                              <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2709                              <1> ;	     - PRINTER BIOS (Functions)		
  2710                              <1> 
  2711                              <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 
  2712                              <1> ;
  2713                              <1> ;--- INT 17 H ------------------------------------------------------------------
  2714                              <1> ; PRINTER_IO								       :
  2715                              <1> ;	THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER		       :
  2716                              <1> ; INPUT 								       :
  2717                              <1> ;	(AH)= 00H  PRINT THE CHARACTER IN (AL)				       :
  2718                              <1> ;		    ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT)  :
  2719                              <1> ;		    OTHER BITS SET AS ON NORMAL STATUS CALL		       :
  2720                              <1> ;	(AH)= 01H  INITIALIZE THE PRINTER PORT				       :
  2721                              <1> ;		    RETURNS WITH (AH) SET WITH PRINTER STATUS		       :
  2722                              <1> ;	(AH)= 02H  READ THE PRINTER STATUS INTO (AH)			       :
  2723                              <1> ;		   7	   6	   5	   4	   3	   2-1	   0	       :
  2724                              <1> ;		   |	   |	   |	   |	   |	   |	   |_TIME OUT  :
  2725                              <1> ;		   |	   |	   |	   |	   |	   |		       :
  2726                              <1> ;		   |	   |	   |	   |	   |	   |_ UNUSED	       :
  2727                              <1> ;		   |	   |	   |	   |	   |			       :
  2728                              <1> ;		   |	   |	   |	   |	   |_ 1 = I/O ERROR	       :
  2729                              <1> ;		   |	   |	   |	   |				       :
  2730                              <1> ;		   |	   |	   |	   |_ 1 = SELECTED		       :
  2731                              <1> ;		   |	   |	   |					       :
  2732                              <1> ;		   |	   |	   |_ 1 = OUT OF PAPER			       :
  2733                              <1> ;		   |	   |						       :
  2734                              <1> ;		   |	   |_ 1 = ACKNOWLEDGE				       :
  2735                              <1> ;		   |							       :
  2736                              <1> ;		   |_ 1 = NOT BUSY					       :
  2737                              <1> ;									       :
  2738                              <1> ;	(DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES       :
  2739                              <1> ;		IN @PRINTER_BASE AREA					       :
  2740                              <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S)     :
  2741                              <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS)     :
  2742                              <1> ;									       :
  2743                              <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT	       :
  2744                              <1> ; TIME OUT WAITS. DEFAULT=20 * 4					       :
  2745                              <1> ;									       :
  2746                              <1> ; REGISTERS	(AH) IS MODIFIED WITH STATUS INFORMATION		       :
  2747                              <1> ;		ALL OTHERS UNCHANGED					       :
  2748                              <1> ;-------------------------------------------------------------------------------
  2749                              <1> 
  2750                              <1> int17h:
  2751                              <1> 	; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4)
  2752                              <1> 	; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985)
  2753                              <1> 	;
  2754                              <1> 	; (Default printer port: 378h) ; LPT1
  2755                              <1> 	; (Number of printers = 1)
  2756                              <1> 	
  2757                              <1> 	PRINTER_BASE equ 378h ; LPT1
  2758                              <1> 	;PRINT_TIM_OUT equ 4*80*65536 
  2759                              <1> 			; (Ref: IBM PC-AT BIOS v2 PRT.ASM)	 
  2760                              <1> 
  2761                              <1> 	PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY
  2762                              <1> 			; (Ref: AWARD BIOS 1999 ATORGS.ASM)		
  2763                              <1> 
  2764                              <1> 	; INPUT:
  2765                              <1> 	;	ah = 0 -> print the character in AL 
  2766                              <1> 	;		 (sys write with write count >0)
  2767                              <1> 	;	ah = 1 -> initialize printer port
  2768                              <1> 	;		 (sys open)	
  2769                              <1> 	;	ah = 2 -> read the printer status 
  2770                              <1> 	;		 (sys write with write count = 0)
  2771                              <1> 	; OUTPUT:
  2772                              <1> 	;	ah = printer status
  2773                              <1> 
  2774                              <1> 	; Modified registers: eax, ecx, edx
  2775                              <1> 
  2776                              <1> PRINTER_IO_1:
  2777 0000592B 08E4                <1> 	or	ah, ah
  2778 0000592D 7417                <1> 	jz	short _b20
  2779 0000592F FECC                <1> 	dec	ah
  2780 00005931 7444                <1> 	jz	short _b80
  2781                              <1> 	;dec 	ah
  2782                              <1> 	;jz	short _b50
  2783                              <1> _b50:
  2784                              <1> 	;-----	PRINTER STATUS
  2785                              <1> B50:
  2786 00005933 50                  <1> 	push	eax		; SAVE (AL) REGISTER
  2787                              <1> B60:
  2788 00005934 66BA7903            <1> 	mov	dx, PRINTER_BASE+1
  2789                              <1> 				; GET PRINTER ATTACHMENT BASE ADDRESS
  2790                              <1> 				; POINT TO CONTROL PORT
  2791 00005938 EC                  <1> 	in	al, dx		; PRE-CHARGE +BUSY LINE IF FLOATING
  2792 00005939 EC                  <1> 	in	al, dx		; GET PRINTER STATUS HARDWARE BITS
  2793 0000593A 88C4                <1> 	mov	ah, al		; SAVE
  2794 0000593C 80E4F8              <1> 	and	ah, 0F8h	; TURN OFF UNUSED BITS
  2795                              <1> B70:
  2796 0000593F 5A                  <1> 	pop	edx		; RECOVER (AL) REGISTER
  2797 00005940 88D0                <1> 	mov	al, dl		; MOVE CHARACTER INTO (AL)
  2798 00005942 80F448              <1> 	xor	ah, 48h		; FLIP A COUPLE OF BITS
  2799                              <1> B10:
  2800 00005945 C3                  <1> 	retn			; RETURN FROM ROUTINE WITH STATUS IN AH
  2801                              <1> _b20:
  2802                              <1> 	;-----	PRINT THE CHARACTER IN (AL)
  2803 00005946 B9A08C0000          <1> 	mov	ecx, PRINT_TIM_OUT ; (1 second)
  2804                              <1> B20:
  2805 0000594B 50                  <1> 	push	eax		; SAVE VALUE TO PRINT
  2806 0000594C 66BA7803            <1> 	mov	dx, PRINTER_BASE
  2807 00005950 EE                  <1> 	out	dx, al		; OUTPUT CHARACTER TO DATA PORT
  2808 00005951 FEC2                <1> 	inc	dl		; POINT TO STATUS PORT
  2809                              <1> 
  2810                              <1> 	;-----	CHECK FOR PRINTER BUSY
  2811                              <1> B25:
  2812                              <1> 	;-----	WAIT BUSY
  2813                              <1> B35:
  2814 00005953 EC                  <1> 	in	al, dx		; GET STATUS
  2815 00005954 88C4                <1> 	mov	ah, al		; STATUS TO (AH) ALSO
  2816 00005956 A880                <1> 	test	al, 80h		; IS THE PRINTER CURRENTLY BUSY? (*)
  2817 00005958 750F                <1> 	jnz	short B40	; GO TO OUTPUT STROBE
  2818 0000595A E831000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2819 0000595F E2F2                <1> 	loop	B35		; LOOP IF YES (*)
  2820                              <1> 
  2821 00005961 80CC01              <1> 	or	ah, 1		; SET ERROR FLAG
  2822 00005964 80E4F9              <1> 	and	ah, 0F9h	; TURN OFF THE UNUSED BITS
  2823 00005967 EBD6                <1> 	jmp	short B70	; RETURN WITH ERROR FLAG SET
  2824                              <1> 
  2825                              <1> B40:				; SEND STROBE PULSE
  2826 00005969 B00D                <1> 	mov	al, 0Dh		; SET THE STROBE LOW (BIT ON)
  2827 0000596B 6642                <1> 	inc	dx		; OUTPUT STROBE TO CONTROL PORT
  2828 0000596D FA                  <1> 	cli			; PREVENT INTERRUPT PULSE STRETCHING
  2829 0000596E EE                  <1> 	out	dx, al		; OUTPUT STROBE BIT > 1us < 5us
  2830                              <1> 	; IODELAY
  2831                              <1> 	;jmp	short $+2	; I/O DELAY TO ALLOW FOR LINE LOADING
  2832                              <1> 	;jmp	short $+2	; AND FOR CORRECT PULSE WIDTH
  2833                              <1> 	; NEWIODELAY
  2834 0000596F E6EB                <1> 	out	0EBh, al
  2835                              <1> 
  2836 00005971 B00C                <1> 	mov	al, 0Ch		; SET THE -STROBE HIGH
  2837 00005973 EE                  <1> 	out	dx, al
  2838 00005974 FB                  <1> 	sti			; INTERRUPTS BACK ON
  2839                              <1> 	;pop	eax		; RECOVER THE OUTPUT CHAR
  2840                              <1> 	;jmp	short B50
  2841 00005975 EBBD                <1> 	jmp	short B60
  2842                              <1> 
  2843                              <1> _b80:
  2844                              <1> 	;-----	INITIALIZE THE PRINTER PORT
  2845                              <1> B80:
  2846 00005977 50                  <1> 	push	eax		; SAVE (AL)
  2847 00005978 66BA7A03            <1> 	mov	dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT
  2848 0000597C B008                <1> 	mov	al, 8		; SET INIT LINE LOW
  2849 0000597E EE                  <1> 	out	dx, al
  2850                              <1> 	;mov	eax, 1000*4	; ADJUST FOR INITIALIZATION DELAY LOOP
  2851 0000597F B989080000          <1> 	mov	ecx, WAIT_PRN_INIT ; (65536 micro seconds)
  2852                              <1> B90:				; INIT_LOOP
  2853                              <1> 	;dec	eax		; LOOP FOR RESET TO TAKE
  2854                              <1> 	;jnz	short B90	; INIT_LOOP
  2855 00005984 E807000000          <1> 	call	WAIT_REFRESH	; (wait for 30 micro seconds)
  2856 00005989 E2F9                <1> 	loop	B90	
  2857 0000598B B00C                <1> 	mov	al, 0Ch		; NO INTERRUPTS, NON AUTO LF, INIT HIGH
  2858 0000598D EE                  <1> 	out	dx, al
  2859 0000598E EBA4                <1> 	jmp	short B60	; EXIT THROUGH STATUS ROUTINE
  2860                              <1> 
  2861                              <1> 
  2862                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2863                              <1> ; -------------------------------------------------------------------
  2864                              <1> ;
  2865                              <1> ;;Wait while printer initializes should be 65,536 microseconds.
  2866                              <1> ;;65536/30 = 2185
  2867                              <1> ;			PUBLIC	WAIT_PRN_INIT_LO
  2868                              <1> ;WAIT_PRN_INIT_LO	DW	2185
  2869                              <1> ;			PUBLIC	WAIT_PRN_INIT_HI
  2870                              <1> ;WAIT_PRN_INIT_HI	DW	0
  2871                              <1> ;
  2872                              <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022
  2873                              <1> ;
  2874                              <1> ;;Wait for printer not busy should be 1,080,000 microseconds.
  2875                              <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us.
  2876                              <1> ;;1,080,000 / 30 = 36,000
  2877                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_LO
  2878                              <1> ;WAIT_PRN_NBUSY_LO	DW	36000
  2879                              <1> ;			PUBLIC	WAIT_PRN_NBUSY_HI
  2880                              <1> ;WAIT_PRN_NBUSY_HI	DB	0
  2881                              <1> ;
  2882                              <1> ;WAIT_PRN_NBUSY	equ 36000 ; 12/06/2022
  2883                              <1> 
  2884                              <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999)
  2885                              <1> ; ------------------------------------------
  2886                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2887                              <1> ;   	INPUT: BX:CX = number of refresh periods to wait
  2888                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2889                              <1> ;	OUTPUT: BX:CX destroyed.
  2890                              <1> ;
  2891                              <1> ;	SAVES:	AX (except when NO STACK)
  2892                              <1> ;
  2893                              <1> ;	NOTES:	This routine can be (and is) used with no stack. When
  2894                              <1> ;		used this way, AX is assumed to be destroyed.
  2895                              <1> 
  2896                              <1> WAIT_REFRESH:
  2897                              <1> 	; 13/06/2022
  2898                              <1> 	; Modified for Retro UNIX 386 v1.1
  2899                              <1> 	
  2900                              <1> 	; (wait for 30 micro seconds)
  2901                              <1> 
  2902                              <1> 	SYS1	equ 61h ; PORT_B
  2903                              <1> 
  2904                              <1> WR_SHORT:
  2905 00005990 50                  <1> 	push	eax
  2906                              <1> WR_STAT_0:
  2907 00005991 E461                <1> 	in	al, SYS1	; wait for high to low
  2908 00005993 A810                <1> 	test	al, 10h		; transition on memory
  2909 00005995 75FA                <1> 	jnz	short WR_STAT_0 
  2910                              <1> WR_STAT_1:
  2911 00005997 E461                <1> 	in	al, SYS1
  2912 00005999 A810                <1> 	test	al, 10h
  2913 0000599B 74FA                <1> 	jz	short WR_STAT_1
  2914 0000599D 58                  <1> 	pop	eax
  2915 0000599E C3                  <1> 	retn
  2122                                  
  2123                                  ; 07/03/2015
  2124                                  ; Temporary Code
  2125                                  display_disks:
  2126 0000599F 803D[5C5D0000]00        	cmp 	byte [fd0_type], 0
  2127 000059A6 7605                    	jna 	short ddsks1
  2128 000059A8 E87D000000              	call	pdskm
  2129                                  ddsks1:
  2130 000059AD 803D[5D5D0000]00        	cmp	byte [fd1_type], 0
  2131 000059B4 760C                    	jna	short ddsks2
  2132 000059B6 C605[235F0000]31        	mov	byte [dskx], '1'
  2133 000059BD E868000000              	call	pdskm
  2134                                  ddsks2:
  2135 000059C2 803D[5E5D0000]00        	cmp	byte [hd0_type], 0
  2136 000059C9 7654                    	jna	short ddsk6
  2137 000059CB 66C705[215F0000]68-     	mov	word [dsktype], 'hd'
  2137 000059D3 64                 
  2138 000059D4 C605[235F0000]30        	mov	byte [dskx], '0'
  2139 000059DB E84A000000              	call	pdskm
  2140                                  ddsks3:
  2141 000059E0 803D[5F5D0000]00        	cmp	byte [hd1_type], 0
  2142 000059E7 7636                    	jna	short ddsk6
  2143 000059E9 C605[235F0000]31        	mov	byte [dskx], '1'
  2144 000059F0 E835000000              	call	pdskm
  2145                                  ddsks4:
  2146 000059F5 803D[605D0000]00        	cmp	byte [hd2_type], 0
  2147 000059FC 7621                    	jna	short ddsk6
  2148 000059FE C605[235F0000]32        	mov	byte [dskx], '2'
  2149 00005A05 E820000000              	call	pdskm
  2150                                  ddsks5:
  2151 00005A0A 803D[615D0000]00        	cmp	byte [hd3_type], 0
  2152 00005A11 760C                    	jna	short ddsk6
  2153 00005A13 C605[235F0000]33        	mov	byte [dskx], '3'
  2154 00005A1A E80B000000              	call	pdskm
  2155                                  ddsk6:
  2156 00005A1F BE[325F0000]            	mov	esi, nextline
  2157 00005A24 E806000000              	call	pdskml
  2158                                  pdskm_ok:
  2159 00005A29 C3                      	retn
  2160                                  pdskm:
  2161 00005A2A BE[1F5F0000]            	mov	esi, dsk_ready_msg
  2162                                  pdskml:	
  2163 00005A2F AC                      	lodsb
  2164 00005A30 08C0                    	or	al, al
  2165 00005A32 74F5                    	jz	short pdskm_ok
  2166 00005A34 56                      	push	esi
  2167 00005A35 31DB                    	xor	ebx, ebx ; 0
  2168                                  			; Video page 0 (bl=0)
  2169 00005A37 B407                    	mov	ah, 07h ; Black background, 
  2170                                  			; light gray forecolor
  2171 00005A39 E864B9FFFF              	call	write_tty
  2172 00005A3E 5E                      	pop	esi
  2173 00005A3F EBEE                    	jmp	short pdskml
  2174                                  
  2175 00005A41 90<rep Fh>              align 16
  2176                                  
  2177                                  gdt:	; Global Descriptor Table
  2178                                  	; (30/07/2015, conforming cs)
  2179                                  	; (26/03/2015)
  2180                                  	; (24/03/2015, tss)
  2181                                  	; (19/03/2015)
  2182                                  	; (29/12/2013)
  2183                                  	;
  2184 00005A50 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2185                                  	; 18/08/2014
  2186                                  			; 8h kernel code segment, base = 00000000h		
  2187 00005A58 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2188                                  			; 10h kernel data segment, base = 00000000h	
  2189 00005A60 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2190                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2191 00005A68 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2192                                  			; 23h user data segment, base address = 400000h ; CORE
  2193 00005A70 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2194                                  			; Task State Segment
  2195 00005A78 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2196                                  			       ;  no IO permission in ring 3)
  2197                                  gdt_tss0:
  2198 00005A7A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2199                                  gdt_tss1:
  2200 00005A7C 00                      	db 0  ; TSS base address, bits 16-23 
  2201                                  	      		; 49h	
  2202 00005A7D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2203 00005A7E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2204                                  gdt_tss2:
  2205 00005A7F 00                      	db 0  ; TSS base address, bits 24-31 
  2206                                  
  2207                                  gdt_end:
  2208                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2209                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2210                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2211                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2212                                  
  2213                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2214                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2215                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2216                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2217                                  		; W= Writeable, A= Accessed
  2218                                  	
  2219                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2220                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2221                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2222                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2223                                  
  2224                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2225                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2226                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2227                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2228                                  	
  2229                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2230                                  
  2231                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2232                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2233                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2234                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2235                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2236                                  		; AVL= Available to programmers	
  2237                                  
  2238                                  gdtd:
  2239 00005A80 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2240 00005A82 [505A0000]                      dd gdt			; Address of the GDT
  2241                                  
  2242                                  	; 20/08/2014
  2243                                  idtd:
  2244 00005A86 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2245 00005A88 [D05F0000]                      dd idt			; Address of the IDT
  2246                                  
  2247                                  Align 4
  2248                                  
  2249                                  	; 21/08/2014
  2250                                  ilist:
  2251                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2252                                  	;
  2253                                  	; Exception list
  2254                                  	; 25/08/2014	
  2255 00005A8C [05080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2256 00005A90 [0C080000]              	dd	exc1	
  2257 00005A94 [13080000]              	dd 	exc2	
  2258 00005A98 [1A080000]              	dd	exc3	
  2259 00005A9C [1E080000]              	dd	exc4	
  2260 00005AA0 [22080000]              	dd	exc5	
  2261 00005AA4 [26080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2262 00005AA8 [2A080000]              	dd	exc7	
  2263 00005AAC [2E080000]              	dd	exc8	
  2264 00005AB0 [32080000]              	dd	exc9	
  2265 00005AB4 [36080000]              	dd 	exc10	
  2266 00005AB8 [3A080000]              	dd	exc11
  2267 00005ABC [3E080000]              	dd	exc12
  2268 00005AC0 [42080000]              	dd	exc13	; 0Dh, General Protection Fault
  2269 00005AC4 [46080000]              	dd 	exc14	; 0Eh, Page Fault
  2270 00005AC8 [4A080000]              	dd	exc15
  2271 00005ACC [4E080000]              	dd	exc16
  2272 00005AD0 [52080000]              	dd	exc17
  2273 00005AD4 [56080000]              	dd 	exc18
  2274 00005AD8 [5A080000]              	dd	exc19
  2275 00005ADC [5E080000]              	dd 	exc20
  2276 00005AE0 [62080000]              	dd	exc21
  2277 00005AE4 [66080000]              	dd	exc22
  2278 00005AE8 [6A080000]              	dd	exc23
  2279 00005AEC [6E080000]              	dd 	exc24
  2280 00005AF0 [72080000]              	dd	exc25
  2281 00005AF4 [76080000]              	dd	exc26
  2282 00005AF8 [7A080000]              	dd	exc27
  2283 00005AFC [7E080000]              	dd 	exc28
  2284 00005B00 [82080000]              	dd	exc29
  2285 00005B04 [86080000]              	dd 	exc30
  2286 00005B08 [8A080000]              	dd	exc31
  2287                                  	; Interrupt list
  2288 00005B0C [40060000]              	dd	timer_int	; INT 20h
  2289                                  		;dd	irq0	
  2290 00005B10 [440B0000]              	dd	keyb_int	; 27/08/2014
  2291                                  		;dd	irq1
  2292 00005B14 [5F070000]              	dd	irq2
  2293                                  		; COM2 int
  2294 00005B18 [63070000]              	dd	irq3
  2295                                  		; COM1 int
  2296 00005B1C [6E070000]              	dd	irq4
  2297 00005B20 [79070000]              	dd	irq5
  2298                                  ;DISKETTE_INT: ;06/02/2015
  2299 00005B24 [B61F0000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2300                                  		;dd	irq6
  2301                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2302                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2303 00005B28 [F50A0000]              	dd	default_irq7	; 25/02/2015
  2304                                  		;dd	irq7
  2305                                  ; Real Time Clock Interrupt
  2306 00005B2C [93090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2307                                  		;dd	irq8	; INT 28h
  2308 00005B30 [89070000]              	dd	irq9
  2309 00005B34 [8D070000]              	dd	irq10
  2310 00005B38 [91070000]              	dd	irq11
  2311 00005B3C [95070000]              	dd	irq12
  2312 00005B40 [99070000]              	dd	irq13
  2313                                  ;HDISK_INT1:  ;06/02/2015 	
  2314 00005B44 [80240000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2315                                  		;dd	irq14
  2316                                  ;HDISK_INT2:  ;06/02/2015
  2317 00005B48 [A3240000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2318                                  		;dd	irq15	; INT 2Fh
  2319                                  		; 14/08/2015
  2320 00005B4C [D9300000]              	dd	sysent		; INT 30h (system calls)
  2321                                  	
  2322                                  	;dd	ignore_int
  2323 00005B50 00000000                	dd	0
  2324                                  
  2325                                  ;;;
  2326                                  ;;; 11/03/2015
  2327                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2328                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KYBDATA.INC
  2329                              <1> ; Last Modification: 13/06/2022
  2330                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2331                              <1> ;
  2332                              <1> ; ///////// KEYBOARD DATA ///////////////
  2333                              <1> 
  2334                              <1> ; 11/03/2015
  2335                              <1> ; 05/12/2014
  2336                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2337                              <1> ; 03/06/86  KEYBOARD BIOS
  2338                              <1> 
  2339                              <1> ;---------------------------------------------------------------------------------
  2340                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2341                              <1> ;---------------------------------------------------------------------------------
  2342                              <1> 
  2343                              <1> ;-----	TABLES FOR ALT CASE ------------
  2344                              <1> ;-----	ALT-INPUT-TABLE 
  2345 00005B54 524F50514B          <1> K30:	db	82,79,80,81,75
  2346 00005B59 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2347                              <1> ;-----	SUPER-SHIFT-TABLE 
  2348 00005B5E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2349 00005B64 161718191E1F        <1> 	db	22,23,24,25,30,31
  2350 00005B6A 202122232425        <1> 	db	32,33,34,35,36,37
  2351 00005B70 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2352 00005B76 3132                <1> 	db	49,50
  2353                              <1> 
  2354                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2355                              <1> ;-----	KEY_TABLE 
  2356 00005B78 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2357 00005B79 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2358 00005B7E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2359                              <1> _K6L    equ     $-_K6
  2360                              <1> 
  2361                              <1> ;-----	MASK_TABLE
  2362 00005B80 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2363 00005B81 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2364 00005B86 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2365                              <1> 
  2366                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2367 00005B88 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2368 00005B8E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2369                              <1> 	;db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2370 00005B94 FF7F94111705        <1> 	db	-1,127,148,17,23,5 ; 13/06/2022
  2371 00005B9A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2372 00005BA0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2373 00005BA6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2374 00005BAC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2375 00005BB2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2376 00005BB8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2377 00005BBE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2378                              <1> 	;				;----- FUNCTIONS ------		
  2379 00005BC2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2380 00005BC8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2381 00005BCE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2382 00005BD4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2383 00005BDA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2384                              <1> 
  2385                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2386 00005BE0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2386 00005BE9 39302D3D0809        <1>
  2387 00005BEF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2387 00005BF8 705B5D0DFF61736466- <1>
  2387 00005C01 67686A6B6C3B27      <1>
  2388 00005C08 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2388 00005C11 6D2C2E2FFF2AFF20FF  <1>
  2389                              <1> ;-----	LC TABLE SCAN
  2390 00005C1A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2391 00005C1F 4041424344          <1> 	db	64,65,66,67,68
  2392 00005C24 FFFF                <1> 	db	-1,-1			; NL, SL
  2393                              <1> 
  2394                              <1> ;-----	KEYPAD TABLE
  2395 00005C26 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2396 00005C2C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2397 00005C33 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2398                              <1> 
  2399                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2400 00005C38 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2400 00005C41 28295F2B0800        <1>
  2401 00005C47 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2401 00005C50 507B7D0DFF41534446- <1>
  2401 00005C59 47484A4B4C3A22      <1>
  2402 00005C60 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2402 00005C69 4D3C3E3FFF2AFF20FF  <1>
  2403                              <1> ;-----	UC TABLE SCAN
  2404 00005C72 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2405 00005C77 595A5B5C5D          <1> 	db	89,90,91,92,93
  2406 00005C7C FFFF                <1> 	db	-1,-1			; NL, SL
  2407                              <1> 
  2408                              <1> ;-----	NUM STATE TABLE
  2409 00005C7E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2409 00005C87 3233302E            <1>
  2410                              <1> 	;
  2411 00005C8B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2412                              <1> 
  2413                              <1> Align	4
  2414                              <1> ;----------------------------------------
  2415                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2416                              <1> ;----------------------------------------
  2417 00005C90 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2418 00005C91 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2419                              <1> 				; (29h default setting for video mode 3)
  2420                              <1> 				; Mode Select register Bits
  2421                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2422                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2423                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2424                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2425                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2426                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2427                              <1> 				;   BIT 6, 7 - Not Used
  2428                              <1> 
  2429                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2430                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2431                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2432                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2433                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2434                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2435                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2436                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2437                              <1> ; Mode & 37h = Video signal OFF
  2438                              <1> 			
  2439                              <1> 
  2440                              <1> ; 26/08/2014
  2441                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2442                              <1> ; Derived from IBM "pc-at" 
  2443                              <1> ; rombios source code (06/10/1985)
  2444                              <1> ; 'dseg.inc'
  2445                              <1> 
  2446                              <1> ;---------------------------------------;
  2447                              <1> ;	SYSTEM DATA AREA		;
  2448                              <1> ;----------------------------------------
  2449 00005C92 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2450                              <1> 
  2451                              <1> ;----------------------------------------
  2452                              <1> ;	KEYBOARD DATA AREAS		;
  2453                              <1> ;----------------------------------------
  2454                              <1> 
  2455 00005C93 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2456 00005C94 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2457 00005C95 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2458 00005C96 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2459 00005C97 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2460 00005C98 [A85C0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2461 00005C9C [C85C0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2462 00005CA0 [A85C0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2463 00005CA4 [A85C0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2464                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2465 00005CA8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2466                              <1> 
  2467                              <1> ; /// End Of KEYBOARD DATA ///
  2328                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2329                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2330                              <1> ; Last Modification: 11/03/2015
  2331                              <1> ;		    (Data section for 'VIDEO.INC')	
  2332                              <1> ;
  2333                              <1> ; ///////// VIDEO DATA ///////////////
  2334                              <1> 
  2335                              <1> video_params:
  2336                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2337                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2338                              <1> 	; VIDEO MODE 3
  2339 00005CC8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2340 00005CCF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2341 00005CD4 00000000            <1> 	db	0,0,0,0
  2342                              <1> 
  2343                              <1> ; /// End Of VIDEO DATA ///
  2329                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2330                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKDATA.INC
  2331                              <1> ; Last Modification: 11/07/2022
  2332                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2333                              <1> ;
  2334                              <1> ; *****************************************************************************
  2335                              <1> 
  2336                              <1> ;----------------------------------------
  2337                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2338                              <1> ;	REFERENCED BY POST & BIOS	:
  2339                              <1> ;----------------------------------------
  2340                              <1> 
  2341 00005CD8 [3B5D0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2342                              <1> 
  2343                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2344                              <1> ;----------------------------------------------------------------
  2345                              <1> ; DISK_BASE							:
  2346                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2347                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2348                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2349                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2350                              <1> ;----------------------------------------------------------------
  2351                              <1> 
  2352                              <1> ;DISK_BASE:	
  2353                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2354                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2355                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2356                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2357                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2358                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2359                              <1> ;	DB	01BH		; GAP LENGTH
  2360                              <1> ;	DB	0FFH		; DTL
  2361                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2362                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2363                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2364                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2365                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2366                              <1> 
  2367                              <1> ;----------------------------------------
  2368                              <1> ;	ROM BIOS DATA AREAS		:
  2369                              <1> ;----------------------------------------
  2370                              <1> 
  2371                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2372                              <1> 
  2373                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2374                              <1> 
  2375                              <1> ;----------------------------------------
  2376                              <1> ;	DISKETTE DATA AREAS		:
  2377                              <1> ;----------------------------------------
  2378                              <1> 
  2379                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2380                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2381                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2382                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2383                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2384                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2385                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2386                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2387                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2388                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2389                              <1> 
  2390                              <1> ;----------------------------------------
  2391                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2392                              <1> ;----------------------------------------
  2393                              <1> 
  2394                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2395                              <1> 
  2396                              <1> ;----------------------------------------
  2397                              <1> ;	TIMER DATA AREA 		:
  2398                              <1> ;----------------------------------------
  2399                              <1> 
  2400                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2401                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2402                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2403                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2404                              <1> 
  2405                              <1> ;----------------------------------------
  2406                              <1> ;	ADDITIONAL MEDIA DATA		:
  2407                              <1> ;----------------------------------------
  2408                              <1> 
  2409                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2410                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2411                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2412                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2413                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2414                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2415                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2416                              <1> 
  2417                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2418                              <1> 
  2419                              <1> ;--------------------------------------------------------
  2420                              <1> ;	DRIVE TYPE TABLE				:
  2421                              <1> ;--------------------------------------------------------
  2422                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2423                              <1> DR_TYPE:
  2424 00005CDC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2425                              <1>                 ;DW      MD_TBL1
  2426 00005CDD [FA5C0000]          <1> 		dd	MD_TBL1
  2427 00005CE1 82                  <1> 		DB	02+BIT7ON
  2428                              <1> 		;DW      MD_TBL2
  2429 00005CE2 [075D0000]          <1>                 dd      MD_TBL2
  2430 00005CE6 02                  <1> DR_DEFAULT:	DB	02
  2431                              <1>                 ;DW      MD_TBL3
  2432 00005CE7 [145D0000]          <1> 		dd      MD_TBL3
  2433 00005CEB 03                  <1> 		DB	03
  2434                              <1>                 ;DW      MD_TBL4
  2435 00005CEC [215D0000]          <1> 		dd      MD_TBL4
  2436 00005CF0 84                  <1> 		DB	04+BIT7ON
  2437                              <1>                 ;DW      MD_TBL5
  2438 00005CF1 [2E5D0000]          <1> 		dd      MD_TBL5
  2439 00005CF5 04                  <1> 		DB	04
  2440                              <1>                 ;DW      MD_TBL6
  2441 00005CF6 [3B5D0000]          <1> 		dd      MD_TBL6
  2442                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2443                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2444                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2445                              <1> ;--------------------------------------------------------
  2446                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2447                              <1> ;--------------------------------------------------------
  2448                              <1> ;--------------------------------------------------------
  2449                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2450                              <1> ;--------------------------------------------------------
  2451                              <1> MD_TBL1:        
  2452 00005CFA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2453 00005CFB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2454 00005CFC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2455 00005CFD 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2456 00005CFE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2457 00005CFF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2458 00005D00 FF                  <1> 	DB	0FFH		; DTL
  2459 00005D01 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2460 00005D02 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2461 00005D03 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2462 00005D04 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2463 00005D05 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2464 00005D06 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2465                              <1> ;--------------------------------------------------------
  2466                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2467                              <1> ;--------------------------------------------------------
  2468                              <1> MD_TBL2:        
  2469 00005D07 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2470 00005D08 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2471 00005D09 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2472 00005D0A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2473 00005D0B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2474 00005D0C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2475 00005D0D FF                  <1> 	DB	0FFH		; DTL
  2476 00005D0E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2477 00005D0F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2478 00005D10 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2479 00005D11 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2480 00005D12 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2481 00005D13 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2482                              <1> ;--------------------------------------------------------
  2483                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2484                              <1> ;--------------------------------------------------------
  2485                              <1> MD_TBL3:
  2486 00005D14 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2487 00005D15 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2488 00005D16 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2489 00005D17 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2490 00005D18 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2491 00005D19 1B                  <1> 	DB	01BH		; GAP LENGTH
  2492 00005D1A FF                  <1> 	DB	0FFH		; DTL
  2493 00005D1B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2494 00005D1C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2495 00005D1D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2496 00005D1E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2497 00005D1F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2498 00005D20 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2499                              <1> ;--------------------------------------------------------
  2500                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2501                              <1> ;--------------------------------------------------------
  2502                              <1> MD_TBL4:
  2503 00005D21 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2504 00005D22 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2505 00005D23 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2506 00005D24 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2507 00005D25 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2508 00005D26 2A                  <1> 	DB	02AH		; GAP LENGTH
  2509 00005D27 FF                  <1> 	DB	0FFH		; DTL
  2510 00005D28 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2511 00005D29 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2512 00005D2A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2513 00005D2B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2514 00005D2C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2515 00005D2D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2516                              <1> ;--------------------------------------------------------
  2517                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2518                              <1> ;--------------------------------------------------------
  2519                              <1> MD_TBL5:
  2520 00005D2E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2521 00005D2F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2522 00005D30 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2523 00005D31 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2524 00005D32 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2525 00005D33 2A                  <1> 	DB	02AH		; GAP LENGTH
  2526 00005D34 FF                  <1> 	DB	0FFH		; DTL
  2527 00005D35 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2528 00005D36 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2529 00005D37 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2530 00005D38 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2531 00005D39 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2532 00005D3A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2533                              <1> ;--------------------------------------------------------
  2534                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2535                              <1> ;--------------------------------------------------------
  2536                              <1> MD_TBL6:
  2537 00005D3B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2538 00005D3C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2539 00005D3D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2540 00005D3E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2541 00005D3F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2542 00005D40 1B                  <1> 	DB	01BH		; GAP LENGTH
  2543 00005D41 FF                  <1> 	DB	0FFH		; DTL
  2544 00005D42 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2545 00005D43 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2546 00005D44 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2547 00005D45 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2548 00005D46 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2549 00005D47 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2550                              <1> 
  2551                              <1> 
  2552                              <1> ; << diskette.inc >>
  2553                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2554                              <1> ;
  2555                              <1> ;----------------------------------------
  2556                              <1> ;	ROM BIOS DATA AREAS		:
  2557                              <1> ;----------------------------------------
  2558                              <1> 
  2559                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2560                              <1> 
  2561                              <1> ;----------------------------------------
  2562                              <1> ;	FIXED DISK DATA AREAS		:
  2563                              <1> ;----------------------------------------
  2564                              <1> 
  2565                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2566                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2567                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2568                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2569                              <1> 
  2570                              <1> ;----------------------------------------
  2571                              <1> ;	ADDITIONAL MEDIA DATA		:
  2572                              <1> ;----------------------------------------
  2573                              <1> 
  2574                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2575                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2576                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2577                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2578                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2579                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2580                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2581                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2582                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2583                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2584                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2585                              <1> 
  2586                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2587                              <1> ;
  2588                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2589                              <1> 
  2590                              <1> ERR_TBL:
  2591 00005D48 E0                  <1> 	db	NO_ERR
  2592 00005D49 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2593 00005D4D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2594                              <1> 
  2595                              <1> ; 11/07/2022
  2596                              <1> ; 17/12/2014 (mov ax, [cfd])
  2597                              <1> ; 11/12/2014
  2598                              <1> ;cfd:		db 0			; current floppy drive (for GET_PARM)
  2599                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2600                              <1> ;pfd:		db 1			; previous floppy drive (for GET_PARM)
  2601                              <1> 					; (initial value of 'pfd 
  2602                              <1> 					; must be different then 'cfd' value
  2603                              <1> 					; to force updating/initializing
  2604                              <1> 					; current drive parameters) 
  2605                              <1> 
  2606                              <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2607 00005D51 FF                  <1> pfd:		db 0FFh
  2608                              <1> 
  2609                              <1> align 2
  2610                              <1> 
  2611 00005D52 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2612                              <1> 			      ; (170h)
  2613 00005D54 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2614                              <1> 
  2615                              <1> ; 05/01/2015 
  2616 00005D56 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2617                              <1> 
  2618                              <1> ; *****************************************************************************
  2330                                  ;;;
  2331                                  
  2332 00005D57 90                      Align 2
  2333                                  
  2334                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2335 00005D58 00                      boot_drv:    db 0 ; boot drive number (physical)
  2336                                  ; 24/11/2014
  2337 00005D59 00                      drv:	     db 0 
  2338 00005D5A 00                      last_drv:    db 0 ; last hdd
  2339 00005D5B 00                      hdc:         db 0  ; number of hard disk drives
  2340                                  		     ; (present/detected)
  2341                                  ;
  2342                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2343                                  ; Physical drive type & flags
  2344 00005D5C 00                      fd0_type:    db 0  ; floppy drive type
  2345 00005D5D 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2346                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2347                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2348                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2349                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2350 00005D5E 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2351 00005D5F 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2352 00005D60 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2353 00005D61 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2354                                  		     ; bit 0 - Fixed disk access subset supported
  2355                                  		     ; bit 1 - Drive locking and ejecting
  2356                                  		     ; bit 2 - Enhanced disk drive support
  2357                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2358                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2359                                  		     ; will interpret it as 'LBA ready'!)		
  2360                                  
  2361                                  ; 12/07/2022
  2362                                  ; (drv.cylinders, drv.spt, drv.spt will not be used now on)
  2363                                  ; ('diskio.inc')
  2364                                  ; ((spt and heads and cylinder counts will be taken from DPT))
  2365                                  
  2366                                  ; 11/03/2015 - 10/07/2015
  2367                                  ;drv.cylinders: dw 0,0,0,0,0,0,0
  2368                                  ;drv.heads:     dw 0,0,0,0,0,0,0
  2369                                  ;drv.spt:       dw 0,0,0,0,0,0,0
  2370                                  ; 12/07/2022 - 11/03/2015
  2371 00005D62 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2371 00005D6B 000000000000000000-
  2371 00005D74 000000000000000000-
  2371 00005D7D 00                 
  2372 00005D7E 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2373 00005D85 00000000000000          drv.error:     db 0,0,0,0,0,0,0
  2374                                  ;
  2375                                  
  2376                                  ; 27/08/2014
  2377                                  scr_row:
  2378 00005D8C E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2379                                  scr_col:
  2380 00005D90 00000000                	dd 0
  2381                                  
  2382                                  ;; 14/08/2015
  2383                                  ;;msgPM:
  2384                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2385                                  msgKVER:
  2386                                  	;;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0
  2387                                  	;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.3 [02/06/2022]", 0
  2388                                  	;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.4 [14/06/2022]", 0
  2389                                  	;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.5 [12/07/2022]", 0
  2390 00005D94 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.6 [19/07/2022]", 0
  2390 00005D9D 58203338362076312E-
  2390 00005DA6 31202D204B65726E65-
  2390 00005DAF 6C2076302E322E312E-
  2390 00005DB8 36205B31392F30372F-
  2390 00005DC1 323032325D00       
  2391                                  
  2392 00005DC7 90                      Align 2
  2393                                  
  2394                                  ; 20/08/2014
  2395                                    ; /* This is the default interrupt "handler" :-) */ 
  2396                                    ; Linux v0.12 (head.s)
  2397                                  int_msg:
  2398 00005DC8 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2398 00005DD1 6E7465727275707420-
  2398 00005DDA 212000             
  2399                                  
  2400 00005DDD 90                      Align 2  
  2401                                  
  2402                                  ; 21/08/2014
  2403                                  timer_msg:
  2404 00005DDE 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2404 00005DE7 542032306829202120-
  2404 00005DF0 54696D657220496E74-
  2404 00005DF9 657272757074203A20 
  2405                                  tcountstr:
  2406 00005E02 303030303020            	db "00000 "
  2407 00005E08 00                      	db 0
  2408                                  
  2409 00005E09 90                      Align 2
  2410                                  	; 21/08/2014
  2411                                  exc_msg:
  2412 00005E0A 435055206578636570-     	db "CPU exception ! "
  2412 00005E13 74696F6E202120     
  2413                                  excnstr: 		; 25/08/2014
  2414 00005E1A 3F3F68202045495020-     	db "??h", "  EIP : "
  2414 00005E23 3A20               
  2415                                  EIPstr: ; 29/08/2014
  2416 00005E25 00<rep Ch>              	times 12 db 0
  2417                                  rtc_msg:
  2418 00005E31 5265616C2054696D65-     	db "Real Time Clock - "
  2418 00005E3A 20436C6F636B202D20 
  2419                                  datestr:
  2420 00005E43 30302F30302F303030-     	db "00/00/0000"
  2420 00005E4C 30                 
  2421 00005E4D 20                      	db " "
  2422                                  daystr:
  2423 00005E4E 44415920                	db "DAY "
  2424                                  timestr:	
  2425 00005E52 30303A30303A3030                db "00:00:00"
  2426 00005E5A 20                      	db " "
  2427 00005E5B 00                      	db 0 
  2428                                  
  2429                                  daytmp:
  2430                                  	; 28/02/2015
  2431 00005E5C 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2431 00005E65 4F4E20545545205745-
  2431 00005E6E 442054485520465249-
  2431 00005E77 2053415420         
  2432                                  
  2433 00005E7C FF                      ptime_seconds: db 0FFh
  2434                                  
  2435                                  	; 23/02/2015
  2436                                  	; 25/08/2014
  2437                                  ;scounter:
  2438                                  ;	db 5
  2439                                  ;	db 19
  2440                                  
  2441                                  ; 02/01/2022
  2442                                  ; 05/11/2014
  2443                                  ;msg_out_of_memory:
  2444                                  ;	db 	07h, 0Dh, 0Ah
  2445                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2446                                  ; 	db	0Dh, 0Ah, 0
  2447                                  	;
  2448                                  setup_error_msg:
  2449 00005E7D 0D0A                    	db 0Dh, 0Ah
  2450 00005E7F 4469736B2053657475-     	db 'Disk Setup Error!' 
  2450 00005E88 70204572726F7221   
  2451 00005E90 0D0A00                  	db 0Dh, 0Ah,0
  2452                                  
  2453                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2454                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2455                                  ;	  db 0 ; upper left row (for scroll)	
  2456                                  
  2457                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2458                                  ;	  db 24 ; lower right row (for scroll)
  2459                                  
  2460                                  
  2461                                  ; 06/11/2014 (Temporary Data)
  2462                                  ; Memory Information message
  2463                                  ; 14/08/2015
  2464                                  msg_memory_info:
  2465 00005E93 07                      	db	07h
  2466 00005E94 0D0A                    	db	0Dh, 0Ah
  2467                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2468 00005E96 546F74616C206D656D-     	db	"Total memory : "
  2468 00005E9F 6F7279203A20       
  2469                                  mem_total_b_str: ; 10 digits
  2470 00005EA5 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2470 00005EAE 302062797465730D0A 
  2471 00005EB7 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2471 00005EC0 202020202020202020 
  2472                                  mem_total_p_str: ; 7 digits
  2473 00005EC9 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2473 00005ED2 616765730D0A       
  2474 00005ED8 0D0A                    	db 	0Dh, 0Ah
  2475 00005EDA 46726565206D656D6F-     	db	"Free memory  : "
  2475 00005EE3 727920203A20       
  2476                                  free_mem_b_str:  ; 10 digits
  2477 00005EE9 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2477 00005EF2 3F2062797465730D0A 
  2478 00005EFB 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2478 00005F04 202020202020202020 
  2479                                  free_mem_p_str:  ; 7 digits
  2480 00005F0D 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2480 00005F16 616765730D0A       
  2481 00005F1C 0D0A00                  	db	0Dh, 0Ah, 0
  2482                                  
  2483                                  dsk_ready_msg:
  2484 00005F1F 0D0A                    	db 	0Dh, 0Ah
  2485                                  dsktype:
  2486 00005F21 6664                    	db	'fd'
  2487                                  dskx:
  2488 00005F23 30                      	db	'0'
  2489 00005F24 20                      	db	20h
  2490 00005F25 697320524541445920-     	db 	'is READY ...'
  2490 00005F2E 2E2E2E             
  2491 00005F31 00                      	db 	0
  2492                                  nextline:
  2493 00005F32 0D0A00                  	db 	0Dh, 0Ah, 0
  2494                                  
  2495                                  ; KERNEL - SYSINIT Messages
  2496                                  ; 24/08/2015
  2497                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2498                                  ; 14/07/2013
  2499                                  ;kernel_init_err_msg:
  2500                                  ;	db 0Dh, 0Ah
  2501                                  ;	db 07h
  2502                                  ;	db 'Kernel initialization ERROR !'
  2503                                  ;	db 0Dh, 0Ah, 0 
  2504                                  ; 24/08/2015
  2505                                  ;;; (temporary kernel init message has been removed
  2506                                  ;;;  from 'sys_init' code)
  2507                                  ;kernel_init_ok_msg: 
  2508                                  ;	db 0Dh, 0Ah
  2509                                  ;	db 07h
  2510                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2511                                  ;	db 0Dh, 0Ah
  2512                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2513                                  ;	db 0Dh, 0Ah, 0
  2514                                  panic_msg:
  2515 00005F35 0D0A07                  	db 0Dh, 0Ah, 07h
  2516 00005F38 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2516 00005F41 726E656C2050616E69-
  2516 00005F4A 632021             
  2517 00005F4D 0D0A00                  	db 0Dh, 0Ah, 0
  2518                                  etc_init_err_msg:
  2519 00005F50 0D0A                    	db 0Dh, 0Ah
  2520 00005F52 07                      	db 07h
  2521 00005F53 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2521 00005F5C 74632F696E69742021-
  2521 00005F65 3F                 
  2522 00005F66 0D0A00                  	db 0Dh, 0Ah, 0
  2523                                  
  2524                                  ; 10/05/2015
  2525                                  badsys_msg:
  2526 00005F69 0D0A                    	db 0Dh, 0Ah
  2527 00005F6B 07                      	db 07h
  2528 00005F6C 496E76616C69642053-     	db 'Invalid System Call !'
  2528 00005F75 797374656D2043616C-
  2528 00005F7E 6C2021             
  2529 00005F81 0D0A                    	db 0Dh, 0Ah
  2530 00005F83 4541583A20              	db 'EAX: '
  2531                                  bsys_msg_eax:
  2532 00005F88 303030303030303068      	db '00000000h'
  2533 00005F91 0D0A                    	db 0Dh, 0Ah
  2534 00005F93 4549503A20              	db 'EIP: '
  2535                                  bsys_msg_eip:
  2536 00005F98 303030303030303068      	db '00000000h' 
  2537 00005FA1 0D0A00                  	db 0Dh, 0Ah, 0
  2538                                  
  2539                                  BSYS_M_SIZE equ $ - badsys_msg
  2540                                  
  2541                                  
  2542                                  align 2
  2543                                  
  2544                                  ; EPOCH Variables
  2545                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2546                                  ; 09/04/2013 epoch variables
  2547                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2548                                  ;
  2549 00005FA4 B207                    year: 	dw 1970
  2550                                  ;month: dw 1
  2551                                  ;day: 	dw 1
  2552                                  ;hour: 	dw 0
  2553                                  ;minute: dw 0
  2554                                  ;second: dw 0
  2555                                  ; 02/06/2022
  2556 00005FA6 01                      month:	db 1
  2557 00005FA7 01                      day:	db 1
  2558 00005FA8 01                      hour:	db 1
  2559 00005FA9 01                      minute: db 1
  2560 00005FAA 01                      second:	db 1
  2561 00005FAB 01                      	db 1
  2562                                  
  2563                                  DMonth:
  2564 00005FAC 0000                    	dw 0
  2565 00005FAE 1F00                    	dw 31
  2566 00005FB0 3B00                    	dw 59
  2567 00005FB2 5A00                    	dw 90
  2568 00005FB4 7800                    	dw 120
  2569 00005FB6 9700                    	dw 151
  2570 00005FB8 B500                    	dw 181
  2571 00005FBA D400                    	dw 212
  2572 00005FBC F300                    	dw 243
  2573 00005FBE 1101                    	dw 273
  2574 00005FC0 3001                    	dw 304
  2575 00005FC2 4E01                    	dw 334
  2576                                  
  2577                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2578                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2579 00005FC4 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2580                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2581 00005FC6 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2582 00005FC8 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2583                                  		   ;   between 16 MB and 4 GB.
  2584 00005FCA 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2585                                  
  2586                                  ; 02/01/2022
  2587                                  KEND:
  2588                                  
  2589 00005FCC 90<rep 4h>              align 16
  2590                                  
  2591                                  bss_start:
  2592                                  
  2593                                  ABSOLUTE bss_start
  2594                                  
  2595                                  	; 11/03/2015
  2596                                  	; Interrupt Descriptor Table (20/08/2014)
  2597                                  idt:
  2598 00005FD0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2599                                  idt_end:
  2600                                  
  2601                                  ;alignb 4
  2602                                  
  2603                                  task_state_segment:
  2604                                  	; 24/03/2015
  2605 000061D0 ????                    tss.link:   resw 1
  2606 000061D2 ????                    	    resw 1
  2607                                  ; tss offset 4	
  2608 000061D4 ????????                tss.esp0:   resd 1
  2609 000061D8 ????                    tss.ss0:    resw 1
  2610 000061DA ????                    	    resw 1	
  2611 000061DC ????????                tss.esp1:   resd 1
  2612 000061E0 ????                    tss.ss1:    resw 1
  2613 000061E2 ????                    	    resw 1 	
  2614 000061E4 ????????                tss.esp2:   resd 1
  2615 000061E8 ????                    tss.ss2:    resw 1
  2616 000061EA ????                    	    resw 1
  2617                                  ; tss offset 28
  2618 000061EC ????????                tss.CR3:    resd 1
  2619 000061F0 ????????                tss.eip:    resd 1
  2620 000061F4 ????????                tss.eflags: resd 1
  2621                                  ; tss offset 40
  2622 000061F8 ????????                tss.eax:    resd 1		 		
  2623 000061FC ????????                tss.ecx:    resd 1
  2624 00006200 ????????                tss.edx:    resd 1
  2625 00006204 ????????                tss.ebx:    resd 1
  2626 00006208 ????????                tss.esp:    resd 1
  2627 0000620C ????????                tss.ebp:    resd 1
  2628 00006210 ????????                tss.esi:    resd 1
  2629 00006214 ????????                tss.edi:    resd 1
  2630                                  ; tss offset 72
  2631 00006218 ????                    tss.ES:     resw 1
  2632 0000621A ????                    	    resw 1	
  2633 0000621C ????                    tss.CS:	    resw 1
  2634 0000621E ????                    	    resw 1
  2635 00006220 ????                    tss.SS:	    resw 1
  2636 00006222 ????                    	    resw 1
  2637 00006224 ????                    tss.DS:	    resw 1
  2638 00006226 ????                    	    resw 1
  2639 00006228 ????                    tss.FS:	    resw 1
  2640 0000622A ????                    	    resw 1
  2641 0000622C ????                    tss.GS:	    resw 1
  2642 0000622E ????                    	    resw 1		
  2643 00006230 ????                    tss.LDTR:   resw 1
  2644 00006232 ????                    	    resw 1
  2645                                  ; tss offset 100		
  2646 00006234 ????                    	    resw 1		
  2647 00006236 ????                    tss.IOPB:   resw 1
  2648                                  ; tss offset 104 
  2649                                  tss_end:
  2650                                  
  2651 00006238 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2652                                  		  ;   (Physical address = Virtual address)	 	
  2653 0000623C ????????                memory_size: resd 1 ; memory size in pages
  2654 00006240 ????????                free_pages:  resd 1 ; number of free pages		
  2655 00006244 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2656                                  		  ;   first free page search
  2657 00006248 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2658                                  		  ;   next free page search will be
  2659                                  		  ; stopped after it. (end of M.A.T.)
  2660 0000624C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2661                                  		  ; first free page search
  2662                                  		  ;   will be started on it. (for user)
  2663 00006250 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2664                                  
  2665                                  ;;;
  2666                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2667                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2668 00006254 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2669                                  			  ; NOTE: active page only
  2670 00006256 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2671                                  active_page: 
  2672 00006266 ??                      ptty: 	     resb 1 	  ; current tty
  2673                                  ; 01/07/2015
  2674 00006267 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2675                                  ; 26/10/2015
  2676                                  ; 07/09/2014
  2677 00006268 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2678                                  
  2679                                  ; 21/08/2014
  2680 0000627C ????????                tcount:	     resd 1
  2681                                  
  2682                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2683 00006280 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2684                                  
  2685                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2686                                  ; (open mode locks for pseudo TTYs)
  2687                                  ; [ major tty locks (return error in any conflicts) ]
  2688 00006284 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2689                                  
  2690                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2691                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2692 00006298 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2693                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2694                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2695                                  ;; 0 means serial port is not available 
  2696                                  ;;comprm: ; 25/06/2014
  2697 000062A2 ??                      com1p:       resb 1  ;;0E3h
  2698 000062A3 ??                      com2p:       resb 1  ;;0E3h
  2699                                  
  2700                                  ; 17/11/2015
  2701                                  ; request for response (from the terminal)	
  2702 000062A4 ????                    req_resp:     resw 1 			
  2703                                  ; 07/11/2015
  2704 000062A6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2705                                  		    ; (0= COM1, 1= COM2)
  2706                                  ; 09/11/2015
  2707 000062A7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2708                                  ; 07/11/2015
  2709 000062A8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2710 000062AA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2711                                  
  2712                                  ; 23/10/2015
  2713                                  ; SERIAL PORTS - COMMUNICATION MODES
  2714                                  ; (Retro UNIX 386 v1 feature only!)
  2715                                  ; 0 - command mode (default/initial mode)
  2716                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2717                                  ;;; communication modes for futre versions:  
  2718                                  ; // 2 - keyboard mode (ascii+scancode input)
  2719                                  ; // 3 - mouse mode
  2720                                  ; // 4 - device control (output) mode
  2721                                  ; VALID COMMANDS for current version:
  2722                                  ; 	'LOGIN'
  2723                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2724                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2725                                  ;  Login response: db 0FFh, 'login', 0
  2726                                  ;	 ("login request accepted, wait for login prompt") 
  2727                                  ; When a login requests is received and acknowledged (by
  2728                                  ; serial port interrupt handler (communication procedure),
  2729                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2730                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2731                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2732                                  ; 
  2733                                  ; 'sys connect' system call is used to change communication mode
  2734                                  ; except 'LOGIN' command which is used to start terminal mode
  2735                                  ; by using (COM port) terminal.
  2736                                  
  2737                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2738                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2739                                  ;com1mode:    resb 1 ; communication mode for COM1
  2740                                  ;com1com:     resb 1 ; communication command for COM1
  2741                                  ;com2mode:    resb 1 ; communication mode for COM1
  2742                                  ;com2com      resb 1 ; communication command for COM1
  2743                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2744                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2745                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2746                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2747                                  
  2748                                  ; 22/08/2014 (RTC)
  2749                                  ; (Packed BCD)
  2750 000062AC ??                      time_seconds: resb 1
  2751 000062AD ??                      time_minutes: resb 1
  2752 000062AE ??                      time_hours:   resb 1
  2753 000062AF ??                      date_wday:    resb 1
  2754 000062B0 ??                      date_day:     resb 1
  2755 000062B1 ??                      date_month:   resb 1			
  2756 000062B2 ??                      date_year:    resb 1
  2757 000062B3 ??                      date_century: resb 1
  2758                                  
  2759                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2760                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKBSS.INC
  2761                              <1> ; Last Modification: 10/07/2022
  2762                              <1> ;	(Uninitialized Disk Parameters Data section for 'DISKIO.INC') 
  2763                              <1> ;
  2764                              <1> ; *****************************************************************************
  2765                              <1> 
  2766                              <1> alignb 2
  2767                              <1> 
  2768                              <1> ;----------------------------------------
  2769                              <1> ;	TIMER DATA AREA 		:
  2770                              <1> ;----------------------------------------
  2771                              <1> 
  2772                              <1> TIMER_LH:	; 16/02/205
  2773 000062B4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2774 000062B6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2775 000062B8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2776                              <1> 
  2777                              <1> ;----------------------------------------
  2778                              <1> ;	DISKETTE DATA AREAS		:
  2779                              <1> ;----------------------------------------
  2780                              <1> 
  2781 000062B9 ??                  <1> SEEK_STATUS:	resb	1
  2782 000062BA ??                  <1> MOTOR_STATUS:	resb	1
  2783 000062BB ??                  <1> MOTOR_COUNT:	resb	1
  2784 000062BC ??                  <1> DSKETTE_STATUS:	resb	1
  2785 000062BD ??????????????      <1> NEC_STATUS:	resb	7
  2786                              <1> 
  2787                              <1> ;----------------------------------------
  2788                              <1> ;	ADDITIONAL MEDIA DATA		:
  2789                              <1> ;----------------------------------------
  2790                              <1> 
  2791 000062C4 ??                  <1> LASTRATE:	resb 	1
  2792 000062C5 ??                  <1> HF_STATUS:	resb 	1
  2793                              <1> ;HF_ERROR:	resb 	1  ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)	
  2794 000062C6 ??                  <1> HF_INT_FLAG:	resb	1
  2795                              <1> ;HF_CNTRL:	resb 	1  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2796                              <1> ;DSK_STATE:	resb 	4
  2797 000062C7 ????                <1> DSK_STATE:	resb 	2  ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5)
  2798 000062C9 ????                <1> DSK_TRK:	resb 	2
  2799                              <1> 
  2800                              <1> ;----------------------------------------
  2801                              <1> ;	FIXED DISK DATA AREAS		:
  2802                              <1> ;----------------------------------------
  2803                              <1> 
  2804 000062CB ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2805 000062CC ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2806 000062CD ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2807                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2808                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2809                              <1> ;port2_off	resb	1		; Hard disk controller 2 - port offset
  2810                              <1> 
  2811 000062CE ????                <1> alignb 4
  2812                              <1> 
  2813                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2814                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2815                              <1> HF_TBL_VEC: ; 22/12/2014	
  2816 000062D0 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2817 000062D4 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2818 000062D8 ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2819 000062DC ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2820                              <1> 
  2821                              <1> ; 03/01/2015
  2822 000062E0 ??                  <1> LBAMode:     	resb	1
  2823                              <1> 
  2824                              <1> ; *****************************************************************************
  2760                                  
  2761                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2762                                  
  2763                                  ;alignb 2
  2764                                  
  2765                                  ; 02/01/2022
  2766                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2767                                  
  2768                                  ; 24/12/2021
  2769                                  ; (memory page swap parameters are disabled as temporary)
  2770                                  ;
  2771                                  ;; Memory (swap) Data (11/03/2015)
  2772                                  ; 09/03/2015
  2773                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2774                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2775                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2776                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2777                                  ;swpd_next:  resd 1 ; next free page block
  2778                                  ;swpd_last:  resd 1 ; last swap page block	
  2779                                  	
  2780 000062E1 ??????                  alignb 4
  2781                                  
  2782                                  ; 10/07/2015
  2783                                  ; 28/08/2014
  2784 000062E4 ????????                error_code:	resd 1
  2785                                  ; 29/08/2014
  2786 000062E8 ????????                FaultOffset: 	resd 1
  2787                                  ; 21/09/2015
  2788 000062EC ????????                PF_Count:	resd 1	; total page fault count
  2789                                  		       	; (for debugging - page fault analyze)
  2790                                  		 	; 'page _fault_handler' (memory.inc)
  2791                                  			; 'sysgeterr' (u9.s)
  2792                                  ; 26/02/2022
  2793 000062F0 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2794                                  			;  for a system call in next retro unix 386 version)
  2795                                  			; -2 ticks per second-
  2796                                  ;; 21/08/2015
  2797                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2798                                  
  2799                                  ; 02/01/2022
  2800                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2801                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYSX.INC (ux.s)
  2802                              <1> ; Last Modification: 15/07/2022
  2803                              <1> ; ----------------------------------------------------------------------------
  2804                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2805                              <1> ; (Modified from 
  2806                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2807                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2808                              <1> ; ----------------------------------------------------------------------------
  2809                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2810                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2811                              <1> ; <Bell Laboratories (17/3/1972)>
  2812                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2813                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2814                              <1> ; ****************************************************************************
  2815                              <1> ; 04/12/2015
  2816                              <1> 
  2817                              <1> alignb 2
  2818                              <1> 
  2819                              <1> inode:
  2820                              <1> 	; 11/03/2013. 
  2821                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2822                              <1> 	;i.
  2823                              <1> 
  2824 000062F4 ????                <1> 	i.flgs:	 resw 1
  2825 000062F6 ??                  <1> 	i.nlks:	 resb 1
  2826 000062F7 ??                  <1> 	i.uid:	 resb 1
  2827 000062F8 ????                <1>         i.size:  resw 1 ; size
  2828 000062FA <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2829 0000630A ????????            <1> 	i.ctim:	 resd 1
  2830 0000630E ????????            <1> 	i.mtim:	 resd 1
  2831 00006312 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2832                              <1> 
  2833                              <1> I_SIZE	equ $ - inode 
  2834                              <1> 
  2835                              <1> process:
  2836                              <1> 	; 26/02/2022
  2837                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2838                              <1> 	; 06/05/2015
  2839                              <1> 	; 11/03/2013 - 05/02/2014
  2840                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2841                              <1> 	;p.
  2842                              <1> 	
  2843 00006314 <res 20h>           <1>         p.pid:   resw nproc
  2844 00006334 <res 20h>           <1>         p.ppid:  resw nproc
  2845                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2846 00006354 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2847                              <1> 	; 26/02/2022 (p.waitc is not used)
  2848                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2849 00006364 <res 10h>           <1> 	p.link:	 resb nproc
  2850 00006374 <res 10h>           <1> 	p.stat:	 resb nproc
  2851                              <1> 
  2852                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2853 00006384 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2854                              <1> 			    ; 'user' structure	
  2855                              <1> 
  2856                              <1> P_SIZE	equ $ - process
  2857                              <1> 
  2858                              <1> ; fsp table (original UNIX v1)
  2859                              <1> ;
  2860                              <1> ;Entry
  2861                              <1> ;          15                                      0
  2862                              <1> ;  1     |---|---------------------------------------|
  2863                              <1> ;        |r/w|       i-number of open file           |
  2864                              <1> ;        |---|---------------------------------------| 
  2865                              <1> ;        |               device number               |
  2866                              <1> ;        |-------------------------------------------|
  2867                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2868                              <1> ;        |-------------------------------------------| 
  2869                              <1> ;        |  flag that says    | number of processes  |
  2870                              <1> ;        |   file deleted     | that have file open  |
  2871                              <1> ;        |-------------------------------------------| 
  2872                              <1> ;  2     |                                           |
  2873                              <1> ;        |-------------------------------------------| 
  2874                              <1> ;        |                                           |
  2875                              <1> ;        |-------------------------------------------|
  2876                              <1> ;        |                                           |
  2877                              <1> ;        |-------------------------------------------|
  2878                              <1> ;        |                                           |
  2879                              <1> ;        |-------------------------------------------| 
  2880                              <1> ;  3     |                                           | 
  2881                              <1> ;        |                                           |  
  2882                              <1> ;
  2883                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2884                              <1> 
  2885                              <1> ; 15/04/2015
  2886 000063C4 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2887 000065B8 <res 28h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2888 000065E0 ????                <1> ii:	 resw 1
  2889                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2890                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2891                              <1> ; 11/01/2022
  2892 000065E2 ??                  <1> idev:	 resb 1
  2893 000065E3 ??                  <1> cdev:	 resb 1
  2894                              <1> ; 18/05/2015
  2895                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2896                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2897                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2898                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2899                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2900                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2901                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2902                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2903                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2904                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2905                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2906 000065E4 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2907                              <1> 	        ; as above, for physical drives numbers in following table
  2908 000065E5 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2909                              <1> ; 15/04/2015
  2910                              <1> ;active: resb 1 ; 15/07/2022
  2911                              <1> ;	 resb 1 ; 09/06/2015
  2912 000065E6 ????                <1> mnti:	 resw 1
  2913 000065E8 ????                <1> mntp:	 resw 1 ; 15/05/2022 ; (parent dir inumber of [mnti])
  2914 000065EA ????                <1> mpid:	 resw 1
  2915 000065EC ????                <1> rootdir: resw 1
  2916                              <1> ; 14/02/2014
  2917                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2918                              <1> ;		      Single level run queue
  2919                              <1> ;		      (in order to solve sleep/wakeup lock)
  2920 000065EE ????                <1> runq:	 resw 1
  2921 000065F0 ??                  <1> imod:	 resb 1
  2922 000065F1 ??                  <1> smod:	 resb 1
  2923 000065F2 ??                  <1> mmod:	 resb 1
  2924 000065F3 ??                  <1> sysflg:	 resb 1
  2925                              <1> 
  2926                              <1> alignb 4
  2927                              <1> 
  2928                              <1> user:
  2929                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2930                              <1> 	; 04/12/2015 
  2931                              <1> 	; 18/10/2015
  2932                              <1> 	; 12/10/2015
  2933                              <1> 	; 21/09/2015
  2934                              <1> 	; 24/07/2015
  2935                              <1> 	; 16/06/2015
  2936                              <1> 	; 09/06/2015
  2937                              <1> 	; 11/05/2015
  2938                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2939                              <1> 	; 10/10/2013
  2940                              <1> 	; 11/03/2013. 
  2941                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2942                              <1> 	;u.
  2943                              <1> 
  2944 000065F4 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2945 000065F8 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2946 000065FC ????????            <1> 	u.r0:	  resd 1 ; eax
  2947 00006600 ????                <1> 	u.cdir:	  resw 1
  2948 00006602 <res Ah>            <1> 	u.fp:	  resb 10
  2949 0000660C ????????            <1> 	u.fofp:	  resd 1
  2950 00006610 ????????            <1> 	u.dirp:	  resd 1
  2951 00006614 ????????            <1> 	u.namep:  resd 1
  2952 00006618 ????????            <1> 	u.off:	  resd 1
  2953 0000661C ????????            <1> 	u.base:	  resd 1
  2954 00006620 ????????            <1> 	u.count:  resd 1
  2955 00006624 ????????            <1> 	u.nread:  resd 1
  2956 00006628 ????????            <1> 	u.break:  resd 1 ; break
  2957 0000662C ????                <1> 	u.ttyp:	  resw 1 
  2958 0000662E <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2959                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2960 0000663E ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2961 0000663F ??                  <1> 	u.pri:	  resb 1 ; 
  2962 00006640 ????                <1> 	u.intr:	  resw 1
  2963 00006642 ????                <1> 	u.quit:	  resw 1
  2964                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2965 00006644 ????                <1> 	u.ilgins: resw 1
  2966                              <1> 	;u.cdrv:  resw 1 ; cdev
  2967 00006646 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2968 00006647 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2969 00006648 ??                  <1> 	u.uid:	  resb 1 ; uid
  2970 00006649 ??                  <1> 	u.ruid:	  resb 1
  2971 0000664A ??                  <1> 	u.bsys:	  resb 1
  2972 0000664B ??                  <1> 	u.uno:	  resb 1
  2973 0000664C ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2974                              <1> 	; tty number (rtty, rcvt, wtty)
  2975 00006650 ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2976                              <1> 	; last error number
  2977 00006651 ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2978                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2979 00006655 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2980 00006659 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2981 0000665D ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2982 00006661 ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2983                              <1> 	;u.pncount: resw 1 
  2984                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2985                              <1> 	;u.pnbase:  resd 1 
  2986                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2987                              <1> 			 ; 09/06/2015
  2988 00006663 ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2989 00006664 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2990                              <1> 			 ; 24/07/2015 - 24/06/2015
  2991                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2992                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2993                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2994                              <1>  			 ; 24/06/2015	  	
  2995                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2996                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2997                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2998 00006665 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2999                              <1> 
  3000 00006669 ??????              <1> alignb 4
  3001                              <1> 
  3002                              <1> U_SIZE	equ $ - user
  3003                              <1> 
  3004                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3005 0000666C ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3006 00006670 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3007 00006674 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3008 00006678 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  3009                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3010 0000667A ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3011 0000667B ??                  <1> 	resb 1 
  3012 0000667C ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3013                              <1> 
  3014                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3015                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3016 00006680 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3017 00006681 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3018 00006682 ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3019 00006683 ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  3020                              <1> 
  3021                              <1> ;alignb 4
  3022                              <1> 
  3023                              <1> ; 22/08/2015
  3024 00006684 <res 1040h>         <1> buffer: resb nbuf * 520
  3025                              <1> 
  3026 000076C4 ????????????????    <1> sb0:	resd 2
  3027                              <1> ;s:
  3028                              <1> ; (root disk) super block buffer
  3029                              <1> systm:
  3030                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3031                              <1> 	; 11/03/2013. 
  3032                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3033                              <1> 	;s.
  3034                              <1> 
  3035 000076CC ????                <1> 	resw 1
  3036 000076CE <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3037 00007836 ????                <1> 	resw 1
  3038 00007838 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  3039                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  3040 00007858 ????????            <1> 	s.time:	 resd 1
  3041 0000785C ????????            <1> 	s.syst:	 resd 1
  3042 00007860 ????????            <1>         s.wait_: resd 1 ; wait
  3043 00007864 ????????            <1> 	s.idlet: resd 1
  3044 00007868 ????????            <1> 	s.chrgt: resd 1
  3045 0000786C ????                <1> 	s.drerr: resw 1
  3046                              <1> 
  3047                              <1> S_SIZE	equ $ - systm
  3048                              <1> 
  3049 0000786E <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3050                              <1> 
  3051 000078CC ????????????????    <1> sb1:	resd 2
  3052                              <1> ; (mounted disk) super block buffer
  3053                              <1> mount:	
  3054 000078D4 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3055                              <1> 
  3056                              <1> ;/ ux -- unix
  3057                              <1> ;
  3058                              <1> ;systm:
  3059                              <1> ;
  3060                              <1> ;	.=.+2
  3061                              <1> ;	.=.+128.
  3062                              <1> ;	.=.+2
  3063                              <1> ;	.=.+64.
  3064                              <1> ;	s.time: .=.+4
  3065                              <1> ;	s.syst: .=.+4
  3066                              <1> ;	s.wait: .=.+4
  3067                              <1> ;	s.idlet:.=.+4
  3068                              <1> ;	s.chrgt:.=.+4
  3069                              <1> ;	s.drerr:.=.+2
  3070                              <1> ;inode:
  3071                              <1> ;	i.flgs: .=.+2
  3072                              <1> ;	i.nlks: .=.+1
  3073                              <1> ;	i.uid:  .=.+1
  3074                              <1> ;	i.size: .=.+2
  3075                              <1> ;	i.dskp: .=.+16.
  3076                              <1> ;	i.ctim: .=.+4
  3077                              <1> ;	i.mtim: .=.+4
  3078                              <1> ;	. = inode+32.
  3079                              <1> ;mount:	.=.+1024.
  3080                              <1> ;proc:
  3081                              <1> ;	p.pid:  .=.+[2*nproc]
  3082                              <1> ;	p.dska: .=.+[2*nproc]
  3083                              <1> ;	p.ppid: .=.+[2*nproc]
  3084                              <1> ;	p.break:.=.+[2*nproc]
  3085                              <1> ;	p.link: .=.+nproc
  3086                              <1> ;	p.stat: .=.+nproc
  3087                              <1> ;tty:
  3088                              <1> ;	. = .+[ntty*8.]
  3089                              <1> ;fsp:	.=.+[nfiles*8.]
  3090                              <1> ;bufp:	.=.+[nbuf*2]+6
  3091                              <1> ;sb0:	.=.+8
  3092                              <1> ;sb1:	.=.+8
  3093                              <1> ;swp:	.=.+8
  3094                              <1> ;ii:	.=.+2
  3095                              <1> ;idev:	.=.+2
  3096                              <1> ;cdev:	.=.+2
  3097                              <1> ;deverr: .=.+12.
  3098                              <1> ;active: .=.+2
  3099                              <1> ;rfap:	.=.+2
  3100                              <1> ;rkap:	.=.+2
  3101                              <1> ;tcap:	.=.+2
  3102                              <1> ;tcstate:.=.+2
  3103                              <1> ;tcerrc: .=.+2
  3104                              <1> ;mnti:	.=.+2
  3105                              <1> ;mntd:	.=.+2
  3106                              <1> ;mpid:	.=.+2
  3107                              <1> ;clockp: .=.+2
  3108                              <1> ;rootdir:.=.+2
  3109                              <1> ;toutt:	.=.+16.
  3110                              <1> ;touts: .=.+32.
  3111                              <1> ;runq:	.=.+6
  3112                              <1> ;
  3113                              <1> ;wlist:	.=.+40.
  3114                              <1> ;cc:	.=.+30.
  3115                              <1> ;cf:	.=.+31.
  3116                              <1> ;cl:	.=.+31.
  3117                              <1> ;clist:	.=.+510.
  3118                              <1> ;imod:	.=.+1
  3119                              <1> ;smod:	.=.+1
  3120                              <1> ;mmod:	.=.+1
  3121                              <1> ;uquant: .=.+1
  3122                              <1> ;sysflg: .=.+1
  3123                              <1> ;pptiflg:.=.+1
  3124                              <1> ;ttyoch: .=.+1
  3125                              <1> ; .even
  3126                              <1> ; .=.+100.; sstack:
  3127                              <1> ;buffer: .=.+[ntty*140.]
  3128                              <1> ;	.=.+[nbuf*520.]
  3129                              <1> ;
  3130                              <1> ; . = core-64.
  3131                              <1> ;user:
  3132                              <1> ;	u.sp:    .=.+2
  3133                              <1> ;	u.usp:   .=.+2
  3134                              <1> ;	u.r0:    .=.+2
  3135                              <1> ;	u.cdir:  .=.+2
  3136                              <1> ;	u.fp:    .=.+10.
  3137                              <1> ;	u.fofp:  .=.+2
  3138                              <1> ;	u.dirp:  .=.+2
  3139                              <1> ;	u.namep: .=.+2
  3140                              <1> ;	u.off:   .=.+2
  3141                              <1> ;	u.base:  .=.+2
  3142                              <1> ;	u.count: .=.+2
  3143                              <1> ;	u.nread: .=.+2
  3144                              <1> ;	u.break: .=.+2
  3145                              <1> ;	u.ttyp:  .=.+2
  3146                              <1> ;	u.dirbuf:.=.+10.
  3147                              <1> ;	u.pri:   .=.+2
  3148                              <1> ;	u.intr:  .=.+2
  3149                              <1> ;	u.quit:  .=.+2
  3150                              <1> ;	u.emt:   .=.+2
  3151                              <1> ;	u.ilgins:.=.+2
  3152                              <1> ;	u.cdev:  .=.+2
  3153                              <1> ;	u.uid:   .=.+1
  3154                              <1> ;	u.ruid:  .=.+1
  3155                              <1> ;	u.bsys:  .=.+1
  3156                              <1> ;	u.uno:   .=.+1
  3157                              <1> ;. = core
  2801                                  
  2802                                  ; 27/12/2021
  2803                                  ;buffer: resb (nbuf*520)
  2804                                  
  2805                                  bss_end:
  2806                                  
  2807                                  ; 02/01/2022
  2808                                  BSS_SIZE equ bss_end - bss_start
  2809                                  
  2810                                  ; 27/12/2013
  2811                                  _end:  ; end of kernel code (and read only data, just before bss)
